diff options
author | marha <marha@users.sourceforge.net> | 2012-03-26 14:23:28 +0200 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2012-03-26 14:23:28 +0200 |
commit | 76bcc36ed305418a3ddc5752d287ede894243e1b (patch) | |
tree | bacb320c825768471ce56f058f17ce863d592376 /xorg-server/miext/rootless | |
parent | 7d894e32566b710952c44cbc71939ad1d9e2fa8d (diff) | |
parent | 0f834b91a4768673833ab4917e87d86c237bb1a6 (diff) | |
download | vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.gz vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.tar.bz2 vcxsrv-76bcc36ed305418a3ddc5752d287ede894243e1b.zip |
Merge remote-tracking branch 'origin/released'
Conflicts:
pixman/pixman/pixman-mmx.c
xorg-server/Xext/shm.c
xorg-server/Xext/syncsrv.h
xorg-server/Xext/xvmain.c
xorg-server/Xi/exevents.c
xorg-server/Xi/opendev.c
xorg-server/composite/compalloc.c
xorg-server/composite/compoverlay.c
xorg-server/dix/colormap.c
xorg-server/dix/devices.c
xorg-server/dix/dispatch.c
xorg-server/dix/dixfonts.c
xorg-server/dix/eventconvert.c
xorg-server/dix/events.c
xorg-server/dix/gc.c
xorg-server/dix/getevents.c
xorg-server/dix/main.c
xorg-server/dix/privates.c
xorg-server/dix/registry.c
xorg-server/dix/resource.c
xorg-server/exa/exa_accel.c
xorg-server/exa/exa_migration_classic.c
xorg-server/exa/exa_unaccel.c
xorg-server/fb/fb.h
xorg-server/fb/fbcopy.c
xorg-server/fb/fbpixmap.c
xorg-server/glx/dispatch.h
xorg-server/glx/glapi.h
xorg-server/glx/glapi_gentable.c
xorg-server/glx/glapitable.h
xorg-server/glx/glprocs.h
xorg-server/glx/glxcmds.c
xorg-server/glx/glxcmdsswap.c
xorg-server/glx/glxdricommon.c
xorg-server/glx/glxdriswrast.c
xorg-server/glx/glxext.c
xorg-server/glx/indirect_dispatch.c
xorg-server/glx/indirect_dispatch.h
xorg-server/glx/indirect_dispatch_swap.c
xorg-server/glx/indirect_size.h
xorg-server/glx/indirect_size_get.h
xorg-server/glx/indirect_table.c
xorg-server/glx/indirect_util.c
xorg-server/glx/rensize.c
xorg-server/glx/single2swap.c
xorg-server/glx/singlepix.c
xorg-server/glx/singlepixswap.c
xorg-server/glx/singlesize.c
xorg-server/hw/dmx/dmxinit.c
xorg-server/hw/kdrive/ephyr/ephyr.c
xorg-server/hw/kdrive/ephyr/hostx.c
xorg-server/hw/kdrive/ephyr/hostx.h
xorg-server/hw/kdrive/src/kinput.c
xorg-server/hw/xfree86/common/compiler.h
xorg-server/hw/xwin/InitInput.c
xorg-server/hw/xwin/InitOutput.c
xorg-server/hw/xwin/ddraw.h
xorg-server/hw/xwin/glx/glwrap.c
xorg-server/hw/xwin/glx/indirect.c
xorg-server/hw/xwin/glx/wgl_ext_api.h
xorg-server/hw/xwin/glx/winpriv.c
xorg-server/hw/xwin/win.h
xorg-server/hw/xwin/winallpriv.c
xorg-server/hw/xwin/winauth.c
xorg-server/hw/xwin/winclipboard.h
xorg-server/hw/xwin/winclipboardinit.c
xorg-server/hw/xwin/winclipboardthread.c
xorg-server/hw/xwin/winclipboardunicode.c
xorg-server/hw/xwin/winclipboardwndproc.c
xorg-server/hw/xwin/winclipboardwrappers.c
xorg-server/hw/xwin/winclipboardxevents.c
xorg-server/hw/xwin/wincmap.c
xorg-server/hw/xwin/winconfig.c
xorg-server/hw/xwin/wincreatewnd.c
xorg-server/hw/xwin/wincursor.c
xorg-server/hw/xwin/windialogs.c
xorg-server/hw/xwin/winengine.c
xorg-server/hw/xwin/winerror.c
xorg-server/hw/xwin/wingc.c
xorg-server/hw/xwin/wingetsp.c
xorg-server/hw/xwin/winkeybd.c
xorg-server/hw/xwin/winkeybd.h
xorg-server/hw/xwin/winlayouts.h
xorg-server/hw/xwin/winmisc.c
xorg-server/hw/xwin/winmonitors.c
xorg-server/hw/xwin/winmouse.c
xorg-server/hw/xwin/winmsg.c
xorg-server/hw/xwin/winmsg.h
xorg-server/hw/xwin/winmultiwindowclass.c
xorg-server/hw/xwin/winmultiwindowicons.c
xorg-server/hw/xwin/winmultiwindowshape.c
xorg-server/hw/xwin/winmultiwindowwindow.c
xorg-server/hw/xwin/winmultiwindowwm.c
xorg-server/hw/xwin/winmultiwindowwndproc.c
xorg-server/hw/xwin/winnativegdi.c
xorg-server/hw/xwin/winpfbdd.c
xorg-server/hw/xwin/winpixmap.c
xorg-server/hw/xwin/winpolyline.c
xorg-server/hw/xwin/winprefs.c
xorg-server/hw/xwin/winprocarg.c
xorg-server/hw/xwin/winregistry.c
xorg-server/hw/xwin/winscrinit.c
xorg-server/hw/xwin/winsetsp.c
xorg-server/hw/xwin/winshaddd.c
xorg-server/hw/xwin/winshadddnl.c
xorg-server/hw/xwin/winshadgdi.c
xorg-server/hw/xwin/wintrayicon.c
xorg-server/hw/xwin/winwin32rootless.c
xorg-server/hw/xwin/winwin32rootlesswindow.c
xorg-server/hw/xwin/winwin32rootlesswndproc.c
xorg-server/hw/xwin/winwindow.c
xorg-server/hw/xwin/winwindow.h
xorg-server/hw/xwin/winwindowswm.c
xorg-server/hw/xwin/winwndproc.c
xorg-server/include/callback.h
xorg-server/include/dixstruct.h
xorg-server/include/misc.h
xorg-server/include/os.h
xorg-server/include/scrnintstr.h
xorg-server/mi/micmap.c
xorg-server/mi/miinitext.c
xorg-server/mi/mioverlay.c
xorg-server/mi/misprite.c
xorg-server/mi/mivaltree.c
xorg-server/mi/miwindow.c
xorg-server/miext/damage/damage.c
xorg-server/miext/rootless/rootlessGC.c
xorg-server/miext/rootless/rootlessWindow.c
xorg-server/os/WaitFor.c
xorg-server/os/access.c
xorg-server/os/connection.c
xorg-server/os/io.c
xorg-server/os/log.c
xorg-server/os/osinit.c
xorg-server/os/utils.c
xorg-server/os/xdmcp.c
xorg-server/os/xprintf.c
xorg-server/os/xstrans.c
xorg-server/render/mipict.c
xorg-server/xkb/xkbActions.c
xorg-server/xkb/xkbInit.c
xorg-server/xkeyboard-config/compat/default.in
Diffstat (limited to 'xorg-server/miext/rootless')
-rw-r--r-- | xorg-server/miext/rootless/rootless.h | 731 | ||||
-rw-r--r-- | xorg-server/miext/rootless/rootlessCommon.c | 908 | ||||
-rw-r--r-- | xorg-server/miext/rootless/rootlessGC.c | 2953 | ||||
-rw-r--r-- | xorg-server/miext/rootless/rootlessScreen.c | 233 | ||||
-rw-r--r-- | xorg-server/miext/rootless/rootlessValTree.c | 589 | ||||
-rw-r--r-- | xorg-server/miext/rootless/rootlessWindow.c | 3289 | ||||
-rw-r--r-- | xorg-server/miext/rootless/rootlessWindow.h | 123 |
7 files changed, 4413 insertions, 4413 deletions
diff --git a/xorg-server/miext/rootless/rootless.h b/xorg-server/miext/rootless/rootless.h index 757e4d372..a3f38b633 100644 --- a/xorg-server/miext/rootless/rootless.h +++ b/xorg-server/miext/rootless/rootless.h @@ -1,368 +1,363 @@ -/*
- * External interface to generic rootless mode
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef _ROOTLESS_H
-#define _ROOTLESS_H
-
-#include "rootlessConfig.h"
-#include "mi.h"
-#include "gcstruct.h"
-
-/*
- Each top-level rootless window has a one-to-one correspondence to a physical
- on-screen window. The physical window is refered to as a "frame".
- */
-
-typedef void * RootlessFrameID;
-
-/*
- * RootlessWindowRec
- * This structure stores the per-frame data used by the rootless code.
- * Each top-level X window has one RootlessWindowRec associated with it.
- */
-typedef struct _RootlessWindowRec {
- // Position and size includes the window border
- // Position is in per-screen coordinates
- int x, y;
- unsigned int width, height;
- unsigned int borderWidth;
- int level;
-
- RootlessFrameID wid; // implementation specific frame id
- WindowPtr win; // underlying X window
-
- // Valid only when drawing (ie. is_drawing is set)
- char *pixelData;
- int bytesPerRow;
-
- PixmapPtr pixmap;
-
- unsigned int is_drawing :1; // Currently drawing?
- unsigned int is_reorder_pending :1;
- unsigned int is_offscreen :1;
- unsigned int is_obscured :1;
-} RootlessWindowRec, *RootlessWindowPtr;
-
-
-/* Offset for screen-local to global coordinate transforms */
-extern int rootlessGlobalOffsetX;
-extern int rootlessGlobalOffsetY;
-
-/* The minimum number of bytes or pixels for which to use the
- implementation's accelerated functions. */
-extern unsigned int rootless_CopyBytes_threshold;
-extern unsigned int rootless_CopyWindow_threshold;
-
-/* Gravity for window contents during resizing */
-enum rl_gravity_enum {
- RL_GRAVITY_NONE = 0, /* no gravity, fill everything */
- RL_GRAVITY_NORTH_WEST = 1, /* anchor to top-left corner */
- RL_GRAVITY_NORTH_EAST = 2, /* anchor to top-right corner */
- RL_GRAVITY_SOUTH_EAST = 3, /* anchor to bottom-right corner */
- RL_GRAVITY_SOUTH_WEST = 4, /* anchor to bottom-left corner */
-};
-
-
-/*------------------------------------------
- Rootless Implementation Functions
- ------------------------------------------*/
-
-/*
- * Create a new frame.
- * The frame is created unmapped.
- *
- * pFrame RootlessWindowPtr for this frame should be completely
- * initialized before calling except for pFrame->wid, which
- * is set by this function.
- * pScreen Screen on which to place the new frame
- * newX, newY Position of the frame.
- * pNewShape Shape for the frame (in frame-local coordinates). NULL for
- * unshaped frames.
- */
-typedef Bool (*RootlessCreateFrameProc)
- (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY,
- RegionPtr pNewShape);
-
-/*
- * Destroy a frame.
- * Drawing is stopped and all updates are flushed before this is called.
- *
- * wid Frame id
- */
-typedef void (*RootlessDestroyFrameProc)
- (RootlessFrameID wid);
-
-/*
- * Move a frame on screen.
- * Drawing is stopped and all updates are flushed before this is called.
- *
- * wid Frame id
- * pScreen Screen to move the new frame to
- * newX, newY New position of the frame
- */
-typedef void (*RootlessMoveFrameProc)
- (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY);
-
-/*
- * Resize and move a frame.
- * Drawing is stopped and all updates are flushed before this is called.
- *
- * wid Frame id
- * pScreen Screen to move the new frame to
- * newX, newY New position of the frame
- * newW, newH New size of the frame
- * gravity Gravity for window contents (rl_gravity_enum). This is always
- * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set.
- */
-typedef void (*RootlessResizeFrameProc)
- (RootlessFrameID wid, ScreenPtr pScreen,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int gravity);
-
-/*
- * Change frame ordering (AKA stacking, layering).
- * Drawing is stopped before this is called. Unmapped frames are mapped by
- * setting their ordering.
- *
- * wid Frame id
- * nextWid Frame id of frame that is now above this one or NULL if this
- * frame is at the top.
- */
-typedef void (*RootlessRestackFrameProc)
- (RootlessFrameID wid, RootlessFrameID nextWid);
-
-/*
- * Change frame's shape.
- * Drawing is stopped before this is called.
- *
- * wid Frame id
- * pNewShape New shape for the frame (in frame-local coordinates)
- * or NULL if now unshaped.
- */
-typedef void (*RootlessReshapeFrameProc)
- (RootlessFrameID wid, RegionPtr pNewShape);
-
-/*
- * Unmap a frame.
- *
- * wid Frame id
- */
-typedef void (*RootlessUnmapFrameProc)
- (RootlessFrameID wid);
-
-/*
- * Start drawing to a frame.
- * Prepare a frame for direct access to its backing buffer.
- *
- * wid Frame id
- * pixelData Address of the backing buffer (returned)
- * bytesPerRow Width in bytes of the backing buffer (returned)
- */
-typedef void (*RootlessStartDrawingProc)
- (RootlessFrameID wid, char **pixelData, int *bytesPerRow);
-
-/*
- * Stop drawing to a frame.
- * No drawing to the frame's backing buffer will occur until drawing
- * is started again.
- *
- * wid Frame id
- * flush Flush drawing updates for this frame to the screen.
- */
-typedef void (*RootlessStopDrawingProc)
- (RootlessFrameID wid, Bool flush);
-
-/*
- * Flush drawing updates to the screen.
- * Drawing is stopped before this is called.
- *
- * wid Frame id
- * pDamage Region containing all the changed pixels in frame-lcoal
- * coordinates. This is clipped to the window's clip.
- */
-typedef void (*RootlessUpdateRegionProc)
- (RootlessFrameID wid, RegionPtr pDamage);
-
-/*
- * Mark damaged rectangles as requiring redisplay to screen.
- *
- * wid Frame id
- * nrects Number of damaged rectangles
- * rects Array of damaged rectangles in frame-local coordinates
- * shift_x, Vector to shift rectangles by
- * shift_y
- */
-typedef void (*RootlessDamageRectsProc)
- (RootlessFrameID wid, int nrects, const BoxRec *rects,
- int shift_x, int shift_y);
-
-/*
- * Switch the window associated with a frame. (Optional)
- * When a framed window is reparented, the frame is resized and set to
- * use the new top-level parent. If defined this function will be called
- * afterwards for implementation specific bookkeeping.
- *
- * pFrame Frame whose window has switched
- * oldWin Previous window wrapped by this frame
- */
-typedef void (*RootlessSwitchWindowProc)
- (RootlessWindowPtr pFrame, WindowPtr oldWin);
-
-/*
- * Check if window should be reordered. (Optional)
- * The underlying window system may animate windows being ordered in.
- * We want them to be mapped but remain ordered out until the animation
- * completes. If defined this function will be called to check if a
- * framed window should be reordered now. If this function returns
- * FALSE, the window will still be mapped from the X11 perspective, but
- * the RestackFrame function will not be called for its frame.
- *
- * pFrame Frame to reorder
- */
-typedef Bool (*RootlessDoReorderWindowProc)
- (RootlessWindowPtr pFrame);
-
-/*
- * Copy bytes. (Optional)
- * Source and destinate may overlap and the right thing should happen.
- *
- * width Bytes to copy per row
- * height Number of rows
- * src Source data
- * srcRowBytes Width of source in bytes
- * dst Destination data
- * dstRowBytes Width of destination in bytes
- */
-typedef void (*RootlessCopyBytesProc)
- (unsigned int width, unsigned int height,
- const void *src, unsigned int srcRowBytes,
- void *dst, unsigned int dstRowBytes);
-
-/*
- * Copy area in frame to another part of frame. (Optional)
- *
- * wid Frame id
- * dstNrects Number of rectangles to copy
- * dstRects Array of rectangles to copy
- * dx, dy Number of pixels away to copy area
- */
-typedef void (*RootlessCopyWindowProc)
- (RootlessFrameID wid, int dstNrects, const BoxRec *dstRects,
- int dx, int dy);
-
-
-typedef void (*RootlessHideWindowProc)
- (RootlessFrameID wid);
-
-typedef void (*RootlessUpdateColormapProc)
- (RootlessFrameID wid, ScreenPtr pScreen);
-
-/*
- * Rootless implementation function list
- */
-typedef struct _RootlessFrameProcs {
- RootlessCreateFrameProc CreateFrame;
- RootlessDestroyFrameProc DestroyFrame;
-
- RootlessMoveFrameProc MoveFrame;
- RootlessResizeFrameProc ResizeFrame;
- RootlessRestackFrameProc RestackFrame;
- RootlessReshapeFrameProc ReshapeFrame;
- RootlessUnmapFrameProc UnmapFrame;
-
- RootlessStartDrawingProc StartDrawing;
- RootlessStopDrawingProc StopDrawing;
- RootlessUpdateRegionProc UpdateRegion;
- RootlessDamageRectsProc DamageRects;
-
- /* Optional frame functions */
- RootlessSwitchWindowProc SwitchWindow;
- RootlessDoReorderWindowProc DoReorderWindow;
- RootlessHideWindowProc HideWindow;
- RootlessUpdateColormapProc UpdateColormap;
-
- /* Optional acceleration functions */
- RootlessCopyBytesProc CopyBytes;
- RootlessCopyWindowProc CopyWindow;
-} RootlessFrameProcsRec, *RootlessFrameProcsPtr;
-
-
-/*
- * Initialize rootless mode on the given screen.
- */
-Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs);
-
-/*
- * Return the frame ID for the physical window displaying the given window.
- *
- * create If true and the window has no frame, attempt to create one
- */
-RootlessFrameID RootlessFrameForWindow(WindowPtr pWin, Bool create);
-
-/*
- * Return the top-level parent of a window.
- * The root is the top-level parent of itself, even though the root is
- * not otherwise considered to be a top-level window.
- */
-WindowPtr TopLevelParent(WindowPtr pWindow);
-
-/*
- * Prepare a window for direct access to its backing buffer.
- */
-void RootlessStartDrawing(WindowPtr pWindow);
-
-/*
- * Finish drawing to a window's backing buffer.
- *
- * flush If true, damaged areas are flushed to the screen.
- */
-void RootlessStopDrawing(WindowPtr pWindow, Bool flush);
-
-/*
- * Alocate a new screen pixmap.
- * miCreateScreenResources does not do this properly with a null
- * framebuffer pointer.
- */
-void RootlessUpdateScreenPixmap(ScreenPtr pScreen);
-
-/*
- * Reposition all windows on a screen to their correct positions.
- */
-void RootlessRepositionWindows(ScreenPtr pScreen);
-
-/*
- * Bring all windows to the front of the native stack
- */
-void RootlessOrderAllWindows (Bool include_unhitable);
-#endif /* _ROOTLESS_H */
+/* + * External interface to generic rootless mode + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _ROOTLESS_H +#define _ROOTLESS_H + +#include "rootlessConfig.h" +#include "mi.h" +#include "gcstruct.h" + +/* + Each top-level rootless window has a one-to-one correspondence to a physical + on-screen window. The physical window is refered to as a "frame". + */ + +typedef void *RootlessFrameID; + +/* + * RootlessWindowRec + * This structure stores the per-frame data used by the rootless code. + * Each top-level X window has one RootlessWindowRec associated with it. + */ +typedef struct _RootlessWindowRec { + // Position and size includes the window border + // Position is in per-screen coordinates + int x, y; + unsigned int width, height; + unsigned int borderWidth; + int level; + + RootlessFrameID wid; // implementation specific frame id + WindowPtr win; // underlying X window + + // Valid only when drawing (ie. is_drawing is set) + char *pixelData; + int bytesPerRow; + + PixmapPtr pixmap; + + unsigned int is_drawing:1; // Currently drawing? + unsigned int is_reorder_pending:1; + unsigned int is_offscreen:1; + unsigned int is_obscured:1; +} RootlessWindowRec, *RootlessWindowPtr; + +/* Offset for screen-local to global coordinate transforms */ +extern int rootlessGlobalOffsetX; +extern int rootlessGlobalOffsetY; + +/* The minimum number of bytes or pixels for which to use the + implementation's accelerated functions. */ +extern unsigned int rootless_CopyBytes_threshold; +extern unsigned int rootless_CopyWindow_threshold; + +/* Gravity for window contents during resizing */ +enum rl_gravity_enum { + RL_GRAVITY_NONE = 0, /* no gravity, fill everything */ + RL_GRAVITY_NORTH_WEST = 1, /* anchor to top-left corner */ + RL_GRAVITY_NORTH_EAST = 2, /* anchor to top-right corner */ + RL_GRAVITY_SOUTH_EAST = 3, /* anchor to bottom-right corner */ + RL_GRAVITY_SOUTH_WEST = 4, /* anchor to bottom-left corner */ +}; + +/*------------------------------------------ + Rootless Implementation Functions + ------------------------------------------*/ + +/* + * Create a new frame. + * The frame is created unmapped. + * + * pFrame RootlessWindowPtr for this frame should be completely + * initialized before calling except for pFrame->wid, which + * is set by this function. + * pScreen Screen on which to place the new frame + * newX, newY Position of the frame. + * pNewShape Shape for the frame (in frame-local coordinates). NULL for + * unshaped frames. + */ +typedef Bool (*RootlessCreateFrameProc) + (RootlessWindowPtr pFrame, ScreenPtr pScreen, int newX, int newY, + RegionPtr pNewShape); + +/* + * Destroy a frame. + * Drawing is stopped and all updates are flushed before this is called. + * + * wid Frame id + */ +typedef void (*RootlessDestroyFrameProc) + (RootlessFrameID wid); + +/* + * Move a frame on screen. + * Drawing is stopped and all updates are flushed before this is called. + * + * wid Frame id + * pScreen Screen to move the new frame to + * newX, newY New position of the frame + */ +typedef void (*RootlessMoveFrameProc) + (RootlessFrameID wid, ScreenPtr pScreen, int newX, int newY); + +/* + * Resize and move a frame. + * Drawing is stopped and all updates are flushed before this is called. + * + * wid Frame id + * pScreen Screen to move the new frame to + * newX, newY New position of the frame + * newW, newH New size of the frame + * gravity Gravity for window contents (rl_gravity_enum). This is always + * RL_GRAVITY_NONE unless ROOTLESS_RESIZE_GRAVITY is set. + */ +typedef void (*RootlessResizeFrameProc) + (RootlessFrameID wid, ScreenPtr pScreen, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int gravity); + +/* + * Change frame ordering (AKA stacking, layering). + * Drawing is stopped before this is called. Unmapped frames are mapped by + * setting their ordering. + * + * wid Frame id + * nextWid Frame id of frame that is now above this one or NULL if this + * frame is at the top. + */ +typedef void (*RootlessRestackFrameProc) + (RootlessFrameID wid, RootlessFrameID nextWid); + +/* + * Change frame's shape. + * Drawing is stopped before this is called. + * + * wid Frame id + * pNewShape New shape for the frame (in frame-local coordinates) + * or NULL if now unshaped. + */ +typedef void (*RootlessReshapeFrameProc) + (RootlessFrameID wid, RegionPtr pNewShape); + +/* + * Unmap a frame. + * + * wid Frame id + */ +typedef void (*RootlessUnmapFrameProc) + (RootlessFrameID wid); + +/* + * Start drawing to a frame. + * Prepare a frame for direct access to its backing buffer. + * + * wid Frame id + * pixelData Address of the backing buffer (returned) + * bytesPerRow Width in bytes of the backing buffer (returned) + */ +typedef void (*RootlessStartDrawingProc) + (RootlessFrameID wid, char **pixelData, int *bytesPerRow); + +/* + * Stop drawing to a frame. + * No drawing to the frame's backing buffer will occur until drawing + * is started again. + * + * wid Frame id + * flush Flush drawing updates for this frame to the screen. + */ +typedef void (*RootlessStopDrawingProc) + (RootlessFrameID wid, Bool flush); + +/* + * Flush drawing updates to the screen. + * Drawing is stopped before this is called. + * + * wid Frame id + * pDamage Region containing all the changed pixels in frame-lcoal + * coordinates. This is clipped to the window's clip. + */ +typedef void (*RootlessUpdateRegionProc) + (RootlessFrameID wid, RegionPtr pDamage); + +/* + * Mark damaged rectangles as requiring redisplay to screen. + * + * wid Frame id + * nrects Number of damaged rectangles + * rects Array of damaged rectangles in frame-local coordinates + * shift_x, Vector to shift rectangles by + * shift_y + */ +typedef void (*RootlessDamageRectsProc) + (RootlessFrameID wid, int nrects, const BoxRec * rects, + int shift_x, int shift_y); + +/* + * Switch the window associated with a frame. (Optional) + * When a framed window is reparented, the frame is resized and set to + * use the new top-level parent. If defined this function will be called + * afterwards for implementation specific bookkeeping. + * + * pFrame Frame whose window has switched + * oldWin Previous window wrapped by this frame + */ +typedef void (*RootlessSwitchWindowProc) + (RootlessWindowPtr pFrame, WindowPtr oldWin); + +/* + * Check if window should be reordered. (Optional) + * The underlying window system may animate windows being ordered in. + * We want them to be mapped but remain ordered out until the animation + * completes. If defined this function will be called to check if a + * framed window should be reordered now. If this function returns + * FALSE, the window will still be mapped from the X11 perspective, but + * the RestackFrame function will not be called for its frame. + * + * pFrame Frame to reorder + */ +typedef Bool (*RootlessDoReorderWindowProc) + (RootlessWindowPtr pFrame); + +/* + * Copy bytes. (Optional) + * Source and destinate may overlap and the right thing should happen. + * + * width Bytes to copy per row + * height Number of rows + * src Source data + * srcRowBytes Width of source in bytes + * dst Destination data + * dstRowBytes Width of destination in bytes + */ +typedef void (*RootlessCopyBytesProc) + (unsigned int width, unsigned int height, + const void *src, unsigned int srcRowBytes, + void *dst, unsigned int dstRowBytes); + +/* + * Copy area in frame to another part of frame. (Optional) + * + * wid Frame id + * dstNrects Number of rectangles to copy + * dstRects Array of rectangles to copy + * dx, dy Number of pixels away to copy area + */ +typedef void (*RootlessCopyWindowProc) + (RootlessFrameID wid, int dstNrects, const BoxRec * dstRects, int dx, int dy); + +typedef void (*RootlessHideWindowProc) + (RootlessFrameID wid); + +typedef void (*RootlessUpdateColormapProc) + (RootlessFrameID wid, ScreenPtr pScreen); + +/* + * Rootless implementation function list + */ +typedef struct _RootlessFrameProcs { + RootlessCreateFrameProc CreateFrame; + RootlessDestroyFrameProc DestroyFrame; + + RootlessMoveFrameProc MoveFrame; + RootlessResizeFrameProc ResizeFrame; + RootlessRestackFrameProc RestackFrame; + RootlessReshapeFrameProc ReshapeFrame; + RootlessUnmapFrameProc UnmapFrame; + + RootlessStartDrawingProc StartDrawing; + RootlessStopDrawingProc StopDrawing; + RootlessUpdateRegionProc UpdateRegion; + RootlessDamageRectsProc DamageRects; + + /* Optional frame functions */ + RootlessSwitchWindowProc SwitchWindow; + RootlessDoReorderWindowProc DoReorderWindow; + RootlessHideWindowProc HideWindow; + RootlessUpdateColormapProc UpdateColormap; + + /* Optional acceleration functions */ + RootlessCopyBytesProc CopyBytes; + RootlessCopyWindowProc CopyWindow; +} RootlessFrameProcsRec, *RootlessFrameProcsPtr; + +/* + * Initialize rootless mode on the given screen. + */ +Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs); + +/* + * Return the frame ID for the physical window displaying the given window. + * + * create If true and the window has no frame, attempt to create one + */ +RootlessFrameID RootlessFrameForWindow(WindowPtr pWin, Bool create); + +/* + * Return the top-level parent of a window. + * The root is the top-level parent of itself, even though the root is + * not otherwise considered to be a top-level window. + */ +WindowPtr TopLevelParent(WindowPtr pWindow); + +/* + * Prepare a window for direct access to its backing buffer. + */ +void RootlessStartDrawing(WindowPtr pWindow); + +/* + * Finish drawing to a window's backing buffer. + * + * flush If true, damaged areas are flushed to the screen. + */ +void RootlessStopDrawing(WindowPtr pWindow, Bool flush); + +/* + * Alocate a new screen pixmap. + * miCreateScreenResources does not do this properly with a null + * framebuffer pointer. + */ +void RootlessUpdateScreenPixmap(ScreenPtr pScreen); + +/* + * Reposition all windows on a screen to their correct positions. + */ +void RootlessRepositionWindows(ScreenPtr pScreen); + +/* + * Bring all windows to the front of the native stack + */ +void RootlessOrderAllWindows(Bool include_unhitable); +#endif /* _ROOTLESS_H */ diff --git a/xorg-server/miext/rootless/rootlessCommon.c b/xorg-server/miext/rootless/rootlessCommon.c index 3ea3e5970..d8f43bd1b 100644 --- a/xorg-server/miext/rootless/rootlessCommon.c +++ b/xorg-server/miext/rootless/rootlessCommon.c @@ -1,448 +1,460 @@ -/*
- * Common rootless definitions and code
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stddef.h> /* For NULL */
-#include <limits.h> /* For CHAR_BIT */
-
-#include "rootlessCommon.h"
-#include "colormapst.h"
-
-unsigned int rootless_CopyBytes_threshold = 0;
-unsigned int rootless_CopyWindow_threshold = 0;
-int rootlessGlobalOffsetX = 0;
-int rootlessGlobalOffsetY = 0;
-
-RegionRec rootlessHugeRoot = {{-32767, -32767, 32767, 32767}, NULL};
-
-/* Following macro from miregion.c */
-
-/* true iff two Boxes overlap */
-#define EXTENTCHECK(r1,r2) \
- (!( ((r1)->x2 <= (r2)->x1) || \
- ((r1)->x1 >= (r2)->x2) || \
- ((r1)->y2 <= (r2)->y1) || \
- ((r1)->y1 >= (r2)->y2) ) )
-
-
-/*
- * TopLevelParent
- * Returns the top-level parent of pWindow.
- * The root is the top-level parent of itself, even though the root is
- * not otherwise considered to be a top-level window.
- */
-WindowPtr
-TopLevelParent(WindowPtr pWindow)
-{
- WindowPtr top;
-
- if (IsRoot(pWindow))
- return pWindow;
-
- top = pWindow;
- while (top && ! IsTopLevel(top))
- top = top->parent;
-
- return top;
-}
-
-
-/*
- * IsFramedWindow
- * Returns TRUE if this window is visible inside a frame
- * (e.g. it is visible and has a top-level or root parent)
- */
-Bool
-IsFramedWindow(WindowPtr pWin)
-{
- WindowPtr top;
-
- if (!dixPrivateKeyRegistered(&rootlessWindowPrivateKeyRec))
- return FALSE;
-
- if (!pWin->realized)
- return FALSE;
- top = TopLevelParent(pWin);
-
- return (top && WINREC(top));
-}
-
-Bool
-RootlessResolveColormap (ScreenPtr pScreen, int first_color,
- int n_colors, uint32_t *colors)
-{
- int last, i;
- ColormapPtr map;
-
- map = RootlessGetColormap (pScreen);
- if (map == NULL || map->class != PseudoColor) return FALSE;
-
- last = min (map->pVisual->ColormapEntries, first_color + n_colors);
- for (i = max (0, first_color); i < last; i++) {
- Entry *ent = map->red + i;
- uint16_t red, green, blue;
-
- if (!ent->refcnt) continue;
- if (ent->fShared) {
- red = ent->co.shco.red->color;
- green = ent->co.shco.green->color;
- blue = ent->co.shco.blue->color;
- } else {
- red = ent->co.local.red;
- green = ent->co.local.green;
- blue = ent->co.local.blue;
- }
-
- colors[i - first_color] = (0xFF000000UL
- | ((uint32_t) red & 0xff00) << 8
- | (green & 0xff00)
- | (blue >> 8));
- }
-
- return TRUE;
-}
-
-
-/*
- * RootlessStartDrawing
- * Prepare a window for direct access to its backing buffer.
- * Each top-level parent has a Pixmap representing its backing buffer,
- * which all of its children inherit.
- */
-void RootlessStartDrawing(WindowPtr pWindow)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- WindowPtr top = TopLevelParent(pWindow);
- RootlessWindowRec *winRec;
- PixmapPtr curPixmap;
-
- if (top == NULL)
- return;
- winRec = WINREC(top);
- if (winRec == NULL)
- return;
-
- // Make sure the window's top-level parent is prepared for drawing.
- if (!winRec->is_drawing) {
- int bw = wBorderWidth(top);
-
- SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData,
- &winRec->bytesPerRow);
-
- winRec->pixmap =
- GetScratchPixmapHeader(pScreen, winRec->width, winRec->height,
- top->drawable.depth,
- top->drawable.bitsPerPixel,
- winRec->bytesPerRow,
- winRec->pixelData);
- SetPixmapBaseToScreen(winRec->pixmap,
- top->drawable.x - bw, top->drawable.y - bw);
-
- winRec->is_drawing = TRUE;
- }
-
- curPixmap = pScreen->GetWindowPixmap(pWindow);
- if (curPixmap == winRec->pixmap)
- {
- RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n", pWindow, winRec->pixmap);
- }
- else
- {
- PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey);
- if (oldPixmap != NULL)
- {
- if (oldPixmap == curPixmap)
- RL_DEBUG_MSG("Window %p's curPixmap %p is the same as its oldPixmap; strange\n", pWindow, curPixmap);
- else
- RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n", pWindow, oldPixmap);
- }
- dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, curPixmap);
- pScreen->SetWindowPixmap(pWindow, winRec->pixmap);
- }
-}
-
-
-/*
- * RootlessStopDrawing
- * Stop drawing to a window's backing buffer. If flush is true,
- * damaged regions are flushed to the screen.
- */
-static int RestorePreDrawingPixmapVisitor(WindowPtr pWindow, pointer data)
-{
- RootlessWindowRec *winRec = (RootlessWindowRec*)data;
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- PixmapPtr exPixmap = pScreen->GetWindowPixmap(pWindow);
- PixmapPtr oldPixmap = dixLookupPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey);
- if (oldPixmap == NULL)
- {
- if (exPixmap == winRec->pixmap)
- RL_DEBUG_MSG("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n", pWindow, exPixmap);
- }
- else
- {
- if (exPixmap != winRec->pixmap)
- RL_DEBUG_MSG("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n", pWindow, oldPixmap, exPixmap, winRec->pixmap);
- if (oldPixmap == winRec->pixmap)
- RL_DEBUG_MSG("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n", pWindow, oldPixmap);
- pScreen->SetWindowPixmap(pWindow, oldPixmap);
- dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
- }
- return WT_WALKCHILDREN;
-}
-
-void RootlessStopDrawing(WindowPtr pWindow, Bool flush)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- WindowPtr top = TopLevelParent(pWindow);
- RootlessWindowRec *winRec;
-
- if (top == NULL)
- return;
- winRec = WINREC(top);
- if (winRec == NULL)
- return;
-
- if (winRec->is_drawing) {
- SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush);
-
- FreeScratchPixmapHeader(winRec->pixmap);
- TraverseTree(top, RestorePreDrawingPixmapVisitor, (pointer)winRec);
- winRec->pixmap = NULL;
-
- winRec->is_drawing = FALSE;
- }
- else if (flush) {
- SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL);
- }
-
- if (flush && winRec->is_reorder_pending) {
- winRec->is_reorder_pending = FALSE;
- RootlessReorderWindow(pWindow);
- }
-}
-
-
-/*
- * RootlessDamageRegion
- * Mark a damaged region as requiring redisplay to screen.
- * pRegion is in GLOBAL coordinates.
- */
-void
-RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion)
-{
- RootlessWindowRec *winRec;
- RegionRec clipped;
- WindowPtr pTop;
- BoxPtr b1, b2;
-
- RL_DEBUG_MSG("Damaged win 0x%x ", pWindow);
-
- pTop = TopLevelParent(pWindow);
- if (pTop == NULL)
- return;
-
- winRec = WINREC(pTop);
- if (winRec == NULL)
- return;
-
- /* We need to intersect the drawn region with the clip of the window
- to avoid marking places we didn't actually draw (which can cause
- problems when the window has an extra client-side backing store)
-
- But this is a costly operation and since we'll normally just be
- drawing inside the clip, go to some lengths to avoid the general
- case intersection. */
-
- b1 = RegionExtents(&pWindow->borderClip);
- b2 = RegionExtents(pRegion);
-
- if (EXTENTCHECK(b1, b2)) {
- /* Regions may overlap. */
-
- if (RegionNumRects(pRegion) == 1) {
- int in;
-
- /* Damaged region only has a single rect, so we can
- just compare that against the region */
-
- in = RegionContainsRect(&pWindow->borderClip,
- RegionRects (pRegion));
- if (in == rgnIN) {
- /* clip totally contains pRegion */
-
- SCREENREC(pWindow->drawable.pScreen)->imp->
- DamageRects(winRec->wid,
- RegionNumRects(pRegion),
- RegionRects(pRegion),
- -winRec->x, -winRec->y);
-
- RootlessQueueRedisplay(pTop->drawable.pScreen);
- goto out;
- }
- else if (in == rgnOUT) {
- /* clip doesn't contain pRegion */
-
- goto out;
- }
- }
-
- /* clip overlaps pRegion, need to intersect */
-
- RegionNull(&clipped);
- RegionIntersect(&clipped, &pWindow->borderClip, pRegion);
-
- SCREENREC(pWindow->drawable.pScreen)->imp->
- DamageRects(winRec->wid,
- RegionNumRects(&clipped),
- RegionRects(&clipped),
- -winRec->x, -winRec->y);
-
- RegionUninit(&clipped);
-
- RootlessQueueRedisplay(pTop->drawable.pScreen);
- }
-
-out:
-#ifdef ROOTLESSDEBUG
- {
- BoxRec *box = RegionRects(pRegion), *end;
- int numBox = RegionNumRects(pRegion);
-
- for (end = box+numBox; box < end; box++) {
- RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n",
- box->x1, box->x2, box->y1, box->y2);
- }
- }
-#endif
- return;
-}
-
-
-/*
- * RootlessDamageBox
- * Mark a damaged box as requiring redisplay to screen.
- * pRegion is in GLOBAL coordinates.
- */
-void
-RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox)
-{
- RegionRec region;
-
- RegionInit(®ion, pBox, 1);
-
- RootlessDamageRegion(pWindow, ®ion);
-
- RegionUninit(®ion); /* no-op */
-}
-
-
-/*
- * RootlessDamageRect
- * Mark a damaged rectangle as requiring redisplay to screen.
- * (x, y, w, h) is in window-local coordinates.
- */
-void
-RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h)
-{
- BoxRec box;
- RegionRec region;
-
- x += pWindow->drawable.x;
- y += pWindow->drawable.y;
-
- box.x1 = x;
- box.x2 = x + w;
- box.y1 = y;
- box.y2 = y + h;
-
- RegionInit(®ion, &box, 1);
-
- RootlessDamageRegion(pWindow, ®ion);
-
- RegionUninit(®ion); /* no-op */
-}
-
-
-/*
- * RootlessRedisplay
- * Stop drawing and redisplay the damaged region of a window.
- */
-void
-RootlessRedisplay(WindowPtr pWindow)
-{
- RootlessStopDrawing(pWindow, TRUE);
-}
-
-
-/*
- * RootlessRepositionWindows
- * Reposition all windows on a screen to their correct positions.
- */
-void
-RootlessRepositionWindows(ScreenPtr pScreen)
-{
- WindowPtr root = pScreen->root;
- WindowPtr win;
-
- if (root != NULL) {
- RootlessRepositionWindow(root);
-
- for (win = root->firstChild; win; win = win->nextSib) {
- if (WINREC(win) != NULL)
- RootlessRepositionWindow(win);
- }
- }
-}
-
-
-/*
- * RootlessRedisplayScreen
- * Walk every window on a screen and redisplay the damaged regions.
- */
-void
-RootlessRedisplayScreen(ScreenPtr pScreen)
-{
- WindowPtr root = pScreen->root;
-
- if (root != NULL) {
- WindowPtr win;
-
- RootlessRedisplay(root);
- for (win = root->firstChild; win; win = win->nextSib) {
- if (WINREC(win) != NULL) {
- RootlessRedisplay(win);
- }
- }
- }
-}
+/* + * Common rootless definitions and code + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stddef.h> /* For NULL */ +#include <limits.h> /* For CHAR_BIT */ + +#include "rootlessCommon.h" +#include "colormapst.h" + +unsigned int rootless_CopyBytes_threshold = 0; +unsigned int rootless_CopyWindow_threshold = 0; +int rootlessGlobalOffsetX = 0; +int rootlessGlobalOffsetY = 0; + +RegionRec rootlessHugeRoot = { {-32767, -32767, 32767, 32767}, NULL }; + +/* Following macro from miregion.c */ + +/* true iff two Boxes overlap */ +#define EXTENTCHECK(r1,r2) \ + (!( ((r1)->x2 <= (r2)->x1) || \ + ((r1)->x1 >= (r2)->x2) || \ + ((r1)->y2 <= (r2)->y1) || \ + ((r1)->y1 >= (r2)->y2) ) ) + +/* + * TopLevelParent + * Returns the top-level parent of pWindow. + * The root is the top-level parent of itself, even though the root is + * not otherwise considered to be a top-level window. + */ +WindowPtr +TopLevelParent(WindowPtr pWindow) +{ + WindowPtr top; + + if (IsRoot(pWindow)) + return pWindow; + + top = pWindow; + while (top && !IsTopLevel(top)) + top = top->parent; + + return top; +} + +/* + * IsFramedWindow + * Returns TRUE if this window is visible inside a frame + * (e.g. it is visible and has a top-level or root parent) + */ +Bool +IsFramedWindow(WindowPtr pWin) +{ + WindowPtr top; + + if (!dixPrivateKeyRegistered(&rootlessWindowPrivateKeyRec)) + return FALSE; + + if (!pWin->realized) + return FALSE; + top = TopLevelParent(pWin); + + return (top && WINREC(top)); +} + +Bool +RootlessResolveColormap(ScreenPtr pScreen, int first_color, + int n_colors, uint32_t * colors) +{ + int last, i; + ColormapPtr map; + + map = RootlessGetColormap(pScreen); + if (map == NULL || map->class != PseudoColor) + return FALSE; + + last = min(map->pVisual->ColormapEntries, first_color + n_colors); + for (i = max(0, first_color); i < last; i++) { + Entry *ent = map->red + i; + uint16_t red, green, blue; + + if (!ent->refcnt) + continue; + if (ent->fShared) { + red = ent->co.shco.red->color; + green = ent->co.shco.green->color; + blue = ent->co.shco.blue->color; + } + else { + red = ent->co.local.red; + green = ent->co.local.green; + blue = ent->co.local.blue; + } + + colors[i - first_color] = (0xFF000000UL + | ((uint32_t) red & 0xff00) << 8 + | (green & 0xff00) + | (blue >> 8)); + } + + return TRUE; +} + +/* + * RootlessStartDrawing + * Prepare a window for direct access to its backing buffer. + * Each top-level parent has a Pixmap representing its backing buffer, + * which all of its children inherit. + */ +void +RootlessStartDrawing(WindowPtr pWindow) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + WindowPtr top = TopLevelParent(pWindow); + RootlessWindowRec *winRec; + PixmapPtr curPixmap; + + if (top == NULL) + return; + winRec = WINREC(top); + if (winRec == NULL) + return; + + // Make sure the window's top-level parent is prepared for drawing. + if (!winRec->is_drawing) { + int bw = wBorderWidth(top); + + SCREENREC(pScreen)->imp->StartDrawing(winRec->wid, &winRec->pixelData, + &winRec->bytesPerRow); + + winRec->pixmap = + GetScratchPixmapHeader(pScreen, winRec->width, winRec->height, + top->drawable.depth, + top->drawable.bitsPerPixel, + winRec->bytesPerRow, winRec->pixelData); + SetPixmapBaseToScreen(winRec->pixmap, + top->drawable.x - bw, top->drawable.y - bw); + + winRec->is_drawing = TRUE; + } + + curPixmap = pScreen->GetWindowPixmap(pWindow); + if (curPixmap == winRec->pixmap) { + RL_DEBUG_MSG("Window %p already has winRec->pixmap %p; not pushing\n", + pWindow, winRec->pixmap); + } + else { + PixmapPtr oldPixmap = + dixLookupPrivate(&pWindow->devPrivates, + rootlessWindowOldPixmapPrivateKey); + if (oldPixmap != NULL) { + if (oldPixmap == curPixmap) + RL_DEBUG_MSG + ("Window %p's curPixmap %p is the same as its oldPixmap; strange\n", + pWindow, curPixmap); + else + RL_DEBUG_MSG("Window %p's existing oldPixmap %p being lost!\n", + pWindow, oldPixmap); + } + dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, + curPixmap); + pScreen->SetWindowPixmap(pWindow, winRec->pixmap); + } +} + +/* + * RootlessStopDrawing + * Stop drawing to a window's backing buffer. If flush is true, + * damaged regions are flushed to the screen. + */ +static int +RestorePreDrawingPixmapVisitor(WindowPtr pWindow, pointer data) +{ + RootlessWindowRec *winRec = (RootlessWindowRec *) data; + ScreenPtr pScreen = pWindow->drawable.pScreen; + PixmapPtr exPixmap = pScreen->GetWindowPixmap(pWindow); + PixmapPtr oldPixmap = + dixLookupPrivate(&pWindow->devPrivates, + rootlessWindowOldPixmapPrivateKey); + if (oldPixmap == NULL) { + if (exPixmap == winRec->pixmap) + RL_DEBUG_MSG + ("Window %p appears to be in drawing mode (ex-pixmap %p equals winRec->pixmap, which is being freed) but has no oldPixmap!\n", + pWindow, exPixmap); + } + else { + if (exPixmap != winRec->pixmap) + RL_DEBUG_MSG + ("Window %p appears to be in drawing mode (oldPixmap %p) but ex-pixmap %p not winRec->pixmap %p!\n", + pWindow, oldPixmap, exPixmap, winRec->pixmap); + if (oldPixmap == winRec->pixmap) + RL_DEBUG_MSG + ("Window %p's oldPixmap %p is winRec->pixmap, which has just been freed!\n", + pWindow, oldPixmap); + pScreen->SetWindowPixmap(pWindow, oldPixmap); + dixSetPrivate(&pWindow->devPrivates, rootlessWindowOldPixmapPrivateKey, + NULL); + } + return WT_WALKCHILDREN; +} + +void +RootlessStopDrawing(WindowPtr pWindow, Bool flush) +{ + ScreenPtr pScreen = pWindow->drawable.pScreen; + WindowPtr top = TopLevelParent(pWindow); + RootlessWindowRec *winRec; + + if (top == NULL) + return; + winRec = WINREC(top); + if (winRec == NULL) + return; + + if (winRec->is_drawing) { + SCREENREC(pScreen)->imp->StopDrawing(winRec->wid, flush); + + FreeScratchPixmapHeader(winRec->pixmap); + TraverseTree(top, RestorePreDrawingPixmapVisitor, (pointer) winRec); + winRec->pixmap = NULL; + + winRec->is_drawing = FALSE; + } + else if (flush) { + SCREENREC(pScreen)->imp->UpdateRegion(winRec->wid, NULL); + } + + if (flush && winRec->is_reorder_pending) { + winRec->is_reorder_pending = FALSE; + RootlessReorderWindow(pWindow); + } +} + +/* + * RootlessDamageRegion + * Mark a damaged region as requiring redisplay to screen. + * pRegion is in GLOBAL coordinates. + */ +void +RootlessDamageRegion(WindowPtr pWindow, RegionPtr pRegion) +{ + RootlessWindowRec *winRec; + RegionRec clipped; + WindowPtr pTop; + BoxPtr b1, b2; + + RL_DEBUG_MSG("Damaged win 0x%x ", pWindow); + + pTop = TopLevelParent(pWindow); + if (pTop == NULL) + return; + + winRec = WINREC(pTop); + if (winRec == NULL) + return; + + /* We need to intersect the drawn region with the clip of the window + to avoid marking places we didn't actually draw (which can cause + problems when the window has an extra client-side backing store) + + But this is a costly operation and since we'll normally just be + drawing inside the clip, go to some lengths to avoid the general + case intersection. */ + + b1 = RegionExtents(&pWindow->borderClip); + b2 = RegionExtents(pRegion); + + if (EXTENTCHECK(b1, b2)) { + /* Regions may overlap. */ + + if (RegionNumRects(pRegion) == 1) { + int in; + + /* Damaged region only has a single rect, so we can + just compare that against the region */ + + in = RegionContainsRect(&pWindow->borderClip, RegionRects(pRegion)); + if (in == rgnIN) { + /* clip totally contains pRegion */ + + SCREENREC(pWindow->drawable.pScreen)->imp->DamageRects(winRec-> + wid, + RegionNumRects + (pRegion), + RegionRects + (pRegion), + -winRec-> + x, + -winRec-> + y); + + RootlessQueueRedisplay(pTop->drawable.pScreen); + goto out; + } + else if (in == rgnOUT) { + /* clip doesn't contain pRegion */ + + goto out; + } + } + + /* clip overlaps pRegion, need to intersect */ + + RegionNull(&clipped); + RegionIntersect(&clipped, &pWindow->borderClip, pRegion); + + SCREENREC(pWindow->drawable.pScreen)->imp->DamageRects(winRec->wid, + RegionNumRects + (&clipped), + RegionRects + (&clipped), + -winRec->x, + -winRec->y); + + RegionUninit(&clipped); + + RootlessQueueRedisplay(pTop->drawable.pScreen); + } + + out: +#ifdef ROOTLESSDEBUG + { + BoxRec *box = RegionRects(pRegion), *end; + int numBox = RegionNumRects(pRegion); + + for (end = box + numBox; box < end; box++) { + RL_DEBUG_MSG("Damage rect: %i, %i, %i, %i\n", + box->x1, box->x2, box->y1, box->y2); + } + } +#endif + return; +} + +/* + * RootlessDamageBox + * Mark a damaged box as requiring redisplay to screen. + * pRegion is in GLOBAL coordinates. + */ +void +RootlessDamageBox(WindowPtr pWindow, BoxPtr pBox) +{ + RegionRec region; + + RegionInit(®ion, pBox, 1); + + RootlessDamageRegion(pWindow, ®ion); + + RegionUninit(®ion); /* no-op */ +} + +/* + * RootlessDamageRect + * Mark a damaged rectangle as requiring redisplay to screen. + * (x, y, w, h) is in window-local coordinates. + */ +void +RootlessDamageRect(WindowPtr pWindow, int x, int y, int w, int h) +{ + BoxRec box; + RegionRec region; + + x += pWindow->drawable.x; + y += pWindow->drawable.y; + + box.x1 = x; + box.x2 = x + w; + box.y1 = y; + box.y2 = y + h; + + RegionInit(®ion, &box, 1); + + RootlessDamageRegion(pWindow, ®ion); + + RegionUninit(®ion); /* no-op */ +} + +/* + * RootlessRedisplay + * Stop drawing and redisplay the damaged region of a window. + */ +void +RootlessRedisplay(WindowPtr pWindow) +{ + RootlessStopDrawing(pWindow, TRUE); +} + +/* + * RootlessRepositionWindows + * Reposition all windows on a screen to their correct positions. + */ +void +RootlessRepositionWindows(ScreenPtr pScreen) +{ + WindowPtr root = pScreen->root; + WindowPtr win; + + if (root != NULL) { + RootlessRepositionWindow(root); + + for (win = root->firstChild; win; win = win->nextSib) { + if (WINREC(win) != NULL) + RootlessRepositionWindow(win); + } + } +} + +/* + * RootlessRedisplayScreen + * Walk every window on a screen and redisplay the damaged regions. + */ +void +RootlessRedisplayScreen(ScreenPtr pScreen) +{ + WindowPtr root = pScreen->root; + + if (root != NULL) { + WindowPtr win; + + RootlessRedisplay(root); + for (win = root->firstChild; win; win = win->nextSib) { + if (WINREC(win) != NULL) { + RootlessRedisplay(win); + } + } + } +} diff --git a/xorg-server/miext/rootless/rootlessGC.c b/xorg-server/miext/rootless/rootlessGC.c index 2af251ee6..526709350 100644 --- a/xorg-server/miext/rootless/rootlessGC.c +++ b/xorg-server/miext/rootless/rootlessGC.c @@ -1,1463 +1,1490 @@ -/*
- * Graphics Context support for generic rootless X server
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved.
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stddef.h> /* For NULL */
-#include "mi.h"
-#include "scrnintstr.h"
-#include "gcstruct.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "dixfontstr.h"
-#include "mivalidate.h"
-#include "fb.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "rootlessCommon.h"
-
-#ifdef _MSC_VER
-#define inline __inline
-#endif
-
-// GC functions
-static void RootlessValidateGC(GCPtr pGC, unsigned long changes,
- DrawablePtr pDrawable);
-static void RootlessChangeGC(GCPtr pGC, unsigned long mask);
-static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
-static void RootlessDestroyGC(GCPtr pGC);
-static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue,
- int nrects);
-static void RootlessDestroyClip(GCPtr pGC);
-static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
-
-Bool RootlessCreateGC(GCPtr pGC);
-
-GCFuncs rootlessGCFuncs = {
- RootlessValidateGC,
- RootlessChangeGC,
- RootlessCopyGC,
- RootlessDestroyGC,
- RootlessChangeClip,
- RootlessDestroyClip,
- RootlessCopyClip,
-};
-
-// GC operations
-static void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit,
- int sorted);
-static void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
- DDXPointPtr pptInit, int *pwidthInit,
- int nspans, int sorted);
-static void RootlessPutImage(DrawablePtr dst, GCPtr pGC,
- int depth, int x, int y, int w, int h,
- int leftPad, int format, char *pBits);
-static RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
- int srcx, int srcy, int w, int h,
- int dstx, int dsty);
-static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
- GCPtr pGC, int srcx, int srcy,
- int w, int h, int dstx, int dsty,
- unsigned long plane);
-static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit);
-static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit);
-static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
- int nseg, xSegment *pSeg);
-static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
- int nRects, xRectangle *pRects);
-static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs);
-static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
- int shape, int mode, int count,
- DDXPointPtr pptInit);
-static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
- int nRectsInit, xRectangle *pRectsInit);
-static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
- int narcsInit, xArc *parcsInit);
-static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars);
-static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars);
-static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars);
-static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars);
-static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyphInit,
- CharInfoPtr *ppciInit, pointer unused);
-static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase);
-static void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
- int dx, int dy, int xOrg, int yOrg);
-
-
-static GCOps rootlessGCOps = {
- RootlessFillSpans,
- RootlessSetSpans,
- RootlessPutImage,
- RootlessCopyArea,
- RootlessCopyPlane,
- RootlessPolyPoint,
- RootlessPolylines,
- RootlessPolySegment,
- RootlessPolyRectangle,
- RootlessPolyArc,
- RootlessFillPolygon,
- RootlessPolyFillRect,
- RootlessPolyFillArc,
- RootlessPolyText8,
- RootlessPolyText16,
- RootlessImageText8,
- RootlessImageText16,
- RootlessImageGlyphBlt,
- RootlessPolyGlyphBlt,
- RootlessPushPixels
-};
-
-/*
- If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha
- channel of the on screen windows is always opaque. fb makes this harder
- than it would otherwise be by noticing that a planemask of 0x00ffffff
- includes all bits when depth==24, and so it "optimizes" the planemask to
- 0xffffffff. We work around this by temporarily setting depth=bpp while
- changing the GC.
-
- So the normal situation (in 32 bit mode) is that the planemask is
- 0x00ffffff and thus fb leaves the alpha channel alone. The rootless
- implementation is responsible for setting the alpha channel opaque
- initially.
-
- Unfortunately drawing with a planemask that doesn't have all bits set
- normally causes fb to fall off its fastest paths when blitting and
- filling. So we try to recognize when we can relax the planemask back to
- 0xffffffff, and do that for the duration of the drawing operation,
- setting the alpha channel in fg/bg pixels to opaque at the same time. We
- can do this when drawing op is GXcopy. We can also do this when copying
- from another window since its alpha channel must also be opaque.
-
- The three macros below are used to implement this. Drawing ops that can
- potentially have their planemask relaxed look like:
-
- OP {
- GC_SAVE(gc);
- GCOP_UNWRAP(gc);
-
- ...
-
- if (canAccelxxx(..) && otherwise-suitable)
- GC_UNSET_PM(gc, dst);
-
- gc->funcs->OP(gc, ...);
-
- GC_RESTORE(gc, dst);
- GCOP_WRAP(gc);
- }
-
- */
-
-#define GC_SAVE(pGC) \
- unsigned long _save_fg = (pGC)->fgPixel; \
- unsigned long _save_bg = (pGC)->bgPixel; \
- unsigned long _save_pm = (pGC)->planemask; \
- Bool _changed = FALSE
-
-#define GC_RESTORE(pGC, pDraw) \
- do { \
- if (_changed) { \
- unsigned int depth = (pDraw)->depth; \
- (pGC)->fgPixel = _save_fg; \
- (pGC)->bgPixel = _save_bg; \
- (pGC)->planemask = _save_pm; \
- (pDraw)->depth = (pDraw)->bitsPerPixel; \
- VALIDATE_GC(pGC, GCForeground | GCBackground | \
- GCPlaneMask, pDraw); \
- (pDraw)->depth = depth; \
- } \
- } while (0)
-
-#define GC_UNSET_PM(pGC, pDraw) \
- do { \
- unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \
- if (((pGC)->planemask & mask) != mask) { \
- unsigned int depth = (pDraw)->depth; \
- (pGC)->fgPixel |= mask; \
- (pGC)->bgPixel |= mask; \
- (pGC)->planemask |= mask; \
- (pDraw)->depth = (pDraw)->bitsPerPixel; \
- VALIDATE_GC(pGC, GCForeground | \
- GCBackground | GCPlaneMask, pDraw); \
- (pDraw)->depth = depth; \
- _changed = TRUE; \
- } \
- } while (0)
-
-#define VALIDATE_GC(pGC, changes, pDrawable) \
- do { \
- pGC->funcs->ValidateGC(pGC, changes, pDrawable); \
- if (((WindowPtr) pDrawable)->viewable) { \
- gcrec->originalOps = pGC->ops; \
- } \
- } while(0)
-
-static RootlessWindowRec *
-canAccelBlit (DrawablePtr pDraw, GCPtr pGC)
-{
- WindowPtr pTop;
- RootlessWindowRec *winRec;
- unsigned int pm;
-
- if (pGC->alu != GXcopy)
- return NULL;
-
- if (pDraw->type != DRAWABLE_WINDOW)
- return NULL;
-
- pm = ~RootlessAlphaMask(pDraw->bitsPerPixel);
- if ((pGC->planemask & pm) != pm)
- return NULL;
-
- pTop = TopLevelParent((WindowPtr) pDraw);
- if (pTop == NULL)
- return NULL;
-
- winRec = WINREC(pTop);
- if (winRec == NULL)
- return NULL;
-
- return winRec;
-}
-
-static inline RootlessWindowRec *
-canAccelFill(DrawablePtr pDraw, GCPtr pGC)
-{
- if (pGC->fillStyle != FillSolid)
- return NULL;
-
- return canAccelBlit(pDraw, pGC);
-}
-
-
-/*
- * Screen function to create a graphics context
- */
-Bool
-RootlessCreateGC(GCPtr pGC)
-{
- RootlessGCRec *gcrec;
- RootlessScreenRec *s;
- Bool result;
-
- SCREEN_UNWRAP(pGC->pScreen, CreateGC);
- s = SCREENREC(pGC->pScreen);
- result = s->CreateGC(pGC);
-
- gcrec = (RootlessGCRec *)
- dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey);
- gcrec->originalOps = NULL; // don't wrap ops yet
- gcrec->originalFuncs = pGC->funcs;
- pGC->funcs = &rootlessGCFuncs;
-
- SCREEN_WRAP(pGC->pScreen, CreateGC);
- return result;
-}
-
-
-/*
- * GC funcs
- *
- * These wrap lower level GC funcs.
- * ValidateGC wraps the GC ops iff dest is viewable.
- * All the others just unwrap and call.
- */
-
-// GCFUNC_UNRAP assumes funcs have been wrapped and
-// does not assume ops have been wrapped
-#define GCFUNC_UNWRAP(pGC) \
- RootlessGCRec *gcrec = (RootlessGCRec *) \
- dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
- (pGC)->funcs = gcrec->originalFuncs; \
- if (gcrec->originalOps) { \
- (pGC)->ops = gcrec->originalOps; \
-}
-
-#define GCFUNC_WRAP(pGC) \
- gcrec->originalFuncs = (pGC)->funcs; \
- (pGC)->funcs = &rootlessGCFuncs; \
- if (gcrec->originalOps) { \
- gcrec->originalOps = (pGC)->ops; \
- (pGC)->ops = &rootlessGCOps; \
-}
-
-
-static void
-RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
-{
- GCFUNC_UNWRAP(pGC);
-
- gcrec->originalOps = NULL;
-
- if (pDrawable->type == DRAWABLE_WINDOW)
- {
-#ifdef ROOTLESS_PROTECT_ALPHA
- unsigned int depth = pDrawable->depth;
-
- // We force a planemask so fb doesn't overwrite the alpha channel.
- // Left to its own devices, fb will optimize away the planemask.
- pDrawable->depth = pDrawable->bitsPerPixel;
- pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel);
- VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable);
- pDrawable->depth = depth;
-#else
- VALIDATE_GC(pGC, changes, pDrawable);
-#endif
- } else {
- pGC->funcs->ValidateGC(pGC, changes, pDrawable);
- }
-
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessChangeGC(GCPtr pGC, unsigned long mask)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->ChangeGC(pGC, mask);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
-{
- GCFUNC_UNWRAP(pGCDst);
- pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst);
- GCFUNC_WRAP(pGCDst);
-}
-
-static void RootlessDestroyGC(GCPtr pGC)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->DestroyGC(pGC);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->ChangeClip(pGC, type, pvalue, nrects);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessDestroyClip(GCPtr pGC)
-{
- GCFUNC_UNWRAP(pGC);
- pGC->funcs->DestroyClip(pGC);
- GCFUNC_WRAP(pGC);
-}
-
-static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
-{
- GCFUNC_UNWRAP(pgcDst);
- pgcDst->funcs->CopyClip(pgcDst, pgcSrc);
- GCFUNC_WRAP(pgcDst);
-}
-
-
-/*
- * GC ops
- *
- * We can't use shadowfb because shadowfb assumes one pixmap
- * and our root window is a special case.
- * However, much of this code is copied from shadowfb.
- */
-
-// assumes both funcs and ops are wrapped
-#define GCOP_UNWRAP(pGC) \
- RootlessGCRec *gcrec = (RootlessGCRec *) \
- dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \
- GCFuncs *saveFuncs = pGC->funcs; \
- (pGC)->funcs = gcrec->originalFuncs; \
- (pGC)->ops = gcrec->originalOps;
-
-#define GCOP_WRAP(pGC) \
- gcrec->originalOps = (pGC)->ops; \
- (pGC)->funcs = saveFuncs; \
- (pGC)->ops = &rootlessGCOps;
-
-static void
-RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit,
- DDXPointPtr pptInit, int *pwidthInit, int sorted)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill spans start ");
-
- if (nInit <= 0) {
- pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
- } else {
- DDXPointPtr ppt = pptInit;
- int *pwidth = pwidthInit;
- int i = nInit;
- BoxRec box;
-
- box.x1 = ppt->x;
- box.x2 = box.x1 + *pwidth;
- box.y2 = box.y1 = ppt->y;
-
- while (--i) {
- ppt++;
- pwidth++;
- if (box.x1 > ppt->x)
- box.x1 = ppt->x;
- if (box.x2 < (ppt->x + *pwidth))
- box.x2 = ppt->x + *pwidth;
- if (box.y1 > ppt->y)
- box.y1 = ppt->y;
- else if (box.y2 < ppt->y)
- box.y2 = ppt->y;
- }
-
- box.y2++;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill spans end\n");
-}
-
-static void
-RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc,
- DDXPointPtr pptInit, int *pwidthInit,
- int nspans, int sorted)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("set spans start ");
-
- if (nspans <= 0) {
- pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
- nspans, sorted);
- } else {
- DDXPointPtr ppt = pptInit;
- int *pwidth = pwidthInit;
- int i = nspans;
- BoxRec box;
-
- box.x1 = ppt->x;
- box.x2 = box.x1 + *pwidth;
- box.y2 = box.y1 = ppt->y;
-
- while (--i) {
- ppt++;
- pwidth++;
- if (box.x1 > ppt->x)
- box.x1 = ppt->x;
- if (box.x2 < (ppt->x + *pwidth))
- box.x2 = ppt->x + *pwidth;
- if (box.y1 > ppt->y)
- box.y1 = ppt->y;
- else if (box.y2 < ppt->y)
- box.y2 = ppt->y;
- }
-
- box.y2++;
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit,
- nspans, sorted);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("set spans end\n");
-}
-
-static void
-RootlessPutImage(DrawablePtr dst, GCPtr pGC,
- int depth, int x, int y, int w, int h,
- int leftPad, int format, char *pBits)
-{
- BoxRec box;
-
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("put image start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PutImage(dst, pGC, depth, x,y,w,h, leftPad, format, pBits);
-
- box.x1 = x + dst->x;
- box.x2 = box.x1 + w;
- box.y1 = y + dst->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("put image end\n");
-}
-
-/* changed area is *dest* rect */
-static RegionPtr
-RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC,
- int srcx, int srcy, int w, int h,
- int dstx, int dsty)
-{
- RegionPtr result;
- BoxRec box;
-
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst);
-
- if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
- /* If both source and dest are windows, and we're doing
- a simple copy operation, we can remove the alpha-protecting
- planemask (since source has opaque alpha as well) */
-
- if (canAccelBlit(pSrc, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- RootlessStartDrawing((WindowPtr) pSrc);
- }
- RootlessStartDrawing((WindowPtr) dst);
- result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty);
-
- box.x1 = dstx + dst->x;
- box.x2 = box.x1 + w;
- box.y1 = dsty + dst->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("copy area end\n");
- return result;
-}
-
-/* changed area is *dest* rect */
-static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst,
- GCPtr pGC, int srcx, int srcy,
- int w, int h, int dstx, int dsty,
- unsigned long plane)
-{
- RegionPtr result;
- BoxRec box;
-
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("copy plane start ");
-
- if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr)pSrc)) {
- RootlessStartDrawing((WindowPtr) pSrc);
- }
- RootlessStartDrawing((WindowPtr) dst);
- result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h,
- dstx, dsty, plane);
-
- box.x1 = dstx + dst->x;
- box.x2 = box.x1 + w;
- box.y1 = dsty + dst->y;
- box.y2 = box.y1 + h;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("copy plane end\n");
- return result;
-}
-
-// Options for size of changed area:
-// 0 = box per point
-// 1 = big box around all points
-// 2 = accumulate point in 20 pixel radius
-#define ROOTLESS_CHANGED_AREA 1
-#define abs(a) ((a) > 0 ? (a) : -(a))
-
-/* changed area is box around all points */
-static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("polypoint start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit);
-
- if (npt > 0) {
-#if ROOTLESS_CHANGED_AREA==0
- // box per point
- BoxRec box;
-
- while (npt) {
- box.x1 = pptInit->x;
- box.y1 = pptInit->y;
- box.x2 = box.x1 + 1;
- box.y2 = box.y1 + 1;
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- npt--;
- pptInit++;
- }
-
-#elif ROOTLESS_CHANGED_AREA==1
- // one big box
- BoxRec box;
-
- box.x2 = box.x1 = pptInit->x;
- box.y2 = box.y1 = pptInit->y;
- while (--npt) {
- pptInit++;
- if (box.x1 > pptInit->x)
- box.x1 = pptInit->x;
- else if (box.x2 < pptInit->x)
- box.x2 = pptInit->x;
- if (box.y1 > pptInit->y)
- box.y1 = pptInit->y;
- else if (box.y2 < pptInit->y)
- box.y2 = pptInit->y;
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
-#elif ROOTLESS_CHANGED_AREA==2
- // clever(?) method: accumulate point in 20-pixel radius
- BoxRec box;
- int firstx, firsty;
-
- box.x2 = box.x1 = firstx = pptInit->x;
- box.y2 = box.y1 = firsty = pptInit->y;
- while (--npt) {
- pptInit++;
- if (abs(pptInit->x - firstx) > 20 ||
- abs(pptInit->y - firsty) > 20) {
- box.x2++;
- box.y2++;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- box.x2 = box.x1 = firstx = pptInit->x;
- box.y2 = box.y1 = firsty = pptInit->y;
- } else {
- if (box.x1 > pptInit->x) box.x1 = pptInit->x;
- else if (box.x2 < pptInit->x) box.x2 = pptInit->x;
- if (box.y1 > pptInit->y) box.y1 = pptInit->y;
- else if (box.y2 < pptInit->y) box.y2 = pptInit->y;
- }
- }
- box.x2++;
- box.y2++;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox((WindowPtr) dst, &box);
-#endif /* ROOTLESS_CHANGED_AREA */
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polypoint end\n");
-}
-
-#undef ROOTLESS_CHANGED_AREA
-
-/* changed area is box around each line */
-static void RootlessPolylines(DrawablePtr dst, GCPtr pGC,
- int mode, int npt, DDXPointPtr pptInit)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly lines start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->Polylines(dst, pGC, mode, npt, pptInit);
-
- if (npt > 0) {
- BoxRec box;
- int extra = pGC->lineWidth >> 1;
-
- box.x2 = box.x1 = pptInit->x;
- box.y2 = box.y1 = pptInit->y;
-
- if (npt > 1) {
- if (pGC->joinStyle == JoinMiter)
- extra = 6 * pGC->lineWidth;
- else if (pGC->capStyle == CapProjecting)
- extra = pGC->lineWidth;
- }
-
- if (mode == CoordModePrevious) {
- int x = box.x1;
- int y = box.y1;
-
- while (--npt) {
- pptInit++;
- x += pptInit->x;
- y += pptInit->y;
- if (box.x1 > x)
- box.x1 = x;
- else if (box.x2 < x)
- box.x2 = x;
- if (box.y1 > y)
- box.y1 = y;
- else if (box.y2 < y)
- box.y2 = y;
- }
- } else {
- while (--npt) {
- pptInit++;
- if (box.x1 > pptInit->x)
- box.x1 = pptInit->x;
- else if (box.x2 < pptInit->x)
- box.x2 = pptInit->x;
- if (box.y1 > pptInit->y)
- box.y1 = pptInit->y;
- else if (box.y2 < pptInit->y)
- box.y2 = pptInit->y;
- }
- }
-
- box.x2++;
- box.y2++;
-
- if (extra) {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly lines end\n");
-}
-
-/* changed area is box around each line segment */
-static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC,
- int nseg, xSegment *pSeg)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly segment start (win 0x%x)", dst);
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolySegment(dst, pGC, nseg, pSeg);
-
- if (nseg > 0) {
- BoxRec box;
- int extra = pGC->lineWidth;
-
- if (pGC->capStyle != CapProjecting)
- extra >>= 1;
-
- if (pSeg->x2 > pSeg->x1) {
- box.x1 = pSeg->x1;
- box.x2 = pSeg->x2;
- } else {
- box.x2 = pSeg->x1;
- box.x1 = pSeg->x2;
- }
-
- if (pSeg->y2 > pSeg->y1) {
- box.y1 = pSeg->y1;
- box.y2 = pSeg->y2;
- } else {
- box.y2 = pSeg->y1;
- box.y1 = pSeg->y2;
- }
-
- while (--nseg) {
- pSeg++;
- if (pSeg->x2 > pSeg->x1) {
- if (pSeg->x1 < box.x1) box.x1 = pSeg->x1;
- if (pSeg->x2 > box.x2) box.x2 = pSeg->x2;
- } else {
- if (pSeg->x2 < box.x1) box.x1 = pSeg->x2;
- if (pSeg->x1 > box.x2) box.x2 = pSeg->x1;
- }
- if (pSeg->y2 > pSeg->y1) {
- if (pSeg->y1 < box.y1) box.y1 = pSeg->y1;
- if (pSeg->y2 > box.y2) box.y2 = pSeg->y2;
- } else {
- if (pSeg->y2 < box.y1) box.y1 = pSeg->y2;
- if (pSeg->y1 > box.y2) box.y2 = pSeg->y1;
- }
- }
-
- box.x2++;
- box.y2++;
-
- if (extra) {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly segment end\n");
-}
-
-/* changed area is box around each line (not entire rects) */
-static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC,
- int nRects, xRectangle *pRects)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly rectangle start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyRectangle(dst, pGC, nRects, pRects);
-
- if (nRects > 0) {
- BoxRec box;
- int offset1, offset2, offset3;
-
- offset2 = pGC->lineWidth;
- if (!offset2) offset2 = 1;
- offset1 = offset2 >> 1;
- offset3 = offset2 - offset1;
-
- while (nRects--) {
- box.x1 = pRects->x - offset1;
- box.y1 = pRects->y - offset1;
- box.x2 = box.x1 + pRects->width + offset2;
- box.y2 = box.y1 + offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- box.x1 = pRects->x - offset1;
- box.y1 = pRects->y + offset3;
- box.x2 = box.x1 + offset2;
- box.y2 = box.y1 + pRects->height - offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- box.x1 = pRects->x + pRects->width - offset1;
- box.y1 = pRects->y + offset3;
- box.x2 = box.x1 + offset2;
- box.y2 = box.y1 + pRects->height - offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- box.x1 = pRects->x - offset1;
- box.y1 = pRects->y + pRects->height - offset1;
- box.x2 = box.x1 + pRects->width + offset2;
- box.y2 = box.y1 + offset2;
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- pRects++;
- }
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly rectangle end\n");
-}
-
-
-/* changed area is box around each arc (assumes all arcs are 360 degrees) */
-static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc *parcs)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("poly arc start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyArc(dst, pGC, narcs, parcs);
-
- if (narcs > 0) {
- int extra = pGC->lineWidth >> 1;
- BoxRec box;
-
- box.x1 = parcs->x;
- box.x2 = box.x1 + parcs->width;
- box.y1 = parcs->y;
- box.y2 = box.y1 + parcs->height;
-
- /* should I break these up instead ? */
-
- while (--narcs) {
- parcs++;
- if (box.x1 > parcs->x)
- box.x1 = parcs->x;
- if (box.x2 < (parcs->x + parcs->width))
- box.x2 = parcs->x + parcs->width;
- if (box.y1 > parcs->y)
- box.y1 = parcs->y;
- if (box.y2 < (parcs->y + parcs->height))
- box.y2 = parcs->y + parcs->height;
- }
-
- if (extra) {
- box.x1 -= extra;
- box.x2 += extra;
- box.y1 -= extra;
- box.y2 += extra;
- }
-
- box.x2++;
- box.y2++;
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("poly arc end\n");
-}
-
-
-/* changed area is box around each poly */
-static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC,
- int shape, int mode, int count,
- DDXPointPtr pptInit)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst,
- pGC->fillStyle);
-
- if (count <= 2) {
- pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
- } else {
- DDXPointPtr ppt = pptInit;
- int i = count;
- BoxRec box;
-
- box.x2 = box.x1 = ppt->x;
- box.y2 = box.y1 = ppt->y;
-
- if (mode != CoordModeOrigin) {
- int x = box.x1;
- int y = box.y1;
-
- while (--i) {
- ppt++;
- x += ppt->x;
- y += ppt->y;
- if (box.x1 > x)
- box.x1 = x;
- else if (box.x2 < x)
- box.x2 = x;
- if (box.y1 > y)
- box.y1 = y;
- else if (box.y2 < y)
- box.y2 = y;
- }
- } else {
- while (--i) {
- ppt++;
- if (box.x1 > ppt->x)
- box.x1 = ppt->x;
- else if (box.x2 < ppt->x)
- box.x2 = ppt->x;
- if (box.y1 > ppt->y)
- box.y1 = ppt->y;
- else if (box.y2 < ppt->y)
- box.y2 = ppt->y;
- }
- }
-
- box.x2++;
- box.y2++;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill poly end\n");
-}
-
-/* changed area is the rects */
-static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC,
- int nRectsInit, xRectangle *pRectsInit)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst,
- pGC->fillStyle);
-
- if (nRectsInit <= 0) {
- pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
- } else {
- BoxRec box;
- xRectangle *pRects = pRectsInit;
- int nRects = nRectsInit;
-
- box.x1 = pRects->x;
- box.x2 = box.x1 + pRects->width;
- box.y1 = pRects->y;
- box.y2 = box.y1 + pRects->height;
-
- while (--nRects) {
- pRects++;
- if (box.x1 > pRects->x)
- box.x1 = pRects->x;
- if (box.x2 < (pRects->x + pRects->width))
- box.x2 = pRects->x + pRects->width;
- if (box.y1 > pRects->y)
- box.y1 = pRects->y;
- if (box.y2 < (pRects->y + pRects->height))
- box.y2 = pRects->y + pRects->height;
- }
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill rect end\n");
-}
-
-
-/* changed area is box around each arc (assuming arcs are all 360 degrees) */
-static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC,
- int narcsInit, xArc *parcsInit)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("fill arc start ");
-
- if (narcsInit > 0) {
- BoxRec box;
- int narcs = narcsInit;
- xArc *parcs = parcsInit;
-
- box.x1 = parcs->x;
- box.x2 = box.x1 + parcs->width;
- box.y1 = parcs->y;
- box.y2 = box.y1 + parcs->height;
-
- /* should I break these up instead ? */
-
- while (--narcs) {
- parcs++;
- if (box.x1 > parcs->x)
- box.x1 = parcs->x;
- if (box.x2 < (parcs->x + parcs->width))
- box.x2 = parcs->x + parcs->width;
- if (box.y1 > parcs->y)
- box.y1 = parcs->y;
- if (box.y2 < (parcs->y + parcs->height))
- box.y2 = parcs->y + parcs->height;
- }
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
-
- TRIM_AND_TRANSLATE_BOX(box, dst, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("fill arc end\n");
-}
-
-
-static void RootlessImageText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("imagetext8 start ");
-
- if (count > 0) {
- int top, bot, Min, Max;
- BoxRec box;
-
- top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
- bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
- Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
- if (Min > 0) Min = 0;
- Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
- if (Max < 0) Max = 0;
-
- /* ugh */
- box.x1 = dst->x + x + Min +
- FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + Max +
- FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- box.y1 = dst->y + y - top;
- box.y2 = dst->y + y + bot;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->ImageText8(dst, pGC, x, y, count, chars);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("imagetext8 end\n");
-}
-
-static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, char *chars)
-{
- int width; // the result, sorta
-
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("polytext8 start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars);
- width -= x;
-
- if (width > 0) {
- BoxRec box;
-
- /* ugh */
- box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- if (count > 1) {
- if (width > 0) box.x2 += width;
- else box.x1 += width;
- }
-
- box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
- box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polytext8 end\n");
- return width + x;
-}
-
-static void RootlessImageText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("imagetext16 start ");
-
- if (count > 0) {
- int top, bot, Min, Max;
- BoxRec box;
-
- top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
- bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
- Min = count * FONTMINBOUNDS(pGC->font, characterWidth);
- if (Min > 0) Min = 0;
- Max = count * FONTMAXBOUNDS(pGC->font, characterWidth);
- if (Max < 0) Max = 0;
-
- /* ugh */
- box.x1 = dst->x + x + Min +
- FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + Max +
- FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- box.y1 = dst->y + y - top;
- box.y2 = dst->y + y + bot;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->ImageText16(dst, pGC, x, y, count, chars);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("imagetext16 end\n");
-}
-
-static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC,
- int x, int y, int count, unsigned short *chars)
-{
- int width; // the result, sorta
-
- GCOP_UNWRAP(pGC);
-
- RL_DEBUG_MSG("polytext16 start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars);
- width -= x;
-
- if (width > 0) {
- BoxRec box;
-
- /* ugh */
- box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing);
- box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing);
-
- if (count > 1) {
- if (width > 0) box.x2 += width;
- else box.x1 += width;
- }
-
- box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
- box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polytext16 end\n");
- return width + x;
-}
-
-static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyphInit,
- CharInfoPtr *ppciInit, pointer unused)
-{
- GC_SAVE(pGC);
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("imageglyph start ");
-
- if (nglyphInit > 0) {
- int top, bot, width = 0;
- BoxRec box;
- unsigned int nglyph = nglyphInit;
- CharInfoPtr *ppci = ppciInit;
-
- top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font));
- bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font));
-
- box.x1 = ppci[0]->metrics.leftSideBearing;
- if (box.x1 > 0) box.x1 = 0;
- box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing -
- ppci[nglyph - 1]->metrics.characterWidth;
- if (box.x2 < 0) box.x2 = 0;
-
- box.x2 += dst->x + x;
- box.x1 += dst->x + x;
-
- while (nglyph--) {
- width += (*ppci)->metrics.characterWidth;
- ppci++;
- }
-
- if (width > 0)
- box.x2 += width;
- else
- box.x1 += width;
-
- box.y1 = dst->y + y - top;
- box.y2 = dst->y + y + bot;
-
- RootlessStartDrawing((WindowPtr) dst);
-
- if (canAccelFill(dst, pGC))
- {
- GC_UNSET_PM(pGC, dst);
- }
-
- pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- } else {
- pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused);
- }
-
- GC_RESTORE(pGC, dst);
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("imageglyph end\n");
-}
-
-static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC,
- int x, int y, unsigned int nglyph,
- CharInfoPtr *ppci, pointer pglyphBase)
-{
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("polyglyph start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase);
-
- if (nglyph > 0) {
- BoxRec box;
-
- /* ugh */
- box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing;
- box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing;
-
- if (nglyph > 1) {
- int width = 0;
-
- while (--nglyph) {
- width += (*ppci)->metrics.characterWidth;
- ppci++;
- }
-
- if (width > 0) box.x2 += width;
- else box.x1 += width;
- }
-
- box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent);
- box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent);
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
- }
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("polyglyph end\n");
-}
-
-
-/* changed area is in dest */
-static void
-RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst,
- int dx, int dy, int xOrg, int yOrg)
-{
- BoxRec box;
-
- GCOP_UNWRAP(pGC);
- RL_DEBUG_MSG("push pixels start ");
-
- RootlessStartDrawing((WindowPtr) dst);
- pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg);
-
- box.x1 = xOrg + dst->x;
- box.x2 = box.x1 + dx;
- box.y1 = yOrg + dst->y;
- box.y2 = box.y1 + dy;
-
- TRIM_BOX(box, pGC);
- if (BOX_NOT_EMPTY(box))
- RootlessDamageBox ((WindowPtr) dst, &box);
-
- GCOP_WRAP(pGC);
- RL_DEBUG_MSG("push pixels end\n");
-}
+/* + * Graphics Context support for generic rootless X server + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * Copyright (c) 2002-2003 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stddef.h> /* For NULL */ +#include "mi.h" +#include "scrnintstr.h" +#include "gcstruct.h" +#include "pixmapstr.h" +#include "windowstr.h" +#include "dixfontstr.h" +#include "mivalidate.h" +#include "fb.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "rootlessCommon.h" + +#ifdef _MSC_VER +#define inline __inline +#endif +// GC functions +static void RootlessValidateGC(GCPtr pGC, unsigned long changes, + DrawablePtr pDrawable); +static void RootlessChangeGC(GCPtr pGC, unsigned long mask); +static void RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst); +static void RootlessDestroyGC(GCPtr pGC); +static void RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects); +static void RootlessDestroyClip(GCPtr pGC); +static void RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc); + +Bool RootlessCreateGC(GCPtr pGC); + +GCFuncs rootlessGCFuncs = { + RootlessValidateGC, + RootlessChangeGC, + RootlessCopyGC, + RootlessDestroyGC, + RootlessChangeClip, + RootlessDestroyClip, + RootlessCopyClip, +}; + +// GC operations +static void RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, int sorted); +static void RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, + DDXPointPtr pptInit, int *pwidthInit, + int nspans, int sorted); +static void RootlessPutImage(DrawablePtr dst, GCPtr pGC, + int depth, int x, int y, int w, int h, + int leftPad, int format, char *pBits); +static RegionPtr RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, + int srcx, int srcy, int w, int h, + int dstx, int dsty); +static RegionPtr RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, + GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty, + unsigned long plane); +static void RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit); +static void RootlessPolylines(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit); +static void RootlessPolySegment(DrawablePtr dst, GCPtr pGC, + int nseg, xSegment * pSeg); +static void RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, + int nRects, xRectangle *pRects); +static void RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, + xArc * parcs); +static void RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, int shape, int mode, + int count, DDXPointPtr pptInit); +static void RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, int nRectsInit, + xRectangle *pRectsInit); +static void RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit, + xArc * parcsInit); +static int RootlessPolyText8(DrawablePtr dst, GCPtr pGC, int x, int y, + int count, char *chars); +static int RootlessPolyText16(DrawablePtr dst, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void RootlessImageText8(DrawablePtr dst, GCPtr pGC, int x, int y, + int count, char *chars); +static void RootlessImageText16(DrawablePtr dst, GCPtr pGC, int x, int y, + int count, unsigned short *chars); +static void RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y, + unsigned int nglyphInit, + CharInfoPtr * ppciInit, pointer unused); +static void RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, int x, int y, + unsigned int nglyph, CharInfoPtr * ppci, + pointer pglyphBase); +static void RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, + int dx, int dy, int xOrg, int yOrg); + +static GCOps rootlessGCOps = { + RootlessFillSpans, + RootlessSetSpans, + RootlessPutImage, + RootlessCopyArea, + RootlessCopyPlane, + RootlessPolyPoint, + RootlessPolylines, + RootlessPolySegment, + RootlessPolyRectangle, + RootlessPolyArc, + RootlessFillPolygon, + RootlessPolyFillRect, + RootlessPolyFillArc, + RootlessPolyText8, + RootlessPolyText16, + RootlessImageText8, + RootlessImageText16, + RootlessImageGlyphBlt, + RootlessPolyGlyphBlt, + RootlessPushPixels +}; + +/* + If ROOTLESS_PROTECT_ALPHA is set, we have to make sure that the alpha + channel of the on screen windows is always opaque. fb makes this harder + than it would otherwise be by noticing that a planemask of 0x00ffffff + includes all bits when depth==24, and so it "optimizes" the planemask to + 0xffffffff. We work around this by temporarily setting depth=bpp while + changing the GC. + + So the normal situation (in 32 bit mode) is that the planemask is + 0x00ffffff and thus fb leaves the alpha channel alone. The rootless + implementation is responsible for setting the alpha channel opaque + initially. + + Unfortunately drawing with a planemask that doesn't have all bits set + normally causes fb to fall off its fastest paths when blitting and + filling. So we try to recognize when we can relax the planemask back to + 0xffffffff, and do that for the duration of the drawing operation, + setting the alpha channel in fg/bg pixels to opaque at the same time. We + can do this when drawing op is GXcopy. We can also do this when copying + from another window since its alpha channel must also be opaque. + + The three macros below are used to implement this. Drawing ops that can + potentially have their planemask relaxed look like: + + OP { + GC_SAVE(gc); + GCOP_UNWRAP(gc); + + ... + + if (canAccelxxx(..) && otherwise-suitable) + GC_UNSET_PM(gc, dst); + + gc->funcs->OP(gc, ...); + + GC_RESTORE(gc, dst); + GCOP_WRAP(gc); + } + + */ + +#define GC_SAVE(pGC) \ + unsigned long _save_fg = (pGC)->fgPixel; \ + unsigned long _save_bg = (pGC)->bgPixel; \ + unsigned long _save_pm = (pGC)->planemask; \ + Bool _changed = FALSE + +#define GC_RESTORE(pGC, pDraw) \ + do { \ + if (_changed) { \ + unsigned int depth = (pDraw)->depth; \ + (pGC)->fgPixel = _save_fg; \ + (pGC)->bgPixel = _save_bg; \ + (pGC)->planemask = _save_pm; \ + (pDraw)->depth = (pDraw)->bitsPerPixel; \ + VALIDATE_GC(pGC, GCForeground | GCBackground | \ + GCPlaneMask, pDraw); \ + (pDraw)->depth = depth; \ + } \ + } while (0) + +#define GC_UNSET_PM(pGC, pDraw) \ + do { \ + unsigned int mask = RootlessAlphaMask ((pDraw)->bitsPerPixel); \ + if (((pGC)->planemask & mask) != mask) { \ + unsigned int depth = (pDraw)->depth; \ + (pGC)->fgPixel |= mask; \ + (pGC)->bgPixel |= mask; \ + (pGC)->planemask |= mask; \ + (pDraw)->depth = (pDraw)->bitsPerPixel; \ + VALIDATE_GC(pGC, GCForeground | \ + GCBackground | GCPlaneMask, pDraw); \ + (pDraw)->depth = depth; \ + _changed = TRUE; \ + } \ + } while (0) + +#define VALIDATE_GC(pGC, changes, pDrawable) \ + do { \ + pGC->funcs->ValidateGC(pGC, changes, pDrawable); \ + if (((WindowPtr) pDrawable)->viewable) { \ + gcrec->originalOps = pGC->ops; \ + } \ + } while(0) + +static RootlessWindowRec * +canAccelBlit(DrawablePtr pDraw, GCPtr pGC) +{ + WindowPtr pTop; + RootlessWindowRec *winRec; + unsigned int pm; + + if (pGC->alu != GXcopy) + return NULL; + + if (pDraw->type != DRAWABLE_WINDOW) + return NULL; + + pm = ~RootlessAlphaMask(pDraw->bitsPerPixel); + if ((pGC->planemask & pm) != pm) + return NULL; + + pTop = TopLevelParent((WindowPtr) pDraw); + if (pTop == NULL) + return NULL; + + winRec = WINREC(pTop); + if (winRec == NULL) + return NULL; + + return winRec; +} + +static inline RootlessWindowRec * +canAccelFill(DrawablePtr pDraw, GCPtr pGC) +{ + if (pGC->fillStyle != FillSolid) + return NULL; + + return canAccelBlit(pDraw, pGC); +} + +/* + * Screen function to create a graphics context + */ +Bool +RootlessCreateGC(GCPtr pGC) +{ + RootlessGCRec *gcrec; + RootlessScreenRec *s; + Bool result; + + SCREEN_UNWRAP(pGC->pScreen, CreateGC); + s = SCREENREC(pGC->pScreen); + result = s->CreateGC(pGC); + + gcrec = (RootlessGCRec *) + dixLookupPrivate(&pGC->devPrivates, rootlessGCPrivateKey); + gcrec->originalOps = NULL; // don't wrap ops yet + gcrec->originalFuncs = pGC->funcs; + pGC->funcs = &rootlessGCFuncs; + + SCREEN_WRAP(pGC->pScreen, CreateGC); + return result; +} + +/* + * GC funcs + * + * These wrap lower level GC funcs. + * ValidateGC wraps the GC ops iff dest is viewable. + * All the others just unwrap and call. + */ + +// GCFUNC_UNRAP assumes funcs have been wrapped and +// does not assume ops have been wrapped +#define GCFUNC_UNWRAP(pGC) \ + RootlessGCRec *gcrec = (RootlessGCRec *) \ + dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \ + (pGC)->funcs = gcrec->originalFuncs; \ + if (gcrec->originalOps) { \ + (pGC)->ops = gcrec->originalOps; \ +} + +#define GCFUNC_WRAP(pGC) \ + gcrec->originalFuncs = (pGC)->funcs; \ + (pGC)->funcs = &rootlessGCFuncs; \ + if (gcrec->originalOps) { \ + gcrec->originalOps = (pGC)->ops; \ + (pGC)->ops = &rootlessGCOps; \ +} + +static void +RootlessValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable) +{ + GCFUNC_UNWRAP(pGC); + + gcrec->originalOps = NULL; + + if (pDrawable->type == DRAWABLE_WINDOW) { +#ifdef ROOTLESS_PROTECT_ALPHA + unsigned int depth = pDrawable->depth; + + // We force a planemask so fb doesn't overwrite the alpha channel. + // Left to its own devices, fb will optimize away the planemask. + pDrawable->depth = pDrawable->bitsPerPixel; + pGC->planemask &= ~RootlessAlphaMask(pDrawable->bitsPerPixel); + VALIDATE_GC(pGC, changes | GCPlaneMask, pDrawable); + pDrawable->depth = depth; +#else + VALIDATE_GC(pGC, changes, pDrawable); +#endif + } + else { + pGC->funcs->ValidateGC(pGC, changes, pDrawable); + } + + GCFUNC_WRAP(pGC); +} + +static void +RootlessChangeGC(GCPtr pGC, unsigned long mask) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->ChangeGC(pGC, mask); + GCFUNC_WRAP(pGC); +} + +static void +RootlessCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst) +{ + GCFUNC_UNWRAP(pGCDst); + pGCDst->funcs->CopyGC(pGCSrc, mask, pGCDst); + GCFUNC_WRAP(pGCDst); +} + +static void +RootlessDestroyGC(GCPtr pGC) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->DestroyGC(pGC); + GCFUNC_WRAP(pGC); +} + +static void +RootlessChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->ChangeClip(pGC, type, pvalue, nrects); + GCFUNC_WRAP(pGC); +} + +static void +RootlessDestroyClip(GCPtr pGC) +{ + GCFUNC_UNWRAP(pGC); + pGC->funcs->DestroyClip(pGC); + GCFUNC_WRAP(pGC); +} + +static void +RootlessCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + GCFUNC_UNWRAP(pgcDst); + pgcDst->funcs->CopyClip(pgcDst, pgcSrc); + GCFUNC_WRAP(pgcDst); +} + +/* + * GC ops + * + * We can't use shadowfb because shadowfb assumes one pixmap + * and our root window is a special case. + * However, much of this code is copied from shadowfb. + */ + +// assumes both funcs and ops are wrapped +#define GCOP_UNWRAP(pGC) \ + RootlessGCRec *gcrec = (RootlessGCRec *) \ + dixLookupPrivate(&(pGC)->devPrivates, rootlessGCPrivateKey); \ + GCFuncs *saveFuncs = pGC->funcs; \ + (pGC)->funcs = gcrec->originalFuncs; \ + (pGC)->ops = gcrec->originalOps; + +#define GCOP_WRAP(pGC) \ + gcrec->originalOps = (pGC)->ops; \ + (pGC)->funcs = saveFuncs; \ + (pGC)->ops = &rootlessGCOps; + +static void +RootlessFillSpans(DrawablePtr dst, GCPtr pGC, int nInit, + DDXPointPtr pptInit, int *pwidthInit, int sorted) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("fill spans start "); + + if (nInit <= 0) { + pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); + } + else { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nInit; + BoxRec box; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while (--i) { + ppt++; + pwidth++; + if (box.x1 > ppt->x) + box.x1 = ppt->x; + if (box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if (box.y1 > ppt->y) + box.y1 = ppt->y; + else if (box.y2 < ppt->y) + box.y2 = ppt->y; + } + + box.y2++; + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->FillSpans(dst, pGC, nInit, pptInit, pwidthInit, sorted); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill spans end\n"); +} + +static void +RootlessSetSpans(DrawablePtr dst, GCPtr pGC, char *pSrc, + DDXPointPtr pptInit, int *pwidthInit, int nspans, int sorted) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("set spans start "); + + if (nspans <= 0) { + pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); + } + else { + DDXPointPtr ppt = pptInit; + int *pwidth = pwidthInit; + int i = nspans; + BoxRec box; + + box.x1 = ppt->x; + box.x2 = box.x1 + *pwidth; + box.y2 = box.y1 = ppt->y; + + while (--i) { + ppt++; + pwidth++; + if (box.x1 > ppt->x) + box.x1 = ppt->x; + if (box.x2 < (ppt->x + *pwidth)) + box.x2 = ppt->x + *pwidth; + if (box.y1 > ppt->y) + box.y1 = ppt->y; + else if (box.y2 < ppt->y) + box.y2 = ppt->y; + } + + box.y2++; + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->SetSpans(dst, pGC, pSrc, pptInit, pwidthInit, nspans, sorted); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + GCOP_WRAP(pGC); + RL_DEBUG_MSG("set spans end\n"); +} + +static void +RootlessPutImage(DrawablePtr dst, GCPtr pGC, + int depth, int x, int y, int w, int h, + int leftPad, int format, char *pBits) +{ + BoxRec box; + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("put image start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBits); + + box.x1 = x + dst->x; + box.x2 = box.x1 + w; + box.y1 = y + dst->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("put image end\n"); +} + +/* changed area is *dest* rect */ +static RegionPtr +RootlessCopyArea(DrawablePtr pSrc, DrawablePtr dst, GCPtr pGC, + int srcx, int srcy, int w, int h, int dstx, int dsty) +{ + RegionPtr result; + BoxRec box; + + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("copy area start (src 0x%x, dst 0x%x)", pSrc, dst); + + if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) { + /* If both source and dest are windows, and we're doing + a simple copy operation, we can remove the alpha-protecting + planemask (since source has opaque alpha as well) */ + + if (canAccelBlit(pSrc, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + RootlessStartDrawing((WindowPtr) pSrc); + } + RootlessStartDrawing((WindowPtr) dst); + result = pGC->ops->CopyArea(pSrc, dst, pGC, srcx, srcy, w, h, dstx, dsty); + + box.x1 = dstx + dst->x; + box.x2 = box.x1 + w; + box.y1 = dsty + dst->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("copy area end\n"); + return result; +} + +/* changed area is *dest* rect */ +static RegionPtr +RootlessCopyPlane(DrawablePtr pSrc, DrawablePtr dst, + GCPtr pGC, int srcx, int srcy, + int w, int h, int dstx, int dsty, unsigned long plane) +{ + RegionPtr result; + BoxRec box; + + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("copy plane start "); + + if (pSrc->type == DRAWABLE_WINDOW && IsFramedWindow((WindowPtr) pSrc)) { + RootlessStartDrawing((WindowPtr) pSrc); + } + RootlessStartDrawing((WindowPtr) dst); + result = pGC->ops->CopyPlane(pSrc, dst, pGC, srcx, srcy, w, h, + dstx, dsty, plane); + + box.x1 = dstx + dst->x; + box.x2 = box.x1 + w; + box.y1 = dsty + dst->y; + box.y2 = box.y1 + h; + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("copy plane end\n"); + return result; +} + +// Options for size of changed area: +// 0 = box per point +// 1 = big box around all points +// 2 = accumulate point in 20 pixel radius +#define ROOTLESS_CHANGED_AREA 1 +#define abs(a) ((a) > 0 ? (a) : -(a)) + +/* changed area is box around all points */ +static void +RootlessPolyPoint(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("polypoint start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PolyPoint(dst, pGC, mode, npt, pptInit); + + if (npt > 0) { +#if ROOTLESS_CHANGED_AREA==0 + // box per point + BoxRec box; + + while (npt) { + box.x1 = pptInit->x; + box.y1 = pptInit->y; + box.x2 = box.x1 + 1; + box.y2 = box.y1 + 1; + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + npt--; + pptInit++; + } + +#elif ROOTLESS_CHANGED_AREA==1 + // one big box + BoxRec box; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + while (--npt) { + pptInit++; + if (box.x1 > pptInit->x) + box.x1 = pptInit->x; + else if (box.x2 < pptInit->x) + box.x2 = pptInit->x; + if (box.y1 > pptInit->y) + box.y1 = pptInit->y; + else if (box.y2 < pptInit->y) + box.y2 = pptInit->y; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + +#elif ROOTLESS_CHANGED_AREA==2 + // clever(?) method: accumulate point in 20-pixel radius + BoxRec box; + int firstx, firsty; + + box.x2 = box.x1 = firstx = pptInit->x; + box.y2 = box.y1 = firsty = pptInit->y; + while (--npt) { + pptInit++; + if (abs(pptInit->x - firstx) > 20 || abs(pptInit->y - firsty) > 20) { + box.x2++; + box.y2++; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + box.x2 = box.x1 = firstx = pptInit->x; + box.y2 = box.y1 = firsty = pptInit->y; + } + else { + if (box.x1 > pptInit->x) + box.x1 = pptInit->x; + else if (box.x2 < pptInit->x) + box.x2 = pptInit->x; + if (box.y1 > pptInit->y) + box.y1 = pptInit->y; + else if (box.y2 < pptInit->y) + box.y2 = pptInit->y; + } + } + box.x2++; + box.y2++; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); +#endif /* ROOTLESS_CHANGED_AREA */ + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polypoint end\n"); +} + +#undef ROOTLESS_CHANGED_AREA + +/* changed area is box around each line */ +static void +RootlessPolylines(DrawablePtr dst, GCPtr pGC, + int mode, int npt, DDXPointPtr pptInit) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("poly lines start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->Polylines(dst, pGC, mode, npt, pptInit); + + if (npt > 0) { + BoxRec box; + int extra = pGC->lineWidth >> 1; + + box.x2 = box.x1 = pptInit->x; + box.y2 = box.y1 = pptInit->y; + + if (npt > 1) { + if (pGC->joinStyle == JoinMiter) + extra = 6 * pGC->lineWidth; + else if (pGC->capStyle == CapProjecting) + extra = pGC->lineWidth; + } + + if (mode == CoordModePrevious) { + int x = box.x1; + int y = box.y1; + + while (--npt) { + pptInit++; + x += pptInit->x; + y += pptInit->y; + if (box.x1 > x) + box.x1 = x; + else if (box.x2 < x) + box.x2 = x; + if (box.y1 > y) + box.y1 = y; + else if (box.y2 < y) + box.y2 = y; + } + } + else { + while (--npt) { + pptInit++; + if (box.x1 > pptInit->x) + box.x1 = pptInit->x; + else if (box.x2 < pptInit->x) + box.x2 = pptInit->x; + if (box.y1 > pptInit->y) + box.y1 = pptInit->y; + else if (box.y2 < pptInit->y) + box.y2 = pptInit->y; + } + } + + box.x2++; + box.y2++; + + if (extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly lines end\n"); +} + +/* changed area is box around each line segment */ +static void +RootlessPolySegment(DrawablePtr dst, GCPtr pGC, int nseg, xSegment * pSeg) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("poly segment start (win 0x%x)", dst); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PolySegment(dst, pGC, nseg, pSeg); + + if (nseg > 0) { + BoxRec box; + int extra = pGC->lineWidth; + + if (pGC->capStyle != CapProjecting) + extra >>= 1; + + if (pSeg->x2 > pSeg->x1) { + box.x1 = pSeg->x1; + box.x2 = pSeg->x2; + } + else { + box.x2 = pSeg->x1; + box.x1 = pSeg->x2; + } + + if (pSeg->y2 > pSeg->y1) { + box.y1 = pSeg->y1; + box.y2 = pSeg->y2; + } + else { + box.y2 = pSeg->y1; + box.y1 = pSeg->y2; + } + + while (--nseg) { + pSeg++; + if (pSeg->x2 > pSeg->x1) { + if (pSeg->x1 < box.x1) + box.x1 = pSeg->x1; + if (pSeg->x2 > box.x2) + box.x2 = pSeg->x2; + } + else { + if (pSeg->x2 < box.x1) + box.x1 = pSeg->x2; + if (pSeg->x1 > box.x2) + box.x2 = pSeg->x1; + } + if (pSeg->y2 > pSeg->y1) { + if (pSeg->y1 < box.y1) + box.y1 = pSeg->y1; + if (pSeg->y2 > box.y2) + box.y2 = pSeg->y2; + } + else { + if (pSeg->y2 < box.y1) + box.y1 = pSeg->y2; + if (pSeg->y1 > box.y2) + box.y2 = pSeg->y1; + } + } + + box.x2++; + box.y2++; + + if (extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly segment end\n"); +} + +/* changed area is box around each line (not entire rects) */ +static void +RootlessPolyRectangle(DrawablePtr dst, GCPtr pGC, + int nRects, xRectangle *pRects) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("poly rectangle start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PolyRectangle(dst, pGC, nRects, pRects); + + if (nRects > 0) { + BoxRec box; + int offset1, offset2, offset3; + + offset2 = pGC->lineWidth; + if (!offset2) + offset2 = 1; + offset1 = offset2 >> 1; + offset3 = offset2 - offset1; + + while (nRects--) { + box.x1 = pRects->x - offset1; + box.y1 = pRects->y - offset1; + box.x2 = box.x1 + pRects->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + box.x1 = pRects->x - offset1; + box.y1 = pRects->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + box.x1 = pRects->x + pRects->width - offset1; + box.y1 = pRects->y + offset3; + box.x2 = box.x1 + offset2; + box.y2 = box.y1 + pRects->height - offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + box.x1 = pRects->x - offset1; + box.y1 = pRects->y + pRects->height - offset1; + box.x2 = box.x1 + pRects->width + offset2; + box.y2 = box.y1 + offset2; + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + pRects++; + } + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly rectangle end\n"); +} + +/* changed area is box around each arc (assumes all arcs are 360 degrees) */ +static void +RootlessPolyArc(DrawablePtr dst, GCPtr pGC, int narcs, xArc * parcs) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("poly arc start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PolyArc(dst, pGC, narcs, parcs); + + if (narcs > 0) { + int extra = pGC->lineWidth >> 1; + BoxRec box; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while (--narcs) { + parcs++; + if (box.x1 > parcs->x) + box.x1 = parcs->x; + if (box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if (box.y1 > parcs->y) + box.y1 = parcs->y; + if (box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + if (extra) { + box.x1 -= extra; + box.x2 += extra; + box.y1 -= extra; + box.y2 += extra; + } + + box.x2++; + box.y2++; + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("poly arc end\n"); +} + +/* changed area is box around each poly */ +static void +RootlessFillPolygon(DrawablePtr dst, GCPtr pGC, + int shape, int mode, int count, DDXPointPtr pptInit) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("fill poly start (win 0x%x, fillStyle 0x%x)", dst, + pGC->fillStyle); + + if (count <= 2) { + pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); + } + else { + DDXPointPtr ppt = pptInit; + int i = count; + BoxRec box; + + box.x2 = box.x1 = ppt->x; + box.y2 = box.y1 = ppt->y; + + if (mode != CoordModeOrigin) { + int x = box.x1; + int y = box.y1; + + while (--i) { + ppt++; + x += ppt->x; + y += ppt->y; + if (box.x1 > x) + box.x1 = x; + else if (box.x2 < x) + box.x2 = x; + if (box.y1 > y) + box.y1 = y; + else if (box.y2 < y) + box.y2 = y; + } + } + else { + while (--i) { + ppt++; + if (box.x1 > ppt->x) + box.x1 = ppt->x; + else if (box.x2 < ppt->x) + box.x2 = ppt->x; + if (box.y1 > ppt->y) + box.y1 = ppt->y; + else if (box.y2 < ppt->y) + box.y2 = ppt->y; + } + } + + box.x2++; + box.y2++; + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pptInit); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill poly end\n"); +} + +/* changed area is the rects */ +static void +RootlessPolyFillRect(DrawablePtr dst, GCPtr pGC, + int nRectsInit, xRectangle *pRectsInit) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("fill rect start (win 0x%x, fillStyle 0x%x)", dst, + pGC->fillStyle); + + if (nRectsInit <= 0) { + pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); + } + else { + BoxRec box; + xRectangle *pRects = pRectsInit; + int nRects = nRectsInit; + + box.x1 = pRects->x; + box.x2 = box.x1 + pRects->width; + box.y1 = pRects->y; + box.y2 = box.y1 + pRects->height; + + while (--nRects) { + pRects++; + if (box.x1 > pRects->x) + box.x1 = pRects->x; + if (box.x2 < (pRects->x + pRects->width)) + box.x2 = pRects->x + pRects->width; + if (box.y1 > pRects->y) + box.y1 = pRects->y; + if (box.y2 < (pRects->y + pRects->height)) + box.y2 = pRects->y + pRects->height; + } + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->PolyFillRect(dst, pGC, nRectsInit, pRectsInit); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill rect end\n"); +} + +/* changed area is box around each arc (assuming arcs are all 360 degrees) */ +static void +RootlessPolyFillArc(DrawablePtr dst, GCPtr pGC, int narcsInit, xArc * parcsInit) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("fill arc start "); + + if (narcsInit > 0) { + BoxRec box; + int narcs = narcsInit; + xArc *parcs = parcsInit; + + box.x1 = parcs->x; + box.x2 = box.x1 + parcs->width; + box.y1 = parcs->y; + box.y2 = box.y1 + parcs->height; + + /* should I break these up instead ? */ + + while (--narcs) { + parcs++; + if (box.x1 > parcs->x) + box.x1 = parcs->x; + if (box.x2 < (parcs->x + parcs->width)) + box.x2 = parcs->x + parcs->width; + if (box.y1 > parcs->y) + box.y1 = parcs->y; + if (box.y2 < (parcs->y + parcs->height)) + box.y2 = parcs->y + parcs->height; + } + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); + + TRIM_AND_TRANSLATE_BOX(box, dst, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + else { + pGC->ops->PolyFillArc(dst, pGC, narcsInit, parcsInit); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("fill arc end\n"); +} + +static void +RootlessImageText8(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, char *chars) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("imagetext8 start "); + + if (count > 0) { + int top, bot, Min, Max; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if (Min > 0) + Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if (Max < 0) + Max = 0; + + /* ugh */ + box.x1 = dst->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + Max + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = dst->y + y - top; + box.y2 = dst->y + y + bot; + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->ImageText8(dst, pGC, x, y, count, chars); + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + else { + pGC->ops->ImageText8(dst, pGC, x, y, count, chars); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("imagetext8 end\n"); +} + +static int +RootlessPolyText8(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, char *chars) +{ + int width; // the result, sorta + + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("polytext8 start "); + + RootlessStartDrawing((WindowPtr) dst); + width = pGC->ops->PolyText8(dst, pGC, x, y, count, chars); + width -= x; + + if (width > 0) { + BoxRec box; + + /* ugh */ + box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + if (count > 1) { + if (width > 0) + box.x2 += width; + else + box.x1 += width; + } + + box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polytext8 end\n"); + return width + x; +} + +static void +RootlessImageText16(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("imagetext16 start "); + + if (count > 0) { + int top, bot, Min, Max; + BoxRec box; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + Min = count * FONTMINBOUNDS(pGC->font, characterWidth); + if (Min > 0) + Min = 0; + Max = count * FONTMAXBOUNDS(pGC->font, characterWidth); + if (Max < 0) + Max = 0; + + /* ugh */ + box.x1 = dst->x + x + Min + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + Max + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + box.y1 = dst->y + y - top; + box.y2 = dst->y + y + bot; + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->ImageText16(dst, pGC, x, y, count, chars); + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + else { + pGC->ops->ImageText16(dst, pGC, x, y, count, chars); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("imagetext16 end\n"); +} + +static int +RootlessPolyText16(DrawablePtr dst, GCPtr pGC, + int x, int y, int count, unsigned short *chars) +{ + int width; // the result, sorta + + GCOP_UNWRAP(pGC); + + RL_DEBUG_MSG("polytext16 start "); + + RootlessStartDrawing((WindowPtr) dst); + width = pGC->ops->PolyText16(dst, pGC, x, y, count, chars); + width -= x; + + if (width > 0) { + BoxRec box; + + /* ugh */ + box.x1 = dst->x + x + FONTMINBOUNDS(pGC->font, leftSideBearing); + box.x2 = dst->x + x + FONTMAXBOUNDS(pGC->font, rightSideBearing); + + if (count > 1) { + if (width > 0) + box.x2 += width; + else + box.x1 += width; + } + + box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polytext16 end\n"); + return width + x; +} + +static void +RootlessImageGlyphBlt(DrawablePtr dst, GCPtr pGC, + int x, int y, unsigned int nglyphInit, + CharInfoPtr * ppciInit, pointer unused) +{ + GC_SAVE(pGC); + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("imageglyph start "); + + if (nglyphInit > 0) { + int top, bot, width = 0; + BoxRec box; + unsigned int nglyph = nglyphInit; + CharInfoPtr *ppci = ppciInit; + + top = max(FONTMAXBOUNDS(pGC->font, ascent), FONTASCENT(pGC->font)); + bot = max(FONTMAXBOUNDS(pGC->font, descent), FONTDESCENT(pGC->font)); + + box.x1 = ppci[0]->metrics.leftSideBearing; + if (box.x1 > 0) + box.x1 = 0; + box.x2 = ppci[nglyph - 1]->metrics.rightSideBearing - + ppci[nglyph - 1]->metrics.characterWidth; + if (box.x2 < 0) + box.x2 = 0; + + box.x2 += dst->x + x; + box.x1 += dst->x + x; + + while (nglyph--) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if (width > 0) + box.x2 += width; + else + box.x1 += width; + + box.y1 = dst->y + y - top; + box.y2 = dst->y + y + bot; + + RootlessStartDrawing((WindowPtr) dst); + + if (canAccelFill(dst, pGC)) { + GC_UNSET_PM(pGC, dst); + } + + pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + else { + pGC->ops->ImageGlyphBlt(dst, pGC, x, y, nglyphInit, ppciInit, unused); + } + + GC_RESTORE(pGC, dst); + GCOP_WRAP(pGC); + RL_DEBUG_MSG("imageglyph end\n"); +} + +static void +RootlessPolyGlyphBlt(DrawablePtr dst, GCPtr pGC, + int x, int y, unsigned int nglyph, + CharInfoPtr * ppci, pointer pglyphBase) +{ + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("polyglyph start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PolyGlyphBlt(dst, pGC, x, y, nglyph, ppci, pglyphBase); + + if (nglyph > 0) { + BoxRec box; + + /* ugh */ + box.x1 = dst->x + x + ppci[0]->metrics.leftSideBearing; + box.x2 = dst->x + x + ppci[nglyph - 1]->metrics.rightSideBearing; + + if (nglyph > 1) { + int width = 0; + + while (--nglyph) { + width += (*ppci)->metrics.characterWidth; + ppci++; + } + + if (width > 0) + box.x2 += width; + else + box.x1 += width; + } + + box.y1 = dst->y + y - FONTMAXBOUNDS(pGC->font, ascent); + box.y2 = dst->y + y + FONTMAXBOUNDS(pGC->font, descent); + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + } + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("polyglyph end\n"); +} + +/* changed area is in dest */ +static void +RootlessPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr dst, + int dx, int dy, int xOrg, int yOrg) +{ + BoxRec box; + + GCOP_UNWRAP(pGC); + RL_DEBUG_MSG("push pixels start "); + + RootlessStartDrawing((WindowPtr) dst); + pGC->ops->PushPixels(pGC, pBitMap, dst, dx, dy, xOrg, yOrg); + + box.x1 = xOrg + dst->x; + box.x2 = box.x1 + dx; + box.y1 = yOrg + dst->y; + box.y2 = box.y1 + dy; + + TRIM_BOX(box, pGC); + if (BOX_NOT_EMPTY(box)) + RootlessDamageBox((WindowPtr) dst, &box); + + GCOP_WRAP(pGC); + RL_DEBUG_MSG("push pixels end\n"); +} diff --git a/xorg-server/miext/rootless/rootlessScreen.c b/xorg-server/miext/rootless/rootlessScreen.c index c8557066e..ecc72ea92 100644 --- a/xorg-server/miext/rootless/rootlessScreen.c +++ b/xorg-server/miext/rootless/rootlessScreen.c @@ -29,7 +29,6 @@ * use or other dealings in this Software without prior written authorization. */ - #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif @@ -83,10 +82,10 @@ RootlessUpdateScreenPixmap(ScreenPtr pScreen) PixmapPtr pPix; unsigned int rowbytes; - pPix = (*pScreen->GetScreenPixmap)(pScreen); + pPix = (*pScreen->GetScreenPixmap) (pScreen); if (pPix == NULL) { - pPix = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); - (*pScreen->SetScreenPixmap)(pPix); + pPix = (*pScreen->CreatePixmap) (pScreen, 0, 0, pScreen->rootDepth, 0); + (*pScreen->SetScreenPixmap) (pPix); } rowbytes = PixmapBytePad(pScreen->width, pScreen->rootDepth); @@ -111,7 +110,6 @@ RootlessUpdateScreenPixmap(ScreenPtr pScreen) } } - /* * RootlessCreateScreenResources * Rootless implementations typically set a null framebuffer pointer, which @@ -125,7 +123,7 @@ RootlessCreateScreenResources(ScreenPtr pScreen) SCREEN_UNWRAP(pScreen, CreateScreenResources); if (pScreen->CreateScreenResources != NULL) - ret = (*pScreen->CreateScreenResources)(pScreen); + ret = (*pScreen->CreateScreenResources) (pScreen); SCREEN_WRAP(pScreen, CreateScreenResources); @@ -139,7 +137,6 @@ RootlessCreateScreenResources(ScreenPtr pScreen) return ret; } - static Bool RootlessCloseScreen(int i, ScreenPtr pScreen) { @@ -160,12 +157,12 @@ RootlessCloseScreen(int i, ScreenPtr pScreen) return pScreen->CloseScreen(i, pScreen); } - static void RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, unsigned int format, unsigned long planeMask, char *pdstLine) { ScreenPtr pScreen = pDrawable->pScreen; + SCREEN_UNWRAP(pScreen, GetImage); if (pDrawable->type == DRAWABLE_WINDOW) { @@ -177,7 +174,7 @@ RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, RootlessRedisplayScreen(pScreen); // RedisplayScreen stops drawing, so we need to start it again - RootlessStartDrawing((WindowPtr)pDrawable); + RootlessStartDrawing((WindowPtr) pDrawable); /* Check that we have some place to read from. */ winRec = WINREC(TopLevelParent((WindowPtr) pDrawable)); @@ -194,10 +191,10 @@ RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, x1 = x0 + w; y1 = y0 + h; - x0 = max (x0, winRec->x); - y0 = max (y0, winRec->y); - x1 = min (x1, winRec->x + winRec->width); - y1 = min (y1, winRec->y + winRec->height); + x0 = max(x0, winRec->x); + y0 = max(y0, winRec->y); + x1 = min(x1, winRec->x + winRec->width); + y1 = min(y1, winRec->y + winRec->height); sx = x0 - pDrawable->x; sy = y0 - pDrawable->y; @@ -210,11 +207,10 @@ RootlessGetImage(DrawablePtr pDrawable, int sx, int sy, int w, int h, pScreen->GetImage(pDrawable, sx, sy, w, h, format, planeMask, pdstLine); -out: + out: SCREEN_WRAP(pScreen, GetImage); } - /* * RootlessSourceValidate * CopyArea and CopyPlane use a GC tied to the destination drawable. @@ -228,48 +224,50 @@ RootlessSourceValidate(DrawablePtr pDrawable, int x, int y, int w, int h, { SCREEN_UNWRAP(pDrawable->pScreen, SourceValidate); if (pDrawable->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr)pDrawable; + WindowPtr pWin = (WindowPtr) pDrawable; + RootlessStartDrawing(pWin); } if (pDrawable->pScreen->SourceValidate) { - pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, subWindowMode); + pDrawable->pScreen->SourceValidate(pDrawable, x, y, w, h, + subWindowMode); } SCREEN_WRAP(pDrawable->pScreen, SourceValidate); } static void RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, + INT16 xSrc, INT16 ySrc, INT16 xMask, INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); WindowPtr srcWin, dstWin, maskWin = NULL; - if (pMask) { // pMask can be NULL - maskWin = (pMask->pDrawable && pMask->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pMask->pDrawable : NULL; + if (pMask) { // pMask can be NULL + maskWin = (pMask->pDrawable && + pMask->pDrawable->type == + DRAWABLE_WINDOW) ? (WindowPtr) pMask->pDrawable : NULL; } - srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pSrc->pDrawable : NULL; - dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pDst->pDrawable : NULL; + srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pSrc->pDrawable : NULL; + dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? + (WindowPtr) pDst->pDrawable : NULL; // SCREEN_UNWRAP(ps, Composite); ps->Composite = SCREENREC(pScreen)->Composite; - if (srcWin && IsFramedWindow(srcWin)) + if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); if (maskWin && IsFramedWindow(maskWin)) RootlessStartDrawing(maskWin); - if (dstWin && IsFramedWindow(dstWin)) + if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); ps->Composite(op, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, - xDst, yDst, width, height); + xSrc, ySrc, xMask, yMask, xDst, yDst, width, height); - if (dstWin && IsFramedWindow(dstWin)) { + if (dstWin && IsFramedWindow(dstWin)) { RootlessDamageRect(dstWin, xDst, yDst, width, height); } @@ -277,11 +275,10 @@ RootlessComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, // SCREEN_WRAP(ps, Composite); } - static void RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc, - int nlist, GlyphListPtr list, GlyphPtr *glyphs) + int nlist, GlyphListPtr list, GlyphPtr * glyphs) { ScreenPtr pScreen = pDst->pDrawable->pScreen; PictureScreenPtr ps = GetPictureScreen(pScreen); @@ -291,12 +288,14 @@ RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, WindowPtr srcWin, dstWin; srcWin = (pSrc->pDrawable && pSrc->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pSrc->pDrawable : NULL; + (WindowPtr) pSrc->pDrawable : NULL; dstWin = (pDst->pDrawable->type == DRAWABLE_WINDOW) ? - (WindowPtr)pDst->pDrawable : NULL; + (WindowPtr) pDst->pDrawable : NULL; - if (srcWin && IsFramedWindow(srcWin)) RootlessStartDrawing(srcWin); - if (dstWin && IsFramedWindow(dstWin)) RootlessStartDrawing(dstWin); + if (srcWin && IsFramedWindow(srcWin)) + RootlessStartDrawing(srcWin); + if (dstWin && IsFramedWindow(dstWin)) + RootlessStartDrawing(dstWin); //SCREEN_UNWRAP(ps, Glyphs); ps->Glyphs = SCREENREC(pScreen)->Glyphs; @@ -340,10 +339,10 @@ RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, x2 = x1 + glyph->info.width; y2 = y1 + glyph->info.height; - box.x1 = max (box.x1, x1); - box.y1 = max (box.y1, y1); - box.x2 = max (box.x2, x2); - box.y2 = max (box.y2, y2); + box.x1 = max(box.x1, x1); + box.y1 = max(box.y1, y1); + box.x2 = max(box.x2, x2); + box.y2 = max(box.y2, y2); x += glyph->info.xOff; y += glyph->info.yOff; @@ -356,7 +355,6 @@ RootlessGlyphs(CARD8 op, PicturePtr pSrc, PicturePtr pDst, } } - /* * RootlessValidateTree * ValidateTree is modified in two ways: @@ -378,7 +376,8 @@ RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) if (IsRoot(pParent)) { RL_DEBUG_MSG("custom "); result = RootlessMiValidateTree(pParent, pChild, kind); - } else { + } + else { HUGE_ROOT(pParent); result = pScreen->ValidateTree(pParent, pChild, kind); NORMAL_ROOT(pParent); @@ -390,7 +389,6 @@ RootlessValidateTree(WindowPtr pParent, WindowPtr pChild, VTKind kind) return result; } - /* * RootlessMarkOverlappedWindows * MarkOverlappedWindows is modified to ignore overlapping @@ -403,6 +401,7 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, RegionRec saveRoot; Bool result; ScreenPtr pScreen = pWin->drawable.pScreen; + SCREEN_UNWRAP(pScreen, MarkOverlappedWindows); RL_DEBUG_MSG("MARKOVERLAPPEDWINDOWS start "); @@ -412,7 +411,7 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, RL_DEBUG_MSG("is root not marking "); result = FALSE; } - else if (! IsTopLevel(pWin)) { + else if (!IsTopLevel(pWin)) { // not top-level window - mark normally result = pScreen->MarkOverlappedWindows(pWin, pFirst, ppLayerWin); } @@ -426,7 +425,8 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, RL_DEBUG_MSG("is top level! "); /* single layered systems are easy */ - if (ppLayerWin) *ppLayerWin = pWin; + if (ppLayerWin) + *ppLayerWin = pWin; if (pWin == pFirst) { /* Blindly mark pWin and all of its inferiors. This is a slight @@ -437,10 +437,10 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, while (1) { if (pChild->viewable) { if (RegionBroken(&pChild->winSize)) - SetWinSize (pChild); + SetWinSize(pChild); if (RegionBroken(&pChild->borderSize)) - SetBorderSize (pChild); - (* MarkWindow)(pChild); + SetBorderSize(pChild); + (*MarkWindow) (pChild); if (pChild->firstChild) { pChild = pChild->firstChild; continue; @@ -455,7 +455,7 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, anyMarked = TRUE; } if (anyMarked) - (* MarkWindow)(pWin->parent); + (*MarkWindow) (pWin->parent); result = anyMarked; } NORMAL_ROOT(pWin); @@ -465,94 +465,94 @@ RootlessMarkOverlappedWindows(WindowPtr pWin, WindowPtr pFirst, return result; } -static void expose_1 (WindowPtr pWin) { +static void +expose_1(WindowPtr pWin) +{ WindowPtr pChild; - + if (!pWin->realized) return; - + miPaintWindow(pWin, &pWin->borderClip, PW_BACKGROUND); - + /* FIXME: comments in windowstr.h indicate that borderClip doesn't - include subwindow visibility. But I'm not so sure.. so we may - be exposing too much.. */ - - miSendExposures (pWin, &pWin->borderClip, - pWin->drawable.x, pWin->drawable.y); - + include subwindow visibility. But I'm not so sure.. so we may + be exposing too much.. */ + + miSendExposures(pWin, &pWin->borderClip, + pWin->drawable.x, pWin->drawable.y); + for (pChild = pWin->firstChild; pChild != NULL; pChild = pChild->nextSib) - expose_1 (pChild); + expose_1(pChild); } void -RootlessScreenExpose (ScreenPtr pScreen) +RootlessScreenExpose(ScreenPtr pScreen) { - expose_1 (pScreen->root); + expose_1(pScreen->root); } - ColormapPtr -RootlessGetColormap (ScreenPtr pScreen) +RootlessGetColormap(ScreenPtr pScreen) { - RootlessScreenRec *s = SCREENREC (pScreen); + RootlessScreenRec *s = SCREENREC(pScreen); - return s->colormap; + return s->colormap; } static void -RootlessInstallColormap (ColormapPtr pMap) +RootlessInstallColormap(ColormapPtr pMap) { - ScreenPtr pScreen = pMap->pScreen; - RootlessScreenRec *s = SCREENREC (pScreen); + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC(pScreen); - SCREEN_UNWRAP(pScreen, InstallColormap); + SCREEN_UNWRAP(pScreen, InstallColormap); - if (s->colormap != pMap) { - s->colormap = pMap; - s->colormap_changed = TRUE; - RootlessQueueRedisplay (pScreen); - } + if (s->colormap != pMap) { + s->colormap = pMap; + s->colormap_changed = TRUE; + RootlessQueueRedisplay(pScreen); + } - pScreen->InstallColormap (pMap); + pScreen->InstallColormap(pMap); - SCREEN_WRAP (pScreen, InstallColormap); + SCREEN_WRAP(pScreen, InstallColormap); } static void -RootlessUninstallColormap (ColormapPtr pMap) +RootlessUninstallColormap(ColormapPtr pMap) { - ScreenPtr pScreen = pMap->pScreen; - RootlessScreenRec *s = SCREENREC (pScreen); + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC(pScreen); - SCREEN_UNWRAP(pScreen, UninstallColormap); + SCREEN_UNWRAP(pScreen, UninstallColormap); - if (s->colormap == pMap) - s->colormap = NULL; + if (s->colormap == pMap) + s->colormap = NULL; - pScreen->UninstallColormap (pMap); + pScreen->UninstallColormap(pMap); - SCREEN_WRAP(pScreen, UninstallColormap); + SCREEN_WRAP(pScreen, UninstallColormap); } static void -RootlessStoreColors (ColormapPtr pMap, int ndef, xColorItem *pdef) +RootlessStoreColors(ColormapPtr pMap, int ndef, xColorItem * pdef) { - ScreenPtr pScreen = pMap->pScreen; - RootlessScreenRec *s = SCREENREC (pScreen); + ScreenPtr pScreen = pMap->pScreen; + RootlessScreenRec *s = SCREENREC(pScreen); - SCREEN_UNWRAP(pScreen, StoreColors); + SCREEN_UNWRAP(pScreen, StoreColors); - if (s->colormap == pMap && ndef > 0) { - s->colormap_changed = TRUE; - RootlessQueueRedisplay (pScreen); - } + if (s->colormap == pMap && ndef > 0) { + s->colormap_changed = TRUE; + RootlessQueueRedisplay(pScreen); + } - pScreen->StoreColors (pMap, ndef, pdef); + pScreen->StoreColors(pMap, ndef, pdef); - SCREEN_WRAP(pScreen, StoreColors); + SCREEN_WRAP(pScreen, StoreColors); } - static CARD32 RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) { @@ -576,7 +576,6 @@ RootlessRedisplayCallback(OsTimerPtr timer, CARD32 time, void *arg) return ROOTLESS_REDISPLAY_DELAY; } - /* * RootlessQueueRedisplay * Queue a redisplay after a timer delay to ensure we do not redisplay @@ -594,12 +593,10 @@ RootlessQueueRedisplay(ScreenPtr pScreen) screenRec->redisplay_timer = TimerSet(screenRec->redisplay_timer, 0, ROOTLESS_REDISPLAY_DELAY, - RootlessRedisplayCallback, - screenRec); + RootlessRedisplayCallback, screenRec); screenRec->redisplay_timer_set = TRUE; } - /* * RootlessBlockHandler * If the redisplay timer has expired, flush drawing before blocking @@ -618,30 +615,31 @@ RootlessBlockHandler(pointer pbdata, OSTimePtr pTimeout, pointer pReadmask) } } - static void RootlessWakeupHandler(pointer data, int i, pointer LastSelectMask) { // nothing here } - static Bool RootlessAllocatePrivates(ScreenPtr pScreen) { RootlessScreenRec *s; - if (!dixRegisterPrivateKey(&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) + if (!dixRegisterPrivateKey + (&rootlessGCPrivateKeyRec, PRIVATE_GC, sizeof(RootlessGCRec))) return FALSE; if (!dixRegisterPrivateKey(&rootlessScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) return FALSE; if (!dixRegisterPrivateKey(&rootlessWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) return FALSE; - if (!dixRegisterPrivateKey(&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) + if (!dixRegisterPrivateKey + (&rootlessWindowOldPixmapPrivateKeyRec, PRIVATE_WINDOW, 0)) return FALSE; s = malloc(sizeof(RootlessScreenRec)); - if (! s) return FALSE; + if (!s) + return FALSE; SETSCREENREC(pScreen, s); s->pixmap_data = NULL; @@ -653,7 +651,6 @@ RootlessAllocatePrivates(ScreenPtr pScreen) return TRUE; } - static void RootlessWrap(ScreenPtr pScreen) { @@ -696,6 +693,7 @@ RootlessWrap(ScreenPtr pScreen) { // Composite and Glyphs don't use normal screen wrapping PictureScreenPtr ps = GetPictureScreen(pScreen); + s->Composite = ps->Composite; ps->Composite = RootlessComposite; s->Glyphs = ps->Glyphs; @@ -707,13 +705,13 @@ RootlessWrap(ScreenPtr pScreen) #undef WRAP } - /* * RootlessInit * Called by the rootless implementation to initialize the rootless layer. * Rootless wraps lots of stuff and needs a bunch of devPrivates. */ -Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) +Bool +RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) { RootlessScreenRec *s; @@ -730,25 +728,24 @@ Bool RootlessInit(ScreenPtr pScreen, RootlessFrameProcsPtr procs) if (!RegisterBlockAndWakeupHandlers(RootlessBlockHandler, RootlessWakeupHandler, - (pointer) pScreen)) - { + (pointer) pScreen)) { return FALSE; } return TRUE; } -void RootlessUpdateRooted (Bool state) { +void +RootlessUpdateRooted(Bool state) +{ int i; - - if (!state) - { + + if (!state) { for (i = 0; i < screenInfo.numScreens; i++) - RootlessDisableRoot (screenInfo.screens[i]); + RootlessDisableRoot(screenInfo.screens[i]); } - else - { + else { for (i = 0; i < screenInfo.numScreens; i++) - RootlessEnableRoot (screenInfo.screens[i]); + RootlessEnableRoot(screenInfo.screens[i]); } } diff --git a/xorg-server/miext/rootless/rootlessValTree.c b/xorg-server/miext/rootless/rootlessValTree.c index 9aa881423..730d2917e 100644 --- a/xorg-server/miext/rootless/rootlessValTree.c +++ b/xorg-server/miext/rootless/rootlessValTree.c @@ -86,14 +86,14 @@ Equipment Corporation. * Summer '89: Joel McCormack -- so fast you wouldn't believe it possible. * In particular, much improved code for window mapping and * circulating. - * Bob Scheifler -- avoid miComputeClips for unmapped windows, - * valdata changes + * Bob Scheifler -- avoid miComputeClips for unmapped windows, + * valdata changes */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif -#include <stddef.h> /* For NULL */ +#include <stddef.h> /* For NULL */ #include <X11/X.h> #include "scrnintstr.h" #include "validate.h" @@ -104,65 +104,63 @@ Equipment Corporation. #include "globals.h" -int RootlessMiValidateTree (WindowPtr pRoot, WindowPtr pChild, VTKind kind); +int RootlessMiValidateTree(WindowPtr pRoot, WindowPtr pChild, VTKind kind); /* * Compute the visibility of a shaped window */ static int -RootlessShapedWindowIn (RegionPtr universe, - RegionPtr bounding, BoxPtr rect, int x, int y) +RootlessShapedWindowIn(RegionPtr universe, + RegionPtr bounding, BoxPtr rect, int x, int y) { - BoxRec box; - register BoxPtr boundBox; - int nbox; - Bool someIn, someOut; + BoxRec box; + register BoxPtr boundBox; + int nbox; + Bool someIn, someOut; register int t, x1, y1, x2, y2; - nbox = RegionNumRects (bounding); - boundBox = RegionRects (bounding); + nbox = RegionNumRects(bounding); + boundBox = RegionRects(bounding); someIn = someOut = FALSE; x1 = rect->x1; y1 = rect->y1; x2 = rect->x2; y2 = rect->y2; - while (nbox--) - { - if ((t = boundBox->x1 + x) < x1) - t = x1; - box.x1 = t; - if ((t = boundBox->y1 + y) < y1) - t = y1; - box.y1 = t; - if ((t = boundBox->x2 + x) > x2) - t = x2; - box.x2 = t; - if ((t = boundBox->y2 + y) > y2) - t = y2; - box.y2 = t; - if (box.x1 > box.x2) - box.x2 = box.x1; - if (box.y1 > box.y2) - box.y2 = box.y1; - switch (RegionContainsRect(universe, &box)) - { - case rgnIN: - if (someOut) - return rgnPART; - someIn = TRUE; - break; - case rgnOUT: - if (someIn) - return rgnPART; - someOut = TRUE; - break; - default: - return rgnPART; - } - boundBox++; + while (nbox--) { + if ((t = boundBox->x1 + x) < x1) + t = x1; + box.x1 = t; + if ((t = boundBox->y1 + y) < y1) + t = y1; + box.y1 = t; + if ((t = boundBox->x2 + x) > x2) + t = x2; + box.x2 = t; + if ((t = boundBox->y2 + y) > y2) + t = y2; + box.y2 = t; + if (box.x1 > box.x2) + box.x2 = box.x1; + if (box.y1 > box.y2) + box.y2 = box.y1; + switch (RegionContainsRect(universe, &box)) { + case rgnIN: + if (someOut) + return rgnPART; + someIn = TRUE; + break; + case rgnOUT: + if (someIn) + return rgnPART; + someOut = TRUE; + break; + default: + return rgnPART; + } + boundBox++; } if (someIn) - return rgnIN; + return rgnIN; return rgnOUT; } @@ -170,7 +168,6 @@ RootlessShapedWindowIn (RegionPtr universe, HasBorder(w) && \ (w)->backgroundState == ParentRelative) - /* *----------------------------------------------------------------------- * RootlessComputeClips -- @@ -188,18 +185,18 @@ RootlessShapedWindowIn (RegionPtr universe, *----------------------------------------------------------------------- */ static void -RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, - RegionPtr universe, VTKind kind, RegionPtr exposed) +RootlessComputeClips(WindowPtr pParent, ScreenPtr pScreen, + RegionPtr universe, VTKind kind, RegionPtr exposed) { - int dx, - dy; - RegionRec childUniverse; - register WindowPtr pChild; - int oldVis, newVis; - BoxRec borderSize; - RegionRec childUnion; - Bool overlap; - RegionPtr borderVisible; + int dx, dy; + RegionRec childUniverse; + register WindowPtr pChild; + int oldVis, newVis; + BoxRec borderSize; + RegionRec childUnion; + Bool overlap; + RegionPtr borderVisible; + /* * Figure out the new visibility of this window. * The extent of the universe should be the same as the extent of @@ -210,52 +207,52 @@ RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, */ borderSize.x1 = pParent->drawable.x - wBorderWidth(pParent); borderSize.y1 = pParent->drawable.y - wBorderWidth(pParent); - dx = (int) pParent->drawable.x + (int) pParent->drawable.width + wBorderWidth(pParent); + dx = (int) pParent->drawable.x + (int) pParent->drawable.width + + wBorderWidth(pParent); if (dx > 32767) - dx = 32767; + dx = 32767; borderSize.x2 = dx; - dy = (int) pParent->drawable.y + (int) pParent->drawable.height + wBorderWidth(pParent); + dy = (int) pParent->drawable.y + (int) pParent->drawable.height + + wBorderWidth(pParent); if (dy > 32767) - dy = 32767; + dy = 32767; borderSize.y2 = dy; oldVis = pParent->visibility; - switch (RegionContainsRect(universe, &borderSize)) - { + switch (RegionContainsRect(universe, &borderSize)) { case rgnIN: - newVis = VisibilityUnobscured; - break; - case rgnPART: - newVis = VisibilityPartiallyObscured; - { - RegionPtr pBounding; - - if ((pBounding = wBoundingShape (pParent))) - { - switch (RootlessShapedWindowIn (universe, - pBounding, &borderSize, - pParent->drawable.x, - pParent->drawable.y)) - { - case rgnIN: - newVis = VisibilityUnobscured; - break; - case rgnOUT: - newVis = VisibilityFullyObscured; - break; - } - } - } - break; - default: - newVis = VisibilityFullyObscured; - break; + newVis = VisibilityUnobscured; + break; + case rgnPART: + newVis = VisibilityPartiallyObscured; + { + RegionPtr pBounding; + + if ((pBounding = wBoundingShape(pParent))) { + switch (RootlessShapedWindowIn(universe, + pBounding, &borderSize, + pParent->drawable.x, + pParent->drawable.y)) { + case rgnIN: + newVis = VisibilityUnobscured; + break; + case rgnOUT: + newVis = VisibilityFullyObscured; + break; + } + } + } + break; + default: + newVis = VisibilityFullyObscured; + break; } pParent->visibility = newVis; if (oldVis != newVis && - ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) - SendVisibilityNotify(pParent); + ((pParent-> + eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) + SendVisibilityNotify(pParent); dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x; dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y; @@ -268,74 +265,64 @@ RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, case VTMap: case VTStack: case VTUnmap: - break; + break; case VTMove: - if ((oldVis == newVis) && - ((oldVis == VisibilityFullyObscured) || - (oldVis == VisibilityUnobscured))) - { - pChild = pParent; - while (1) - { - if (pChild->viewable) - { - if (pChild->visibility != VisibilityFullyObscured) - { - RegionTranslate(&pChild->borderClip, - dx, dy); - RegionTranslate(&pChild->clipList, - dx, dy); - pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; - if (pScreen->ClipNotify) - (* pScreen->ClipNotify) (pChild, dx, dy); - - } - if (pChild->valdata) - { - RegionNull(&pChild->valdata->after.borderExposed); - if (HasParentRelativeBorder(pChild)) - { - RegionSubtract(&pChild->valdata->after.borderExposed, - &pChild->borderClip, - &pChild->winSize); - } - RegionNull(&pChild->valdata->after.exposed); - } - if (pChild->firstChild) - { - pChild = pChild->firstChild; - continue; - } - } - while (!pChild->nextSib && (pChild != pParent)) - pChild = pChild->parent; - if (pChild == pParent) - break; - pChild = pChild->nextSib; - } - return; - } - /* fall through */ + if ((oldVis == newVis) && + ((oldVis == VisibilityFullyObscured) || + (oldVis == VisibilityUnobscured))) { + pChild = pParent; + while (1) { + if (pChild->viewable) { + if (pChild->visibility != VisibilityFullyObscured) { + RegionTranslate(&pChild->borderClip, dx, dy); + RegionTranslate(&pChild->clipList, dx, dy); + pChild->drawable.serialNumber = NEXT_SERIAL_NUMBER; + if (pScreen->ClipNotify) + (*pScreen->ClipNotify) (pChild, dx, dy); + + } + if (pChild->valdata) { + RegionNull(&pChild->valdata->after.borderExposed); + if (HasParentRelativeBorder(pChild)) { + RegionSubtract(&pChild->valdata->after. + borderExposed, &pChild->borderClip, + &pChild->winSize); + } + RegionNull(&pChild->valdata->after.exposed); + } + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pParent)) + pChild = pChild->parent; + if (pChild == pParent) + break; + pChild = pChild->nextSib; + } + return; + } + /* fall through */ default: - /* - * To calculate exposures correctly, we have to translate the old - * borderClip and clipList regions to the window's new location so there - * is a correspondence between pieces of the new and old clipping regions. - */ - if (dx || dy) - { - /* - * We translate the old clipList because that will be exposed or copied - * if gravity is right. - */ - RegionTranslate(&pParent->borderClip, dx, dy); - RegionTranslate(&pParent->clipList, dx, dy); - } - break; + /* + * To calculate exposures correctly, we have to translate the old + * borderClip and clipList regions to the window's new location so there + * is a correspondence between pieces of the new and old clipping regions. + */ + if (dx || dy) { + /* + * We translate the old clipList because that will be exposed or copied + * if gravity is right. + */ + RegionTranslate(&pParent->borderClip, dx, dy); + RegionTranslate(&pParent->clipList, dx, dy); + } + break; case VTBroken: - RegionEmpty(&pParent->borderClip); - RegionEmpty(&pParent->clipList); - break; + RegionEmpty(&pParent->borderClip); + RegionEmpty(&pParent->clipList); + break; } borderVisible = pParent->valdata->before.borderVisible; @@ -351,104 +338,91 @@ RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, * This leaves a region of pieces that weren't exposed before. */ - if (HasBorder (pParent)) - { - if (borderVisible) - { - /* - * when the border changes shape, the old visible portions - * of the border will be saved by DIX in borderVisible -- - * use that region and destroy it - */ - RegionSubtract(exposed, universe, borderVisible); - RegionDestroy(borderVisible); - } - else - { - RegionSubtract(exposed, universe, &pParent->borderClip); - } - if (HasParentRelativeBorder(pParent) && (dx || dy)) { - RegionSubtract(&pParent->valdata->after.borderExposed, - universe, - &pParent->winSize); - } else { - RegionSubtract(&pParent->valdata->after.borderExposed, - exposed, &pParent->winSize); - } - - RegionCopy(&pParent->borderClip, universe); - - /* - * To get the right clipList for the parent, and to make doubly sure - * that no child overlaps the parent's border, we remove the parent's - * border from the universe before proceeding. - */ - - RegionIntersect(universe, universe, &pParent->winSize); + if (HasBorder(pParent)) { + if (borderVisible) { + /* + * when the border changes shape, the old visible portions + * of the border will be saved by DIX in borderVisible -- + * use that region and destroy it + */ + RegionSubtract(exposed, universe, borderVisible); + RegionDestroy(borderVisible); + } + else { + RegionSubtract(exposed, universe, &pParent->borderClip); + } + if (HasParentRelativeBorder(pParent) && (dx || dy)) { + RegionSubtract(&pParent->valdata->after.borderExposed, + universe, &pParent->winSize); + } + else { + RegionSubtract(&pParent->valdata->after.borderExposed, + exposed, &pParent->winSize); + } + + RegionCopy(&pParent->borderClip, universe); + + /* + * To get the right clipList for the parent, and to make doubly sure + * that no child overlaps the parent's border, we remove the parent's + * border from the universe before proceeding. + */ + + RegionIntersect(universe, universe, &pParent->winSize); } else - RegionCopy(&pParent->borderClip, universe); - - if ((pChild = pParent->firstChild) && pParent->mapped) - { - RegionNull(&childUniverse); - RegionNull(&childUnion); - if ((pChild->drawable.y < pParent->lastChild->drawable.y) || - ((pChild->drawable.y == pParent->lastChild->drawable.y) && - (pChild->drawable.x < pParent->lastChild->drawable.x))) - { - for (; pChild; pChild = pChild->nextSib) - { - if (pChild->viewable) - RegionAppend(&childUnion, &pChild->borderSize); - } - } - else - { - for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) - { - if (pChild->viewable) - RegionAppend(&childUnion, &pChild->borderSize); - } - } - RegionValidate(&childUnion, &overlap); - - for (pChild = pParent->firstChild; - pChild; - pChild = pChild->nextSib) - { - if (pChild->viewable) { - /* - * If the child is viewable, we want to remove its extents - * from the current universe, but we only re-clip it if - * it's been marked. - */ - if (pChild->valdata) { - /* - * Figure out the new universe from the child's - * perspective and recurse. - */ - RegionIntersect(&childUniverse, - universe, - &pChild->borderSize); - RootlessComputeClips (pChild, pScreen, &childUniverse, - kind, exposed); - } - /* - * Once the child has been processed, we remove its extents - * from the current universe, thus denying its space to any - * other sibling. - */ - if (overlap) - RegionSubtract(universe, universe, - &pChild->borderSize); - } - } - if (!overlap) - RegionSubtract(universe, universe, &childUnion); - RegionUninit(&childUnion); - RegionUninit(&childUniverse); - } /* if any children */ + RegionCopy(&pParent->borderClip, universe); + + if ((pChild = pParent->firstChild) && pParent->mapped) { + RegionNull(&childUniverse); + RegionNull(&childUnion); + if ((pChild->drawable.y < pParent->lastChild->drawable.y) || + ((pChild->drawable.y == pParent->lastChild->drawable.y) && + (pChild->drawable.x < pParent->lastChild->drawable.x))) { + for (; pChild; pChild = pChild->nextSib) { + if (pChild->viewable) + RegionAppend(&childUnion, &pChild->borderSize); + } + } + else { + for (pChild = pParent->lastChild; pChild; pChild = pChild->prevSib) { + if (pChild->viewable) + RegionAppend(&childUnion, &pChild->borderSize); + } + } + RegionValidate(&childUnion, &overlap); + + for (pChild = pParent->firstChild; pChild; pChild = pChild->nextSib) { + if (pChild->viewable) { + /* + * If the child is viewable, we want to remove its extents + * from the current universe, but we only re-clip it if + * it's been marked. + */ + if (pChild->valdata) { + /* + * Figure out the new universe from the child's + * perspective and recurse. + */ + RegionIntersect(&childUniverse, + universe, &pChild->borderSize); + RootlessComputeClips(pChild, pScreen, &childUniverse, + kind, exposed); + } + /* + * Once the child has been processed, we remove its extents + * from the current universe, thus denying its space to any + * other sibling. + */ + if (overlap) + RegionSubtract(universe, universe, &pChild->borderSize); + } + } + if (!overlap) + RegionSubtract(universe, universe, &childUnion); + RegionUninit(&childUnion); + RegionUninit(&childUniverse); + } /* if any children */ /* * 'universe' now contains the new clipList for the parent window. @@ -457,25 +431,22 @@ RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, * new, just as for the border. */ - if (oldVis == VisibilityFullyObscured || - oldVis == VisibilityNotViewable) - { - RegionCopy(&pParent->valdata->after.exposed, universe); + if (oldVis == VisibilityFullyObscured || oldVis == VisibilityNotViewable) { + RegionCopy(&pParent->valdata->after.exposed, universe); } else if (newVis != VisibilityFullyObscured && - newVis != VisibilityNotViewable) - { - RegionSubtract(&pParent->valdata->after.exposed, - universe, &pParent->clipList); + newVis != VisibilityNotViewable) { + RegionSubtract(&pParent->valdata->after.exposed, + universe, &pParent->clipList); } /* HACK ALERT - copying contents of regions, instead of regions */ { - RegionRec tmp; + RegionRec tmp; - tmp = pParent->clipList; - pParent->clipList = *universe; - *universe = tmp; + tmp = pParent->clipList; + pParent->clipList = *universe; + *universe = tmp; } #ifdef NOTDEF @@ -485,35 +456,33 @@ RootlessComputeClips (WindowPtr pParent, ScreenPtr pScreen, pParent->drawable.serialNumber = NEXT_SERIAL_NUMBER; if (pScreen->ClipNotify) - (* pScreen->ClipNotify) (pParent, dx, dy); + (*pScreen->ClipNotify) (pParent, dx, dy); } static void RootlessTreeObscured(WindowPtr pParent) { register WindowPtr pChild; - register int oldVis; + register int oldVis; pChild = pParent; - while (1) - { - if (pChild->viewable) - { - oldVis = pChild->visibility; - if (oldVis != (pChild->visibility = VisibilityFullyObscured) && - ((pChild->eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) - SendVisibilityNotify(pChild); - if (pChild->firstChild) - { - pChild = pChild->firstChild; - continue; - } - } - while (!pChild->nextSib && (pChild != pParent)) - pChild = pChild->parent; - if (pChild == pParent) - break; - pChild = pChild->nextSib; + while (1) { + if (pChild->viewable) { + oldVis = pChild->visibility; + if (oldVis != (pChild->visibility = VisibilityFullyObscured) && + ((pChild-> + eventMask | wOtherEventMasks(pChild)) & VisibilityChangeMask)) + SendVisibilityNotify(pChild); + if (pChild->firstChild) { + pChild = pChild->firstChild; + continue; + } + } + while (!pChild->nextSib && (pChild != pParent)) + pChild = pChild->parent; + if (pChild == pParent) + break; + pChild = pChild->nextSib; } } @@ -551,31 +520,30 @@ RootlessTreeObscured(WindowPtr pParent) We need to make sure top-level windows don't clip each other, and that top-level windows aren't clipped to the root window. */ -/*ARGSUSED*/ + /*ARGSUSED*/ // fixme this is ugly // Xprint/ValTree.c doesn't work, but maybe that method can? -int -RootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */ - WindowPtr pChild, /* First child of pRoot that was - * affected */ - VTKind kind /* What kind of configuration caused call */) + int +RootlessMiValidateTree(WindowPtr pRoot, /* Parent to validate */ + WindowPtr pChild, /* First child of pRoot that was + * affected */ + VTKind kind /* What kind of configuration caused call */ + ) { - RegionRec childClip; /* The new borderClip for the current - * child */ - RegionRec exposed; /* For intermediate calculations */ - register ScreenPtr pScreen; - register WindowPtr pWin; + RegionRec childClip; /* The new borderClip for the current + * child */ + RegionRec exposed; /* For intermediate calculations */ + register ScreenPtr pScreen; + register WindowPtr pWin; pScreen = pRoot->drawable.pScreen; if (pChild == NullWindow) - pChild = pRoot->firstChild; + pChild = pRoot->firstChild; RegionNull(&childClip); RegionNull(&exposed); - if (RegionBroken(&pRoot->clipList) && - !RegionBroken(&pRoot->borderClip)) - { + if (RegionBroken(&pRoot->clipList) && !RegionBroken(&pRoot->borderClip)) { // fixme this might not work, but hopefully doesn't happen anyway. kind = VTBroken; RegionEmpty(&pRoot->clipList); @@ -588,22 +556,21 @@ RootlessMiValidateTree (WindowPtr pRoot, /* Parent to validate */ * childClip is always reset to that child's size. */ - for (pWin = pChild; - pWin != NullWindow; - pWin = pWin->nextSib) - { + for (pWin = pChild; pWin != NullWindow; pWin = pWin->nextSib) { if (pWin->viewable) { if (pWin->valdata) { RegionCopy(&childClip, &pWin->borderSize); - RootlessComputeClips (pWin, pScreen, &childClip, kind, &exposed); - } else if (pWin->visibility == VisibilityNotViewable) { + RootlessComputeClips(pWin, pScreen, &childClip, kind, &exposed); + } + else if (pWin->visibility == VisibilityNotViewable) { RootlessTreeObscured(pWin); } - } else { + } + else { if (pWin->valdata) { RegionEmpty(&pWin->clipList); if (pScreen->ClipNotify) - (* pScreen->ClipNotify) (pWin, 0, 0); + (*pScreen->ClipNotify) (pWin, 0, 0); RegionEmpty(&pWin->borderClip); pWin->valdata = NULL; } diff --git a/xorg-server/miext/rootless/rootlessWindow.c b/xorg-server/miext/rootless/rootlessWindow.c index 4c7f7b044..cf1611c1e 100644 --- a/xorg-server/miext/rootless/rootlessWindow.c +++ b/xorg-server/miext/rootless/rootlessWindow.c @@ -1,1645 +1,1644 @@ -/*
- * Rootless window management
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved.
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stddef.h> /* For NULL */
-#include <limits.h> /* For CHAR_BIT */
-#include <assert.h>
-#include <X11/Xatom.h>
-#ifdef __APPLE__
-#include <Xplugin.h>
-#include "mi.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-//#include <X11/extensions/applewm.h>
-extern int darwinMainScreenX, darwinMainScreenY;
-extern Bool no_configure_window;
-#endif
-#include "fb.h"
-
-#include "rootlessCommon.h"
-#include "rootlessWindow.h"
-
-#ifdef _MSC_VER
-#define inline __inline
-#include "xplugin.h"
-extern int darwinMainScreenX, darwinMainScreenY;
-#endif
-
-#define SCREEN_TO_GLOBAL_X \
- (pScreen->x + rootlessGlobalOffsetX)
-#define SCREEN_TO_GLOBAL_Y \
- (pScreen->y + rootlessGlobalOffsetY)
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
- static Atom func (void) { \
- static unsigned int generation = 0; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
- }
-
-DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
-
-static Bool windows_hidden;
-// TODO - abstract xp functions
-
-#ifdef __APPLE__
-
-// XXX: identical to x_cvt_vptr_to_uint ?
-#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x)))
-
-void
-RootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state)
-{
- RootlessWindowRec *winRec;
-
- if (pWin == NULL) return;
-
- winRec = WINREC (pWin);
- if (winRec == NULL) return;
-
- winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0);
- winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0);
- pWin->rootlessUnhittable = winRec->is_offscreen;
-}
-
-void RootlessNativeWindowMoved (WindowPtr pWin) {
- xp_box bounds;
- int sx, sy, err;
- XID vlist[2];
- Mask mask;
- ClientPtr pClient;
- RootlessWindowRec *winRec;
-
- winRec = WINREC(pWin);
-
- if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return;
-
- sx = pWin->drawable.pScreen->x + darwinMainScreenX;
- sy = pWin->drawable.pScreen->y + darwinMainScreenY;
-
- /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */
- vlist[0] = (INT16) bounds.x1 - sx;
- vlist[1] = (INT16) bounds.y1 - sy;
- mask = CWX | CWY;
-
- /* pretend we're the owner of the window! */
- err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess);
- if(err != Success) {
- ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id);
- return;
- }
-
- /* Don't want to do anything to the physical window (avoids
- notification-response feedback loops) */
-
- no_configure_window = TRUE;
- ConfigureWindow (pWin, mask, vlist, pClient);
- no_configure_window = FALSE;
-}
-
-#endif /* __APPLE__ */
-
-/*
- * RootlessCreateWindow
- * For now, don't create a physical window until either the window is
- * realized, or we really need it (e.g. to attach VRAM surfaces to).
- * Do reset the window size so it's not clipped by the root window.
- */
-Bool
-RootlessCreateWindow(WindowPtr pWin)
-{
- Bool result;
- RegionRec saveRoot;
-
- SETWINREC(pWin, NULL);
- dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL);
-
- SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow);
-
- if (!IsRoot(pWin)) {
- /* win/border size set by DIX, not by wrapped CreateWindow, so
- correct it here. Don't HUGE_ROOT when pWin is the root! */
-
- HUGE_ROOT(pWin);
- SetWinSize(pWin);
- SetBorderSize(pWin);
- }
-
- result = pWin->drawable.pScreen->CreateWindow(pWin);
-
- if (pWin->parent) {
- NORMAL_ROOT(pWin);
- }
-
- SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow);
-
- return result;
-}
-
-
-/*
- * RootlessDestroyFrame
- * Destroy the physical window associated with the given window.
- */
-static void
-RootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec)
-{
- SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid);
- free(winRec);
- SETWINREC(pWin, NULL);
-}
-
-
-/*
- * RootlessDestroyWindow
- * Destroy the physical window associated with the given window.
- */
-Bool
-RootlessDestroyWindow(WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- Bool result;
-
- if (winRec != NULL) {
- RootlessDestroyFrame(pWin, winRec);
- }
-
- SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
- result = pWin->drawable.pScreen->DestroyWindow(pWin);
- SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
-
- return result;
-}
-
-
-
-static Bool
-RootlessGetShape(WindowPtr pWin, RegionPtr pShape)
-{
- if (wBoundingShape(pWin) == NULL)
- return FALSE;
-
- /* wBoundingShape is relative to *inner* origin of window.
- Translate by borderWidth to get the outside-relative position. */
-
- RegionNull(pShape);
- RegionCopy(pShape, wBoundingShape(pWin));
- RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth);
-
- return TRUE;
-}
-
-
-/*
- * RootlessReshapeFrame
- * Set the frame shape.
- */
-static void RootlessReshapeFrame(WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- RegionRec newShape;
- RegionPtr pShape;
-
- // If the window is not yet framed, do nothing
- if (winRec == NULL)
- return;
-
- if (IsRoot(pWin))
- return;
-
- RootlessStopDrawing(pWin, FALSE);
-
- pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL;
-
-#ifdef ROOTLESSDEBUG
- RL_DEBUG_MSG("reshaping...");
- if (pShape != NULL) {
- RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ",
- RegionNumRects(&newShape),
- newShape.extents.x1, newShape.extents.y1,
- newShape.extents.x2, newShape.extents.y2);
- } else {
- RL_DEBUG_MSG("no shape ");
- }
-#endif
-
- SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape);
-
- if (pShape != NULL)
- RegionUninit(&newShape);
-}
-
-
-/*
- * RootlessSetShape
- * Shape is usually set before a window is mapped and the window will
- * not have a frame associated with it. In this case, the frame will be
- * shaped when the window is framed.
- */
-void
-RootlessSetShape(WindowPtr pWin, int kind)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- SCREEN_UNWRAP(pScreen, SetShape);
- pScreen->SetShape(pWin, kind);
- SCREEN_WRAP(pScreen, SetShape);
-
- RootlessReshapeFrame(pWin);
-}
-
-
-
-/* Disallow ParentRelative background on top-level windows
- because the root window doesn't really have the right background.
- */
-Bool
-RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask)
-{
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- RL_DEBUG_MSG("change window attributes start ");
-
- SCREEN_UNWRAP(pScreen, ChangeWindowAttributes);
- result = pScreen->ChangeWindowAttributes(pWin, vmask);
- SCREEN_WRAP(pScreen, ChangeWindowAttributes);
-
- if (WINREC(pWin)) {
- // disallow ParentRelative background state
- if (pWin->backgroundState == ParentRelative) {
- XID pixel = 0;
- ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
- }
- }
-
- RL_DEBUG_MSG("change window attributes end\n");
- return result;
-}
-
-
-/*
- * RootlessPositionWindow
- * This is a hook for when DIX moves or resizes a window.
- * Update the frame position now although the physical window is moved
- * in RootlessMoveWindow. (x, y) are *inside* position. After this,
- * mi and fb are expecting the pixmap to be at the new location.
- */
-Bool
-RootlessPositionWindow(WindowPtr pWin, int x, int y)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- Bool result;
-
- RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y);
-
- if (winRec) {
- if (winRec->is_drawing) {
- // Reset frame's pixmap and move it to the new position.
- int bw = wBorderWidth(pWin);
-
- winRec->pixmap->devPrivate.ptr = winRec->pixelData;
- SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw);
- }
- }
-
- SCREEN_UNWRAP(pScreen, PositionWindow);
- result = pScreen->PositionWindow(pWin, x, y);
- SCREEN_WRAP(pScreen, PositionWindow);
-
- RL_DEBUG_MSG("positionwindow end\n");
- return result;
-}
-
-
-/*
- * RootlessInitializeFrame
- * Initialize some basic attributes of the frame. Note that winRec
- * may already have valid data in it, so don't overwrite anything
- * valuable.
- */
-static void
-RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec)
-{
- DrawablePtr d = &pWin->drawable;
- int bw = wBorderWidth(pWin);
-
- winRec->win = pWin;
-
- winRec->x = d->x - bw;
- winRec->y = d->y - bw;
- winRec->width = d->width + 2*bw;
- winRec->height = d->height + 2*bw;
- winRec->borderWidth = bw;
-}
-
-/*
- * RootlessEnsureFrame
- * Make sure the given window is framed. If the window doesn't have a
- * physical window associated with it, attempt to create one. If that
- * is unsuccessful, return NULL.
- */
-static RootlessWindowRec *
-RootlessEnsureFrame(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec;
- RegionRec shape;
- RegionPtr pShape = NULL;
-
- if (WINREC(pWin) != NULL)
- return WINREC(pWin);
-
- if (!IsTopLevel(pWin) && !IsRoot(pWin))
- return NULL;
-
- if (pWin->drawable.class != InputOutput)
- return NULL;
-
- winRec = malloc(sizeof(RootlessWindowRec));
-
- if (!winRec)
- return NULL;
-
- RootlessInitializeFrame(pWin, winRec);
-
- winRec->is_drawing = FALSE;
- winRec->is_reorder_pending = FALSE;
- winRec->pixmap = NULL;
- winRec->wid = NULL;
- winRec->level = 0;
-
- SETWINREC(pWin, winRec);
-
- // Set the frame's shape if the window is shaped
- if (RootlessGetShape(pWin, &shape))
- pShape = &shape;
-
- RL_DEBUG_MSG("creating frame ");
-
- if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen,
- winRec->x + SCREEN_TO_GLOBAL_X,
- winRec->y + SCREEN_TO_GLOBAL_Y,
- pShape))
- {
- RL_DEBUG_MSG("implementation failed to create frame!\n");
- free(winRec);
- SETWINREC(pWin, NULL);
- return NULL;
- }
-
- if (pWin->drawable.depth == 8)
- RootlessFlushWindowColormap(pWin);
-
- if (pShape != NULL)
- RegionUninit(&shape);
-
- return winRec;
-}
-
-
-/*
- * RootlessRealizeWindow
- * The frame is usually created here and not in CreateWindow so that
- * windows do not eat memory until they are realized.
- */
-Bool
-RootlessRealizeWindow(WindowPtr pWin)
-{
- Bool result;
- RegionRec saveRoot;
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin);
-
- if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) {
- RootlessWindowRec *winRec;
-
- winRec = RootlessEnsureFrame(pWin);
- if (winRec == NULL)
- return FALSE;
-
- winRec->is_reorder_pending = TRUE;
-
- RL_DEBUG_MSG("Top level window ");
-
- // Disallow ParentRelative background state on top-level windows.
- // This might have been set before the window was mapped.
- if (pWin->backgroundState == ParentRelative) {
- XID pixel = 0;
- ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
- }
- }
-
- if (!IsRoot(pWin)) HUGE_ROOT(pWin);
- SCREEN_UNWRAP(pScreen, RealizeWindow);
- result = pScreen->RealizeWindow(pWin);
- SCREEN_WRAP(pScreen, RealizeWindow);
- if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
-
- RL_DEBUG_MSG("realizewindow end\n");
- return result;
-}
-
-
-/*
- * RootlessFrameForWindow
- * Returns the frame ID for the physical window displaying the given window.
- * If CREATE is true and the window has no frame, attempt to create one.
- */
-RootlessFrameID
-RootlessFrameForWindow(WindowPtr pWin, Bool create)
-{
- WindowPtr pTopWin;
- RootlessWindowRec *winRec;
-
- pTopWin = TopLevelParent(pWin);
- if (pTopWin == NULL)
- return NULL;
-
- winRec = WINREC(pTopWin);
-
- if (winRec == NULL && create && pWin->drawable.class == InputOutput) {
- winRec = RootlessEnsureFrame(pTopWin);
- }
-
- if (winRec == NULL)
- return NULL;
-
- return winRec->wid;
-}
-
-
-/*
- * RootlessUnrealizeWindow
- * Unmap the physical window.
- */
-Bool
-RootlessUnrealizeWindow(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- Bool result;
-
- RL_DEBUG_MSG("unrealizewindow start ");
-
- if (winRec) {
- RootlessStopDrawing(pWin, FALSE);
-
- SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
-
- winRec->is_reorder_pending = FALSE;
- }
-
- SCREEN_UNWRAP(pScreen, UnrealizeWindow);
- result = pScreen->UnrealizeWindow(pWin);
- SCREEN_WRAP(pScreen, UnrealizeWindow);
-
- RL_DEBUG_MSG("unrealizewindow end\n");
- return result;
-}
-
-
-/*
- * RootlessReorderWindow
- * Reorder the frame associated with the given window so that it's
- * physically above the window below it in the X stacking order.
- */
-void
-RootlessReorderWindow(WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
-
- if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) {
- WindowPtr newPrevW;
- RootlessWindowRec *newPrev;
- RootlessFrameID newPrevID;
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- /* Check if the implementation wants the frame to not be reordered
- even though the X11 window is restacked. This can be useful if
- frames are ordered-in with animation so that the reordering is not
- done until the animation is complete. */
- if (SCREENREC(pScreen)->imp->DoReorderWindow) {
- if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec))
- return;
- }
-
- RootlessStopDrawing(pWin, FALSE);
-
- /* Find the next window above this one that has a mapped frame.
- * Only include cases where the windows are in the same category of
- * hittability to ensure offscreen windows dont get restacked
- * relative to onscreen ones (but that the offscreen ones maintain
- * their stacking order if they are explicitly asked to Reorder
- */
-
- newPrevW = pWin->prevSib;
- while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable))
- newPrevW = newPrevW->prevSib;
-
- newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL;
- newPrevID = newPrev != NULL ? newPrev->wid : 0;
-
- /* If it exists, reorder the frame above us first. */
-
- if (newPrev && newPrev->is_reorder_pending) {
- newPrev->is_reorder_pending = FALSE;
- RootlessReorderWindow(newPrevW);
- }
-
- SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID);
- }
-}
-
-
-/*
- * RootlessRestackWindow
- * This is a hook for when DIX changes the window stacking order.
- * The window has already been inserted into its new position in the
- * DIX window stack. We need to change the order of the physical
- * window to match.
- */
-void
-RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib)
-{
- RegionRec saveRoot;
- RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- RL_DEBUG_MSG("restackwindow start ");
- if (winRec)
- RL_DEBUG_MSG("restack top level \n");
-
- HUGE_ROOT(pWin);
- SCREEN_UNWRAP(pScreen, RestackWindow);
-
- if (pScreen->RestackWindow)
- pScreen->RestackWindow(pWin, pOldNextSib);
-
- SCREEN_WRAP(pScreen, RestackWindow);
- NORMAL_ROOT(pWin);
-
- if (winRec && pWin->viewable) {
- RootlessReorderWindow(pWin);
- }
-
- RL_DEBUG_MSG("restackwindow end\n");
-}
-
-/*
- * Specialized window copy procedures
- */
-
-// Globals needed during window resize and move.
-static pointer gResizeDeathBits = NULL;
-static int gResizeDeathCount = 0;
-static PixmapPtr gResizeDeathPix[2] = {NULL, NULL};
-static BoxRec gResizeDeathBounds[2];
-static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
-
-/*
- * RootlessNoCopyWindow
- * CopyWindow() that doesn't do anything. For MoveWindow() of
- * top-level windows.
- */
-static void
-RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr prgnSrc)
-{
- // some code expects the region to be translated
- int dx = ptOldOrg.x - pWin->drawable.x;
- int dy = ptOldOrg.y - pWin->drawable.y;
-
- RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW ");
-
- RegionTranslate(prgnSrc, -dx, -dy);
-}
-
-
-/*
- * RootlessResizeCopyWindow
- * CopyWindow used during ResizeWindow for gravity moves. Based on
- * fbCopyWindow. The original always draws on the root pixmap, which
- * we don't have. Instead, draw on the parent window's pixmap.
- * Resize version: the old location's pixels are in gResizeCopyWindowSource.
- */
-static void
-RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RegionRec rgnDst;
- int dx, dy;
-
- RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin);
-
- /* Don't unwrap pScreen->CopyWindow.
- The bogus rewrap with RootlessCopyWindow causes a crash if
- CopyWindow is called again during the same resize. */
-
- if (gResizeDeathCount == 0)
- return;
-
- RootlessStartDrawing(pWin);
-
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
- RegionTranslate(prgnSrc, -dx, -dy);
- RegionNull(&rgnDst);
- RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
-
- if (gResizeDeathCount == 1) {
- /* Simple case, we only have a single source pixmap. */
-
- miCopyRegion(&gResizeDeathPix[0]->drawable,
- &pScreen->GetWindowPixmap(pWin)->drawable, 0,
- &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
- }
- else {
- int i;
- RegionRec clip, clipped;
-
- /* More complex case, N source pixmaps (usually two). So we
- intersect the destination with each source and copy those bits. */
-
- for (i = 0; i < gResizeDeathCount; i++) {
- RegionInit(&clip, gResizeDeathBounds + 0, 1);
- RegionNull(&clipped);
- RegionIntersect(&rgnDst, &clip, &clipped);
-
- miCopyRegion(&gResizeDeathPix[i]->drawable,
- &pScreen->GetWindowPixmap(pWin)->drawable, 0,
- &clipped, dx, dy, fbCopyWindowProc, 0, 0);
-
- RegionUninit(&clipped);
- RegionUninit(&clip);
- }
- }
-
- /* Don't update - resize will update everything */
- RegionUninit(&rgnDst);
-
- fbValidateDrawable(&pWin->drawable);
-
- RL_DEBUG_MSG("resizecopywindowFB end\n");
-}
-
-
-/*
- * RootlessCopyWindow
- * Update *new* location of window. Old location is redrawn with
- * miPaintWindow. Cloned from fbCopyWindow.
- * The original always draws on the root pixmap, which we don't have.
- * Instead, draw on the parent window's pixmap.
- */
-void
-RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RegionRec rgnDst;
- int dx, dy;
- BoxPtr extents;
- int area;
-
- RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin);
-
- SCREEN_UNWRAP(pScreen, CopyWindow);
-
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
- RegionTranslate(prgnSrc, -dx, -dy);
-
- RegionNull(&rgnDst);
- RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc);
-
- extents = RegionExtents(&rgnDst);
- area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
-
- /* If the area exceeds threshold, use the implementation's
- accelerated version. */
- if (area > rootless_CopyWindow_threshold &&
- SCREENREC(pScreen)->imp->CopyWindow)
- {
- RootlessWindowRec *winRec;
- WindowPtr top;
-
- top = TopLevelParent(pWin);
- if (top == NULL) {
- RL_DEBUG_MSG("no parent\n");
- goto out;
- }
-
- winRec = WINREC(top);
- if (winRec == NULL) {
- RL_DEBUG_MSG("not framed\n");
- goto out;
- }
-
- /* Move region to window local coords */
- RegionTranslate(&rgnDst, -winRec->x, -winRec->y);
-
- RootlessStopDrawing(pWin, FALSE);
-
- SCREENREC(pScreen)->imp->CopyWindow(winRec->wid,
- RegionNumRects(&rgnDst),
- RegionRects(&rgnDst),
- dx, dy);
- }
- else {
- RootlessStartDrawing(pWin);
-
- miCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin,
- 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
-
- /* prgnSrc has been translated to dst position */
- RootlessDamageRegion(pWin, prgnSrc);
- }
-
-out:
- RegionUninit(&rgnDst);
- fbValidateDrawable(&pWin->drawable);
-
- SCREEN_WRAP(pScreen, CopyWindow);
-
- RL_DEBUG_MSG("copywindowFB end\n");
-}
-
-
-/*
- * Window resize procedures
- */
-
-enum {
- WIDTH_SMALLER = 1,
- HEIGHT_SMALLER = 2,
-};
-
-
-/*
- * ResizeWeighting
- * Choose gravity to avoid local copies. Do that by looking for
- * a corner that doesn't move _relative to the screen_.
- */
-static inline unsigned int
-ResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
- int newX1, int newY1, int newX2, int newY2, int newBW)
-{
-#ifdef ROOTLESS_RESIZE_GRAVITY
- if (newBW != oldBW)
- return RL_GRAVITY_NONE;
-
- if (newX1 == oldX1 && newY1 == oldY1)
- return RL_GRAVITY_NORTH_WEST;
- else if (newX1 == oldX1 && newY2 == oldY2)
- return RL_GRAVITY_SOUTH_WEST;
- else if (newX2 == oldX2 && newY2 == oldY2)
- return RL_GRAVITY_SOUTH_EAST;
- else if (newX2 == oldX2 && newY1 == oldY1)
- return RL_GRAVITY_NORTH_EAST;
- else
- return RL_GRAVITY_NONE;
-#else
- return RL_GRAVITY_NONE;
-#endif
-}
-
-
-/*
- * StartFrameResize
- * Prepare to resize a top-level window. The old window's pixels are
- * saved and the implementation is told to change the window size.
- * (x,y,w,h) is outer frame of window (outside border)
- */
-static Bool
-StartFrameResize(WindowPtr pWin, Bool gravity,
- int oldX, int oldY, int oldW, int oldH, int oldBW,
- int newX, int newY, int newW, int newH, int newBW)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- Bool need_window_source = FALSE, resize_after = FALSE;
-
- BoxRec rect;
- int oldX2, newX2;
- int oldY2, newY2;
- unsigned int weight;
-
- oldX2 = oldX + oldW, newX2 = newX + newW;
- oldY2 = oldY + oldH, newY2 = newY + newH;
-
- /* Decide which resize weighting to use */
- weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
-
- /* Compute intersection between old and new rects */
- rect.x1 = max(oldX, newX);
- rect.y1 = max(oldY, newY);
- rect.x2 = min(oldX2, newX2);
- rect.y2 = min(oldY2, newY2);
-
- RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
- RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n",
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
-
- RootlessRedisplay(pWin);
-
- /* If gravity is true, then we need to have a way of recovering all
- the original bits in the window for when X rearranges the contents
- based on the various gravity settings. The obvious way is to just
- snapshot the entire backing store before resizing it, but that
- it slow on large windows.
-
- So the optimization here is to use the implementation's resize
- weighting options (if available) to allow us to reason about what
- is left in the backing store after the resize. We can then only
- copy what won't be there after the resize, and do a two-stage copy
- operation.
-
- Most of these optimizations are only applied when the top-left
- corner of the window is fixed, since that's the common case. They
- could probably be extended with some thought. */
-
- gResizeDeathCount = 0;
-
- if (gravity && weight == RL_GRAVITY_NORTH_WEST) {
- unsigned int code = 0;
-
- /* Top left corner is anchored. We never need to copy the
- entire window. */
-
- need_window_source = TRUE;
-
- /* These comparisons were chosen to avoid setting bits when the sizes
- are the same. (So the fastest case automatically gets taken when
- dimensions are unchanging.) */
-
- if (newW < oldW)
- code |= WIDTH_SMALLER;
- if (newH < oldH)
- code |= HEIGHT_SMALLER;
-
- if (((code ^ (code >> 1)) & 1) == 0) {
- /* Both dimensions are either getting larger, or both
- are getting smaller. No need to copy anything. */
-
- if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) {
- /* Since the window is getting smaller, we can do gravity
- repair on it with it's current size, then resize it
- afterwards. */
-
- resize_after = TRUE;
- }
-
- gResizeDeathCount = 1;
- }
- else {
- unsigned int copy_rowbytes, Bpp;
- unsigned int copy_rect_width, copy_rect_height;
- BoxRec copy_rect;
-
- /* We can get away with a partial copy. 'rect' is the
- intersection between old and new bounds, so copy
- everything to the right of or below the intersection. */
-
- RootlessStartDrawing(pWin);
-
- if (code == WIDTH_SMALLER) {
- copy_rect.x1 = rect.x2;
- copy_rect.y1 = rect.y1;
- copy_rect.x2 = oldX2;
- copy_rect.y2 = oldY2;
- }
- else if (code == HEIGHT_SMALLER) {
- copy_rect.x1 = rect.x1;
- copy_rect.y1 = rect.y2;
- copy_rect.x2 = oldX2;
- copy_rect.y2 = oldY2;
- }
- else
- OsAbort();
-
- Bpp = winRec->win->drawable.bitsPerPixel / 8;
- copy_rect_width = copy_rect.x2 - copy_rect.x1;
- copy_rect_height = copy_rect.y2 - copy_rect.y1;
- copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31;
- gResizeDeathBits = malloc(copy_rowbytes
- * copy_rect_height);
-
- if (copy_rect_width * copy_rect_height >
- rootless_CopyBytes_threshold &&
- SCREENREC(pScreen)->imp->CopyBytes)
- {
- SCREENREC(pScreen)->imp->CopyBytes(
- copy_rect_width * Bpp, copy_rect_height,
- ((char *) winRec->pixelData)
- + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
- + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow,
- gResizeDeathBits, copy_rowbytes);
- } else {
- fbBlt((FbBits *) (winRec->pixelData
- + ((copy_rect.y1 - oldY) * winRec->bytesPerRow)
- + (copy_rect.x1 - oldX) * Bpp),
- winRec->bytesPerRow / sizeof(FbBits), 0,
- (FbBits *) gResizeDeathBits,
- copy_rowbytes / sizeof(FbBits), 0,
- copy_rect_width * Bpp, copy_rect_height,
- GXcopy, FB_ALLONES, Bpp, 0, 0);
- }
-
- gResizeDeathBounds[1] = copy_rect;
- gResizeDeathPix[1]
- = GetScratchPixmapHeader(pScreen, copy_rect_width,
- copy_rect_height,
- winRec->win->drawable.depth,
- winRec->win->drawable.bitsPerPixel,
- winRec->bytesPerRow,
- (void *) gResizeDeathBits);
-
- SetPixmapBaseToScreen(gResizeDeathPix[1],
- copy_rect.x1, copy_rect.y1);
-
- gResizeDeathCount = 2;
- }
- }
- else if (gravity) {
- /* The general case. Just copy everything. */
- BoxRec tmpBoxRec={oldX, oldY, oldX2, oldY2};
-
- RootlessStartDrawing(pWin);
-
- gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height);
-
- memcpy(gResizeDeathBits, winRec->pixelData,
- winRec->bytesPerRow * winRec->height);
-
- gResizeDeathBounds[0] = tmpBoxRec;
- gResizeDeathPix[0]
- = GetScratchPixmapHeader(pScreen, winRec->width,
- winRec->height,
- winRec->win->drawable.depth,
- winRec->win->drawable.bitsPerPixel,
- winRec->bytesPerRow,
- (void *) gResizeDeathBits);
-
- SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
- gResizeDeathCount = 1;
- }
-
- RootlessStopDrawing(pWin, FALSE);
-
- winRec->x = newX;
- winRec->y = newY;
- winRec->width = newW;
- winRec->height = newH;
- winRec->borderWidth = newBW;
-
- /* Unless both dimensions are getting smaller, Resize the frame
- before doing gravity repair */
-
- if (!resize_after) {
- SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
- newX + SCREEN_TO_GLOBAL_X,
- newY + SCREEN_TO_GLOBAL_Y,
- newW, newH, weight);
- }
-
- RootlessStartDrawing(pWin);
-
- /* If necessary, create a source pixmap pointing at the current
- window bits. */
-
- if (need_window_source) {
- BoxRec tmpBoxRec={oldX, oldY, oldX2, oldY2};
- gResizeDeathBounds[0] = tmpBoxRec;
- gResizeDeathPix[0]
- = GetScratchPixmapHeader(pScreen, oldW, oldH,
- winRec->win->drawable.depth,
- winRec->win->drawable.bitsPerPixel,
- winRec->bytesPerRow, winRec->pixelData);
-
- SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY);
- }
-
- /* Use custom CopyWindow when moving gravity bits around
- ResizeWindow assumes the old window contents are in the same
- pixmap, but here they're in deathPix instead. */
-
- if (gravity) {
- gResizeOldCopyWindowProc = pScreen->CopyWindow;
- pScreen->CopyWindow = RootlessResizeCopyWindow;
- }
-
- /* If we can't rely on the window server preserving the bits we
- need in the position we need, copy the pixels in the
- intersection from src to dst. ResizeWindow assumes these pixels
- are already present when making gravity adjustments. pWin
- currently has new-sized pixmap but is in old position.
-
- FIXME: border width change! (?) */
-
- if (gravity && weight == RL_GRAVITY_NONE) {
- PixmapPtr src, dst;
-
- assert(gResizeDeathCount == 1);
-
- src = gResizeDeathPix[0];
- dst = pScreen->GetWindowPixmap(pWin);
-
- RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
- rect.x1, rect.y1, rect.x2, rect.y2);
-
- /* rect is the intersection of the old location and new location */
- if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) {
- /* The window drawable still has the old frame position, which
- means that DST doesn't actually point at the origin of our
- physical backing store when adjusted by the drawable.x,y
- position. So sneakily adjust it temporarily while copying.. */
-
- ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
- SetPixmapBaseToScreen(dst, newX, newY);
-
- fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
- &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
-
- ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData;
- SetPixmapBaseToScreen(dst, oldX, oldY);
- }
- }
-
- return resize_after;
-}
-
-
-static void
-FinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY,
- unsigned int oldW, unsigned int oldH, unsigned int oldBW,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int newBW, Bool resize_now)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- int i;
-
- RootlessStopDrawing(pWin, FALSE);
-
- if (resize_now) {
- unsigned int weight;
-
- /* We didn't resize anything earlier, so do it now, now that
- we've finished gravitating the bits. */
-
- weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
-
- SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
- newX + SCREEN_TO_GLOBAL_X,
- newY + SCREEN_TO_GLOBAL_Y,
- newW, newH, weight);
- }
-
- /* Redraw everything. FIXME: there must be times when we don't need
- to do this. Perhaps when top-left weighting and no gravity? */
-
- RootlessDamageRect(pWin, -newBW, -newBW, newW, newH);
-
- for (i = 0; i < 2; i++) {
- if (gResizeDeathPix[i] != NULL) {
- FreeScratchPixmapHeader(gResizeDeathPix[i]);
- gResizeDeathPix[i] = NULL;
- }
- }
-
- free(gResizeDeathBits);
- gResizeDeathBits = NULL;
-
- if (gravity) {
- pScreen->CopyWindow = gResizeOldCopyWindowProc;
- }
-}
-
-
-/*
- * RootlessMoveWindow
- * If kind==VTOther, window border is resizing (and borderWidth is
- * already changed!!@#$) This case works like window resize, not move.
- */
-void
-RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
- CopyWindowProcPtr oldCopyWindowProc = NULL;
- int oldX = 0, oldY = 0, newX = 0, newY = 0;
- unsigned int oldW = 0, oldH = 0, oldBW = 0;
- unsigned int newW = 0, newH = 0, newBW = 0;
- Bool resize_after = FALSE;
- RegionRec saveRoot;
-
- RL_DEBUG_MSG("movewindow start \n");
-
- if (winRec) {
- if (kind == VTMove) {
- oldX = winRec->x;
- oldY = winRec->y;
- RootlessRedisplay(pWin);
- RootlessStartDrawing(pWin);
- } else {
- RL_DEBUG_MSG("movewindow border resizing ");
-
- oldBW = winRec->borderWidth;
- oldX = winRec->x;
- oldY = winRec->y;
- oldW = winRec->width;
- oldH = winRec->height;
-
- newBW = wBorderWidth(pWin);
- newX = x;
- newY = y;
- newW = pWin->drawable.width + 2*newBW;
- newH = pWin->drawable.height + 2*newBW;
-
- resize_after = StartFrameResize(pWin, FALSE,
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
- }
- }
-
- HUGE_ROOT(pWin);
- SCREEN_UNWRAP(pScreen, MoveWindow);
-
- if (winRec) {
- oldCopyWindowProc = pScreen->CopyWindow;
- pScreen->CopyWindow = RootlessNoCopyWindow;
- }
- pScreen->MoveWindow(pWin, x, y, pSib, kind);
- if (winRec) {
- pScreen->CopyWindow = oldCopyWindowProc;
- }
-
- NORMAL_ROOT(pWin);
- SCREEN_WRAP(pScreen, MoveWindow);
-
- if (winRec) {
- if (kind == VTMove) {
- winRec->x = x;
- winRec->y = y;
- RootlessStopDrawing(pWin, FALSE);
- SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
- x + SCREEN_TO_GLOBAL_X,
- y + SCREEN_TO_GLOBAL_Y);
- } else {
- FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW, resize_after);
- }
- }
-
- RL_DEBUG_MSG("movewindow end\n");
-}
-
-
-/*
- * RootlessResizeWindow
- * Note: (x, y, w, h) as passed to this procedure don't match the frame
- * definition. (x,y) is corner of very outer edge, *outside* border.
- * w,h is width and height *inside* border, *ignoring* border width.
- * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
- * is total rect and (x+bw, y+bw, w, h) is inner rect.
- */
-void
-RootlessResizeWindow(WindowPtr pWin, int x, int y,
- unsigned int w, unsigned int h, WindowPtr pSib)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
- int oldX = 0, oldY = 0, newX = 0, newY = 0;
- unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0;
- Bool resize_after = FALSE;
- RegionRec saveRoot;
-
- RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin);
-
- if(pWin->parent) {
- if (winRec) {
- oldBW = winRec->borderWidth;
- oldX = winRec->x;
- oldY = winRec->y;
- oldW = winRec->width;
- oldH = winRec->height;
-
- newBW = oldBW;
- newX = x;
- newY = y;
- newW = w + 2*newBW;
- newH = h + 2*newBW;
-
- resize_after = StartFrameResize(pWin, TRUE,
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
- }
-
- HUGE_ROOT(pWin);
- SCREEN_UNWRAP(pScreen, ResizeWindow);
- pScreen->ResizeWindow(pWin, x, y, w, h, pSib);
- SCREEN_WRAP(pScreen, ResizeWindow);
- NORMAL_ROOT(pWin);
-
- if (winRec) {
- FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW, resize_after);
- }
- } else {
- /* Special case for resizing the root window */
- BoxRec box;
-
- pWin->drawable.x = x;
- pWin->drawable.y = y;
- pWin->drawable.width = w;
- pWin->drawable.height = h;
-
- box.x1 = x; box.y1 = y;
- box.x2 = x + w; box.y2 = y + h;
- RegionUninit(&pWin->winSize);
- RegionInit(&pWin->winSize, &box, 1);
- RegionCopy(&pWin->borderSize, &pWin->winSize);
- RegionCopy(&pWin->clipList, &pWin->winSize);
- RegionCopy(&pWin->borderClip, &pWin->winSize);
-
- if (winRec) {
- SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
- x + SCREEN_TO_GLOBAL_X,
- y + SCREEN_TO_GLOBAL_Y,
- w, h, RL_GRAVITY_NONE);
- }
-
- miSendExposures(pWin, &pWin->borderClip,
- pWin->drawable.x, pWin->drawable.y);
- }
-
- RL_DEBUG_MSG("resizewindow end\n");
-}
-
-
-/*
- * RootlessRepositionWindow
- * Called by the implementation when a window needs to be repositioned to
- * its correct location on the screen. This routine is typically needed
- * due to changes in the underlying window system, such as a screen layout
- * change.
- */
-void
-RootlessRepositionWindow(WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- if (winRec == NULL)
- return;
-
- RootlessStopDrawing(pWin, FALSE);
- SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen,
- winRec->x + SCREEN_TO_GLOBAL_X,
- winRec->y + SCREEN_TO_GLOBAL_Y);
-
- RootlessReorderWindow(pWin);
-}
-
-
-/*
- * RootlessReparentWindow
- * Called after a window has been reparented. Generally windows are not
- * framed until they are mapped. However, a window may be framed early by the
- * implementation calling RootlessFrameForWindow. (e.g. this could be needed
- * to attach a VRAM surface to it.) If the window is subsequently reparented
- * by the window manager before being mapped, we need to give the frame to
- * the new top-level window.
- */
-void
-RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- WindowPtr pTopWin;
-
- /* Check that window is not top-level now, but used to be. */
- if (IsRoot(pWin) || IsRoot(pWin->parent)
- || IsTopLevel(pWin) || winRec == NULL)
- {
- goto out;
- }
-
- /* If the formerly top-level window has a frame, we want to give the
- frame to its new top-level parent. If we can't do that, we'll just
- have to jettison it... */
-
- pTopWin = TopLevelParent(pWin);
- assert(pTopWin != pWin);
-
- pWin->rootlessUnhittable = FALSE;
-
- DeleteProperty (serverClient, pWin, xa_native_window_id ());
-
- if (WINREC(pTopWin) != NULL) {
- /* We're screwed. */
- RootlessDestroyFrame(pWin, winRec);
- } else {
- if (!pTopWin->realized && pWin->realized) {
- SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid);
- }
-
- /* Switch the frame record from one to the other. */
-
- SETWINREC(pWin, NULL);
- SETWINREC(pTopWin, winRec);
-
- RootlessInitializeFrame(pTopWin, winRec);
- RootlessReshapeFrame(pTopWin);
-
- SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen,
- winRec->x + SCREEN_TO_GLOBAL_X,
- winRec->y + SCREEN_TO_GLOBAL_Y,
- winRec->width, winRec->height,
- RL_GRAVITY_NONE);
-
- if (SCREENREC(pScreen)->imp->SwitchWindow) {
- SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin);
- }
-
- if (pTopWin->realized && !pWin->realized)
- winRec->is_reorder_pending = TRUE;
- }
-
-out:
- if (SCREENREC(pScreen)->ReparentWindow) {
- SCREEN_UNWRAP(pScreen, ReparentWindow);
- pScreen->ReparentWindow(pWin, pPriorParent);
- SCREEN_WRAP(pScreen, ReparentWindow);
- }
-}
-
-
-void
-RootlessFlushWindowColormap (WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC (pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- if (winRec == NULL)
- return;
-
- RootlessStopDrawing (pWin, FALSE);
-
- if (SCREENREC(pScreen)->imp->UpdateColormap)
- SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen);
-}
-
-/*
- * RootlessChangeBorderWidth
- * FIXME: untested!
- * pWin inside corner stays the same; pWin->drawable.[xy] stays the same
- * Frame moves and resizes.
- */
-void
-RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width)
-{
- RegionRec saveRoot;
- Bool resize_after = FALSE;
-
- RL_DEBUG_MSG("change border width ");
-
- if (width != wBorderWidth(pWin)) {
- RootlessWindowRec *winRec = WINREC(pWin);
- int oldX = 0, oldY = 0, newX = 0, newY = 0;
- unsigned int oldW = 0, oldH = 0, oldBW = 0;
- unsigned int newW = 0, newH = 0, newBW = 0;
-
- if (winRec) {
- oldBW = winRec->borderWidth;
- oldX = winRec->x;
- oldY = winRec->y;
- oldW = winRec->width;
- oldH = winRec->height;
-
- newBW = width;
- newX = pWin->drawable.x - newBW;
- newY = pWin->drawable.y - newBW;
- newW = pWin->drawable.width + 2*newBW;
- newH = pWin->drawable.height + 2*newBW;
-
- resize_after = StartFrameResize(pWin, FALSE,
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
- }
-
- HUGE_ROOT(pWin);
- SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth);
- pWin->drawable.pScreen->ChangeBorderWidth(pWin, width);
- SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth);
- NORMAL_ROOT(pWin);
-
- if (winRec) {
- FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW, resize_after);
- }
- }
-
- RL_DEBUG_MSG("change border width end\n");
-}
-
-/*
- * RootlessOrderAllWindows
- * Brings all X11 windows to the top of the window stack
- * (i.e in front of Aqua windows) -- called when X11.app is given focus
- */
-void
-RootlessOrderAllWindows (Bool include_unhitable)
-{
- int i;
- WindowPtr pWin;
-
- if (windows_hidden)
- return;
-
- RL_DEBUG_MSG("RootlessOrderAllWindows() ");
- for (i = 0; i < screenInfo.numScreens; i++) {
- if (screenInfo.screens[i] == NULL) continue;
- pWin = screenInfo.screens[i]->root;
- if (pWin == NULL) continue;
-
- for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) {
- if (!pWin->realized) continue;
- if (RootlessEnsureFrame(pWin) == NULL) continue;
- if (!include_unhitable && pWin->rootlessUnhittable) continue;
- RootlessReorderWindow (pWin);
- }
- }
- RL_DEBUG_MSG("RootlessOrderAllWindows() done");
-}
-
-void
-RootlessEnableRoot (ScreenPtr pScreen)
-{
- WindowPtr pRoot;
- pRoot = pScreen->root;
-
- RootlessEnsureFrame (pRoot);
- (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
- RootlessReorderWindow (pRoot);
-}
-
-void
-RootlessDisableRoot (ScreenPtr pScreen)
-{
- WindowPtr pRoot;
- RootlessWindowRec *winRec;
-
- pRoot = pScreen->root;
- winRec = WINREC (pRoot);
-
- if (NULL == winRec)
- return;
-
- RootlessDestroyFrame (pRoot, winRec);
- DeleteProperty (serverClient, pRoot, xa_native_window_id ());
-}
-
-void
-RootlessHideAllWindows (void)
-{
- int i;
- ScreenPtr pScreen;
- WindowPtr pWin;
- RootlessWindowRec *winRec;
-
- if (windows_hidden)
- return;
-
- windows_hidden = TRUE;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
- if (pScreen == NULL)
- continue;
- pWin = pScreen->root;
- if (pWin == NULL)
- continue;
-
- for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
- {
- if (!pWin->realized)
- continue;
-
- RootlessStopDrawing (pWin, FALSE);
-
- winRec = WINREC (pWin);
- if (winRec != NULL)
- {
- if (SCREENREC(pScreen)->imp->HideWindow)
- SCREENREC(pScreen)->imp->HideWindow(winRec->wid);
- }
- }
- }
-}
-
-void
-RootlessShowAllWindows (void)
-{
- int i;
- ScreenPtr pScreen;
- WindowPtr pWin;
- RootlessWindowRec *winRec;
-
- if (!windows_hidden)
- return;
-
- windows_hidden = FALSE;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
- if (pScreen == NULL)
- continue;
- pWin = pScreen->root;
- if (pWin == NULL)
- continue;
-
- for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
- {
- if (!pWin->realized)
- continue;
-
- winRec = RootlessEnsureFrame (pWin);
- if (winRec == NULL)
- continue;
-
- RootlessReorderWindow (pWin);
- }
-
- RootlessScreenExpose (pScreen);
- }
-}
-
-/*
- * SetPixmapOfAncestors
- * Set the Pixmaps on all ParentRelative windows up the ancestor chain.
- */
-void
-RootlessSetPixmapOfAncestors(WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- WindowPtr topWin = TopLevelParent(pWin);
- RootlessWindowRec *topWinRec = WINREC(topWin);
-
- while (pWin->backgroundState == ParentRelative) {
- if (pWin == topWin) {
- // disallow ParentRelative background state on top level
- XID pixel = 0;
- ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
- RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
- break;
- }
-
- pWin = pWin->parent;
- pScreen->SetWindowPixmap(pWin, topWinRec->pixmap);
- }
-}
-
+/* + * Rootless window management + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. + * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stddef.h> /* For NULL */ +#include <limits.h> /* For CHAR_BIT */ +#include <assert.h> +#include <X11/Xatom.h> +#ifdef __APPLE__ +#include <Xplugin.h> +#include "mi.h" +#include "pixmapstr.h" +#include "windowstr.h" +//#include <X11/extensions/applewm.h> +extern int darwinMainScreenX, darwinMainScreenY; +extern Bool no_configure_window; +#endif +#include "fb.h" + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +#ifdef _MSC_VER +#define inline __inline +#include "xplugin.h" +extern int darwinMainScreenX, darwinMainScreenY; +#endif + +#define SCREEN_TO_GLOBAL_X \ + (pScreen->x + rootlessGlobalOffsetX) +#define SCREEN_TO_GLOBAL_Y \ + (pScreen->y + rootlessGlobalOffsetY) + +#define DEFINE_ATOM_HELPER(func,atom_name) \ + static Atom func (void) { \ + static unsigned int generation = 0; \ + static Atom atom; \ + if (generation != serverGeneration) { \ + generation = serverGeneration; \ + atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ + } \ + return atom; \ + } + +DEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID") + +static Bool windows_hidden; + +// TODO - abstract xp functions + +#ifdef __APPLE__ + +// XXX: identical to x_cvt_vptr_to_uint ? +#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) + +void +RootlessNativeWindowStateChanged(WindowPtr pWin, unsigned int state) +{ + RootlessWindowRec *winRec; + + if (pWin == NULL) + return; + + winRec = WINREC(pWin); + if (winRec == NULL) + return; + + winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); + winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); + pWin->rootlessUnhittable = winRec->is_offscreen; +} + +void +RootlessNativeWindowMoved(WindowPtr pWin) +{ + xp_box bounds; + int sx, sy, err; + XID vlist[2]; + Mask mask; + ClientPtr pClient; + RootlessWindowRec *winRec; + + winRec = WINREC(pWin); + + if (xp_get_window_bounds(MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) + return; + + sx = pWin->drawable.pScreen->x + darwinMainScreenX; + sy = pWin->drawable.pScreen->y + darwinMainScreenY; + + /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ + vlist[0] = (INT16) bounds.x1 - sx; + vlist[1] = (INT16) bounds.y1 - sy; + mask = CWX | CWY; + + /* pretend we're the owner of the window! */ + err = + dixLookupClient(&pClient, pWin->drawable.id, serverClient, + DixUnknownAccess); + if (err != Success) { + ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", + (unsigned int) pWin->drawable.id); + return; + } + + /* Don't want to do anything to the physical window (avoids + notification-response feedback loops) */ + + no_configure_window = TRUE; + ConfigureWindow(pWin, mask, vlist, pClient); + no_configure_window = FALSE; +} + +#endif /* __APPLE__ */ + +/* + * RootlessCreateWindow + * For now, don't create a physical window until either the window is + * realized, or we really need it (e.g. to attach VRAM surfaces to). + * Do reset the window size so it's not clipped by the root window. + */ +Bool +RootlessCreateWindow(WindowPtr pWin) +{ + Bool result; + RegionRec saveRoot; + + SETWINREC(pWin, NULL); + dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); + + SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); + + if (!IsRoot(pWin)) { + /* win/border size set by DIX, not by wrapped CreateWindow, so + correct it here. Don't HUGE_ROOT when pWin is the root! */ + + HUGE_ROOT(pWin); + SetWinSize(pWin); + SetBorderSize(pWin); + } + + result = pWin->drawable.pScreen->CreateWindow(pWin); + + if (pWin->parent) { + NORMAL_ROOT(pWin); + } + + SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); + + return result; +} + +/* + * RootlessDestroyFrame + * Destroy the physical window associated with the given window. + */ +static void +RootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) +{ + SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid); + free(winRec); + SETWINREC(pWin, NULL); +} + +/* + * RootlessDestroyWindow + * Destroy the physical window associated with the given window. + */ +Bool +RootlessDestroyWindow(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + Bool result; + + if (winRec != NULL) { + RootlessDestroyFrame(pWin, winRec); + } + + SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); + result = pWin->drawable.pScreen->DestroyWindow(pWin); + SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); + + return result; +} + +static Bool +RootlessGetShape(WindowPtr pWin, RegionPtr pShape) +{ + if (wBoundingShape(pWin) == NULL) + return FALSE; + + /* wBoundingShape is relative to *inner* origin of window. + Translate by borderWidth to get the outside-relative position. */ + + RegionNull(pShape); + RegionCopy(pShape, wBoundingShape(pWin)); + RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth); + + return TRUE; +} + +/* + * RootlessReshapeFrame + * Set the frame shape. + */ +static void +RootlessReshapeFrame(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + RegionRec newShape; + RegionPtr pShape; + + // If the window is not yet framed, do nothing + if (winRec == NULL) + return; + + if (IsRoot(pWin)) + return; + + RootlessStopDrawing(pWin, FALSE); + + pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; + +#ifdef ROOTLESSDEBUG + RL_DEBUG_MSG("reshaping..."); + if (pShape != NULL) { + RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", + RegionNumRects(&newShape), + newShape.extents.x1, newShape.extents.y1, + newShape.extents.x2, newShape.extents.y2); + } + else { + RL_DEBUG_MSG("no shape "); + } +#endif + + SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape); + + if (pShape != NULL) + RegionUninit(&newShape); +} + +/* + * RootlessSetShape + * Shape is usually set before a window is mapped and the window will + * not have a frame associated with it. In this case, the frame will be + * shaped when the window is framed. + */ +void +RootlessSetShape(WindowPtr pWin, int kind) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + SCREEN_UNWRAP(pScreen, SetShape); + pScreen->SetShape(pWin, kind); + SCREEN_WRAP(pScreen, SetShape); + + RootlessReshapeFrame(pWin); +} + +/* Disallow ParentRelative background on top-level windows + because the root window doesn't really have the right background. + */ +Bool +RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) +{ + Bool result; + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("change window attributes start "); + + SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); + result = pScreen->ChangeWindowAttributes(pWin, vmask); + SCREEN_WRAP(pScreen, ChangeWindowAttributes); + + if (WINREC(pWin)) { + // disallow ParentRelative background state + if (pWin->backgroundState == ParentRelative) { + XID pixel = 0; + + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + } + } + + RL_DEBUG_MSG("change window attributes end\n"); + return result; +} + +/* + * RootlessPositionWindow + * This is a hook for when DIX moves or resizes a window. + * Update the frame position now although the physical window is moved + * in RootlessMoveWindow. (x, y) are *inside* position. After this, + * mi and fb are expecting the pixmap to be at the new location. + */ +Bool +RootlessPositionWindow(WindowPtr pWin, int x, int y) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + Bool result; + + RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); + + if (winRec) { + if (winRec->is_drawing) { + // Reset frame's pixmap and move it to the new position. + int bw = wBorderWidth(pWin); + + winRec->pixmap->devPrivate.ptr = winRec->pixelData; + SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); + } + } + + SCREEN_UNWRAP(pScreen, PositionWindow); + result = pScreen->PositionWindow(pWin, x, y); + SCREEN_WRAP(pScreen, PositionWindow); + + RL_DEBUG_MSG("positionwindow end\n"); + return result; +} + +/* + * RootlessInitializeFrame + * Initialize some basic attributes of the frame. Note that winRec + * may already have valid data in it, so don't overwrite anything + * valuable. + */ +static void +RootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec * winRec) +{ + DrawablePtr d = &pWin->drawable; + int bw = wBorderWidth(pWin); + + winRec->win = pWin; + + winRec->x = d->x - bw; + winRec->y = d->y - bw; + winRec->width = d->width + 2 * bw; + winRec->height = d->height + 2 * bw; + winRec->borderWidth = bw; +} + +/* + * RootlessEnsureFrame + * Make sure the given window is framed. If the window doesn't have a + * physical window associated with it, attempt to create one. If that + * is unsuccessful, return NULL. + */ +static RootlessWindowRec * +RootlessEnsureFrame(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec; + RegionRec shape; + RegionPtr pShape = NULL; + + if (WINREC(pWin) != NULL) + return WINREC(pWin); + + if (!IsTopLevel(pWin) && !IsRoot(pWin)) + return NULL; + + if (pWin->drawable.class != InputOutput) + return NULL; + + winRec = malloc(sizeof(RootlessWindowRec)); + + if (!winRec) + return NULL; + + RootlessInitializeFrame(pWin, winRec); + + winRec->is_drawing = FALSE; + winRec->is_reorder_pending = FALSE; + winRec->pixmap = NULL; + winRec->wid = NULL; + winRec->level = 0; + + SETWINREC(pWin, winRec); + + // Set the frame's shape if the window is shaped + if (RootlessGetShape(pWin, &shape)) + pShape = &shape; + + RL_DEBUG_MSG("creating frame "); + + if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, + winRec->x + SCREEN_TO_GLOBAL_X, + winRec->y + SCREEN_TO_GLOBAL_Y, + pShape)) { + RL_DEBUG_MSG("implementation failed to create frame!\n"); + free(winRec); + SETWINREC(pWin, NULL); + return NULL; + } + + if (pWin->drawable.depth == 8) + RootlessFlushWindowColormap(pWin); + + if (pShape != NULL) + RegionUninit(&shape); + + return winRec; +} + +/* + * RootlessRealizeWindow + * The frame is usually created here and not in CreateWindow so that + * windows do not eat memory until they are realized. + */ +Bool +RootlessRealizeWindow(WindowPtr pWin) +{ + Bool result; + RegionRec saveRoot; + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); + + if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { + RootlessWindowRec *winRec; + + winRec = RootlessEnsureFrame(pWin); + if (winRec == NULL) + return FALSE; + + winRec->is_reorder_pending = TRUE; + + RL_DEBUG_MSG("Top level window "); + + // Disallow ParentRelative background state on top-level windows. + // This might have been set before the window was mapped. + if (pWin->backgroundState == ParentRelative) { + XID pixel = 0; + + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + } + } + + if (!IsRoot(pWin)) + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, RealizeWindow); + result = pScreen->RealizeWindow(pWin); + SCREEN_WRAP(pScreen, RealizeWindow); + if (!IsRoot(pWin)) + NORMAL_ROOT(pWin); + + RL_DEBUG_MSG("realizewindow end\n"); + return result; +} + +/* + * RootlessFrameForWindow + * Returns the frame ID for the physical window displaying the given window. + * If CREATE is true and the window has no frame, attempt to create one. + */ +RootlessFrameID +RootlessFrameForWindow(WindowPtr pWin, Bool create) +{ + WindowPtr pTopWin; + RootlessWindowRec *winRec; + + pTopWin = TopLevelParent(pWin); + if (pTopWin == NULL) + return NULL; + + winRec = WINREC(pTopWin); + + if (winRec == NULL && create && pWin->drawable.class == InputOutput) { + winRec = RootlessEnsureFrame(pTopWin); + } + + if (winRec == NULL) + return NULL; + + return winRec->wid; +} + +/* + * RootlessUnrealizeWindow + * Unmap the physical window. + */ +Bool +RootlessUnrealizeWindow(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + Bool result; + + RL_DEBUG_MSG("unrealizewindow start "); + + if (winRec) { + RootlessStopDrawing(pWin, FALSE); + + SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); + + winRec->is_reorder_pending = FALSE; + } + + SCREEN_UNWRAP(pScreen, UnrealizeWindow); + result = pScreen->UnrealizeWindow(pWin); + SCREEN_WRAP(pScreen, UnrealizeWindow); + + RL_DEBUG_MSG("unrealizewindow end\n"); + return result; +} + +/* + * RootlessReorderWindow + * Reorder the frame associated with the given window so that it's + * physically above the window below it in the X stacking order. + */ +void +RootlessReorderWindow(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + + if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && + !windows_hidden) { + WindowPtr newPrevW; + RootlessWindowRec *newPrev; + RootlessFrameID newPrevID; + ScreenPtr pScreen = pWin->drawable.pScreen; + + /* Check if the implementation wants the frame to not be reordered + even though the X11 window is restacked. This can be useful if + frames are ordered-in with animation so that the reordering is not + done until the animation is complete. */ + if (SCREENREC(pScreen)->imp->DoReorderWindow) { + if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) + return; + } + + RootlessStopDrawing(pWin, FALSE); + + /* Find the next window above this one that has a mapped frame. + * Only include cases where the windows are in the same category of + * hittability to ensure offscreen windows dont get restacked + * relative to onscreen ones (but that the offscreen ones maintain + * their stacking order if they are explicitly asked to Reorder + */ + + newPrevW = pWin->prevSib; + while (newPrevW && + (WINREC(newPrevW) == NULL || !newPrevW->realized || + newPrevW->rootlessUnhittable != pWin->rootlessUnhittable)) + newPrevW = newPrevW->prevSib; + + newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; + newPrevID = newPrev != NULL ? newPrev->wid : 0; + + /* If it exists, reorder the frame above us first. */ + + if (newPrev && newPrev->is_reorder_pending) { + newPrev->is_reorder_pending = FALSE; + RootlessReorderWindow(newPrevW); + } + + SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); + } +} + +/* + * RootlessRestackWindow + * This is a hook for when DIX changes the window stacking order. + * The window has already been inserted into its new position in the + * DIX window stack. We need to change the order of the physical + * window to match. + */ +void +RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) +{ + RegionRec saveRoot; + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + RL_DEBUG_MSG("restackwindow start "); + if (winRec) + RL_DEBUG_MSG("restack top level \n"); + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, RestackWindow); + + if (pScreen->RestackWindow) + pScreen->RestackWindow(pWin, pOldNextSib); + + SCREEN_WRAP(pScreen, RestackWindow); + NORMAL_ROOT(pWin); + + if (winRec && pWin->viewable) { + RootlessReorderWindow(pWin); + } + + RL_DEBUG_MSG("restackwindow end\n"); +} + +/* + * Specialized window copy procedures + */ + +// Globals needed during window resize and move. +static pointer gResizeDeathBits = NULL; +static int gResizeDeathCount = 0; +static PixmapPtr gResizeDeathPix[2] = { NULL, NULL }; + +static BoxRec gResizeDeathBounds[2]; +static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; + +/* + * RootlessNoCopyWindow + * CopyWindow() that doesn't do anything. For MoveWindow() of + * top-level windows. + */ +static void +RootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + // some code expects the region to be translated + int dx = ptOldOrg.x - pWin->drawable.x; + int dy = ptOldOrg.y - pWin->drawable.y; + + RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); + + RegionTranslate(prgnSrc, -dx, -dy); +} + +/* + * RootlessResizeCopyWindow + * CopyWindow used during ResizeWindow for gravity moves. Based on + * fbCopyWindow. The original always draws on the root pixmap, which + * we don't have. Instead, draw on the parent window's pixmap. + * Resize version: the old location's pixels are in gResizeCopyWindowSource. + */ +static void +RootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec rgnDst; + int dx, dy; + + RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); + + /* Don't unwrap pScreen->CopyWindow. + The bogus rewrap with RootlessCopyWindow causes a crash if + CopyWindow is called again during the same resize. */ + + if (gResizeDeathCount == 0) + return; + + RootlessStartDrawing(pWin); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + RegionTranslate(prgnSrc, -dx, -dy); + RegionNull(&rgnDst); + RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); + + if (gResizeDeathCount == 1) { + /* Simple case, we only have a single source pixmap. */ + + miCopyRegion(&gResizeDeathPix[0]->drawable, + &pScreen->GetWindowPixmap(pWin)->drawable, 0, + &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + } + else { + int i; + RegionRec clip, clipped; + + /* More complex case, N source pixmaps (usually two). So we + intersect the destination with each source and copy those bits. */ + + for (i = 0; i < gResizeDeathCount; i++) { + RegionInit(&clip, gResizeDeathBounds + 0, 1); + RegionNull(&clipped); + RegionIntersect(&rgnDst, &clip, &clipped); + + miCopyRegion(&gResizeDeathPix[i]->drawable, + &pScreen->GetWindowPixmap(pWin)->drawable, 0, + &clipped, dx, dy, fbCopyWindowProc, 0, 0); + + RegionUninit(&clipped); + RegionUninit(&clip); + } + } + + /* Don't update - resize will update everything */ + RegionUninit(&rgnDst); + + fbValidateDrawable(&pWin->drawable); + + RL_DEBUG_MSG("resizecopywindowFB end\n"); +} + +/* + * RootlessCopyWindow + * Update *new* location of window. Old location is redrawn with + * miPaintWindow. Cloned from fbCopyWindow. + * The original always draws on the root pixmap, which we don't have. + * Instead, draw on the parent window's pixmap. + */ +void +RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RegionRec rgnDst; + int dx, dy; + BoxPtr extents; + int area; + + RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); + + SCREEN_UNWRAP(pScreen, CopyWindow); + + dx = ptOldOrg.x - pWin->drawable.x; + dy = ptOldOrg.y - pWin->drawable.y; + RegionTranslate(prgnSrc, -dx, -dy); + + RegionNull(&rgnDst); + RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); + + extents = RegionExtents(&rgnDst); + area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); + + /* If the area exceeds threshold, use the implementation's + accelerated version. */ + if (area > rootless_CopyWindow_threshold && + SCREENREC(pScreen)->imp->CopyWindow) { + RootlessWindowRec *winRec; + WindowPtr top; + + top = TopLevelParent(pWin); + if (top == NULL) { + RL_DEBUG_MSG("no parent\n"); + goto out; + } + + winRec = WINREC(top); + if (winRec == NULL) { + RL_DEBUG_MSG("not framed\n"); + goto out; + } + + /* Move region to window local coords */ + RegionTranslate(&rgnDst, -winRec->x, -winRec->y); + + RootlessStopDrawing(pWin, FALSE); + + SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, + RegionNumRects(&rgnDst), + RegionRects(&rgnDst), dx, dy); + } + else { + RootlessStartDrawing(pWin); + + miCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, + 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); + + /* prgnSrc has been translated to dst position */ + RootlessDamageRegion(pWin, prgnSrc); + } + + out: + RegionUninit(&rgnDst); + fbValidateDrawable(&pWin->drawable); + + SCREEN_WRAP(pScreen, CopyWindow); + + RL_DEBUG_MSG("copywindowFB end\n"); +} + +/* + * Window resize procedures + */ + +enum { + WIDTH_SMALLER = 1, + HEIGHT_SMALLER = 2, +}; + +/* + * ResizeWeighting + * Choose gravity to avoid local copies. Do that by looking for + * a corner that doesn't move _relative to the screen_. + */ +static inline unsigned int +ResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, + int newX1, int newY1, int newX2, int newY2, int newBW) +{ +#ifdef ROOTLESS_RESIZE_GRAVITY + if (newBW != oldBW) + return RL_GRAVITY_NONE; + + if (newX1 == oldX1 && newY1 == oldY1) + return RL_GRAVITY_NORTH_WEST; + else if (newX1 == oldX1 && newY2 == oldY2) + return RL_GRAVITY_SOUTH_WEST; + else if (newX2 == oldX2 && newY2 == oldY2) + return RL_GRAVITY_SOUTH_EAST; + else if (newX2 == oldX2 && newY1 == oldY1) + return RL_GRAVITY_NORTH_EAST; + else + return RL_GRAVITY_NONE; +#else + return RL_GRAVITY_NONE; +#endif +} + +/* + * StartFrameResize + * Prepare to resize a top-level window. The old window's pixels are + * saved and the implementation is told to change the window size. + * (x,y,w,h) is outer frame of window (outside border) + */ +static Bool +StartFrameResize(WindowPtr pWin, Bool gravity, + int oldX, int oldY, int oldW, int oldH, int oldBW, + int newX, int newY, int newW, int newH, int newBW) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + Bool need_window_source = FALSE, resize_after = FALSE; + + BoxRec rect; + int oldX2, newX2; + int oldY2, newY2; + unsigned int weight; + + oldX2 = oldX + oldW, newX2 = newX + newW; + oldY2 = oldY + oldH, newY2 = newY + newH; + + /* Decide which resize weighting to use */ + weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + + /* Compute intersection between old and new rects */ + rect.x1 = max(oldX, newX); + rect.y1 = max(oldY, newY); + rect.x2 = min(oldX2, newX2); + rect.y2 = min(oldY2, newY2); + + RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); + RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", + oldX, oldY, oldW, oldH, oldBW, newX, newY, newW, newH, newBW); + + RootlessRedisplay(pWin); + + /* If gravity is true, then we need to have a way of recovering all + the original bits in the window for when X rearranges the contents + based on the various gravity settings. The obvious way is to just + snapshot the entire backing store before resizing it, but that + it slow on large windows. + + So the optimization here is to use the implementation's resize + weighting options (if available) to allow us to reason about what + is left in the backing store after the resize. We can then only + copy what won't be there after the resize, and do a two-stage copy + operation. + + Most of these optimizations are only applied when the top-left + corner of the window is fixed, since that's the common case. They + could probably be extended with some thought. */ + + gResizeDeathCount = 0; + + if (gravity && weight == RL_GRAVITY_NORTH_WEST) { + unsigned int code = 0; + + /* Top left corner is anchored. We never need to copy the + entire window. */ + + need_window_source = TRUE; + + /* These comparisons were chosen to avoid setting bits when the sizes + are the same. (So the fastest case automatically gets taken when + dimensions are unchanging.) */ + + if (newW < oldW) + code |= WIDTH_SMALLER; + if (newH < oldH) + code |= HEIGHT_SMALLER; + + if (((code ^ (code >> 1)) & 1) == 0) { + /* Both dimensions are either getting larger, or both + are getting smaller. No need to copy anything. */ + + if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { + /* Since the window is getting smaller, we can do gravity + repair on it with it's current size, then resize it + afterwards. */ + + resize_after = TRUE; + } + + gResizeDeathCount = 1; + } + else { + unsigned int copy_rowbytes, Bpp; + unsigned int copy_rect_width, copy_rect_height; + BoxRec copy_rect; + + /* We can get away with a partial copy. 'rect' is the + intersection between old and new bounds, so copy + everything to the right of or below the intersection. */ + + RootlessStartDrawing(pWin); + + if (code == WIDTH_SMALLER) { + copy_rect.x1 = rect.x2; + copy_rect.y1 = rect.y1; + copy_rect.x2 = oldX2; + copy_rect.y2 = oldY2; + } + else if (code == HEIGHT_SMALLER) { + copy_rect.x1 = rect.x1; + copy_rect.y1 = rect.y2; + copy_rect.x2 = oldX2; + copy_rect.y2 = oldY2; + } + else + OsAbort(); + + Bpp = winRec->win->drawable.bitsPerPixel / 8; + copy_rect_width = copy_rect.x2 - copy_rect.x1; + copy_rect_height = copy_rect.y2 - copy_rect.y1; + copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; + gResizeDeathBits = malloc(copy_rowbytes * copy_rect_height); + + if (copy_rect_width * copy_rect_height > + rootless_CopyBytes_threshold && + SCREENREC(pScreen)->imp->CopyBytes) { + SCREENREC(pScreen)->imp->CopyBytes(copy_rect_width * Bpp, + copy_rect_height, + ((char *) winRec->pixelData) + + + ((copy_rect.y1 - + oldY) * + winRec->bytesPerRow) + + (copy_rect.x1 - + oldX) * Bpp, + winRec->bytesPerRow, + gResizeDeathBits, + copy_rowbytes); + } + else { + fbBlt((FbBits *) (winRec->pixelData + + + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) + + (copy_rect.x1 - oldX) * Bpp), + winRec->bytesPerRow / sizeof(FbBits), 0, + (FbBits *) gResizeDeathBits, + copy_rowbytes / sizeof(FbBits), 0, copy_rect_width * Bpp, + copy_rect_height, GXcopy, FB_ALLONES, Bpp, 0, 0); + } + + gResizeDeathBounds[1] = copy_rect; + gResizeDeathPix[1] + = GetScratchPixmapHeader(pScreen, copy_rect_width, + copy_rect_height, + winRec->win->drawable.depth, + winRec->win->drawable.bitsPerPixel, + winRec->bytesPerRow, + (void *) gResizeDeathBits); + + SetPixmapBaseToScreen(gResizeDeathPix[1], + copy_rect.x1, copy_rect.y1); + + gResizeDeathCount = 2; + } + } + else if (gravity) { + /* The general case. Just copy everything. */ + BoxRec tmpBoxRec={oldX, oldY, oldX2, oldY2}; + + RootlessStartDrawing(pWin); + + gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); + + memcpy(gResizeDeathBits, winRec->pixelData, + winRec->bytesPerRow * winRec->height); + + gResizeDeathBounds[0] = tmpBoxRec; + gResizeDeathPix[0] + = GetScratchPixmapHeader(pScreen, winRec->width, + winRec->height, + winRec->win->drawable.depth, + winRec->win->drawable.bitsPerPixel, + winRec->bytesPerRow, + (void *) gResizeDeathBits); + + SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); + gResizeDeathCount = 1; + } + + RootlessStopDrawing(pWin, FALSE); + + winRec->x = newX; + winRec->y = newY; + winRec->width = newW; + winRec->height = newH; + winRec->borderWidth = newBW; + + /* Unless both dimensions are getting smaller, Resize the frame + before doing gravity repair */ + + if (!resize_after) { + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + newX + SCREEN_TO_GLOBAL_X, + newY + SCREEN_TO_GLOBAL_Y, + newW, newH, weight); + } + + RootlessStartDrawing(pWin); + + /* If necessary, create a source pixmap pointing at the current + window bits. */ + + if (need_window_source) { + BoxRec tmpBoxRec={oldX, oldY, oldX2, oldY2}; + gResizeDeathBounds[0] = tmpBoxRec; + gResizeDeathPix[0] + = GetScratchPixmapHeader(pScreen, oldW, oldH, + winRec->win->drawable.depth, + winRec->win->drawable.bitsPerPixel, + winRec->bytesPerRow, winRec->pixelData); + + SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); + } + + /* Use custom CopyWindow when moving gravity bits around + ResizeWindow assumes the old window contents are in the same + pixmap, but here they're in deathPix instead. */ + + if (gravity) { + gResizeOldCopyWindowProc = pScreen->CopyWindow; + pScreen->CopyWindow = RootlessResizeCopyWindow; + } + + /* If we can't rely on the window server preserving the bits we + need in the position we need, copy the pixels in the + intersection from src to dst. ResizeWindow assumes these pixels + are already present when making gravity adjustments. pWin + currently has new-sized pixmap but is in old position. + + FIXME: border width change! (?) */ + + if (gravity && weight == RL_GRAVITY_NONE) { + PixmapPtr src, dst; + + assert(gResizeDeathCount == 1); + + src = gResizeDeathPix[0]; + dst = pScreen->GetWindowPixmap(pWin); + + RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", + rect.x1, rect.y1, rect.x2, rect.y2); + + /* rect is the intersection of the old location and new location */ + if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { + /* The window drawable still has the old frame position, which + means that DST doesn't actually point at the origin of our + physical backing store when adjusted by the drawable.x,y + position. So sneakily adjust it temporarily while copying.. */ + + ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; + SetPixmapBaseToScreen(dst, newX, newY); + + fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, + &rect, 1, 0, 0, FALSE, FALSE, 0, 0); + + ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; + SetPixmapBaseToScreen(dst, oldX, oldY); + } + } + + return resize_after; +} + +static void +FinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, + unsigned int oldW, unsigned int oldH, unsigned int oldBW, + int newX, int newY, unsigned int newW, unsigned int newH, + unsigned int newBW, Bool resize_now) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + int i; + + RootlessStopDrawing(pWin, FALSE); + + if (resize_now) { + unsigned int weight; + + /* We didn't resize anything earlier, so do it now, now that + we've finished gravitating the bits. */ + + weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + newX + SCREEN_TO_GLOBAL_X, + newY + SCREEN_TO_GLOBAL_Y, + newW, newH, weight); + } + + /* Redraw everything. FIXME: there must be times when we don't need + to do this. Perhaps when top-left weighting and no gravity? */ + + RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); + + for (i = 0; i < 2; i++) { + if (gResizeDeathPix[i] != NULL) { + FreeScratchPixmapHeader(gResizeDeathPix[i]); + gResizeDeathPix[i] = NULL; + } + } + + free(gResizeDeathBits); + gResizeDeathBits = NULL; + + if (gravity) { + pScreen->CopyWindow = gResizeOldCopyWindowProc; + } +} + +/* + * RootlessMoveWindow + * If kind==VTOther, window border is resizing (and borderWidth is + * already changed!!@#$) This case works like window resize, not move. + */ +void +RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + CopyWindowProcPtr oldCopyWindowProc = NULL; + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0; + unsigned int newW = 0, newH = 0, newBW = 0; + Bool resize_after = FALSE; + RegionRec saveRoot; + + RL_DEBUG_MSG("movewindow start \n"); + + if (winRec) { + if (kind == VTMove) { + oldX = winRec->x; + oldY = winRec->y; + RootlessRedisplay(pWin); + RootlessStartDrawing(pWin); + } + else { + RL_DEBUG_MSG("movewindow border resizing "); + + oldBW = winRec->borderWidth; + oldX = winRec->x; + oldY = winRec->y; + oldW = winRec->width; + oldH = winRec->height; + + newBW = wBorderWidth(pWin); + newX = x; + newY = y; + newW = pWin->drawable.width + 2 * newBW; + newH = pWin->drawable.height + 2 * newBW; + + resize_after = StartFrameResize(pWin, FALSE, + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, MoveWindow); + + if (winRec) { + oldCopyWindowProc = pScreen->CopyWindow; + pScreen->CopyWindow = RootlessNoCopyWindow; + } + pScreen->MoveWindow(pWin, x, y, pSib, kind); + if (winRec) { + pScreen->CopyWindow = oldCopyWindowProc; + } + + NORMAL_ROOT(pWin); + SCREEN_WRAP(pScreen, MoveWindow); + + if (winRec) { + if (kind == VTMove) { + winRec->x = x; + winRec->y = y; + RootlessStopDrawing(pWin, FALSE); + SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, + x + SCREEN_TO_GLOBAL_X, + y + SCREEN_TO_GLOBAL_Y); + } + else { + FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW, resize_after); + } + } + + RL_DEBUG_MSG("movewindow end\n"); +} + +/* + * RootlessResizeWindow + * Note: (x, y, w, h) as passed to this procedure don't match the frame + * definition. (x,y) is corner of very outer edge, *outside* border. + * w,h is width and height *inside* border, *ignoring* border width. + * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) + * is total rect and (x+bw, y+bw, w, h) is inner rect. + */ +void +RootlessResizeWindow(WindowPtr pWin, int x, int y, + unsigned int w, unsigned int h, WindowPtr pSib) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; + Bool resize_after = FALSE; + RegionRec saveRoot; + + RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); + + if (pWin->parent) { + if (winRec) { + oldBW = winRec->borderWidth; + oldX = winRec->x; + oldY = winRec->y; + oldW = winRec->width; + oldH = winRec->height; + + newBW = oldBW; + newX = x; + newY = y; + newW = w + 2 * newBW; + newH = h + 2 * newBW; + + resize_after = StartFrameResize(pWin, TRUE, + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pScreen, ResizeWindow); + pScreen->ResizeWindow(pWin, x, y, w, h, pSib); + SCREEN_WRAP(pScreen, ResizeWindow); + NORMAL_ROOT(pWin); + + if (winRec) { + FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW, resize_after); + } + } + else { + /* Special case for resizing the root window */ + BoxRec box; + + pWin->drawable.x = x; + pWin->drawable.y = y; + pWin->drawable.width = w; + pWin->drawable.height = h; + + box.x1 = x; + box.y1 = y; + box.x2 = x + w; + box.y2 = y + h; + RegionUninit(&pWin->winSize); + RegionInit(&pWin->winSize, &box, 1); + RegionCopy(&pWin->borderSize, &pWin->winSize); + RegionCopy(&pWin->clipList, &pWin->winSize); + RegionCopy(&pWin->borderClip, &pWin->winSize); + + if (winRec) { + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + x + SCREEN_TO_GLOBAL_X, + y + SCREEN_TO_GLOBAL_Y, + w, h, RL_GRAVITY_NONE); + } + + miSendExposures(pWin, &pWin->borderClip, + pWin->drawable.x, pWin->drawable.y); + } + + RL_DEBUG_MSG("resizewindow end\n"); +} + +/* + * RootlessRepositionWindow + * Called by the implementation when a window needs to be repositioned to + * its correct location on the screen. This routine is typically needed + * due to changes in the underlying window system, such as a screen layout + * change. + */ +void +RootlessRepositionWindow(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (winRec == NULL) + return; + + RootlessStopDrawing(pWin, FALSE); + SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, + winRec->x + SCREEN_TO_GLOBAL_X, + winRec->y + SCREEN_TO_GLOBAL_Y); + + RootlessReorderWindow(pWin); +} + +/* + * RootlessReparentWindow + * Called after a window has been reparented. Generally windows are not + * framed until they are mapped. However, a window may be framed early by the + * implementation calling RootlessFrameForWindow. (e.g. this could be needed + * to attach a VRAM surface to it.) If the window is subsequently reparented + * by the window manager before being mapped, we need to give the frame to + * the new top-level window. + */ +void +RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + RootlessWindowRec *winRec = WINREC(pWin); + WindowPtr pTopWin; + + /* Check that window is not top-level now, but used to be. */ + if (IsRoot(pWin) || IsRoot(pWin->parent) + || IsTopLevel(pWin) || winRec == NULL) { + goto out; + } + + /* If the formerly top-level window has a frame, we want to give the + frame to its new top-level parent. If we can't do that, we'll just + have to jettison it... */ + + pTopWin = TopLevelParent(pWin); + assert(pTopWin != pWin); + + pWin->rootlessUnhittable = FALSE; + + DeleteProperty(serverClient, pWin, xa_native_window_id()); + + if (WINREC(pTopWin) != NULL) { + /* We're screwed. */ + RootlessDestroyFrame(pWin, winRec); + } + else { + if (!pTopWin->realized && pWin->realized) { + SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); + } + + /* Switch the frame record from one to the other. */ + + SETWINREC(pWin, NULL); + SETWINREC(pTopWin, winRec); + + RootlessInitializeFrame(pTopWin, winRec); + RootlessReshapeFrame(pTopWin); + + SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, + winRec->x + SCREEN_TO_GLOBAL_X, + winRec->y + SCREEN_TO_GLOBAL_Y, + winRec->width, winRec->height, + RL_GRAVITY_NONE); + + if (SCREENREC(pScreen)->imp->SwitchWindow) { + SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); + } + + if (pTopWin->realized && !pWin->realized) + winRec->is_reorder_pending = TRUE; + } + + out: + if (SCREENREC(pScreen)->ReparentWindow) { + SCREEN_UNWRAP(pScreen, ReparentWindow); + pScreen->ReparentWindow(pWin, pPriorParent); + SCREEN_WRAP(pScreen, ReparentWindow); + } +} + +void +RootlessFlushWindowColormap(WindowPtr pWin) +{ + RootlessWindowRec *winRec = WINREC(pWin); + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (winRec == NULL) + return; + + RootlessStopDrawing(pWin, FALSE); + + if (SCREENREC(pScreen)->imp->UpdateColormap) + SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); +} + +/* + * RootlessChangeBorderWidth + * FIXME: untested! + * pWin inside corner stays the same; pWin->drawable.[xy] stays the same + * Frame moves and resizes. + */ +void +RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) +{ + RegionRec saveRoot; + Bool resize_after = FALSE; + + RL_DEBUG_MSG("change border width "); + + if (width != wBorderWidth(pWin)) { + RootlessWindowRec *winRec = WINREC(pWin); + int oldX = 0, oldY = 0, newX = 0, newY = 0; + unsigned int oldW = 0, oldH = 0, oldBW = 0; + unsigned int newW = 0, newH = 0, newBW = 0; + + if (winRec) { + oldBW = winRec->borderWidth; + oldX = winRec->x; + oldY = winRec->y; + oldW = winRec->width; + oldH = winRec->height; + + newBW = width; + newX = pWin->drawable.x - newBW; + newY = pWin->drawable.y - newBW; + newW = pWin->drawable.width + 2 * newBW; + newH = pWin->drawable.height + 2 * newBW; + + resize_after = StartFrameResize(pWin, FALSE, + oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW); + } + + HUGE_ROOT(pWin); + SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); + pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); + SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); + NORMAL_ROOT(pWin); + + if (winRec) { + FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, + newX, newY, newW, newH, newBW, resize_after); + } + } + + RL_DEBUG_MSG("change border width end\n"); +} + +/* + * RootlessOrderAllWindows + * Brings all X11 windows to the top of the window stack + * (i.e in front of Aqua windows) -- called when X11.app is given focus + */ +void +RootlessOrderAllWindows(Bool include_unhitable) +{ + int i; + WindowPtr pWin; + + if (windows_hidden) + return; + + RL_DEBUG_MSG("RootlessOrderAllWindows() "); + for (i = 0; i < screenInfo.numScreens; i++) { + if (screenInfo.screens[i] == NULL) + continue; + pWin = screenInfo.screens[i]->root; + if (pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { + if (!pWin->realized) + continue; + if (RootlessEnsureFrame(pWin) == NULL) + continue; + if (!include_unhitable && pWin->rootlessUnhittable) + continue; + RootlessReorderWindow(pWin); + } + } + RL_DEBUG_MSG("RootlessOrderAllWindows() done"); +} + +void +RootlessEnableRoot(ScreenPtr pScreen) +{ + WindowPtr pRoot; + + pRoot = pScreen->root; + + RootlessEnsureFrame(pRoot); + (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); + RootlessReorderWindow(pRoot); +} + +void +RootlessDisableRoot(ScreenPtr pScreen) +{ + WindowPtr pRoot; + RootlessWindowRec *winRec; + + pRoot = pScreen->root; + winRec = WINREC(pRoot); + + if (NULL == winRec) + return; + + RootlessDestroyFrame(pRoot, winRec); + DeleteProperty(serverClient, pRoot, xa_native_window_id()); +} + +void +RootlessHideAllWindows(void) +{ + int i; + ScreenPtr pScreen; + WindowPtr pWin; + RootlessWindowRec *winRec; + + if (windows_hidden) + return; + + windows_hidden = TRUE; + + for (i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if (pScreen == NULL) + continue; + pWin = pScreen->root; + if (pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { + if (!pWin->realized) + continue; + + RootlessStopDrawing(pWin, FALSE); + + winRec = WINREC(pWin); + if (winRec != NULL) { + if (SCREENREC(pScreen)->imp->HideWindow) + SCREENREC(pScreen)->imp->HideWindow(winRec->wid); + } + } + } +} + +void +RootlessShowAllWindows(void) +{ + int i; + ScreenPtr pScreen; + WindowPtr pWin; + RootlessWindowRec *winRec; + + if (!windows_hidden) + return; + + windows_hidden = FALSE; + + for (i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if (pScreen == NULL) + continue; + pWin = pScreen->root; + if (pWin == NULL) + continue; + + for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { + if (!pWin->realized) + continue; + + winRec = RootlessEnsureFrame(pWin); + if (winRec == NULL) + continue; + + RootlessReorderWindow(pWin); + } + + RootlessScreenExpose(pScreen); + } +} + +/* + * SetPixmapOfAncestors + * Set the Pixmaps on all ParentRelative windows up the ancestor chain. + */ +void +RootlessSetPixmapOfAncestors(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr topWin = TopLevelParent(pWin); + RootlessWindowRec *topWinRec = WINREC(topWin); + + while (pWin->backgroundState == ParentRelative) { + if (pWin == topWin) { + // disallow ParentRelative background state on top level + XID pixel = 0; + + ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); + RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); + break; + } + + pWin = pWin->parent; + pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); + } +} diff --git a/xorg-server/miext/rootless/rootlessWindow.h b/xorg-server/miext/rootless/rootlessWindow.h index 2da96e661..d3955fc89 100644 --- a/xorg-server/miext/rootless/rootlessWindow.h +++ b/xorg-server/miext/rootless/rootlessWindow.h @@ -1,60 +1,63 @@ -/*
- * Rootless window management
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef _ROOTLESSWINDOW_H
-#define _ROOTLESSWINDOW_H
-
-#include "rootlessCommon.h"
-
-Bool RootlessCreateWindow(WindowPtr pWin);
-Bool RootlessDestroyWindow(WindowPtr pWin);
-
-void RootlessSetShape(WindowPtr pWin, int kind);
-
-Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask);
-Bool RootlessPositionWindow(WindowPtr pWin, int x, int y);
-Bool RootlessRealizeWindow(WindowPtr pWin);
-Bool RootlessUnrealizeWindow(WindowPtr pWin);
-void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib);
-void RootlessCopyWindow(WindowPtr pWin,DDXPointRec ptOldOrg,RegionPtr prgnSrc);
-void RootlessMoveWindow(WindowPtr pWin,int x,int y,WindowPtr pSib,VTKind kind);
-void RootlessResizeWindow(WindowPtr pWin, int x, int y,
- unsigned int w, unsigned int h, WindowPtr pSib);
-void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent);
-void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width);
-#ifdef __APPLE__
-void RootlessNativeWindowMoved (WindowPtr pWin);
-void RootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state);
-#endif
-
-#endif
+/* + * Rootless window management + */ +/* + * Copyright (c) 2001 Greg Parker. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name(s) of the above copyright + * holders shall not be used in advertising or otherwise to promote the sale, + * use or other dealings in this Software without prior written authorization. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _ROOTLESSWINDOW_H +#define _ROOTLESSWINDOW_H + +#include "rootlessCommon.h" + +Bool RootlessCreateWindow(WindowPtr pWin); +Bool RootlessDestroyWindow(WindowPtr pWin); + +void RootlessSetShape(WindowPtr pWin, int kind); + +Bool RootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask); +Bool RootlessPositionWindow(WindowPtr pWin, int x, int y); +Bool RootlessRealizeWindow(WindowPtr pWin); +Bool RootlessUnrealizeWindow(WindowPtr pWin); +void RootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib); +void RootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, + RegionPtr prgnSrc); +void RootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, + VTKind kind); +void RootlessResizeWindow(WindowPtr pWin, int x, int y, unsigned int w, + unsigned int h, WindowPtr pSib); +void RootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent); +void RootlessChangeBorderWidth(WindowPtr pWin, unsigned int width); + +#ifdef __APPLE__ +void RootlessNativeWindowMoved(WindowPtr pWin); +void RootlessNativeWindowStateChanged(WindowPtr pWin, unsigned int state); +#endif + +#endif |