From 0f834b91a4768673833ab4917e87d86c237bb1a6 Mon Sep 17 00:00:00 2001 From: marha Date: Fri, 23 Mar 2012 10:05:55 +0100 Subject: libX11 xserver fontconfig mesa pixman xkbcomp xkeyboard-config git update 23 Mar 2012 --- xorg-server/miext/rootless/rootless.h | 731 +++--- xorg-server/miext/rootless/rootlessCommon.c | 908 +++---- xorg-server/miext/rootless/rootlessGC.c | 2947 +++++++++++------------ xorg-server/miext/rootless/rootlessScreen.c | 233 +- xorg-server/miext/rootless/rootlessValTree.c | 589 +++-- xorg-server/miext/rootless/rootlessWindow.c | 3275 +++++++++++++------------- xorg-server/miext/rootless/rootlessWindow.h | 123 +- 7 files changed, 4404 insertions(+), 4402 deletions(-) (limited to 'xorg-server/miext/rootless') 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 -#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 +#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 -#endif - -#include /* For NULL */ -#include /* 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 +#endif + +#include /* For NULL */ +#include /* 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 21a3bd806..932899591 100644 --- a/xorg-server/miext/rootless/rootlessGC.c +++ b/xorg-server/miext/rootless/rootlessGC.c @@ -1,1460 +1,1487 @@ -/* - * 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 -#endif - -#include /* 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 -#include -#include - -#include "rootlessCommon.h" - - -// 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 +#endif + +#include /* 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 +#include +#include + +#include "rootlessCommon.h" + +// 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 #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 #endif -#include /* For NULL */ +#include /* For NULL */ #include #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 20fdaba8d..cfcb6e558 100644 --- a/xorg-server/miext/rootless/rootlessWindow.c +++ b/xorg-server/miext/rootless/rootlessWindow.c @@ -1,1637 +1,1638 @@ -/* - * 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 -#endif - -#include /* For NULL */ -#include /* For CHAR_BIT */ -#include -#include -#ifdef __APPLE__ -#include -#include "mi.h" -#include "pixmapstr.h" -#include "windowstr.h" -//#include -extern int darwinMainScreenX, darwinMainScreenY; -extern Bool no_configure_window; -#endif -#include "fb.h" - -#include "rootlessCommon.h" -#include "rootlessWindow.h" - -#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. */ - - fbCopyRegion(&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); - - fbCopyRegion(&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); - - fbCopyRegion((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. */ - - RootlessStartDrawing(pWin); - - gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); - - memcpy(gResizeDeathBits, winRec->pixelData, - winRec->bytesPerRow * winRec->height); - - gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; - 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) { - gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; - 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 +#endif + +#include /* For NULL */ +#include /* For CHAR_BIT */ +#include +#include +#ifdef __APPLE__ +#include +#include "mi.h" +#include "pixmapstr.h" +#include "windowstr.h" +//#include +extern int darwinMainScreenX, darwinMainScreenY; +extern Bool no_configure_window; +#endif +#include "fb.h" + +#include "rootlessCommon.h" +#include "rootlessWindow.h" + +#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. */ + + fbCopyRegion(&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); + + fbCopyRegion(&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); + + fbCopyRegion((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. */ + + RootlessStartDrawing(pWin); + + gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); + + memcpy(gResizeDeathBits, winRec->pixelData, + winRec->bytesPerRow * winRec->height); + + gResizeDeathBounds[0] = (BoxRec) { + oldX, oldY, oldX2, oldY2}; + 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) { + gResizeDeathBounds[0] = (BoxRec) { + oldX, oldY, oldX2, oldY2}; + 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 -#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 +#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 -- cgit v1.2.3