rootlessWindow.c revision 9ace9065
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> 394642e01fSmrg#include <X11/Xatom.h> 406747b715Smrg#ifdef __APPLE__ 416747b715Smrg#include <Xplugin.h> 424642e01fSmrg#include "mi.h" 434642e01fSmrg#include "pixmapstr.h" 444642e01fSmrg#include "windowstr.h" 454642e01fSmrg//#include <X11/extensions/applewm.h> 464642e01fSmrgextern int darwinMainScreenX, darwinMainScreenY; 476747b715Smrgextern Bool no_configure_window; 484642e01fSmrg#endif 494642e01fSmrg#include "fb.h" 504642e01fSmrg 5105b261ecSmrg#include "rootlessCommon.h" 5205b261ecSmrg#include "rootlessWindow.h" 5305b261ecSmrg 5405b261ecSmrg#define SCREEN_TO_GLOBAL_X \ 556747b715Smrg (pScreen->x + rootlessGlobalOffsetX) 5605b261ecSmrg#define SCREEN_TO_GLOBAL_Y \ 576747b715Smrg (pScreen->y + rootlessGlobalOffsetY) 5805b261ecSmrg 594642e01fSmrg#define DEFINE_ATOM_HELPER(func,atom_name) \ 604642e01fSmrg static Atom func (void) { \ 614642e01fSmrg static unsigned int generation = 0; \ 624642e01fSmrg static Atom atom; \ 634642e01fSmrg if (generation != serverGeneration) { \ 644642e01fSmrg generation = serverGeneration; \ 654642e01fSmrg atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ 664642e01fSmrg } \ 674642e01fSmrg return atom; \ 684642e01fSmrg } 694642e01fSmrg 704642e01fSmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID") 714642e01fSmrg 724642e01fSmrgstatic Bool windows_hidden; 734642e01fSmrg// TODO - abstract xp functions 744642e01fSmrg 756747b715Smrg#ifdef __APPLE__ 764642e01fSmrg 776747b715Smrg// XXX: identical to x_cvt_vptr_to_uint ? 786747b715Smrg#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) 794642e01fSmrg 804642e01fSmrgvoid 814642e01fSmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state) 824642e01fSmrg{ 834642e01fSmrg RootlessWindowRec *winRec; 844642e01fSmrg 854642e01fSmrg if (pWin == NULL) return; 864642e01fSmrg 874642e01fSmrg winRec = WINREC (pWin); 884642e01fSmrg if (winRec == NULL) return; 894642e01fSmrg 904642e01fSmrg winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); 914642e01fSmrg winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); 924642e01fSmrg pWin->rootlessUnhittable = winRec->is_offscreen; 934642e01fSmrg} 944642e01fSmrg 954642e01fSmrgvoid RootlessNativeWindowMoved (WindowPtr pWin) { 964642e01fSmrg xp_box bounds; 974642e01fSmrg int sx, sy, err; 984642e01fSmrg XID vlist[2]; 994642e01fSmrg Mask mask; 1004642e01fSmrg ClientPtr pClient; 1014642e01fSmrg RootlessWindowRec *winRec; 1024642e01fSmrg 1034642e01fSmrg winRec = WINREC(pWin); 1044642e01fSmrg 1054642e01fSmrg if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return; 1064642e01fSmrg 1076747b715Smrg sx = pWin->drawable.pScreen->x + darwinMainScreenX; 1086747b715Smrg sy = pWin->drawable.pScreen->y + darwinMainScreenY; 1094642e01fSmrg 1104642e01fSmrg /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ 1114642e01fSmrg vlist[0] = (INT16) bounds.x1 - sx; 1124642e01fSmrg vlist[1] = (INT16) bounds.y1 - sy; 1134642e01fSmrg mask = CWX | CWY; 1144642e01fSmrg 1154642e01fSmrg /* pretend we're the owner of the window! */ 1166747b715Smrg err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess); 1174642e01fSmrg if(err != Success) { 1184642e01fSmrg ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id); 1194642e01fSmrg return; 1204642e01fSmrg } 1214642e01fSmrg 1224642e01fSmrg /* Don't want to do anything to the physical window (avoids 1234642e01fSmrg notification-response feedback loops) */ 1244642e01fSmrg 1254642e01fSmrg no_configure_window = TRUE; 1264642e01fSmrg ConfigureWindow (pWin, mask, vlist, pClient); 1274642e01fSmrg no_configure_window = FALSE; 1284642e01fSmrg} 1294642e01fSmrg 1306747b715Smrg#endif /* __APPLE__ */ 13105b261ecSmrg 13205b261ecSmrg/* 13305b261ecSmrg * RootlessCreateWindow 13405b261ecSmrg * For now, don't create a physical window until either the window is 13505b261ecSmrg * realized, or we really need it (e.g. to attach VRAM surfaces to). 13605b261ecSmrg * Do reset the window size so it's not clipped by the root window. 13705b261ecSmrg */ 13805b261ecSmrgBool 13905b261ecSmrgRootlessCreateWindow(WindowPtr pWin) 14005b261ecSmrg{ 14105b261ecSmrg Bool result; 14205b261ecSmrg RegionRec saveRoot; 14305b261ecSmrg 1444642e01fSmrg SETWINREC(pWin, NULL); 1454642e01fSmrg dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); 14605b261ecSmrg 14705b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); 14805b261ecSmrg 14905b261ecSmrg if (!IsRoot(pWin)) { 15005b261ecSmrg /* win/border size set by DIX, not by wrapped CreateWindow, so 15105b261ecSmrg correct it here. Don't HUGE_ROOT when pWin is the root! */ 15205b261ecSmrg 15305b261ecSmrg HUGE_ROOT(pWin); 15405b261ecSmrg SetWinSize(pWin); 15505b261ecSmrg SetBorderSize(pWin); 15605b261ecSmrg } 15705b261ecSmrg 15805b261ecSmrg result = pWin->drawable.pScreen->CreateWindow(pWin); 15905b261ecSmrg 16005b261ecSmrg if (pWin->parent) { 16105b261ecSmrg NORMAL_ROOT(pWin); 16205b261ecSmrg } 16305b261ecSmrg 16405b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); 16505b261ecSmrg 16605b261ecSmrg return result; 16705b261ecSmrg} 16805b261ecSmrg 16905b261ecSmrg 17005b261ecSmrg/* 17105b261ecSmrg * RootlessDestroyFrame 17205b261ecSmrg * Destroy the physical window associated with the given window. 17305b261ecSmrg */ 17405b261ecSmrgstatic void 17505b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) 17605b261ecSmrg{ 1776747b715Smrg SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid); 1786747b715Smrg free(winRec); 1794642e01fSmrg SETWINREC(pWin, NULL); 18005b261ecSmrg} 18105b261ecSmrg 18205b261ecSmrg 18305b261ecSmrg/* 18405b261ecSmrg * RootlessDestroyWindow 18505b261ecSmrg * Destroy the physical window associated with the given window. 18605b261ecSmrg */ 18705b261ecSmrgBool 18805b261ecSmrgRootlessDestroyWindow(WindowPtr pWin) 18905b261ecSmrg{ 19005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 19105b261ecSmrg Bool result; 19205b261ecSmrg 19305b261ecSmrg if (winRec != NULL) { 19405b261ecSmrg RootlessDestroyFrame(pWin, winRec); 19505b261ecSmrg } 19605b261ecSmrg 19705b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); 19805b261ecSmrg result = pWin->drawable.pScreen->DestroyWindow(pWin); 19905b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); 20005b261ecSmrg 20105b261ecSmrg return result; 20205b261ecSmrg} 20305b261ecSmrg 20405b261ecSmrg 20505b261ecSmrg 20605b261ecSmrgstatic Bool 20705b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape) 20805b261ecSmrg{ 20905b261ecSmrg if (wBoundingShape(pWin) == NULL) 21005b261ecSmrg return FALSE; 21105b261ecSmrg 21205b261ecSmrg /* wBoundingShape is relative to *inner* origin of window. 21305b261ecSmrg Translate by borderWidth to get the outside-relative position. */ 21405b261ecSmrg 2156747b715Smrg RegionNull(pShape); 2166747b715Smrg RegionCopy(pShape, wBoundingShape(pWin)); 2176747b715Smrg RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth); 21805b261ecSmrg 21905b261ecSmrg return TRUE; 22005b261ecSmrg} 22105b261ecSmrg 22205b261ecSmrg 22305b261ecSmrg/* 22405b261ecSmrg * RootlessReshapeFrame 22505b261ecSmrg * Set the frame shape. 22605b261ecSmrg */ 22705b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin) 22805b261ecSmrg{ 22905b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 23005b261ecSmrg RegionRec newShape; 23105b261ecSmrg RegionPtr pShape; 23205b261ecSmrg 23305b261ecSmrg // If the window is not yet framed, do nothing 23405b261ecSmrg if (winRec == NULL) 23505b261ecSmrg return; 23605b261ecSmrg 23705b261ecSmrg if (IsRoot(pWin)) 23805b261ecSmrg return; 23905b261ecSmrg 24005b261ecSmrg RootlessStopDrawing(pWin, FALSE); 24105b261ecSmrg 24205b261ecSmrg pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; 24305b261ecSmrg 24405b261ecSmrg#ifdef ROOTLESSDEBUG 24505b261ecSmrg RL_DEBUG_MSG("reshaping..."); 24605b261ecSmrg if (pShape != NULL) { 24705b261ecSmrg RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", 2486747b715Smrg RegionNumRects(&newShape), 24905b261ecSmrg newShape.extents.x1, newShape.extents.y1, 25005b261ecSmrg newShape.extents.x2, newShape.extents.y2); 25105b261ecSmrg } else { 25205b261ecSmrg RL_DEBUG_MSG("no shape "); 25305b261ecSmrg } 25405b261ecSmrg#endif 25505b261ecSmrg 2566747b715Smrg SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape); 25705b261ecSmrg 25805b261ecSmrg if (pShape != NULL) 2596747b715Smrg RegionUninit(&newShape); 26005b261ecSmrg} 26105b261ecSmrg 26205b261ecSmrg 26305b261ecSmrg/* 26405b261ecSmrg * RootlessSetShape 26505b261ecSmrg * Shape is usually set before a window is mapped and the window will 26605b261ecSmrg * not have a frame associated with it. In this case, the frame will be 26705b261ecSmrg * shaped when the window is framed. 26805b261ecSmrg */ 26905b261ecSmrgvoid 2706747b715SmrgRootlessSetShape(WindowPtr pWin, int kind) 27105b261ecSmrg{ 27205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 27305b261ecSmrg 27405b261ecSmrg SCREEN_UNWRAP(pScreen, SetShape); 2756747b715Smrg pScreen->SetShape(pWin, kind); 27605b261ecSmrg SCREEN_WRAP(pScreen, SetShape); 27705b261ecSmrg 27805b261ecSmrg RootlessReshapeFrame(pWin); 27905b261ecSmrg} 28005b261ecSmrg 28105b261ecSmrg 28205b261ecSmrg 28305b261ecSmrg/* Disallow ParentRelative background on top-level windows 2844642e01fSmrg because the root window doesn't really have the right background. 2854642e01fSmrg */ 28605b261ecSmrgBool 28705b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) 28805b261ecSmrg{ 28905b261ecSmrg Bool result; 29005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 29105b261ecSmrg 29205b261ecSmrg RL_DEBUG_MSG("change window attributes start "); 29305b261ecSmrg 29405b261ecSmrg SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); 29505b261ecSmrg result = pScreen->ChangeWindowAttributes(pWin, vmask); 29605b261ecSmrg SCREEN_WRAP(pScreen, ChangeWindowAttributes); 29705b261ecSmrg 29805b261ecSmrg if (WINREC(pWin)) { 29905b261ecSmrg // disallow ParentRelative background state 30005b261ecSmrg if (pWin->backgroundState == ParentRelative) { 30105b261ecSmrg XID pixel = 0; 30205b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 30305b261ecSmrg } 30405b261ecSmrg } 30505b261ecSmrg 30605b261ecSmrg RL_DEBUG_MSG("change window attributes end\n"); 30705b261ecSmrg return result; 30805b261ecSmrg} 30905b261ecSmrg 31005b261ecSmrg 31105b261ecSmrg/* 31205b261ecSmrg * RootlessPositionWindow 31305b261ecSmrg * This is a hook for when DIX moves or resizes a window. 31405b261ecSmrg * Update the frame position now although the physical window is moved 31505b261ecSmrg * in RootlessMoveWindow. (x, y) are *inside* position. After this, 31605b261ecSmrg * mi and fb are expecting the pixmap to be at the new location. 31705b261ecSmrg */ 31805b261ecSmrgBool 31905b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y) 32005b261ecSmrg{ 32105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 32205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 32305b261ecSmrg Bool result; 32405b261ecSmrg 32505b261ecSmrg RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); 32605b261ecSmrg 32705b261ecSmrg if (winRec) { 32805b261ecSmrg if (winRec->is_drawing) { 32905b261ecSmrg // Reset frame's pixmap and move it to the new position. 33005b261ecSmrg int bw = wBorderWidth(pWin); 33105b261ecSmrg 33205b261ecSmrg winRec->pixmap->devPrivate.ptr = winRec->pixelData; 33305b261ecSmrg SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); 33405b261ecSmrg } 33505b261ecSmrg } 33605b261ecSmrg 33705b261ecSmrg SCREEN_UNWRAP(pScreen, PositionWindow); 33805b261ecSmrg result = pScreen->PositionWindow(pWin, x, y); 33905b261ecSmrg SCREEN_WRAP(pScreen, PositionWindow); 34005b261ecSmrg 34105b261ecSmrg RL_DEBUG_MSG("positionwindow end\n"); 34205b261ecSmrg return result; 34305b261ecSmrg} 34405b261ecSmrg 34505b261ecSmrg 34605b261ecSmrg/* 34705b261ecSmrg * RootlessInitializeFrame 34805b261ecSmrg * Initialize some basic attributes of the frame. Note that winRec 34905b261ecSmrg * may already have valid data in it, so don't overwrite anything 35005b261ecSmrg * valuable. 35105b261ecSmrg */ 35205b261ecSmrgstatic void 35305b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) 35405b261ecSmrg{ 35505b261ecSmrg DrawablePtr d = &pWin->drawable; 35605b261ecSmrg int bw = wBorderWidth(pWin); 35705b261ecSmrg 35805b261ecSmrg winRec->win = pWin; 35905b261ecSmrg 36005b261ecSmrg winRec->x = d->x - bw; 36105b261ecSmrg winRec->y = d->y - bw; 36205b261ecSmrg winRec->width = d->width + 2*bw; 36305b261ecSmrg winRec->height = d->height + 2*bw; 36405b261ecSmrg winRec->borderWidth = bw; 36505b261ecSmrg} 36605b261ecSmrg 36705b261ecSmrg/* 36805b261ecSmrg * RootlessEnsureFrame 36905b261ecSmrg * Make sure the given window is framed. If the window doesn't have a 37005b261ecSmrg * physical window associated with it, attempt to create one. If that 37105b261ecSmrg * is unsuccessful, return NULL. 37205b261ecSmrg */ 37305b261ecSmrgstatic RootlessWindowRec * 37405b261ecSmrgRootlessEnsureFrame(WindowPtr pWin) 37505b261ecSmrg{ 37605b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 37705b261ecSmrg RootlessWindowRec *winRec; 37805b261ecSmrg RegionRec shape; 37905b261ecSmrg RegionPtr pShape = NULL; 38005b261ecSmrg 38105b261ecSmrg if (WINREC(pWin) != NULL) 38205b261ecSmrg return WINREC(pWin); 38305b261ecSmrg 3844642e01fSmrg if (!IsTopLevel(pWin) && !IsRoot(pWin)) 38505b261ecSmrg return NULL; 38605b261ecSmrg 38705b261ecSmrg if (pWin->drawable.class != InputOutput) 38805b261ecSmrg return NULL; 38905b261ecSmrg 3906747b715Smrg winRec = malloc(sizeof(RootlessWindowRec)); 39105b261ecSmrg 39205b261ecSmrg if (!winRec) 39305b261ecSmrg return NULL; 39405b261ecSmrg 39505b261ecSmrg RootlessInitializeFrame(pWin, winRec); 39605b261ecSmrg 39705b261ecSmrg winRec->is_drawing = FALSE; 39805b261ecSmrg winRec->is_reorder_pending = FALSE; 39905b261ecSmrg winRec->pixmap = NULL; 40005b261ecSmrg winRec->wid = NULL; 4016747b715Smrg winRec->level = 0; 40205b261ecSmrg 4034642e01fSmrg SETWINREC(pWin, winRec); 40405b261ecSmrg 40505b261ecSmrg // Set the frame's shape if the window is shaped 40605b261ecSmrg if (RootlessGetShape(pWin, &shape)) 40705b261ecSmrg pShape = &shape; 40805b261ecSmrg 40905b261ecSmrg RL_DEBUG_MSG("creating frame "); 41005b261ecSmrg 41105b261ecSmrg if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, 41205b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 41305b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 41405b261ecSmrg pShape)) 41505b261ecSmrg { 41605b261ecSmrg RL_DEBUG_MSG("implementation failed to create frame!\n"); 4176747b715Smrg free(winRec); 4184642e01fSmrg SETWINREC(pWin, NULL); 41905b261ecSmrg return NULL; 42005b261ecSmrg } 42105b261ecSmrg 4224642e01fSmrg if (pWin->drawable.depth == 8) 4234642e01fSmrg RootlessFlushWindowColormap(pWin); 4244642e01fSmrg 42505b261ecSmrg if (pShape != NULL) 4266747b715Smrg RegionUninit(&shape); 42705b261ecSmrg 42805b261ecSmrg return winRec; 42905b261ecSmrg} 43005b261ecSmrg 43105b261ecSmrg 43205b261ecSmrg/* 43305b261ecSmrg * RootlessRealizeWindow 43405b261ecSmrg * The frame is usually created here and not in CreateWindow so that 43505b261ecSmrg * windows do not eat memory until they are realized. 43605b261ecSmrg */ 43705b261ecSmrgBool 43805b261ecSmrgRootlessRealizeWindow(WindowPtr pWin) 43905b261ecSmrg{ 44005b261ecSmrg Bool result; 44105b261ecSmrg RegionRec saveRoot; 44205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 44305b261ecSmrg 44405b261ecSmrg RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); 44505b261ecSmrg 44605b261ecSmrg if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { 44705b261ecSmrg RootlessWindowRec *winRec; 44805b261ecSmrg 44905b261ecSmrg winRec = RootlessEnsureFrame(pWin); 45005b261ecSmrg if (winRec == NULL) 45105b261ecSmrg return FALSE; 45205b261ecSmrg 45305b261ecSmrg winRec->is_reorder_pending = TRUE; 45405b261ecSmrg 45505b261ecSmrg RL_DEBUG_MSG("Top level window "); 45605b261ecSmrg 45705b261ecSmrg // Disallow ParentRelative background state on top-level windows. 45805b261ecSmrg // This might have been set before the window was mapped. 45905b261ecSmrg if (pWin->backgroundState == ParentRelative) { 46005b261ecSmrg XID pixel = 0; 46105b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 46205b261ecSmrg } 46305b261ecSmrg } 46405b261ecSmrg 46505b261ecSmrg if (!IsRoot(pWin)) HUGE_ROOT(pWin); 46605b261ecSmrg SCREEN_UNWRAP(pScreen, RealizeWindow); 46705b261ecSmrg result = pScreen->RealizeWindow(pWin); 46805b261ecSmrg SCREEN_WRAP(pScreen, RealizeWindow); 46905b261ecSmrg if (!IsRoot(pWin)) NORMAL_ROOT(pWin); 47005b261ecSmrg 47105b261ecSmrg RL_DEBUG_MSG("realizewindow end\n"); 47205b261ecSmrg return result; 47305b261ecSmrg} 47405b261ecSmrg 47505b261ecSmrg 47605b261ecSmrg/* 47705b261ecSmrg * RootlessFrameForWindow 47805b261ecSmrg * Returns the frame ID for the physical window displaying the given window. 47905b261ecSmrg * If CREATE is true and the window has no frame, attempt to create one. 48005b261ecSmrg */ 48105b261ecSmrgRootlessFrameID 48205b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create) 48305b261ecSmrg{ 48405b261ecSmrg WindowPtr pTopWin; 48505b261ecSmrg RootlessWindowRec *winRec; 48605b261ecSmrg 48705b261ecSmrg pTopWin = TopLevelParent(pWin); 48805b261ecSmrg if (pTopWin == NULL) 48905b261ecSmrg return NULL; 49005b261ecSmrg 49105b261ecSmrg winRec = WINREC(pTopWin); 49205b261ecSmrg 49305b261ecSmrg if (winRec == NULL && create && pWin->drawable.class == InputOutput) { 49405b261ecSmrg winRec = RootlessEnsureFrame(pTopWin); 49505b261ecSmrg } 49605b261ecSmrg 49705b261ecSmrg if (winRec == NULL) 49805b261ecSmrg return NULL; 49905b261ecSmrg 50005b261ecSmrg return winRec->wid; 50105b261ecSmrg} 50205b261ecSmrg 50305b261ecSmrg 50405b261ecSmrg/* 50505b261ecSmrg * RootlessUnrealizeWindow 50605b261ecSmrg * Unmap the physical window. 50705b261ecSmrg */ 50805b261ecSmrgBool 50905b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin) 51005b261ecSmrg{ 51105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 51205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 51305b261ecSmrg Bool result; 51405b261ecSmrg 51505b261ecSmrg RL_DEBUG_MSG("unrealizewindow start "); 51605b261ecSmrg 51705b261ecSmrg if (winRec) { 51805b261ecSmrg RootlessStopDrawing(pWin, FALSE); 51905b261ecSmrg 52005b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 52105b261ecSmrg 52205b261ecSmrg winRec->is_reorder_pending = FALSE; 52305b261ecSmrg } 52405b261ecSmrg 52505b261ecSmrg SCREEN_UNWRAP(pScreen, UnrealizeWindow); 52605b261ecSmrg result = pScreen->UnrealizeWindow(pWin); 52705b261ecSmrg SCREEN_WRAP(pScreen, UnrealizeWindow); 52805b261ecSmrg 52905b261ecSmrg RL_DEBUG_MSG("unrealizewindow end\n"); 53005b261ecSmrg return result; 53105b261ecSmrg} 53205b261ecSmrg 53305b261ecSmrg 53405b261ecSmrg/* 53505b261ecSmrg * RootlessReorderWindow 53605b261ecSmrg * Reorder the frame associated with the given window so that it's 53705b261ecSmrg * physically above the window below it in the X stacking order. 53805b261ecSmrg */ 53905b261ecSmrgvoid 54005b261ecSmrgRootlessReorderWindow(WindowPtr pWin) 54105b261ecSmrg{ 54205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 54305b261ecSmrg 5444642e01fSmrg if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) { 54505b261ecSmrg WindowPtr newPrevW; 54605b261ecSmrg RootlessWindowRec *newPrev; 54705b261ecSmrg RootlessFrameID newPrevID; 54805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 54905b261ecSmrg 55005b261ecSmrg /* Check if the implementation wants the frame to not be reordered 55105b261ecSmrg even though the X11 window is restacked. This can be useful if 55205b261ecSmrg frames are ordered-in with animation so that the reordering is not 55305b261ecSmrg done until the animation is complete. */ 55405b261ecSmrg if (SCREENREC(pScreen)->imp->DoReorderWindow) { 55505b261ecSmrg if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) 55605b261ecSmrg return; 55705b261ecSmrg } 55805b261ecSmrg 55905b261ecSmrg RootlessStopDrawing(pWin, FALSE); 56005b261ecSmrg 5616747b715Smrg /* Find the next window above this one that has a mapped frame. 5626747b715Smrg * Only include cases where the windows are in the same category of 5636747b715Smrg * hittability to ensure offscreen windows dont get restacked 5646747b715Smrg * relative to onscreen ones (but that the offscreen ones maintain 5656747b715Smrg * their stacking order if they are explicitly asked to Reorder 5666747b715Smrg */ 56705b261ecSmrg 56805b261ecSmrg newPrevW = pWin->prevSib; 5696747b715Smrg while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable)) 57005b261ecSmrg newPrevW = newPrevW->prevSib; 57105b261ecSmrg 57205b261ecSmrg newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; 57305b261ecSmrg newPrevID = newPrev != NULL ? newPrev->wid : 0; 57405b261ecSmrg 57505b261ecSmrg /* If it exists, reorder the frame above us first. */ 57605b261ecSmrg 57705b261ecSmrg if (newPrev && newPrev->is_reorder_pending) { 57805b261ecSmrg newPrev->is_reorder_pending = FALSE; 57905b261ecSmrg RootlessReorderWindow(newPrevW); 58005b261ecSmrg } 58105b261ecSmrg 58205b261ecSmrg SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); 58305b261ecSmrg } 58405b261ecSmrg} 58505b261ecSmrg 58605b261ecSmrg 58705b261ecSmrg/* 58805b261ecSmrg * RootlessRestackWindow 58905b261ecSmrg * This is a hook for when DIX changes the window stacking order. 59005b261ecSmrg * The window has already been inserted into its new position in the 59105b261ecSmrg * DIX window stack. We need to change the order of the physical 59205b261ecSmrg * window to match. 59305b261ecSmrg */ 59405b261ecSmrgvoid 59505b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) 59605b261ecSmrg{ 59705b261ecSmrg RegionRec saveRoot; 59805b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 59905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 60005b261ecSmrg 60105b261ecSmrg RL_DEBUG_MSG("restackwindow start "); 60205b261ecSmrg if (winRec) 60305b261ecSmrg RL_DEBUG_MSG("restack top level \n"); 60405b261ecSmrg 60505b261ecSmrg HUGE_ROOT(pWin); 60605b261ecSmrg SCREEN_UNWRAP(pScreen, RestackWindow); 60705b261ecSmrg 60805b261ecSmrg if (pScreen->RestackWindow) 60905b261ecSmrg pScreen->RestackWindow(pWin, pOldNextSib); 61005b261ecSmrg 61105b261ecSmrg SCREEN_WRAP(pScreen, RestackWindow); 61205b261ecSmrg NORMAL_ROOT(pWin); 61305b261ecSmrg 61405b261ecSmrg if (winRec && pWin->viewable) { 61505b261ecSmrg RootlessReorderWindow(pWin); 61605b261ecSmrg } 61705b261ecSmrg 61805b261ecSmrg RL_DEBUG_MSG("restackwindow end\n"); 61905b261ecSmrg} 62005b261ecSmrg 62105b261ecSmrg/* 62205b261ecSmrg * Specialized window copy procedures 62305b261ecSmrg */ 62405b261ecSmrg 62505b261ecSmrg// Globals needed during window resize and move. 62605b261ecSmrgstatic pointer gResizeDeathBits = NULL; 62705b261ecSmrgstatic int gResizeDeathCount = 0; 62805b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; 62905b261ecSmrgstatic BoxRec gResizeDeathBounds[2]; 63005b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; 63105b261ecSmrg 63205b261ecSmrg/* 63305b261ecSmrg * RootlessNoCopyWindow 63405b261ecSmrg * CopyWindow() that doesn't do anything. For MoveWindow() of 63505b261ecSmrg * top-level windows. 63605b261ecSmrg */ 63705b261ecSmrgstatic void 63805b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 63905b261ecSmrg RegionPtr prgnSrc) 64005b261ecSmrg{ 64105b261ecSmrg // some code expects the region to be translated 64205b261ecSmrg int dx = ptOldOrg.x - pWin->drawable.x; 64305b261ecSmrg int dy = ptOldOrg.y - pWin->drawable.y; 64405b261ecSmrg 64505b261ecSmrg RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); 64605b261ecSmrg 6476747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 64805b261ecSmrg} 64905b261ecSmrg 65005b261ecSmrg 65105b261ecSmrg/* 65205b261ecSmrg * RootlessResizeCopyWindow 65305b261ecSmrg * CopyWindow used during ResizeWindow for gravity moves. Based on 65405b261ecSmrg * fbCopyWindow. The original always draws on the root pixmap, which 65505b261ecSmrg * we don't have. Instead, draw on the parent window's pixmap. 65605b261ecSmrg * Resize version: the old location's pixels are in gResizeCopyWindowSource. 65705b261ecSmrg */ 65805b261ecSmrgstatic void 65905b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 66005b261ecSmrg RegionPtr prgnSrc) 66105b261ecSmrg{ 66205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 66305b261ecSmrg RegionRec rgnDst; 66405b261ecSmrg int dx, dy; 66505b261ecSmrg 66605b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); 66705b261ecSmrg 66805b261ecSmrg /* Don't unwrap pScreen->CopyWindow. 66905b261ecSmrg The bogus rewrap with RootlessCopyWindow causes a crash if 67005b261ecSmrg CopyWindow is called again during the same resize. */ 67105b261ecSmrg 67205b261ecSmrg if (gResizeDeathCount == 0) 67305b261ecSmrg return; 67405b261ecSmrg 67505b261ecSmrg RootlessStartDrawing(pWin); 67605b261ecSmrg 67705b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 67805b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 6796747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 6806747b715Smrg RegionNull(&rgnDst); 6816747b715Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 68205b261ecSmrg 68305b261ecSmrg if (gResizeDeathCount == 1) { 68405b261ecSmrg /* Simple case, we only have a single source pixmap. */ 68505b261ecSmrg 68605b261ecSmrg fbCopyRegion(&gResizeDeathPix[0]->drawable, 68705b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 68805b261ecSmrg &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 68905b261ecSmrg } 69005b261ecSmrg else { 69105b261ecSmrg int i; 69205b261ecSmrg RegionRec clip, clipped; 69305b261ecSmrg 69405b261ecSmrg /* More complex case, N source pixmaps (usually two). So we 69505b261ecSmrg intersect the destination with each source and copy those bits. */ 69605b261ecSmrg 69705b261ecSmrg for (i = 0; i < gResizeDeathCount; i++) { 6986747b715Smrg RegionInit(&clip, gResizeDeathBounds + 0, 1); 6996747b715Smrg RegionNull(&clipped); 7006747b715Smrg RegionIntersect(&rgnDst, &clip, &clipped); 70105b261ecSmrg 70205b261ecSmrg fbCopyRegion(&gResizeDeathPix[i]->drawable, 70305b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 70405b261ecSmrg &clipped, dx, dy, fbCopyWindowProc, 0, 0); 70505b261ecSmrg 7066747b715Smrg RegionUninit(&clipped); 7076747b715Smrg RegionUninit(&clip); 70805b261ecSmrg } 70905b261ecSmrg } 71005b261ecSmrg 71105b261ecSmrg /* Don't update - resize will update everything */ 7126747b715Smrg RegionUninit(&rgnDst); 71305b261ecSmrg 71405b261ecSmrg fbValidateDrawable(&pWin->drawable); 71505b261ecSmrg 71605b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB end\n"); 71705b261ecSmrg} 71805b261ecSmrg 71905b261ecSmrg 72005b261ecSmrg/* 72105b261ecSmrg * RootlessCopyWindow 72205b261ecSmrg * Update *new* location of window. Old location is redrawn with 7234642e01fSmrg * miPaintWindow. Cloned from fbCopyWindow. 72405b261ecSmrg * The original always draws on the root pixmap, which we don't have. 72505b261ecSmrg * Instead, draw on the parent window's pixmap. 72605b261ecSmrg */ 72705b261ecSmrgvoid 72805b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 72905b261ecSmrg{ 73005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 73105b261ecSmrg RegionRec rgnDst; 73205b261ecSmrg int dx, dy; 73305b261ecSmrg BoxPtr extents; 73405b261ecSmrg int area; 73505b261ecSmrg 73605b261ecSmrg RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); 73705b261ecSmrg 73805b261ecSmrg SCREEN_UNWRAP(pScreen, CopyWindow); 73905b261ecSmrg 74005b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 74105b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 7426747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 74305b261ecSmrg 7446747b715Smrg RegionNull(&rgnDst); 7456747b715Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 74605b261ecSmrg 7476747b715Smrg extents = RegionExtents(&rgnDst); 74805b261ecSmrg area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); 74905b261ecSmrg 75005b261ecSmrg /* If the area exceeds threshold, use the implementation's 75105b261ecSmrg accelerated version. */ 75205b261ecSmrg if (area > rootless_CopyWindow_threshold && 75305b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow) 75405b261ecSmrg { 75505b261ecSmrg RootlessWindowRec *winRec; 75605b261ecSmrg WindowPtr top; 75705b261ecSmrg 75805b261ecSmrg top = TopLevelParent(pWin); 75905b261ecSmrg if (top == NULL) { 76005b261ecSmrg RL_DEBUG_MSG("no parent\n"); 7614642e01fSmrg goto out; 76205b261ecSmrg } 76305b261ecSmrg 76405b261ecSmrg winRec = WINREC(top); 76505b261ecSmrg if (winRec == NULL) { 76605b261ecSmrg RL_DEBUG_MSG("not framed\n"); 7674642e01fSmrg goto out; 76805b261ecSmrg } 76905b261ecSmrg 77005b261ecSmrg /* Move region to window local coords */ 7716747b715Smrg RegionTranslate(&rgnDst, -winRec->x, -winRec->y); 77205b261ecSmrg 77305b261ecSmrg RootlessStopDrawing(pWin, FALSE); 77405b261ecSmrg 77505b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, 7766747b715Smrg RegionNumRects(&rgnDst), 7776747b715Smrg RegionRects(&rgnDst), 77805b261ecSmrg dx, dy); 77905b261ecSmrg } 78005b261ecSmrg else { 78105b261ecSmrg RootlessStartDrawing(pWin); 78205b261ecSmrg 78305b261ecSmrg fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, 78405b261ecSmrg 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 78505b261ecSmrg 78605b261ecSmrg /* prgnSrc has been translated to dst position */ 78705b261ecSmrg RootlessDamageRegion(pWin, prgnSrc); 78805b261ecSmrg } 78905b261ecSmrg 7904642e01fSmrgout: 7916747b715Smrg RegionUninit(&rgnDst); 79205b261ecSmrg fbValidateDrawable(&pWin->drawable); 79305b261ecSmrg 79405b261ecSmrg SCREEN_WRAP(pScreen, CopyWindow); 79505b261ecSmrg 79605b261ecSmrg RL_DEBUG_MSG("copywindowFB end\n"); 79705b261ecSmrg} 79805b261ecSmrg 79905b261ecSmrg 80005b261ecSmrg/* 80105b261ecSmrg * Window resize procedures 80205b261ecSmrg */ 80305b261ecSmrg 80405b261ecSmrgenum { 80505b261ecSmrg WIDTH_SMALLER = 1, 80605b261ecSmrg HEIGHT_SMALLER = 2, 80705b261ecSmrg}; 80805b261ecSmrg 80905b261ecSmrg 81005b261ecSmrg/* 81105b261ecSmrg * ResizeWeighting 81205b261ecSmrg * Choose gravity to avoid local copies. Do that by looking for 81305b261ecSmrg * a corner that doesn't move _relative to the screen_. 81405b261ecSmrg */ 81505b261ecSmrgstatic inline unsigned int 81605b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, 81705b261ecSmrg int newX1, int newY1, int newX2, int newY2, int newBW) 81805b261ecSmrg{ 81905b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY 82005b261ecSmrg if (newBW != oldBW) 82105b261ecSmrg return RL_GRAVITY_NONE; 82205b261ecSmrg 82305b261ecSmrg if (newX1 == oldX1 && newY1 == oldY1) 82405b261ecSmrg return RL_GRAVITY_NORTH_WEST; 82505b261ecSmrg else if (newX1 == oldX1 && newY2 == oldY2) 82605b261ecSmrg return RL_GRAVITY_SOUTH_WEST; 82705b261ecSmrg else if (newX2 == oldX2 && newY2 == oldY2) 82805b261ecSmrg return RL_GRAVITY_SOUTH_EAST; 82905b261ecSmrg else if (newX2 == oldX2 && newY1 == oldY1) 83005b261ecSmrg return RL_GRAVITY_NORTH_EAST; 83105b261ecSmrg else 83205b261ecSmrg return RL_GRAVITY_NONE; 83305b261ecSmrg#else 83405b261ecSmrg return RL_GRAVITY_NONE; 83505b261ecSmrg#endif 83605b261ecSmrg} 83705b261ecSmrg 83805b261ecSmrg 83905b261ecSmrg/* 84005b261ecSmrg * StartFrameResize 84105b261ecSmrg * Prepare to resize a top-level window. The old window's pixels are 84205b261ecSmrg * saved and the implementation is told to change the window size. 84305b261ecSmrg * (x,y,w,h) is outer frame of window (outside border) 84405b261ecSmrg */ 84505b261ecSmrgstatic Bool 84605b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity, 84705b261ecSmrg int oldX, int oldY, int oldW, int oldH, int oldBW, 84805b261ecSmrg int newX, int newY, int newW, int newH, int newBW) 84905b261ecSmrg{ 85005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 85105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 85205b261ecSmrg Bool need_window_source = FALSE, resize_after = FALSE; 85305b261ecSmrg 85405b261ecSmrg BoxRec rect; 85505b261ecSmrg int oldX2, newX2; 85605b261ecSmrg int oldY2, newY2; 85705b261ecSmrg unsigned int weight; 85805b261ecSmrg 85905b261ecSmrg oldX2 = oldX + oldW, newX2 = newX + newW; 86005b261ecSmrg oldY2 = oldY + oldH, newY2 = newY + newH; 86105b261ecSmrg 86205b261ecSmrg /* Decide which resize weighting to use */ 86305b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 86405b261ecSmrg newX, newY, newW, newH, newBW); 86505b261ecSmrg 86605b261ecSmrg /* Compute intersection between old and new rects */ 86705b261ecSmrg rect.x1 = max(oldX, newX); 86805b261ecSmrg rect.y1 = max(oldY, newY); 86905b261ecSmrg rect.x2 = min(oldX2, newX2); 87005b261ecSmrg rect.y2 = min(oldY2, newY2); 87105b261ecSmrg 87205b261ecSmrg RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); 87305b261ecSmrg RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", 87405b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 87505b261ecSmrg newX, newY, newW, newH, newBW); 87605b261ecSmrg 87705b261ecSmrg RootlessRedisplay(pWin); 87805b261ecSmrg 87905b261ecSmrg /* If gravity is true, then we need to have a way of recovering all 88005b261ecSmrg the original bits in the window for when X rearranges the contents 88105b261ecSmrg based on the various gravity settings. The obvious way is to just 88205b261ecSmrg snapshot the entire backing store before resizing it, but that 88305b261ecSmrg it slow on large windows. 88405b261ecSmrg 88505b261ecSmrg So the optimization here is to use the implementation's resize 88605b261ecSmrg weighting options (if available) to allow us to reason about what 88705b261ecSmrg is left in the backing store after the resize. We can then only 88805b261ecSmrg copy what won't be there after the resize, and do a two-stage copy 88905b261ecSmrg operation. 89005b261ecSmrg 89105b261ecSmrg Most of these optimizations are only applied when the top-left 89205b261ecSmrg corner of the window is fixed, since that's the common case. They 89305b261ecSmrg could probably be extended with some thought. */ 89405b261ecSmrg 89505b261ecSmrg gResizeDeathCount = 0; 89605b261ecSmrg 89705b261ecSmrg if (gravity && weight == RL_GRAVITY_NORTH_WEST) { 89805b261ecSmrg unsigned int code = 0; 89905b261ecSmrg 90005b261ecSmrg /* Top left corner is anchored. We never need to copy the 90105b261ecSmrg entire window. */ 90205b261ecSmrg 90305b261ecSmrg need_window_source = TRUE; 90405b261ecSmrg 90505b261ecSmrg /* These comparisons were chosen to avoid setting bits when the sizes 90605b261ecSmrg are the same. (So the fastest case automatically gets taken when 90705b261ecSmrg dimensions are unchanging.) */ 90805b261ecSmrg 90905b261ecSmrg if (newW < oldW) 91005b261ecSmrg code |= WIDTH_SMALLER; 91105b261ecSmrg if (newH < oldH) 91205b261ecSmrg code |= HEIGHT_SMALLER; 91305b261ecSmrg 91405b261ecSmrg if (((code ^ (code >> 1)) & 1) == 0) { 91505b261ecSmrg /* Both dimensions are either getting larger, or both 91605b261ecSmrg are getting smaller. No need to copy anything. */ 91705b261ecSmrg 91805b261ecSmrg if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { 91905b261ecSmrg /* Since the window is getting smaller, we can do gravity 92005b261ecSmrg repair on it with it's current size, then resize it 92105b261ecSmrg afterwards. */ 92205b261ecSmrg 92305b261ecSmrg resize_after = TRUE; 92405b261ecSmrg } 92505b261ecSmrg 92605b261ecSmrg gResizeDeathCount = 1; 92705b261ecSmrg } 92805b261ecSmrg else { 92905b261ecSmrg unsigned int copy_rowbytes, Bpp; 93005b261ecSmrg unsigned int copy_rect_width, copy_rect_height; 93105b261ecSmrg BoxRec copy_rect; 93205b261ecSmrg 93305b261ecSmrg /* We can get away with a partial copy. 'rect' is the 93405b261ecSmrg intersection between old and new bounds, so copy 93505b261ecSmrg everything to the right of or below the intersection. */ 93605b261ecSmrg 93705b261ecSmrg RootlessStartDrawing(pWin); 93805b261ecSmrg 93905b261ecSmrg if (code == WIDTH_SMALLER) { 94005b261ecSmrg copy_rect.x1 = rect.x2; 94105b261ecSmrg copy_rect.y1 = rect.y1; 94205b261ecSmrg copy_rect.x2 = oldX2; 94305b261ecSmrg copy_rect.y2 = oldY2; 94405b261ecSmrg } 94505b261ecSmrg else if (code == HEIGHT_SMALLER) { 94605b261ecSmrg copy_rect.x1 = rect.x1; 94705b261ecSmrg copy_rect.y1 = rect.y2; 94805b261ecSmrg copy_rect.x2 = oldX2; 94905b261ecSmrg copy_rect.y2 = oldY2; 95005b261ecSmrg } 95105b261ecSmrg else 9526747b715Smrg OsAbort(); 95305b261ecSmrg 95405b261ecSmrg Bpp = winRec->win->drawable.bitsPerPixel / 8; 95505b261ecSmrg copy_rect_width = copy_rect.x2 - copy_rect.x1; 95605b261ecSmrg copy_rect_height = copy_rect.y2 - copy_rect.y1; 95705b261ecSmrg copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; 9586747b715Smrg gResizeDeathBits = malloc(copy_rowbytes 95905b261ecSmrg * copy_rect_height); 96005b261ecSmrg 96105b261ecSmrg if (copy_rect_width * copy_rect_height > 96205b261ecSmrg rootless_CopyBytes_threshold && 96305b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes) 96405b261ecSmrg { 96505b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes( 96605b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 96705b261ecSmrg ((char *) winRec->pixelData) 96805b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 96905b261ecSmrg + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, 97005b261ecSmrg gResizeDeathBits, copy_rowbytes); 97105b261ecSmrg } else { 97205b261ecSmrg fbBlt((FbBits *) (winRec->pixelData 97305b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 97405b261ecSmrg + (copy_rect.x1 - oldX) * Bpp), 97505b261ecSmrg winRec->bytesPerRow / sizeof(FbBits), 0, 97605b261ecSmrg (FbBits *) gResizeDeathBits, 97705b261ecSmrg copy_rowbytes / sizeof(FbBits), 0, 97805b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 97905b261ecSmrg GXcopy, FB_ALLONES, Bpp, 0, 0); 98005b261ecSmrg } 98105b261ecSmrg 98205b261ecSmrg gResizeDeathBounds[1] = copy_rect; 98305b261ecSmrg gResizeDeathPix[1] 98405b261ecSmrg = GetScratchPixmapHeader(pScreen, copy_rect_width, 98505b261ecSmrg copy_rect_height, 98605b261ecSmrg winRec->win->drawable.depth, 98705b261ecSmrg winRec->win->drawable.bitsPerPixel, 98805b261ecSmrg winRec->bytesPerRow, 98905b261ecSmrg (void *) gResizeDeathBits); 99005b261ecSmrg 99105b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[1], 99205b261ecSmrg copy_rect.x1, copy_rect.y1); 99305b261ecSmrg 99405b261ecSmrg gResizeDeathCount = 2; 99505b261ecSmrg } 99605b261ecSmrg } 99705b261ecSmrg else if (gravity) { 99805b261ecSmrg /* The general case. Just copy everything. */ 99905b261ecSmrg 100005b261ecSmrg RootlessStartDrawing(pWin); 100105b261ecSmrg 10026747b715Smrg gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); 100305b261ecSmrg 100405b261ecSmrg memcpy(gResizeDeathBits, winRec->pixelData, 100505b261ecSmrg winRec->bytesPerRow * winRec->height); 100605b261ecSmrg 100705b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 100805b261ecSmrg gResizeDeathPix[0] 100905b261ecSmrg = GetScratchPixmapHeader(pScreen, winRec->width, 101005b261ecSmrg winRec->height, 101105b261ecSmrg winRec->win->drawable.depth, 101205b261ecSmrg winRec->win->drawable.bitsPerPixel, 101305b261ecSmrg winRec->bytesPerRow, 101405b261ecSmrg (void *) gResizeDeathBits); 101505b261ecSmrg 101605b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 101705b261ecSmrg gResizeDeathCount = 1; 101805b261ecSmrg } 101905b261ecSmrg 102005b261ecSmrg RootlessStopDrawing(pWin, FALSE); 102105b261ecSmrg 102205b261ecSmrg winRec->x = newX; 102305b261ecSmrg winRec->y = newY; 102405b261ecSmrg winRec->width = newW; 102505b261ecSmrg winRec->height = newH; 102605b261ecSmrg winRec->borderWidth = newBW; 102705b261ecSmrg 102805b261ecSmrg /* Unless both dimensions are getting smaller, Resize the frame 102905b261ecSmrg before doing gravity repair */ 103005b261ecSmrg 103105b261ecSmrg if (!resize_after) { 103205b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 103305b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 103405b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 103505b261ecSmrg newW, newH, weight); 103605b261ecSmrg } 103705b261ecSmrg 103805b261ecSmrg RootlessStartDrawing(pWin); 103905b261ecSmrg 104005b261ecSmrg /* If necessary, create a source pixmap pointing at the current 104105b261ecSmrg window bits. */ 104205b261ecSmrg 104305b261ecSmrg if (need_window_source) { 104405b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 104505b261ecSmrg gResizeDeathPix[0] 104605b261ecSmrg = GetScratchPixmapHeader(pScreen, oldW, oldH, 104705b261ecSmrg winRec->win->drawable.depth, 104805b261ecSmrg winRec->win->drawable.bitsPerPixel, 104905b261ecSmrg winRec->bytesPerRow, winRec->pixelData); 105005b261ecSmrg 105105b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 105205b261ecSmrg } 105305b261ecSmrg 105405b261ecSmrg /* Use custom CopyWindow when moving gravity bits around 105505b261ecSmrg ResizeWindow assumes the old window contents are in the same 105605b261ecSmrg pixmap, but here they're in deathPix instead. */ 105705b261ecSmrg 105805b261ecSmrg if (gravity) { 105905b261ecSmrg gResizeOldCopyWindowProc = pScreen->CopyWindow; 106005b261ecSmrg pScreen->CopyWindow = RootlessResizeCopyWindow; 106105b261ecSmrg } 106205b261ecSmrg 106305b261ecSmrg /* If we can't rely on the window server preserving the bits we 106405b261ecSmrg need in the position we need, copy the pixels in the 106505b261ecSmrg intersection from src to dst. ResizeWindow assumes these pixels 106605b261ecSmrg are already present when making gravity adjustments. pWin 106705b261ecSmrg currently has new-sized pixmap but is in old position. 106805b261ecSmrg 106905b261ecSmrg FIXME: border width change! (?) */ 107005b261ecSmrg 107105b261ecSmrg if (gravity && weight == RL_GRAVITY_NONE) { 107205b261ecSmrg PixmapPtr src, dst; 107305b261ecSmrg 107405b261ecSmrg assert(gResizeDeathCount == 1); 107505b261ecSmrg 107605b261ecSmrg src = gResizeDeathPix[0]; 107705b261ecSmrg dst = pScreen->GetWindowPixmap(pWin); 107805b261ecSmrg 107905b261ecSmrg RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", 108005b261ecSmrg rect.x1, rect.y1, rect.x2, rect.y2); 108105b261ecSmrg 108205b261ecSmrg /* rect is the intersection of the old location and new location */ 108305b261ecSmrg if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { 108405b261ecSmrg /* The window drawable still has the old frame position, which 108505b261ecSmrg means that DST doesn't actually point at the origin of our 108605b261ecSmrg physical backing store when adjusted by the drawable.x,y 108705b261ecSmrg position. So sneakily adjust it temporarily while copying.. */ 108805b261ecSmrg 108905b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 109005b261ecSmrg SetPixmapBaseToScreen(dst, newX, newY); 109105b261ecSmrg 109205b261ecSmrg fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, 109305b261ecSmrg &rect, 1, 0, 0, FALSE, FALSE, 0, 0); 109405b261ecSmrg 109505b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 109605b261ecSmrg SetPixmapBaseToScreen(dst, oldX, oldY); 109705b261ecSmrg } 109805b261ecSmrg } 109905b261ecSmrg 110005b261ecSmrg return resize_after; 110105b261ecSmrg} 110205b261ecSmrg 110305b261ecSmrg 110405b261ecSmrgstatic void 110505b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, 110605b261ecSmrg unsigned int oldW, unsigned int oldH, unsigned int oldBW, 110705b261ecSmrg int newX, int newY, unsigned int newW, unsigned int newH, 110805b261ecSmrg unsigned int newBW, Bool resize_now) 110905b261ecSmrg{ 111005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 111105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 111205b261ecSmrg int i; 111305b261ecSmrg 111405b261ecSmrg RootlessStopDrawing(pWin, FALSE); 111505b261ecSmrg 111605b261ecSmrg if (resize_now) { 111705b261ecSmrg unsigned int weight; 111805b261ecSmrg 111905b261ecSmrg /* We didn't resize anything earlier, so do it now, now that 112005b261ecSmrg we've finished gravitating the bits. */ 112105b261ecSmrg 112205b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 112305b261ecSmrg newX, newY, newW, newH, newBW); 112405b261ecSmrg 112505b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 112605b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 112705b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 112805b261ecSmrg newW, newH, weight); 112905b261ecSmrg } 113005b261ecSmrg 113105b261ecSmrg /* Redraw everything. FIXME: there must be times when we don't need 113205b261ecSmrg to do this. Perhaps when top-left weighting and no gravity? */ 113305b261ecSmrg 113405b261ecSmrg RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); 113505b261ecSmrg 113605b261ecSmrg for (i = 0; i < 2; i++) { 113705b261ecSmrg if (gResizeDeathPix[i] != NULL) { 113805b261ecSmrg FreeScratchPixmapHeader(gResizeDeathPix[i]); 113905b261ecSmrg gResizeDeathPix[i] = NULL; 114005b261ecSmrg } 114105b261ecSmrg } 114205b261ecSmrg 11439ace9065Smrg free(gResizeDeathBits); 11449ace9065Smrg gResizeDeathBits = NULL; 114505b261ecSmrg 114605b261ecSmrg if (gravity) { 114705b261ecSmrg pScreen->CopyWindow = gResizeOldCopyWindowProc; 114805b261ecSmrg } 114905b261ecSmrg} 115005b261ecSmrg 115105b261ecSmrg 115205b261ecSmrg/* 115305b261ecSmrg * RootlessMoveWindow 115405b261ecSmrg * If kind==VTOther, window border is resizing (and borderWidth is 115505b261ecSmrg * already changed!!@#$) This case works like window resize, not move. 115605b261ecSmrg */ 115705b261ecSmrgvoid 115805b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 115905b261ecSmrg{ 116005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 116105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 116205b261ecSmrg CopyWindowProcPtr oldCopyWindowProc = NULL; 116305b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 116405b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 116505b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 116605b261ecSmrg Bool resize_after = FALSE; 116705b261ecSmrg RegionRec saveRoot; 116805b261ecSmrg 116905b261ecSmrg RL_DEBUG_MSG("movewindow start \n"); 117005b261ecSmrg 117105b261ecSmrg if (winRec) { 117205b261ecSmrg if (kind == VTMove) { 117305b261ecSmrg oldX = winRec->x; 117405b261ecSmrg oldY = winRec->y; 117505b261ecSmrg RootlessRedisplay(pWin); 117605b261ecSmrg RootlessStartDrawing(pWin); 117705b261ecSmrg } else { 117805b261ecSmrg RL_DEBUG_MSG("movewindow border resizing "); 117905b261ecSmrg 118005b261ecSmrg oldBW = winRec->borderWidth; 118105b261ecSmrg oldX = winRec->x; 118205b261ecSmrg oldY = winRec->y; 118305b261ecSmrg oldW = winRec->width; 118405b261ecSmrg oldH = winRec->height; 118505b261ecSmrg 118605b261ecSmrg newBW = wBorderWidth(pWin); 118705b261ecSmrg newX = x; 118805b261ecSmrg newY = y; 118905b261ecSmrg newW = pWin->drawable.width + 2*newBW; 119005b261ecSmrg newH = pWin->drawable.height + 2*newBW; 119105b261ecSmrg 119205b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 119305b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 119405b261ecSmrg newX, newY, newW, newH, newBW); 119505b261ecSmrg } 119605b261ecSmrg } 119705b261ecSmrg 119805b261ecSmrg HUGE_ROOT(pWin); 119905b261ecSmrg SCREEN_UNWRAP(pScreen, MoveWindow); 120005b261ecSmrg 120105b261ecSmrg if (winRec) { 120205b261ecSmrg oldCopyWindowProc = pScreen->CopyWindow; 120305b261ecSmrg pScreen->CopyWindow = RootlessNoCopyWindow; 120405b261ecSmrg } 120505b261ecSmrg pScreen->MoveWindow(pWin, x, y, pSib, kind); 120605b261ecSmrg if (winRec) { 120705b261ecSmrg pScreen->CopyWindow = oldCopyWindowProc; 120805b261ecSmrg } 120905b261ecSmrg 121005b261ecSmrg NORMAL_ROOT(pWin); 121105b261ecSmrg SCREEN_WRAP(pScreen, MoveWindow); 121205b261ecSmrg 121305b261ecSmrg if (winRec) { 121405b261ecSmrg if (kind == VTMove) { 121505b261ecSmrg winRec->x = x; 121605b261ecSmrg winRec->y = y; 121705b261ecSmrg RootlessStopDrawing(pWin, FALSE); 121805b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 121905b261ecSmrg x + SCREEN_TO_GLOBAL_X, 122005b261ecSmrg y + SCREEN_TO_GLOBAL_Y); 122105b261ecSmrg } else { 122205b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 122305b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 122405b261ecSmrg } 122505b261ecSmrg } 122605b261ecSmrg 122705b261ecSmrg RL_DEBUG_MSG("movewindow end\n"); 122805b261ecSmrg} 122905b261ecSmrg 123005b261ecSmrg 123105b261ecSmrg/* 123205b261ecSmrg * RootlessResizeWindow 123305b261ecSmrg * Note: (x, y, w, h) as passed to this procedure don't match the frame 123405b261ecSmrg * definition. (x,y) is corner of very outer edge, *outside* border. 123505b261ecSmrg * w,h is width and height *inside* border, *ignoring* border width. 123605b261ecSmrg * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) 123705b261ecSmrg * is total rect and (x+bw, y+bw, w, h) is inner rect. 123805b261ecSmrg */ 123905b261ecSmrgvoid 124005b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y, 124105b261ecSmrg unsigned int w, unsigned int h, WindowPtr pSib) 124205b261ecSmrg{ 124305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 124405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 124505b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 124605b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; 124705b261ecSmrg Bool resize_after = FALSE; 124805b261ecSmrg RegionRec saveRoot; 124905b261ecSmrg 125005b261ecSmrg RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); 12514642e01fSmrg 12524642e01fSmrg if(pWin->parent) { 12534642e01fSmrg if (winRec) { 12544642e01fSmrg oldBW = winRec->borderWidth; 12554642e01fSmrg oldX = winRec->x; 12564642e01fSmrg oldY = winRec->y; 12574642e01fSmrg oldW = winRec->width; 12584642e01fSmrg oldH = winRec->height; 125905b261ecSmrg 12604642e01fSmrg newBW = oldBW; 12614642e01fSmrg newX = x; 12624642e01fSmrg newY = y; 12634642e01fSmrg newW = w + 2*newBW; 12644642e01fSmrg newH = h + 2*newBW; 126505b261ecSmrg 12664642e01fSmrg resize_after = StartFrameResize(pWin, TRUE, 12674642e01fSmrg oldX, oldY, oldW, oldH, oldBW, 12684642e01fSmrg newX, newY, newW, newH, newBW); 12694642e01fSmrg } 127005b261ecSmrg 12714642e01fSmrg HUGE_ROOT(pWin); 12724642e01fSmrg SCREEN_UNWRAP(pScreen, ResizeWindow); 12734642e01fSmrg pScreen->ResizeWindow(pWin, x, y, w, h, pSib); 12744642e01fSmrg SCREEN_WRAP(pScreen, ResizeWindow); 12754642e01fSmrg NORMAL_ROOT(pWin); 12764642e01fSmrg 12774642e01fSmrg if (winRec) { 12784642e01fSmrg FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, 12794642e01fSmrg newX, newY, newW, newH, newBW, resize_after); 12804642e01fSmrg } 12814642e01fSmrg } else { 12824642e01fSmrg /* Special case for resizing the root window */ 12834642e01fSmrg BoxRec box; 12844642e01fSmrg 12854642e01fSmrg pWin->drawable.x = x; 12864642e01fSmrg pWin->drawable.y = y; 12874642e01fSmrg pWin->drawable.width = w; 12884642e01fSmrg pWin->drawable.height = h; 12894642e01fSmrg 12904642e01fSmrg box.x1 = x; box.y1 = y; 12914642e01fSmrg box.x2 = x + w; box.y2 = y + h; 12926747b715Smrg RegionUninit(&pWin->winSize); 12936747b715Smrg RegionInit(&pWin->winSize, &box, 1); 12946747b715Smrg RegionCopy(&pWin->borderSize, &pWin->winSize); 12956747b715Smrg RegionCopy(&pWin->clipList, &pWin->winSize); 12966747b715Smrg RegionCopy(&pWin->borderClip, &pWin->winSize); 12976747b715Smrg 12986747b715Smrg if (winRec) { 12996747b715Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 13006747b715Smrg x + SCREEN_TO_GLOBAL_X, 13016747b715Smrg y + SCREEN_TO_GLOBAL_Y, 13026747b715Smrg w, h, RL_GRAVITY_NONE); 13036747b715Smrg } 13044642e01fSmrg 13054642e01fSmrg miSendExposures(pWin, &pWin->borderClip, 13064642e01fSmrg pWin->drawable.x, pWin->drawable.y); 130705b261ecSmrg } 130805b261ecSmrg 130905b261ecSmrg RL_DEBUG_MSG("resizewindow end\n"); 131005b261ecSmrg} 131105b261ecSmrg 131205b261ecSmrg 131305b261ecSmrg/* 131405b261ecSmrg * RootlessRepositionWindow 131505b261ecSmrg * Called by the implementation when a window needs to be repositioned to 131605b261ecSmrg * its correct location on the screen. This routine is typically needed 131705b261ecSmrg * due to changes in the underlying window system, such as a screen layout 131805b261ecSmrg * change. 131905b261ecSmrg */ 132005b261ecSmrgvoid 132105b261ecSmrgRootlessRepositionWindow(WindowPtr pWin) 132205b261ecSmrg{ 132305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 132405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 132505b261ecSmrg 132605b261ecSmrg if (winRec == NULL) 132705b261ecSmrg return; 132805b261ecSmrg 132905b261ecSmrg RootlessStopDrawing(pWin, FALSE); 133005b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 133105b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 133205b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y); 133305b261ecSmrg 133405b261ecSmrg RootlessReorderWindow(pWin); 133505b261ecSmrg} 133605b261ecSmrg 133705b261ecSmrg 133805b261ecSmrg/* 133905b261ecSmrg * RootlessReparentWindow 134005b261ecSmrg * Called after a window has been reparented. Generally windows are not 134105b261ecSmrg * framed until they are mapped. However, a window may be framed early by the 134205b261ecSmrg * implementation calling RootlessFrameForWindow. (e.g. this could be needed 134305b261ecSmrg * to attach a VRAM surface to it.) If the window is subsequently reparented 134405b261ecSmrg * by the window manager before being mapped, we need to give the frame to 134505b261ecSmrg * the new top-level window. 134605b261ecSmrg */ 134705b261ecSmrgvoid 134805b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 134905b261ecSmrg{ 135005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 135105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 135205b261ecSmrg WindowPtr pTopWin; 135305b261ecSmrg 135405b261ecSmrg /* Check that window is not top-level now, but used to be. */ 135505b261ecSmrg if (IsRoot(pWin) || IsRoot(pWin->parent) 135605b261ecSmrg || IsTopLevel(pWin) || winRec == NULL) 135705b261ecSmrg { 135805b261ecSmrg goto out; 135905b261ecSmrg } 136005b261ecSmrg 136105b261ecSmrg /* If the formerly top-level window has a frame, we want to give the 136205b261ecSmrg frame to its new top-level parent. If we can't do that, we'll just 136305b261ecSmrg have to jettison it... */ 136405b261ecSmrg 136505b261ecSmrg pTopWin = TopLevelParent(pWin); 136605b261ecSmrg assert(pTopWin != pWin); 13674642e01fSmrg 13684642e01fSmrg pWin->rootlessUnhittable = FALSE; 13694642e01fSmrg 13704642e01fSmrg DeleteProperty (serverClient, pWin, xa_native_window_id ()); 137105b261ecSmrg 137205b261ecSmrg if (WINREC(pTopWin) != NULL) { 137305b261ecSmrg /* We're screwed. */ 137405b261ecSmrg RootlessDestroyFrame(pWin, winRec); 137505b261ecSmrg } else { 137605b261ecSmrg if (!pTopWin->realized && pWin->realized) { 137705b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 137805b261ecSmrg } 137905b261ecSmrg 138005b261ecSmrg /* Switch the frame record from one to the other. */ 138105b261ecSmrg 13824642e01fSmrg SETWINREC(pWin, NULL); 13834642e01fSmrg SETWINREC(pTopWin, winRec); 138405b261ecSmrg 138505b261ecSmrg RootlessInitializeFrame(pTopWin, winRec); 138605b261ecSmrg RootlessReshapeFrame(pTopWin); 138705b261ecSmrg 138805b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 138905b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 139005b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 139105b261ecSmrg winRec->width, winRec->height, 139205b261ecSmrg RL_GRAVITY_NONE); 139305b261ecSmrg 139405b261ecSmrg if (SCREENREC(pScreen)->imp->SwitchWindow) { 139505b261ecSmrg SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); 139605b261ecSmrg } 139705b261ecSmrg 139805b261ecSmrg if (pTopWin->realized && !pWin->realized) 139905b261ecSmrg winRec->is_reorder_pending = TRUE; 140005b261ecSmrg } 140105b261ecSmrg 140205b261ecSmrgout: 140305b261ecSmrg if (SCREENREC(pScreen)->ReparentWindow) { 140405b261ecSmrg SCREEN_UNWRAP(pScreen, ReparentWindow); 140505b261ecSmrg pScreen->ReparentWindow(pWin, pPriorParent); 140605b261ecSmrg SCREEN_WRAP(pScreen, ReparentWindow); 140705b261ecSmrg } 140805b261ecSmrg} 140905b261ecSmrg 141005b261ecSmrg 141105b261ecSmrgvoid 14124642e01fSmrgRootlessFlushWindowColormap (WindowPtr pWin) 141305b261ecSmrg{ 14144642e01fSmrg RootlessWindowRec *winRec = WINREC (pWin); 14156747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 141605b261ecSmrg 14174642e01fSmrg if (winRec == NULL) 14184642e01fSmrg return; 141905b261ecSmrg 14204642e01fSmrg RootlessStopDrawing (pWin, FALSE); 142105b261ecSmrg 14226747b715Smrg if (SCREENREC(pScreen)->imp->UpdateColormap) 14236747b715Smrg SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); 142405b261ecSmrg} 142505b261ecSmrg 142605b261ecSmrg/* 142705b261ecSmrg * RootlessChangeBorderWidth 142805b261ecSmrg * FIXME: untested! 142905b261ecSmrg * pWin inside corner stays the same; pWin->drawable.[xy] stays the same 143005b261ecSmrg * Frame moves and resizes. 143105b261ecSmrg */ 143205b261ecSmrgvoid 143305b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) 143405b261ecSmrg{ 143505b261ecSmrg RegionRec saveRoot; 143605b261ecSmrg Bool resize_after = FALSE; 143705b261ecSmrg 143805b261ecSmrg RL_DEBUG_MSG("change border width "); 143905b261ecSmrg 144005b261ecSmrg if (width != wBorderWidth(pWin)) { 144105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 144205b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 144305b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 144405b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 144505b261ecSmrg 144605b261ecSmrg if (winRec) { 144705b261ecSmrg oldBW = winRec->borderWidth; 144805b261ecSmrg oldX = winRec->x; 144905b261ecSmrg oldY = winRec->y; 145005b261ecSmrg oldW = winRec->width; 145105b261ecSmrg oldH = winRec->height; 145205b261ecSmrg 145305b261ecSmrg newBW = width; 145405b261ecSmrg newX = pWin->drawable.x - newBW; 145505b261ecSmrg newY = pWin->drawable.y - newBW; 145605b261ecSmrg newW = pWin->drawable.width + 2*newBW; 145705b261ecSmrg newH = pWin->drawable.height + 2*newBW; 145805b261ecSmrg 145905b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 146005b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 146105b261ecSmrg newX, newY, newW, newH, newBW); 146205b261ecSmrg } 146305b261ecSmrg 146405b261ecSmrg HUGE_ROOT(pWin); 146505b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); 146605b261ecSmrg pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); 146705b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); 146805b261ecSmrg NORMAL_ROOT(pWin); 146905b261ecSmrg 147005b261ecSmrg if (winRec) { 147105b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 147205b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 147305b261ecSmrg } 147405b261ecSmrg } 147505b261ecSmrg 147605b261ecSmrg RL_DEBUG_MSG("change border width end\n"); 147705b261ecSmrg} 14784642e01fSmrg 14794642e01fSmrg/* 14804642e01fSmrg * RootlessOrderAllWindows 14814642e01fSmrg * Brings all X11 windows to the top of the window stack 14824642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus 14834642e01fSmrg */ 14844642e01fSmrgvoid 14856747b715SmrgRootlessOrderAllWindows (Bool include_unhitable) 14864642e01fSmrg{ 14874642e01fSmrg int i; 14884642e01fSmrg WindowPtr pWin; 14894642e01fSmrg 14904642e01fSmrg if (windows_hidden) 14914642e01fSmrg return; 14924642e01fSmrg 14934642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() "); 14944642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 14954642e01fSmrg if (screenInfo.screens[i] == NULL) continue; 14966747b715Smrg pWin = screenInfo.screens[i]->root; 14974642e01fSmrg if (pWin == NULL) continue; 14984642e01fSmrg 14994642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 15004642e01fSmrg if (!pWin->realized) continue; 15014642e01fSmrg if (RootlessEnsureFrame(pWin) == NULL) continue; 15026747b715Smrg if (!include_unhitable && pWin->rootlessUnhittable) continue; 15034642e01fSmrg RootlessReorderWindow (pWin); 15044642e01fSmrg } 15054642e01fSmrg } 15064642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() done"); 15074642e01fSmrg} 15084642e01fSmrg 15094642e01fSmrgvoid 15104642e01fSmrgRootlessEnableRoot (ScreenPtr pScreen) 15114642e01fSmrg{ 15124642e01fSmrg WindowPtr pRoot; 15136747b715Smrg pRoot = pScreen->root; 15144642e01fSmrg 15154642e01fSmrg RootlessEnsureFrame (pRoot); 15164642e01fSmrg (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); 15174642e01fSmrg RootlessReorderWindow (pRoot); 15184642e01fSmrg} 15194642e01fSmrg 15204642e01fSmrgvoid 15214642e01fSmrgRootlessDisableRoot (ScreenPtr pScreen) 15224642e01fSmrg{ 15234642e01fSmrg WindowPtr pRoot; 15244642e01fSmrg RootlessWindowRec *winRec; 15254642e01fSmrg 15266747b715Smrg pRoot = pScreen->root; 15274642e01fSmrg winRec = WINREC (pRoot); 15284642e01fSmrg 15294642e01fSmrg if (NULL == winRec) 15304642e01fSmrg return; 15314642e01fSmrg 15324642e01fSmrg RootlessDestroyFrame (pRoot, winRec); 15334642e01fSmrg DeleteProperty (serverClient, pRoot, xa_native_window_id ()); 15344642e01fSmrg} 15354642e01fSmrg 15364642e01fSmrgvoid 15374642e01fSmrgRootlessHideAllWindows (void) 15384642e01fSmrg{ 15394642e01fSmrg int i; 15404642e01fSmrg ScreenPtr pScreen; 15414642e01fSmrg WindowPtr pWin; 15424642e01fSmrg RootlessWindowRec *winRec; 15434642e01fSmrg 15444642e01fSmrg if (windows_hidden) 15454642e01fSmrg return; 15464642e01fSmrg 15474642e01fSmrg windows_hidden = TRUE; 15484642e01fSmrg 15494642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 15504642e01fSmrg { 15514642e01fSmrg pScreen = screenInfo.screens[i]; 15526747b715Smrg if (pScreen == NULL) 15536747b715Smrg continue; 15546747b715Smrg pWin = pScreen->root; 15556747b715Smrg if (pWin == NULL) 15564642e01fSmrg continue; 15574642e01fSmrg 15584642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 15594642e01fSmrg { 15604642e01fSmrg if (!pWin->realized) 15614642e01fSmrg continue; 15624642e01fSmrg 15634642e01fSmrg RootlessStopDrawing (pWin, FALSE); 15644642e01fSmrg 15654642e01fSmrg winRec = WINREC (pWin); 15664642e01fSmrg if (winRec != NULL) 15674642e01fSmrg { 15686747b715Smrg if (SCREENREC(pScreen)->imp->HideWindow) 15696747b715Smrg SCREENREC(pScreen)->imp->HideWindow(winRec->wid); 15704642e01fSmrg } 15714642e01fSmrg } 15724642e01fSmrg } 15734642e01fSmrg} 15744642e01fSmrg 15754642e01fSmrgvoid 15764642e01fSmrgRootlessShowAllWindows (void) 15774642e01fSmrg{ 15784642e01fSmrg int i; 15794642e01fSmrg ScreenPtr pScreen; 15804642e01fSmrg WindowPtr pWin; 15814642e01fSmrg RootlessWindowRec *winRec; 15824642e01fSmrg 15834642e01fSmrg if (!windows_hidden) 15844642e01fSmrg return; 15854642e01fSmrg 15864642e01fSmrg windows_hidden = FALSE; 15874642e01fSmrg 15884642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 15894642e01fSmrg { 15904642e01fSmrg pScreen = screenInfo.screens[i]; 15916747b715Smrg if (pScreen == NULL) 15926747b715Smrg continue; 15936747b715Smrg pWin = pScreen->root; 15946747b715Smrg if (pWin == NULL) 15954642e01fSmrg continue; 15964642e01fSmrg 15974642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 15984642e01fSmrg { 15994642e01fSmrg if (!pWin->realized) 16004642e01fSmrg continue; 16014642e01fSmrg 16024642e01fSmrg winRec = RootlessEnsureFrame (pWin); 16034642e01fSmrg if (winRec == NULL) 16044642e01fSmrg continue; 16054642e01fSmrg 16064642e01fSmrg RootlessReorderWindow (pWin); 16074642e01fSmrg } 16084642e01fSmrg 16094642e01fSmrg RootlessScreenExpose (pScreen); 16104642e01fSmrg } 16114642e01fSmrg} 16126747b715Smrg 16136747b715Smrg/* 16146747b715Smrg * SetPixmapOfAncestors 16156747b715Smrg * Set the Pixmaps on all ParentRelative windows up the ancestor chain. 16166747b715Smrg */ 16176747b715Smrgvoid 16186747b715SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin) 16196747b715Smrg{ 16206747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 16216747b715Smrg WindowPtr topWin = TopLevelParent(pWin); 16226747b715Smrg RootlessWindowRec *topWinRec = WINREC(topWin); 16236747b715Smrg 16246747b715Smrg while (pWin->backgroundState == ParentRelative) { 16256747b715Smrg if (pWin == topWin) { 16266747b715Smrg // disallow ParentRelative background state on top level 16276747b715Smrg XID pixel = 0; 16286747b715Smrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 16296747b715Smrg RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); 16306747b715Smrg break; 16316747b715Smrg } 16326747b715Smrg 16336747b715Smrg pWin = pWin->parent; 16346747b715Smrg pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); 16356747b715Smrg } 16366747b715Smrg} 16376747b715Smrg 1638