rootlessWindow.c revision 05b261ec
105b261ecSmrg/* 205b261ecSmrg * Rootless window management 305b261ecSmrg */ 405b261ecSmrg/* 505b261ecSmrg * Copyright (c) 2001 Greg Parker. All Rights Reserved. 605b261ecSmrg * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. 705b261ecSmrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 805b261ecSmrg * 905b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining a 1005b261ecSmrg * copy of this software and associated documentation files (the "Software"), 1105b261ecSmrg * to deal in the Software without restriction, including without limitation 1205b261ecSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1305b261ecSmrg * and/or sell copies of the Software, and to permit persons to whom the 1405b261ecSmrg * Software is furnished to do so, subject to the following conditions: 1505b261ecSmrg * 1605b261ecSmrg * The above copyright notice and this permission notice shall be included in 1705b261ecSmrg * all copies or substantial portions of the Software. 1805b261ecSmrg * 1905b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 2005b261ecSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2105b261ecSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2205b261ecSmrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2305b261ecSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2405b261ecSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2505b261ecSmrg * DEALINGS IN THE SOFTWARE. 2605b261ecSmrg * 2705b261ecSmrg * Except as contained in this notice, the name(s) of the above copyright 2805b261ecSmrg * holders shall not be used in advertising or otherwise to promote the sale, 2905b261ecSmrg * use or other dealings in this Software without prior written authorization. 3005b261ecSmrg */ 3105b261ecSmrg 3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 3305b261ecSmrg#include <dix-config.h> 3405b261ecSmrg#endif 3505b261ecSmrg 3605b261ecSmrg#include <stddef.h> /* For NULL */ 3705b261ecSmrg#include <limits.h> /* For CHAR_BIT */ 3805b261ecSmrg#include <assert.h> 3905b261ecSmrg 4005b261ecSmrg#include "rootlessCommon.h" 4105b261ecSmrg#include "rootlessWindow.h" 4205b261ecSmrg 4305b261ecSmrg#include "fb.h" 4405b261ecSmrg 4505b261ecSmrg 4605b261ecSmrg#ifdef ROOTLESS_GLOBAL_COORDS 4705b261ecSmrg#define SCREEN_TO_GLOBAL_X \ 4805b261ecSmrg (dixScreenOrigins[pScreen->myNum].x + rootlessGlobalOffsetX) 4905b261ecSmrg#define SCREEN_TO_GLOBAL_Y \ 5005b261ecSmrg (dixScreenOrigins[pScreen->myNum].y + rootlessGlobalOffsetY) 5105b261ecSmrg#else 5205b261ecSmrg#define SCREEN_TO_GLOBAL_X 0 5305b261ecSmrg#define SCREEN_TO_GLOBAL_Y 0 5405b261ecSmrg#endif 5505b261ecSmrg 5605b261ecSmrg 5705b261ecSmrg/* 5805b261ecSmrg * RootlessCreateWindow 5905b261ecSmrg * For now, don't create a physical window until either the window is 6005b261ecSmrg * realized, or we really need it (e.g. to attach VRAM surfaces to). 6105b261ecSmrg * Do reset the window size so it's not clipped by the root window. 6205b261ecSmrg */ 6305b261ecSmrgBool 6405b261ecSmrgRootlessCreateWindow(WindowPtr pWin) 6505b261ecSmrg{ 6605b261ecSmrg Bool result; 6705b261ecSmrg RegionRec saveRoot; 6805b261ecSmrg 6905b261ecSmrg WINREC(pWin) = NULL; 7005b261ecSmrg 7105b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); 7205b261ecSmrg 7305b261ecSmrg if (!IsRoot(pWin)) { 7405b261ecSmrg /* win/border size set by DIX, not by wrapped CreateWindow, so 7505b261ecSmrg correct it here. Don't HUGE_ROOT when pWin is the root! */ 7605b261ecSmrg 7705b261ecSmrg HUGE_ROOT(pWin); 7805b261ecSmrg SetWinSize(pWin); 7905b261ecSmrg SetBorderSize(pWin); 8005b261ecSmrg } 8105b261ecSmrg 8205b261ecSmrg result = pWin->drawable.pScreen->CreateWindow(pWin); 8305b261ecSmrg 8405b261ecSmrg if (pWin->parent) { 8505b261ecSmrg NORMAL_ROOT(pWin); 8605b261ecSmrg } 8705b261ecSmrg 8805b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); 8905b261ecSmrg 9005b261ecSmrg return result; 9105b261ecSmrg} 9205b261ecSmrg 9305b261ecSmrg 9405b261ecSmrg/* 9505b261ecSmrg * RootlessDestroyFrame 9605b261ecSmrg * Destroy the physical window associated with the given window. 9705b261ecSmrg */ 9805b261ecSmrgstatic void 9905b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) 10005b261ecSmrg{ 10105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 10205b261ecSmrg 10305b261ecSmrg SCREENREC(pScreen)->imp->DestroyFrame(winRec->wid); 10405b261ecSmrg 10505b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 10605b261ecSmrg REGION_UNINIT(pScreen, &winRec->damage); 10705b261ecSmrg#endif 10805b261ecSmrg 10905b261ecSmrg xfree(winRec); 11005b261ecSmrg WINREC(pWin) = NULL; 11105b261ecSmrg} 11205b261ecSmrg 11305b261ecSmrg 11405b261ecSmrg/* 11505b261ecSmrg * RootlessDestroyWindow 11605b261ecSmrg * Destroy the physical window associated with the given window. 11705b261ecSmrg */ 11805b261ecSmrgBool 11905b261ecSmrgRootlessDestroyWindow(WindowPtr pWin) 12005b261ecSmrg{ 12105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 12205b261ecSmrg Bool result; 12305b261ecSmrg 12405b261ecSmrg if (winRec != NULL) { 12505b261ecSmrg RootlessDestroyFrame(pWin, winRec); 12605b261ecSmrg } 12705b261ecSmrg 12805b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); 12905b261ecSmrg result = pWin->drawable.pScreen->DestroyWindow(pWin); 13005b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); 13105b261ecSmrg 13205b261ecSmrg return result; 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrg 13605b261ecSmrg#ifdef SHAPE 13705b261ecSmrg 13805b261ecSmrgstatic Bool 13905b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape) 14005b261ecSmrg{ 14105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 14205b261ecSmrg 14305b261ecSmrg if (wBoundingShape(pWin) == NULL) 14405b261ecSmrg return FALSE; 14505b261ecSmrg 14605b261ecSmrg /* wBoundingShape is relative to *inner* origin of window. 14705b261ecSmrg Translate by borderWidth to get the outside-relative position. */ 14805b261ecSmrg 14905b261ecSmrg REGION_NULL(pScreen, pShape); 15005b261ecSmrg REGION_COPY(pScreen, pShape, wBoundingShape(pWin)); 15105b261ecSmrg REGION_TRANSLATE(pScreen, pShape, pWin->borderWidth, pWin->borderWidth); 15205b261ecSmrg 15305b261ecSmrg return TRUE; 15405b261ecSmrg} 15505b261ecSmrg 15605b261ecSmrg 15705b261ecSmrg/* 15805b261ecSmrg * RootlessReshapeFrame 15905b261ecSmrg * Set the frame shape. 16005b261ecSmrg */ 16105b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin) 16205b261ecSmrg{ 16305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 16405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 16505b261ecSmrg RegionRec newShape; 16605b261ecSmrg RegionPtr pShape; 16705b261ecSmrg 16805b261ecSmrg // If the window is not yet framed, do nothing 16905b261ecSmrg if (winRec == NULL) 17005b261ecSmrg return; 17105b261ecSmrg 17205b261ecSmrg if (IsRoot(pWin)) 17305b261ecSmrg return; 17405b261ecSmrg 17505b261ecSmrg RootlessStopDrawing(pWin, FALSE); 17605b261ecSmrg 17705b261ecSmrg pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; 17805b261ecSmrg 17905b261ecSmrg#ifdef ROOTLESSDEBUG 18005b261ecSmrg RL_DEBUG_MSG("reshaping..."); 18105b261ecSmrg if (pShape != NULL) { 18205b261ecSmrg RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", 18305b261ecSmrg REGION_NUM_RECTS(&newShape), 18405b261ecSmrg newShape.extents.x1, newShape.extents.y1, 18505b261ecSmrg newShape.extents.x2, newShape.extents.y2); 18605b261ecSmrg } else { 18705b261ecSmrg RL_DEBUG_MSG("no shape "); 18805b261ecSmrg } 18905b261ecSmrg#endif 19005b261ecSmrg 19105b261ecSmrg SCREENREC(pScreen)->imp->ReshapeFrame(winRec->wid, pShape); 19205b261ecSmrg 19305b261ecSmrg if (pShape != NULL) 19405b261ecSmrg REGION_UNINIT(pScreen, &newShape); 19505b261ecSmrg} 19605b261ecSmrg 19705b261ecSmrg 19805b261ecSmrg/* 19905b261ecSmrg * RootlessSetShape 20005b261ecSmrg * Shape is usually set before a window is mapped and the window will 20105b261ecSmrg * not have a frame associated with it. In this case, the frame will be 20205b261ecSmrg * shaped when the window is framed. 20305b261ecSmrg */ 20405b261ecSmrgvoid 20505b261ecSmrgRootlessSetShape(WindowPtr pWin) 20605b261ecSmrg{ 20705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 20805b261ecSmrg 20905b261ecSmrg SCREEN_UNWRAP(pScreen, SetShape); 21005b261ecSmrg pScreen->SetShape(pWin); 21105b261ecSmrg SCREEN_WRAP(pScreen, SetShape); 21205b261ecSmrg 21305b261ecSmrg RootlessReshapeFrame(pWin); 21405b261ecSmrg} 21505b261ecSmrg 21605b261ecSmrg#endif // SHAPE 21705b261ecSmrg 21805b261ecSmrg 21905b261ecSmrg/* Disallow ParentRelative background on top-level windows 22005b261ecSmrg because the root window doesn't really have the right background 22105b261ecSmrg and fb will try to draw on the root instead of on the window. 22205b261ecSmrg ParentRelative prevention is also in PaintWindowBackground/Border() 22305b261ecSmrg so it is no longer really needed here. */ 22405b261ecSmrgBool 22505b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) 22605b261ecSmrg{ 22705b261ecSmrg Bool result; 22805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 22905b261ecSmrg 23005b261ecSmrg RL_DEBUG_MSG("change window attributes start "); 23105b261ecSmrg 23205b261ecSmrg SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); 23305b261ecSmrg result = pScreen->ChangeWindowAttributes(pWin, vmask); 23405b261ecSmrg SCREEN_WRAP(pScreen, ChangeWindowAttributes); 23505b261ecSmrg 23605b261ecSmrg if (WINREC(pWin)) { 23705b261ecSmrg // disallow ParentRelative background state 23805b261ecSmrg if (pWin->backgroundState == ParentRelative) { 23905b261ecSmrg XID pixel = 0; 24005b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 24105b261ecSmrg } 24205b261ecSmrg } 24305b261ecSmrg 24405b261ecSmrg RL_DEBUG_MSG("change window attributes end\n"); 24505b261ecSmrg return result; 24605b261ecSmrg} 24705b261ecSmrg 24805b261ecSmrg 24905b261ecSmrg/* 25005b261ecSmrg * RootlessPositionWindow 25105b261ecSmrg * This is a hook for when DIX moves or resizes a window. 25205b261ecSmrg * Update the frame position now although the physical window is moved 25305b261ecSmrg * in RootlessMoveWindow. (x, y) are *inside* position. After this, 25405b261ecSmrg * mi and fb are expecting the pixmap to be at the new location. 25505b261ecSmrg */ 25605b261ecSmrgBool 25705b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y) 25805b261ecSmrg{ 25905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 26005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 26105b261ecSmrg Bool result; 26205b261ecSmrg 26305b261ecSmrg RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); 26405b261ecSmrg 26505b261ecSmrg if (winRec) { 26605b261ecSmrg if (winRec->is_drawing) { 26705b261ecSmrg // Reset frame's pixmap and move it to the new position. 26805b261ecSmrg int bw = wBorderWidth(pWin); 26905b261ecSmrg 27005b261ecSmrg winRec->pixmap->devPrivate.ptr = winRec->pixelData; 27105b261ecSmrg SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); 27205b261ecSmrg 27305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 27405b261ecSmrg // Move damaged region to correspond to new window position 27505b261ecSmrg if (REGION_NOTEMPTY(pScreen, &winRec->damage)) { 27605b261ecSmrg REGION_TRANSLATE(pScreen, &winRec->damage, 27705b261ecSmrg x - bw - winRec->x, 27805b261ecSmrg y - bw - winRec->y); 27905b261ecSmrg } 28005b261ecSmrg#endif 28105b261ecSmrg } 28205b261ecSmrg } 28305b261ecSmrg 28405b261ecSmrg SCREEN_UNWRAP(pScreen, PositionWindow); 28505b261ecSmrg result = pScreen->PositionWindow(pWin, x, y); 28605b261ecSmrg SCREEN_WRAP(pScreen, PositionWindow); 28705b261ecSmrg 28805b261ecSmrg RL_DEBUG_MSG("positionwindow end\n"); 28905b261ecSmrg return result; 29005b261ecSmrg} 29105b261ecSmrg 29205b261ecSmrg 29305b261ecSmrg/* 29405b261ecSmrg * RootlessInitializeFrame 29505b261ecSmrg * Initialize some basic attributes of the frame. Note that winRec 29605b261ecSmrg * may already have valid data in it, so don't overwrite anything 29705b261ecSmrg * valuable. 29805b261ecSmrg */ 29905b261ecSmrgstatic void 30005b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) 30105b261ecSmrg{ 30205b261ecSmrg DrawablePtr d = &pWin->drawable; 30305b261ecSmrg int bw = wBorderWidth(pWin); 30405b261ecSmrg 30505b261ecSmrg winRec->win = pWin; 30605b261ecSmrg 30705b261ecSmrg winRec->x = d->x - bw; 30805b261ecSmrg winRec->y = d->y - bw; 30905b261ecSmrg winRec->width = d->width + 2*bw; 31005b261ecSmrg winRec->height = d->height + 2*bw; 31105b261ecSmrg winRec->borderWidth = bw; 31205b261ecSmrg 31305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 31405b261ecSmrg REGION_NULL(pScreen, &winRec->damage); 31505b261ecSmrg#endif 31605b261ecSmrg} 31705b261ecSmrg 31805b261ecSmrg 31905b261ecSmrg/* 32005b261ecSmrg * RootlessEnsureFrame 32105b261ecSmrg * Make sure the given window is framed. If the window doesn't have a 32205b261ecSmrg * physical window associated with it, attempt to create one. If that 32305b261ecSmrg * is unsuccessful, return NULL. 32405b261ecSmrg */ 32505b261ecSmrgstatic RootlessWindowRec * 32605b261ecSmrgRootlessEnsureFrame(WindowPtr pWin) 32705b261ecSmrg{ 32805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 32905b261ecSmrg RootlessWindowRec *winRec; 33005b261ecSmrg#ifdef SHAPE 33105b261ecSmrg RegionRec shape; 33205b261ecSmrg#endif 33305b261ecSmrg RegionPtr pShape = NULL; 33405b261ecSmrg 33505b261ecSmrg if (WINREC(pWin) != NULL) 33605b261ecSmrg return WINREC(pWin); 33705b261ecSmrg 33805b261ecSmrg if (!IsTopLevel(pWin)) 33905b261ecSmrg return NULL; 34005b261ecSmrg 34105b261ecSmrg if (pWin->drawable.class != InputOutput) 34205b261ecSmrg return NULL; 34305b261ecSmrg 34405b261ecSmrg winRec = xalloc(sizeof(RootlessWindowRec)); 34505b261ecSmrg 34605b261ecSmrg if (!winRec) 34705b261ecSmrg return NULL; 34805b261ecSmrg 34905b261ecSmrg RootlessInitializeFrame(pWin, winRec); 35005b261ecSmrg 35105b261ecSmrg winRec->is_drawing = FALSE; 35205b261ecSmrg winRec->is_reorder_pending = FALSE; 35305b261ecSmrg winRec->pixmap = NULL; 35405b261ecSmrg winRec->wid = NULL; 35505b261ecSmrg 35605b261ecSmrg WINREC(pWin) = winRec; 35705b261ecSmrg 35805b261ecSmrg#ifdef SHAPE 35905b261ecSmrg // Set the frame's shape if the window is shaped 36005b261ecSmrg if (RootlessGetShape(pWin, &shape)) 36105b261ecSmrg pShape = &shape; 36205b261ecSmrg#endif 36305b261ecSmrg 36405b261ecSmrg RL_DEBUG_MSG("creating frame "); 36505b261ecSmrg 36605b261ecSmrg if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, 36705b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 36805b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 36905b261ecSmrg pShape)) 37005b261ecSmrg { 37105b261ecSmrg RL_DEBUG_MSG("implementation failed to create frame!\n"); 37205b261ecSmrg xfree(winRec); 37305b261ecSmrg WINREC(pWin) = NULL; 37405b261ecSmrg return NULL; 37505b261ecSmrg } 37605b261ecSmrg 37705b261ecSmrg#ifdef SHAPE 37805b261ecSmrg if (pShape != NULL) 37905b261ecSmrg REGION_UNINIT(pScreen, &shape); 38005b261ecSmrg#endif 38105b261ecSmrg 38205b261ecSmrg return winRec; 38305b261ecSmrg} 38405b261ecSmrg 38505b261ecSmrg 38605b261ecSmrg/* 38705b261ecSmrg * RootlessRealizeWindow 38805b261ecSmrg * The frame is usually created here and not in CreateWindow so that 38905b261ecSmrg * windows do not eat memory until they are realized. 39005b261ecSmrg */ 39105b261ecSmrgBool 39205b261ecSmrgRootlessRealizeWindow(WindowPtr pWin) 39305b261ecSmrg{ 39405b261ecSmrg Bool result; 39505b261ecSmrg RegionRec saveRoot; 39605b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 39705b261ecSmrg 39805b261ecSmrg RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); 39905b261ecSmrg 40005b261ecSmrg if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { 40105b261ecSmrg RootlessWindowRec *winRec; 40205b261ecSmrg 40305b261ecSmrg winRec = RootlessEnsureFrame(pWin); 40405b261ecSmrg if (winRec == NULL) 40505b261ecSmrg return FALSE; 40605b261ecSmrg 40705b261ecSmrg winRec->is_reorder_pending = TRUE; 40805b261ecSmrg 40905b261ecSmrg RL_DEBUG_MSG("Top level window "); 41005b261ecSmrg 41105b261ecSmrg // Disallow ParentRelative background state on top-level windows. 41205b261ecSmrg // This might have been set before the window was mapped. 41305b261ecSmrg if (pWin->backgroundState == ParentRelative) { 41405b261ecSmrg XID pixel = 0; 41505b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 41605b261ecSmrg } 41705b261ecSmrg } 41805b261ecSmrg 41905b261ecSmrg if (!IsRoot(pWin)) HUGE_ROOT(pWin); 42005b261ecSmrg SCREEN_UNWRAP(pScreen, RealizeWindow); 42105b261ecSmrg result = pScreen->RealizeWindow(pWin); 42205b261ecSmrg SCREEN_WRAP(pScreen, RealizeWindow); 42305b261ecSmrg if (!IsRoot(pWin)) NORMAL_ROOT(pWin); 42405b261ecSmrg 42505b261ecSmrg RL_DEBUG_MSG("realizewindow end\n"); 42605b261ecSmrg return result; 42705b261ecSmrg} 42805b261ecSmrg 42905b261ecSmrg 43005b261ecSmrg/* 43105b261ecSmrg * RootlessFrameForWindow 43205b261ecSmrg * Returns the frame ID for the physical window displaying the given window. 43305b261ecSmrg * If CREATE is true and the window has no frame, attempt to create one. 43405b261ecSmrg */ 43505b261ecSmrgRootlessFrameID 43605b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create) 43705b261ecSmrg{ 43805b261ecSmrg WindowPtr pTopWin; 43905b261ecSmrg RootlessWindowRec *winRec; 44005b261ecSmrg 44105b261ecSmrg pTopWin = TopLevelParent(pWin); 44205b261ecSmrg if (pTopWin == NULL) 44305b261ecSmrg return NULL; 44405b261ecSmrg 44505b261ecSmrg winRec = WINREC(pTopWin); 44605b261ecSmrg 44705b261ecSmrg if (winRec == NULL && create && pWin->drawable.class == InputOutput) { 44805b261ecSmrg winRec = RootlessEnsureFrame(pTopWin); 44905b261ecSmrg } 45005b261ecSmrg 45105b261ecSmrg if (winRec == NULL) 45205b261ecSmrg return NULL; 45305b261ecSmrg 45405b261ecSmrg return winRec->wid; 45505b261ecSmrg} 45605b261ecSmrg 45705b261ecSmrg 45805b261ecSmrg/* 45905b261ecSmrg * RootlessUnrealizeWindow 46005b261ecSmrg * Unmap the physical window. 46105b261ecSmrg */ 46205b261ecSmrgBool 46305b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin) 46405b261ecSmrg{ 46505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 46605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 46705b261ecSmrg Bool result; 46805b261ecSmrg 46905b261ecSmrg RL_DEBUG_MSG("unrealizewindow start "); 47005b261ecSmrg 47105b261ecSmrg if (winRec) { 47205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 47305b261ecSmrg 47405b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 47505b261ecSmrg 47605b261ecSmrg winRec->is_reorder_pending = FALSE; 47705b261ecSmrg } 47805b261ecSmrg 47905b261ecSmrg SCREEN_UNWRAP(pScreen, UnrealizeWindow); 48005b261ecSmrg result = pScreen->UnrealizeWindow(pWin); 48105b261ecSmrg SCREEN_WRAP(pScreen, UnrealizeWindow); 48205b261ecSmrg 48305b261ecSmrg RL_DEBUG_MSG("unrealizewindow end\n"); 48405b261ecSmrg return result; 48505b261ecSmrg} 48605b261ecSmrg 48705b261ecSmrg 48805b261ecSmrg/* 48905b261ecSmrg * RootlessReorderWindow 49005b261ecSmrg * Reorder the frame associated with the given window so that it's 49105b261ecSmrg * physically above the window below it in the X stacking order. 49205b261ecSmrg */ 49305b261ecSmrgvoid 49405b261ecSmrgRootlessReorderWindow(WindowPtr pWin) 49505b261ecSmrg{ 49605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 49705b261ecSmrg 49805b261ecSmrg if (winRec != NULL && !winRec->is_reorder_pending) { 49905b261ecSmrg WindowPtr newPrevW; 50005b261ecSmrg RootlessWindowRec *newPrev; 50105b261ecSmrg RootlessFrameID newPrevID; 50205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 50305b261ecSmrg 50405b261ecSmrg /* Check if the implementation wants the frame to not be reordered 50505b261ecSmrg even though the X11 window is restacked. This can be useful if 50605b261ecSmrg frames are ordered-in with animation so that the reordering is not 50705b261ecSmrg done until the animation is complete. */ 50805b261ecSmrg if (SCREENREC(pScreen)->imp->DoReorderWindow) { 50905b261ecSmrg if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) 51005b261ecSmrg return; 51105b261ecSmrg } 51205b261ecSmrg 51305b261ecSmrg RootlessStopDrawing(pWin, FALSE); 51405b261ecSmrg 51505b261ecSmrg /* Find the next window above this one that has a mapped frame. */ 51605b261ecSmrg 51705b261ecSmrg newPrevW = pWin->prevSib; 51805b261ecSmrg while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized)) 51905b261ecSmrg newPrevW = newPrevW->prevSib; 52005b261ecSmrg 52105b261ecSmrg newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; 52205b261ecSmrg newPrevID = newPrev != NULL ? newPrev->wid : 0; 52305b261ecSmrg 52405b261ecSmrg /* If it exists, reorder the frame above us first. */ 52505b261ecSmrg 52605b261ecSmrg if (newPrev && newPrev->is_reorder_pending) { 52705b261ecSmrg newPrev->is_reorder_pending = FALSE; 52805b261ecSmrg RootlessReorderWindow(newPrevW); 52905b261ecSmrg } 53005b261ecSmrg 53105b261ecSmrg SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); 53205b261ecSmrg } 53305b261ecSmrg} 53405b261ecSmrg 53505b261ecSmrg 53605b261ecSmrg/* 53705b261ecSmrg * RootlessRestackWindow 53805b261ecSmrg * This is a hook for when DIX changes the window stacking order. 53905b261ecSmrg * The window has already been inserted into its new position in the 54005b261ecSmrg * DIX window stack. We need to change the order of the physical 54105b261ecSmrg * window to match. 54205b261ecSmrg */ 54305b261ecSmrgvoid 54405b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) 54505b261ecSmrg{ 54605b261ecSmrg RegionRec saveRoot; 54705b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 54805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 54905b261ecSmrg 55005b261ecSmrg RL_DEBUG_MSG("restackwindow start "); 55105b261ecSmrg if (winRec) 55205b261ecSmrg RL_DEBUG_MSG("restack top level \n"); 55305b261ecSmrg 55405b261ecSmrg HUGE_ROOT(pWin); 55505b261ecSmrg SCREEN_UNWRAP(pScreen, RestackWindow); 55605b261ecSmrg 55705b261ecSmrg if (pScreen->RestackWindow) 55805b261ecSmrg pScreen->RestackWindow(pWin, pOldNextSib); 55905b261ecSmrg 56005b261ecSmrg SCREEN_WRAP(pScreen, RestackWindow); 56105b261ecSmrg NORMAL_ROOT(pWin); 56205b261ecSmrg 56305b261ecSmrg if (winRec && pWin->viewable) { 56405b261ecSmrg RootlessReorderWindow(pWin); 56505b261ecSmrg } 56605b261ecSmrg 56705b261ecSmrg RL_DEBUG_MSG("restackwindow end\n"); 56805b261ecSmrg} 56905b261ecSmrg 57005b261ecSmrg 57105b261ecSmrg/* 57205b261ecSmrg * Specialized window copy procedures 57305b261ecSmrg */ 57405b261ecSmrg 57505b261ecSmrg// Globals needed during window resize and move. 57605b261ecSmrgstatic pointer gResizeDeathBits = NULL; 57705b261ecSmrgstatic int gResizeDeathCount = 0; 57805b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; 57905b261ecSmrgstatic BoxRec gResizeDeathBounds[2]; 58005b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; 58105b261ecSmrg 58205b261ecSmrg/* 58305b261ecSmrg * RootlessNoCopyWindow 58405b261ecSmrg * CopyWindow() that doesn't do anything. For MoveWindow() of 58505b261ecSmrg * top-level windows. 58605b261ecSmrg */ 58705b261ecSmrgstatic void 58805b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 58905b261ecSmrg RegionPtr prgnSrc) 59005b261ecSmrg{ 59105b261ecSmrg // some code expects the region to be translated 59205b261ecSmrg int dx = ptOldOrg.x - pWin->drawable.x; 59305b261ecSmrg int dy = ptOldOrg.y - pWin->drawable.y; 59405b261ecSmrg 59505b261ecSmrg RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); 59605b261ecSmrg 59705b261ecSmrg REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); 59805b261ecSmrg} 59905b261ecSmrg 60005b261ecSmrg 60105b261ecSmrg/* 60205b261ecSmrg * RootlessResizeCopyWindow 60305b261ecSmrg * CopyWindow used during ResizeWindow for gravity moves. Based on 60405b261ecSmrg * fbCopyWindow. The original always draws on the root pixmap, which 60505b261ecSmrg * we don't have. Instead, draw on the parent window's pixmap. 60605b261ecSmrg * Resize version: the old location's pixels are in gResizeCopyWindowSource. 60705b261ecSmrg */ 60805b261ecSmrgstatic void 60905b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 61005b261ecSmrg RegionPtr prgnSrc) 61105b261ecSmrg{ 61205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 61305b261ecSmrg RegionRec rgnDst; 61405b261ecSmrg int dx, dy; 61505b261ecSmrg 61605b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); 61705b261ecSmrg 61805b261ecSmrg /* Don't unwrap pScreen->CopyWindow. 61905b261ecSmrg The bogus rewrap with RootlessCopyWindow causes a crash if 62005b261ecSmrg CopyWindow is called again during the same resize. */ 62105b261ecSmrg 62205b261ecSmrg if (gResizeDeathCount == 0) 62305b261ecSmrg return; 62405b261ecSmrg 62505b261ecSmrg RootlessStartDrawing(pWin); 62605b261ecSmrg 62705b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 62805b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 62905b261ecSmrg REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); 63005b261ecSmrg REGION_NULL(pScreen, &rgnDst); 63105b261ecSmrg REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); 63205b261ecSmrg 63305b261ecSmrg if (gResizeDeathCount == 1) { 63405b261ecSmrg /* Simple case, we only have a single source pixmap. */ 63505b261ecSmrg 63605b261ecSmrg fbCopyRegion(&gResizeDeathPix[0]->drawable, 63705b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 63805b261ecSmrg &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 63905b261ecSmrg } 64005b261ecSmrg else { 64105b261ecSmrg int i; 64205b261ecSmrg RegionRec clip, clipped; 64305b261ecSmrg 64405b261ecSmrg /* More complex case, N source pixmaps (usually two). So we 64505b261ecSmrg intersect the destination with each source and copy those bits. */ 64605b261ecSmrg 64705b261ecSmrg for (i = 0; i < gResizeDeathCount; i++) { 64805b261ecSmrg REGION_INIT(pScreen, &clip, gResizeDeathBounds + 0, 1); 64905b261ecSmrg REGION_NULL(pScreen, &clipped); 65005b261ecSmrg REGION_INTERSECT(pScreen, &rgnDst, &clip, &clipped); 65105b261ecSmrg 65205b261ecSmrg fbCopyRegion(&gResizeDeathPix[i]->drawable, 65305b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 65405b261ecSmrg &clipped, dx, dy, fbCopyWindowProc, 0, 0); 65505b261ecSmrg 65605b261ecSmrg REGION_UNINIT(pScreen, &clipped); 65705b261ecSmrg REGION_UNINIT(pScreen, &clip); 65805b261ecSmrg } 65905b261ecSmrg } 66005b261ecSmrg 66105b261ecSmrg /* Don't update - resize will update everything */ 66205b261ecSmrg REGION_UNINIT(pScreen, &rgnDst); 66305b261ecSmrg 66405b261ecSmrg fbValidateDrawable(&pWin->drawable); 66505b261ecSmrg 66605b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB end\n"); 66705b261ecSmrg} 66805b261ecSmrg 66905b261ecSmrg 67005b261ecSmrg/* 67105b261ecSmrg * RootlessCopyWindow 67205b261ecSmrg * Update *new* location of window. Old location is redrawn with 67305b261ecSmrg * PaintWindowBackground/Border. Cloned from fbCopyWindow. 67405b261ecSmrg * The original always draws on the root pixmap, which we don't have. 67505b261ecSmrg * Instead, draw on the parent window's pixmap. 67605b261ecSmrg */ 67705b261ecSmrgvoid 67805b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 67905b261ecSmrg{ 68005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 68105b261ecSmrg RegionRec rgnDst; 68205b261ecSmrg int dx, dy; 68305b261ecSmrg BoxPtr extents; 68405b261ecSmrg int area; 68505b261ecSmrg 68605b261ecSmrg RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); 68705b261ecSmrg 68805b261ecSmrg SCREEN_UNWRAP(pScreen, CopyWindow); 68905b261ecSmrg 69005b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 69105b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 69205b261ecSmrg REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); 69305b261ecSmrg 69405b261ecSmrg REGION_NULL(pScreen, &rgnDst); 69505b261ecSmrg REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); 69605b261ecSmrg 69705b261ecSmrg extents = REGION_EXTENTS(pScreen, &rgnDst); 69805b261ecSmrg area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); 69905b261ecSmrg 70005b261ecSmrg /* If the area exceeds threshold, use the implementation's 70105b261ecSmrg accelerated version. */ 70205b261ecSmrg if (area > rootless_CopyWindow_threshold && 70305b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow) 70405b261ecSmrg { 70505b261ecSmrg RootlessWindowRec *winRec; 70605b261ecSmrg WindowPtr top; 70705b261ecSmrg 70805b261ecSmrg top = TopLevelParent(pWin); 70905b261ecSmrg if (top == NULL) { 71005b261ecSmrg RL_DEBUG_MSG("no parent\n"); 71105b261ecSmrg return; 71205b261ecSmrg } 71305b261ecSmrg 71405b261ecSmrg winRec = WINREC(top); 71505b261ecSmrg if (winRec == NULL) { 71605b261ecSmrg RL_DEBUG_MSG("not framed\n"); 71705b261ecSmrg return; 71805b261ecSmrg } 71905b261ecSmrg 72005b261ecSmrg /* Move region to window local coords */ 72105b261ecSmrg REGION_TRANSLATE(pScreen, &rgnDst, -winRec->x, -winRec->y); 72205b261ecSmrg 72305b261ecSmrg RootlessStopDrawing(pWin, FALSE); 72405b261ecSmrg 72505b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, 72605b261ecSmrg REGION_NUM_RECTS(&rgnDst), 72705b261ecSmrg REGION_RECTS(&rgnDst), 72805b261ecSmrg dx, dy); 72905b261ecSmrg } 73005b261ecSmrg else { 73105b261ecSmrg RootlessStartDrawing(pWin); 73205b261ecSmrg 73305b261ecSmrg fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, 73405b261ecSmrg 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 73505b261ecSmrg 73605b261ecSmrg /* prgnSrc has been translated to dst position */ 73705b261ecSmrg RootlessDamageRegion(pWin, prgnSrc); 73805b261ecSmrg } 73905b261ecSmrg 74005b261ecSmrg REGION_UNINIT(pScreen, &rgnDst); 74105b261ecSmrg fbValidateDrawable(&pWin->drawable); 74205b261ecSmrg 74305b261ecSmrg SCREEN_WRAP(pScreen, CopyWindow); 74405b261ecSmrg 74505b261ecSmrg RL_DEBUG_MSG("copywindowFB end\n"); 74605b261ecSmrg} 74705b261ecSmrg 74805b261ecSmrg 74905b261ecSmrg/* 75005b261ecSmrg * Window resize procedures 75105b261ecSmrg */ 75205b261ecSmrg 75305b261ecSmrgenum { 75405b261ecSmrg WIDTH_SMALLER = 1, 75505b261ecSmrg HEIGHT_SMALLER = 2, 75605b261ecSmrg}; 75705b261ecSmrg 75805b261ecSmrg 75905b261ecSmrg/* 76005b261ecSmrg * ResizeWeighting 76105b261ecSmrg * Choose gravity to avoid local copies. Do that by looking for 76205b261ecSmrg * a corner that doesn't move _relative to the screen_. 76305b261ecSmrg */ 76405b261ecSmrgstatic inline unsigned int 76505b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, 76605b261ecSmrg int newX1, int newY1, int newX2, int newY2, int newBW) 76705b261ecSmrg{ 76805b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY 76905b261ecSmrg if (newBW != oldBW) 77005b261ecSmrg return RL_GRAVITY_NONE; 77105b261ecSmrg 77205b261ecSmrg if (newX1 == oldX1 && newY1 == oldY1) 77305b261ecSmrg return RL_GRAVITY_NORTH_WEST; 77405b261ecSmrg else if (newX1 == oldX1 && newY2 == oldY2) 77505b261ecSmrg return RL_GRAVITY_SOUTH_WEST; 77605b261ecSmrg else if (newX2 == oldX2 && newY2 == oldY2) 77705b261ecSmrg return RL_GRAVITY_SOUTH_EAST; 77805b261ecSmrg else if (newX2 == oldX2 && newY1 == oldY1) 77905b261ecSmrg return RL_GRAVITY_NORTH_EAST; 78005b261ecSmrg else 78105b261ecSmrg return RL_GRAVITY_NONE; 78205b261ecSmrg#else 78305b261ecSmrg return RL_GRAVITY_NONE; 78405b261ecSmrg#endif 78505b261ecSmrg} 78605b261ecSmrg 78705b261ecSmrg 78805b261ecSmrg/* 78905b261ecSmrg * StartFrameResize 79005b261ecSmrg * Prepare to resize a top-level window. The old window's pixels are 79105b261ecSmrg * saved and the implementation is told to change the window size. 79205b261ecSmrg * (x,y,w,h) is outer frame of window (outside border) 79305b261ecSmrg */ 79405b261ecSmrgstatic Bool 79505b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity, 79605b261ecSmrg int oldX, int oldY, int oldW, int oldH, int oldBW, 79705b261ecSmrg int newX, int newY, int newW, int newH, int newBW) 79805b261ecSmrg{ 79905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 80005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 80105b261ecSmrg Bool need_window_source = FALSE, resize_after = FALSE; 80205b261ecSmrg 80305b261ecSmrg BoxRec rect; 80405b261ecSmrg int oldX2, newX2; 80505b261ecSmrg int oldY2, newY2; 80605b261ecSmrg unsigned int weight; 80705b261ecSmrg 80805b261ecSmrg oldX2 = oldX + oldW, newX2 = newX + newW; 80905b261ecSmrg oldY2 = oldY + oldH, newY2 = newY + newH; 81005b261ecSmrg 81105b261ecSmrg /* Decide which resize weighting to use */ 81205b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 81305b261ecSmrg newX, newY, newW, newH, newBW); 81405b261ecSmrg 81505b261ecSmrg /* Compute intersection between old and new rects */ 81605b261ecSmrg rect.x1 = max(oldX, newX); 81705b261ecSmrg rect.y1 = max(oldY, newY); 81805b261ecSmrg rect.x2 = min(oldX2, newX2); 81905b261ecSmrg rect.y2 = min(oldY2, newY2); 82005b261ecSmrg 82105b261ecSmrg RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); 82205b261ecSmrg RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", 82305b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 82405b261ecSmrg newX, newY, newW, newH, newBW); 82505b261ecSmrg 82605b261ecSmrg RootlessRedisplay(pWin); 82705b261ecSmrg 82805b261ecSmrg /* If gravity is true, then we need to have a way of recovering all 82905b261ecSmrg the original bits in the window for when X rearranges the contents 83005b261ecSmrg based on the various gravity settings. The obvious way is to just 83105b261ecSmrg snapshot the entire backing store before resizing it, but that 83205b261ecSmrg it slow on large windows. 83305b261ecSmrg 83405b261ecSmrg So the optimization here is to use the implementation's resize 83505b261ecSmrg weighting options (if available) to allow us to reason about what 83605b261ecSmrg is left in the backing store after the resize. We can then only 83705b261ecSmrg copy what won't be there after the resize, and do a two-stage copy 83805b261ecSmrg operation. 83905b261ecSmrg 84005b261ecSmrg Most of these optimizations are only applied when the top-left 84105b261ecSmrg corner of the window is fixed, since that's the common case. They 84205b261ecSmrg could probably be extended with some thought. */ 84305b261ecSmrg 84405b261ecSmrg gResizeDeathCount = 0; 84505b261ecSmrg 84605b261ecSmrg if (gravity && weight == RL_GRAVITY_NORTH_WEST) { 84705b261ecSmrg unsigned int code = 0; 84805b261ecSmrg 84905b261ecSmrg /* Top left corner is anchored. We never need to copy the 85005b261ecSmrg entire window. */ 85105b261ecSmrg 85205b261ecSmrg need_window_source = TRUE; 85305b261ecSmrg 85405b261ecSmrg /* These comparisons were chosen to avoid setting bits when the sizes 85505b261ecSmrg are the same. (So the fastest case automatically gets taken when 85605b261ecSmrg dimensions are unchanging.) */ 85705b261ecSmrg 85805b261ecSmrg if (newW < oldW) 85905b261ecSmrg code |= WIDTH_SMALLER; 86005b261ecSmrg if (newH < oldH) 86105b261ecSmrg code |= HEIGHT_SMALLER; 86205b261ecSmrg 86305b261ecSmrg if (((code ^ (code >> 1)) & 1) == 0) { 86405b261ecSmrg /* Both dimensions are either getting larger, or both 86505b261ecSmrg are getting smaller. No need to copy anything. */ 86605b261ecSmrg 86705b261ecSmrg if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { 86805b261ecSmrg /* Since the window is getting smaller, we can do gravity 86905b261ecSmrg repair on it with it's current size, then resize it 87005b261ecSmrg afterwards. */ 87105b261ecSmrg 87205b261ecSmrg resize_after = TRUE; 87305b261ecSmrg } 87405b261ecSmrg 87505b261ecSmrg gResizeDeathCount = 1; 87605b261ecSmrg } 87705b261ecSmrg else { 87805b261ecSmrg unsigned int copy_rowbytes, Bpp; 87905b261ecSmrg unsigned int copy_rect_width, copy_rect_height; 88005b261ecSmrg BoxRec copy_rect; 88105b261ecSmrg 88205b261ecSmrg /* We can get away with a partial copy. 'rect' is the 88305b261ecSmrg intersection between old and new bounds, so copy 88405b261ecSmrg everything to the right of or below the intersection. */ 88505b261ecSmrg 88605b261ecSmrg RootlessStartDrawing(pWin); 88705b261ecSmrg 88805b261ecSmrg if (code == WIDTH_SMALLER) { 88905b261ecSmrg copy_rect.x1 = rect.x2; 89005b261ecSmrg copy_rect.y1 = rect.y1; 89105b261ecSmrg copy_rect.x2 = oldX2; 89205b261ecSmrg copy_rect.y2 = oldY2; 89305b261ecSmrg } 89405b261ecSmrg else if (code == HEIGHT_SMALLER) { 89505b261ecSmrg copy_rect.x1 = rect.x1; 89605b261ecSmrg copy_rect.y1 = rect.y2; 89705b261ecSmrg copy_rect.x2 = oldX2; 89805b261ecSmrg copy_rect.y2 = oldY2; 89905b261ecSmrg } 90005b261ecSmrg else 90105b261ecSmrg abort(); 90205b261ecSmrg 90305b261ecSmrg Bpp = winRec->win->drawable.bitsPerPixel / 8; 90405b261ecSmrg copy_rect_width = copy_rect.x2 - copy_rect.x1; 90505b261ecSmrg copy_rect_height = copy_rect.y2 - copy_rect.y1; 90605b261ecSmrg copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; 90705b261ecSmrg gResizeDeathBits = xalloc(copy_rowbytes 90805b261ecSmrg * copy_rect_height); 90905b261ecSmrg 91005b261ecSmrg if (copy_rect_width * copy_rect_height > 91105b261ecSmrg rootless_CopyBytes_threshold && 91205b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes) 91305b261ecSmrg { 91405b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes( 91505b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 91605b261ecSmrg ((char *) winRec->pixelData) 91705b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 91805b261ecSmrg + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, 91905b261ecSmrg gResizeDeathBits, copy_rowbytes); 92005b261ecSmrg } else { 92105b261ecSmrg fbBlt((FbBits *) (winRec->pixelData 92205b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 92305b261ecSmrg + (copy_rect.x1 - oldX) * Bpp), 92405b261ecSmrg winRec->bytesPerRow / sizeof(FbBits), 0, 92505b261ecSmrg (FbBits *) gResizeDeathBits, 92605b261ecSmrg copy_rowbytes / sizeof(FbBits), 0, 92705b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 92805b261ecSmrg GXcopy, FB_ALLONES, Bpp, 0, 0); 92905b261ecSmrg } 93005b261ecSmrg 93105b261ecSmrg gResizeDeathBounds[1] = copy_rect; 93205b261ecSmrg gResizeDeathPix[1] 93305b261ecSmrg = GetScratchPixmapHeader(pScreen, copy_rect_width, 93405b261ecSmrg copy_rect_height, 93505b261ecSmrg winRec->win->drawable.depth, 93605b261ecSmrg winRec->win->drawable.bitsPerPixel, 93705b261ecSmrg winRec->bytesPerRow, 93805b261ecSmrg (void *) gResizeDeathBits); 93905b261ecSmrg 94005b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[1], 94105b261ecSmrg copy_rect.x1, copy_rect.y1); 94205b261ecSmrg 94305b261ecSmrg gResizeDeathCount = 2; 94405b261ecSmrg } 94505b261ecSmrg } 94605b261ecSmrg else if (gravity) { 94705b261ecSmrg /* The general case. Just copy everything. */ 94805b261ecSmrg 94905b261ecSmrg RootlessStartDrawing(pWin); 95005b261ecSmrg 95105b261ecSmrg gResizeDeathBits = xalloc(winRec->bytesPerRow * winRec->height); 95205b261ecSmrg 95305b261ecSmrg memcpy(gResizeDeathBits, winRec->pixelData, 95405b261ecSmrg winRec->bytesPerRow * winRec->height); 95505b261ecSmrg 95605b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 95705b261ecSmrg gResizeDeathPix[0] 95805b261ecSmrg = GetScratchPixmapHeader(pScreen, winRec->width, 95905b261ecSmrg winRec->height, 96005b261ecSmrg winRec->win->drawable.depth, 96105b261ecSmrg winRec->win->drawable.bitsPerPixel, 96205b261ecSmrg winRec->bytesPerRow, 96305b261ecSmrg (void *) gResizeDeathBits); 96405b261ecSmrg 96505b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 96605b261ecSmrg gResizeDeathCount = 1; 96705b261ecSmrg } 96805b261ecSmrg 96905b261ecSmrg RootlessStopDrawing(pWin, FALSE); 97005b261ecSmrg 97105b261ecSmrg winRec->x = newX; 97205b261ecSmrg winRec->y = newY; 97305b261ecSmrg winRec->width = newW; 97405b261ecSmrg winRec->height = newH; 97505b261ecSmrg winRec->borderWidth = newBW; 97605b261ecSmrg 97705b261ecSmrg /* Unless both dimensions are getting smaller, Resize the frame 97805b261ecSmrg before doing gravity repair */ 97905b261ecSmrg 98005b261ecSmrg if (!resize_after) { 98105b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 98205b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 98305b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 98405b261ecSmrg newW, newH, weight); 98505b261ecSmrg } 98605b261ecSmrg 98705b261ecSmrg RootlessStartDrawing(pWin); 98805b261ecSmrg 98905b261ecSmrg /* If necessary, create a source pixmap pointing at the current 99005b261ecSmrg window bits. */ 99105b261ecSmrg 99205b261ecSmrg if (need_window_source) { 99305b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 99405b261ecSmrg gResizeDeathPix[0] 99505b261ecSmrg = GetScratchPixmapHeader(pScreen, oldW, oldH, 99605b261ecSmrg winRec->win->drawable.depth, 99705b261ecSmrg winRec->win->drawable.bitsPerPixel, 99805b261ecSmrg winRec->bytesPerRow, winRec->pixelData); 99905b261ecSmrg 100005b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 100105b261ecSmrg } 100205b261ecSmrg 100305b261ecSmrg /* Use custom CopyWindow when moving gravity bits around 100405b261ecSmrg ResizeWindow assumes the old window contents are in the same 100505b261ecSmrg pixmap, but here they're in deathPix instead. */ 100605b261ecSmrg 100705b261ecSmrg if (gravity) { 100805b261ecSmrg gResizeOldCopyWindowProc = pScreen->CopyWindow; 100905b261ecSmrg pScreen->CopyWindow = RootlessResizeCopyWindow; 101005b261ecSmrg } 101105b261ecSmrg 101205b261ecSmrg /* If we can't rely on the window server preserving the bits we 101305b261ecSmrg need in the position we need, copy the pixels in the 101405b261ecSmrg intersection from src to dst. ResizeWindow assumes these pixels 101505b261ecSmrg are already present when making gravity adjustments. pWin 101605b261ecSmrg currently has new-sized pixmap but is in old position. 101705b261ecSmrg 101805b261ecSmrg FIXME: border width change! (?) */ 101905b261ecSmrg 102005b261ecSmrg if (gravity && weight == RL_GRAVITY_NONE) { 102105b261ecSmrg PixmapPtr src, dst; 102205b261ecSmrg 102305b261ecSmrg assert(gResizeDeathCount == 1); 102405b261ecSmrg 102505b261ecSmrg src = gResizeDeathPix[0]; 102605b261ecSmrg dst = pScreen->GetWindowPixmap(pWin); 102705b261ecSmrg 102805b261ecSmrg RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", 102905b261ecSmrg rect.x1, rect.y1, rect.x2, rect.y2); 103005b261ecSmrg 103105b261ecSmrg /* rect is the intersection of the old location and new location */ 103205b261ecSmrg if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { 103305b261ecSmrg /* The window drawable still has the old frame position, which 103405b261ecSmrg means that DST doesn't actually point at the origin of our 103505b261ecSmrg physical backing store when adjusted by the drawable.x,y 103605b261ecSmrg position. So sneakily adjust it temporarily while copying.. */ 103705b261ecSmrg 103805b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 103905b261ecSmrg SetPixmapBaseToScreen(dst, newX, newY); 104005b261ecSmrg 104105b261ecSmrg fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, 104205b261ecSmrg &rect, 1, 0, 0, FALSE, FALSE, 0, 0); 104305b261ecSmrg 104405b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 104505b261ecSmrg SetPixmapBaseToScreen(dst, oldX, oldY); 104605b261ecSmrg } 104705b261ecSmrg } 104805b261ecSmrg 104905b261ecSmrg return resize_after; 105005b261ecSmrg} 105105b261ecSmrg 105205b261ecSmrg 105305b261ecSmrgstatic void 105405b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, 105505b261ecSmrg unsigned int oldW, unsigned int oldH, unsigned int oldBW, 105605b261ecSmrg int newX, int newY, unsigned int newW, unsigned int newH, 105705b261ecSmrg unsigned int newBW, Bool resize_now) 105805b261ecSmrg{ 105905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 106005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 106105b261ecSmrg int i; 106205b261ecSmrg 106305b261ecSmrg RootlessStopDrawing(pWin, FALSE); 106405b261ecSmrg 106505b261ecSmrg if (resize_now) { 106605b261ecSmrg unsigned int weight; 106705b261ecSmrg 106805b261ecSmrg /* We didn't resize anything earlier, so do it now, now that 106905b261ecSmrg we've finished gravitating the bits. */ 107005b261ecSmrg 107105b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 107205b261ecSmrg newX, newY, newW, newH, newBW); 107305b261ecSmrg 107405b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 107505b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 107605b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 107705b261ecSmrg newW, newH, weight); 107805b261ecSmrg } 107905b261ecSmrg 108005b261ecSmrg /* Redraw everything. FIXME: there must be times when we don't need 108105b261ecSmrg to do this. Perhaps when top-left weighting and no gravity? */ 108205b261ecSmrg 108305b261ecSmrg RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); 108405b261ecSmrg 108505b261ecSmrg for (i = 0; i < 2; i++) { 108605b261ecSmrg if (gResizeDeathPix[i] != NULL) { 108705b261ecSmrg FreeScratchPixmapHeader(gResizeDeathPix[i]); 108805b261ecSmrg gResizeDeathPix[i] = NULL; 108905b261ecSmrg } 109005b261ecSmrg } 109105b261ecSmrg 109205b261ecSmrg if (gResizeDeathBits != NULL) { 109305b261ecSmrg xfree(gResizeDeathBits); 109405b261ecSmrg gResizeDeathBits = NULL; 109505b261ecSmrg } 109605b261ecSmrg 109705b261ecSmrg if (gravity) { 109805b261ecSmrg pScreen->CopyWindow = gResizeOldCopyWindowProc; 109905b261ecSmrg } 110005b261ecSmrg} 110105b261ecSmrg 110205b261ecSmrg 110305b261ecSmrg/* 110405b261ecSmrg * RootlessMoveWindow 110505b261ecSmrg * If kind==VTOther, window border is resizing (and borderWidth is 110605b261ecSmrg * already changed!!@#$) This case works like window resize, not move. 110705b261ecSmrg */ 110805b261ecSmrgvoid 110905b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 111005b261ecSmrg{ 111105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 111205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 111305b261ecSmrg CopyWindowProcPtr oldCopyWindowProc = NULL; 111405b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 111505b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 111605b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 111705b261ecSmrg Bool resize_after = FALSE; 111805b261ecSmrg RegionRec saveRoot; 111905b261ecSmrg 112005b261ecSmrg RL_DEBUG_MSG("movewindow start \n"); 112105b261ecSmrg 112205b261ecSmrg if (winRec) { 112305b261ecSmrg if (kind == VTMove) { 112405b261ecSmrg oldX = winRec->x; 112505b261ecSmrg oldY = winRec->y; 112605b261ecSmrg RootlessRedisplay(pWin); 112705b261ecSmrg RootlessStartDrawing(pWin); 112805b261ecSmrg } else { 112905b261ecSmrg RL_DEBUG_MSG("movewindow border resizing "); 113005b261ecSmrg 113105b261ecSmrg oldBW = winRec->borderWidth; 113205b261ecSmrg oldX = winRec->x; 113305b261ecSmrg oldY = winRec->y; 113405b261ecSmrg oldW = winRec->width; 113505b261ecSmrg oldH = winRec->height; 113605b261ecSmrg 113705b261ecSmrg newBW = wBorderWidth(pWin); 113805b261ecSmrg newX = x; 113905b261ecSmrg newY = y; 114005b261ecSmrg newW = pWin->drawable.width + 2*newBW; 114105b261ecSmrg newH = pWin->drawable.height + 2*newBW; 114205b261ecSmrg 114305b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 114405b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 114505b261ecSmrg newX, newY, newW, newH, newBW); 114605b261ecSmrg } 114705b261ecSmrg } 114805b261ecSmrg 114905b261ecSmrg HUGE_ROOT(pWin); 115005b261ecSmrg SCREEN_UNWRAP(pScreen, MoveWindow); 115105b261ecSmrg 115205b261ecSmrg if (winRec) { 115305b261ecSmrg oldCopyWindowProc = pScreen->CopyWindow; 115405b261ecSmrg pScreen->CopyWindow = RootlessNoCopyWindow; 115505b261ecSmrg } 115605b261ecSmrg pScreen->MoveWindow(pWin, x, y, pSib, kind); 115705b261ecSmrg if (winRec) { 115805b261ecSmrg pScreen->CopyWindow = oldCopyWindowProc; 115905b261ecSmrg } 116005b261ecSmrg 116105b261ecSmrg NORMAL_ROOT(pWin); 116205b261ecSmrg SCREEN_WRAP(pScreen, MoveWindow); 116305b261ecSmrg 116405b261ecSmrg if (winRec) { 116505b261ecSmrg if (kind == VTMove) { 116605b261ecSmrg winRec->x = x; 116705b261ecSmrg winRec->y = y; 116805b261ecSmrg RootlessStopDrawing(pWin, FALSE); 116905b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 117005b261ecSmrg x + SCREEN_TO_GLOBAL_X, 117105b261ecSmrg y + SCREEN_TO_GLOBAL_Y); 117205b261ecSmrg } else { 117305b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 117405b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 117505b261ecSmrg } 117605b261ecSmrg } 117705b261ecSmrg 117805b261ecSmrg RL_DEBUG_MSG("movewindow end\n"); 117905b261ecSmrg} 118005b261ecSmrg 118105b261ecSmrg 118205b261ecSmrg/* 118305b261ecSmrg * RootlessResizeWindow 118405b261ecSmrg * Note: (x, y, w, h) as passed to this procedure don't match the frame 118505b261ecSmrg * definition. (x,y) is corner of very outer edge, *outside* border. 118605b261ecSmrg * w,h is width and height *inside* border, *ignoring* border width. 118705b261ecSmrg * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) 118805b261ecSmrg * is total rect and (x+bw, y+bw, w, h) is inner rect. 118905b261ecSmrg */ 119005b261ecSmrgvoid 119105b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y, 119205b261ecSmrg unsigned int w, unsigned int h, WindowPtr pSib) 119305b261ecSmrg{ 119405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 119505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 119605b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 119705b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; 119805b261ecSmrg Bool resize_after = FALSE; 119905b261ecSmrg RegionRec saveRoot; 120005b261ecSmrg 120105b261ecSmrg RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); 120205b261ecSmrg 120305b261ecSmrg if (winRec) { 120405b261ecSmrg oldBW = winRec->borderWidth; 120505b261ecSmrg oldX = winRec->x; 120605b261ecSmrg oldY = winRec->y; 120705b261ecSmrg oldW = winRec->width; 120805b261ecSmrg oldH = winRec->height; 120905b261ecSmrg 121005b261ecSmrg newBW = oldBW; 121105b261ecSmrg newX = x; 121205b261ecSmrg newY = y; 121305b261ecSmrg newW = w + 2*newBW; 121405b261ecSmrg newH = h + 2*newBW; 121505b261ecSmrg 121605b261ecSmrg resize_after = StartFrameResize(pWin, TRUE, 121705b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 121805b261ecSmrg newX, newY, newW, newH, newBW); 121905b261ecSmrg } 122005b261ecSmrg 122105b261ecSmrg HUGE_ROOT(pWin); 122205b261ecSmrg SCREEN_UNWRAP(pScreen, ResizeWindow); 122305b261ecSmrg pScreen->ResizeWindow(pWin, x, y, w, h, pSib); 122405b261ecSmrg SCREEN_WRAP(pScreen, ResizeWindow); 122505b261ecSmrg NORMAL_ROOT(pWin); 122605b261ecSmrg 122705b261ecSmrg if (winRec) { 122805b261ecSmrg FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, 122905b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 123005b261ecSmrg } 123105b261ecSmrg 123205b261ecSmrg RL_DEBUG_MSG("resizewindow end\n"); 123305b261ecSmrg} 123405b261ecSmrg 123505b261ecSmrg 123605b261ecSmrg/* 123705b261ecSmrg * RootlessRepositionWindow 123805b261ecSmrg * Called by the implementation when a window needs to be repositioned to 123905b261ecSmrg * its correct location on the screen. This routine is typically needed 124005b261ecSmrg * due to changes in the underlying window system, such as a screen layout 124105b261ecSmrg * change. 124205b261ecSmrg */ 124305b261ecSmrgvoid 124405b261ecSmrgRootlessRepositionWindow(WindowPtr pWin) 124505b261ecSmrg{ 124605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 124705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 124805b261ecSmrg 124905b261ecSmrg if (winRec == NULL) 125005b261ecSmrg return; 125105b261ecSmrg 125205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 125305b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 125405b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 125505b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y); 125605b261ecSmrg 125705b261ecSmrg RootlessReorderWindow(pWin); 125805b261ecSmrg} 125905b261ecSmrg 126005b261ecSmrg 126105b261ecSmrg/* 126205b261ecSmrg * RootlessReparentWindow 126305b261ecSmrg * Called after a window has been reparented. Generally windows are not 126405b261ecSmrg * framed until they are mapped. However, a window may be framed early by the 126505b261ecSmrg * implementation calling RootlessFrameForWindow. (e.g. this could be needed 126605b261ecSmrg * to attach a VRAM surface to it.) If the window is subsequently reparented 126705b261ecSmrg * by the window manager before being mapped, we need to give the frame to 126805b261ecSmrg * the new top-level window. 126905b261ecSmrg */ 127005b261ecSmrgvoid 127105b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 127205b261ecSmrg{ 127305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 127405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 127505b261ecSmrg WindowPtr pTopWin; 127605b261ecSmrg 127705b261ecSmrg /* Check that window is not top-level now, but used to be. */ 127805b261ecSmrg if (IsRoot(pWin) || IsRoot(pWin->parent) 127905b261ecSmrg || IsTopLevel(pWin) || winRec == NULL) 128005b261ecSmrg { 128105b261ecSmrg goto out; 128205b261ecSmrg } 128305b261ecSmrg 128405b261ecSmrg /* If the formerly top-level window has a frame, we want to give the 128505b261ecSmrg frame to its new top-level parent. If we can't do that, we'll just 128605b261ecSmrg have to jettison it... */ 128705b261ecSmrg 128805b261ecSmrg pTopWin = TopLevelParent(pWin); 128905b261ecSmrg assert(pTopWin != pWin); 129005b261ecSmrg 129105b261ecSmrg if (WINREC(pTopWin) != NULL) { 129205b261ecSmrg /* We're screwed. */ 129305b261ecSmrg RootlessDestroyFrame(pWin, winRec); 129405b261ecSmrg } else { 129505b261ecSmrg if (!pTopWin->realized && pWin->realized) { 129605b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 129705b261ecSmrg } 129805b261ecSmrg 129905b261ecSmrg /* Switch the frame record from one to the other. */ 130005b261ecSmrg 130105b261ecSmrg WINREC(pWin) = NULL; 130205b261ecSmrg WINREC(pTopWin) = winRec; 130305b261ecSmrg 130405b261ecSmrg RootlessInitializeFrame(pTopWin, winRec); 130505b261ecSmrg RootlessReshapeFrame(pTopWin); 130605b261ecSmrg 130705b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 130805b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 130905b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 131005b261ecSmrg winRec->width, winRec->height, 131105b261ecSmrg RL_GRAVITY_NONE); 131205b261ecSmrg 131305b261ecSmrg if (SCREENREC(pScreen)->imp->SwitchWindow) { 131405b261ecSmrg SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); 131505b261ecSmrg } 131605b261ecSmrg 131705b261ecSmrg if (pTopWin->realized && !pWin->realized) 131805b261ecSmrg winRec->is_reorder_pending = TRUE; 131905b261ecSmrg } 132005b261ecSmrg 132105b261ecSmrgout: 132205b261ecSmrg if (SCREENREC(pScreen)->ReparentWindow) { 132305b261ecSmrg SCREEN_UNWRAP(pScreen, ReparentWindow); 132405b261ecSmrg pScreen->ReparentWindow(pWin, pPriorParent); 132505b261ecSmrg SCREEN_WRAP(pScreen, ReparentWindow); 132605b261ecSmrg } 132705b261ecSmrg} 132805b261ecSmrg 132905b261ecSmrg 133005b261ecSmrg/* 133105b261ecSmrg * SetPixmapOfAncestors 133205b261ecSmrg * Set the Pixmaps on all ParentRelative windows up the ancestor chain. 133305b261ecSmrg */ 133405b261ecSmrgstatic void 133505b261ecSmrgSetPixmapOfAncestors(WindowPtr pWin) 133605b261ecSmrg{ 133705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 133805b261ecSmrg WindowPtr topWin = TopLevelParent(pWin); 133905b261ecSmrg RootlessWindowRec *topWinRec = WINREC(topWin); 134005b261ecSmrg 134105b261ecSmrg while (pWin->backgroundState == ParentRelative) { 134205b261ecSmrg if (pWin == topWin) { 134305b261ecSmrg // disallow ParentRelative background state on top level 134405b261ecSmrg XID pixel = 0; 134505b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 134605b261ecSmrg RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); 134705b261ecSmrg break; 134805b261ecSmrg } 134905b261ecSmrg 135005b261ecSmrg pWin = pWin->parent; 135105b261ecSmrg pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); 135205b261ecSmrg } 135305b261ecSmrg} 135405b261ecSmrg 135505b261ecSmrg 135605b261ecSmrg/* 135705b261ecSmrg * RootlessPaintWindowBackground 135805b261ecSmrg */ 135905b261ecSmrgvoid 136005b261ecSmrgRootlessPaintWindowBackground(WindowPtr pWin, RegionPtr pRegion, int what) 136105b261ecSmrg{ 136205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 136305b261ecSmrg 136405b261ecSmrg if (IsRoot(pWin)) 136505b261ecSmrg return; 136605b261ecSmrg 136705b261ecSmrg RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i) ", 136805b261ecSmrg pWin, IsFramedWindow(pWin)); 136905b261ecSmrg 137005b261ecSmrg if (IsFramedWindow(pWin)) { 137105b261ecSmrg RootlessStartDrawing(pWin); 137205b261ecSmrg RootlessDamageRegion(pWin, pRegion); 137305b261ecSmrg 137405b261ecSmrg // For ParentRelative windows, we have to make sure the window 137505b261ecSmrg // pixmap is set correctly all the way up the ancestor chain. 137605b261ecSmrg if (pWin->backgroundState == ParentRelative) { 137705b261ecSmrg SetPixmapOfAncestors(pWin); 137805b261ecSmrg } 137905b261ecSmrg } 138005b261ecSmrg 138105b261ecSmrg SCREEN_UNWRAP(pScreen, PaintWindowBackground); 138205b261ecSmrg pScreen->PaintWindowBackground(pWin, pRegion, what); 138305b261ecSmrg SCREEN_WRAP(pScreen, PaintWindowBackground); 138405b261ecSmrg 138505b261ecSmrg RL_DEBUG_MSG("paintwindowbackground end\n"); 138605b261ecSmrg} 138705b261ecSmrg 138805b261ecSmrg 138905b261ecSmrg/* 139005b261ecSmrg * RootlessPaintWindowBorder 139105b261ecSmrg */ 139205b261ecSmrgvoid 139305b261ecSmrgRootlessPaintWindowBorder(WindowPtr pWin, RegionPtr pRegion, int what) 139405b261ecSmrg{ 139505b261ecSmrg RL_DEBUG_MSG("paintwindowborder start (win 0x%x) ", pWin); 139605b261ecSmrg 139705b261ecSmrg if (IsFramedWindow(pWin)) { 139805b261ecSmrg RootlessStartDrawing(pWin); 139905b261ecSmrg RootlessDamageRegion(pWin, pRegion); 140005b261ecSmrg 140105b261ecSmrg // For ParentRelative windows with tiled borders, we have to make 140205b261ecSmrg // sure the window pixmap is set correctly all the way up the 140305b261ecSmrg // ancestor chain. 140405b261ecSmrg if (!pWin->borderIsPixel && 140505b261ecSmrg pWin->backgroundState == ParentRelative) 140605b261ecSmrg { 140705b261ecSmrg SetPixmapOfAncestors(pWin); 140805b261ecSmrg } 140905b261ecSmrg } 141005b261ecSmrg 141105b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, PaintWindowBorder); 141205b261ecSmrg pWin->drawable.pScreen->PaintWindowBorder(pWin, pRegion, what); 141305b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, PaintWindowBorder); 141405b261ecSmrg 141505b261ecSmrg RL_DEBUG_MSG("paintwindowborder end\n"); 141605b261ecSmrg} 141705b261ecSmrg 141805b261ecSmrg 141905b261ecSmrg/* 142005b261ecSmrg * RootlessChangeBorderWidth 142105b261ecSmrg * FIXME: untested! 142205b261ecSmrg * pWin inside corner stays the same; pWin->drawable.[xy] stays the same 142305b261ecSmrg * Frame moves and resizes. 142405b261ecSmrg */ 142505b261ecSmrgvoid 142605b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) 142705b261ecSmrg{ 142805b261ecSmrg RegionRec saveRoot; 142905b261ecSmrg Bool resize_after = FALSE; 143005b261ecSmrg 143105b261ecSmrg RL_DEBUG_MSG("change border width "); 143205b261ecSmrg 143305b261ecSmrg if (width != wBorderWidth(pWin)) { 143405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 143505b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 143605b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 143705b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 143805b261ecSmrg 143905b261ecSmrg if (winRec) { 144005b261ecSmrg oldBW = winRec->borderWidth; 144105b261ecSmrg oldX = winRec->x; 144205b261ecSmrg oldY = winRec->y; 144305b261ecSmrg oldW = winRec->width; 144405b261ecSmrg oldH = winRec->height; 144505b261ecSmrg 144605b261ecSmrg newBW = width; 144705b261ecSmrg newX = pWin->drawable.x - newBW; 144805b261ecSmrg newY = pWin->drawable.y - newBW; 144905b261ecSmrg newW = pWin->drawable.width + 2*newBW; 145005b261ecSmrg newH = pWin->drawable.height + 2*newBW; 145105b261ecSmrg 145205b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 145305b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 145405b261ecSmrg newX, newY, newW, newH, newBW); 145505b261ecSmrg } 145605b261ecSmrg 145705b261ecSmrg HUGE_ROOT(pWin); 145805b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); 145905b261ecSmrg pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); 146005b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); 146105b261ecSmrg NORMAL_ROOT(pWin); 146205b261ecSmrg 146305b261ecSmrg if (winRec) { 146405b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 146505b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 146605b261ecSmrg } 146705b261ecSmrg } 146805b261ecSmrg 146905b261ecSmrg RL_DEBUG_MSG("change border width end\n"); 147005b261ecSmrg} 1471