rootlessWindow.c revision 6747b715
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#ifdef ROOTLESS_GLOBAL_COORDS 5505b261ecSmrg#define SCREEN_TO_GLOBAL_X \ 566747b715Smrg (pScreen->x + rootlessGlobalOffsetX) 5705b261ecSmrg#define SCREEN_TO_GLOBAL_Y \ 586747b715Smrg (pScreen->y + rootlessGlobalOffsetY) 5905b261ecSmrg#else 6005b261ecSmrg#define SCREEN_TO_GLOBAL_X 0 6105b261ecSmrg#define SCREEN_TO_GLOBAL_Y 0 6205b261ecSmrg#endif 6305b261ecSmrg 644642e01fSmrg#define DEFINE_ATOM_HELPER(func,atom_name) \ 654642e01fSmrg static Atom func (void) { \ 664642e01fSmrg static unsigned int generation = 0; \ 674642e01fSmrg static Atom atom; \ 684642e01fSmrg if (generation != serverGeneration) { \ 694642e01fSmrg generation = serverGeneration; \ 704642e01fSmrg atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ 714642e01fSmrg } \ 724642e01fSmrg return atom; \ 734642e01fSmrg } 744642e01fSmrg 754642e01fSmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID") 764642e01fSmrg 774642e01fSmrgstatic Bool windows_hidden; 784642e01fSmrg// TODO - abstract xp functions 794642e01fSmrg 806747b715Smrg#ifdef __APPLE__ 814642e01fSmrg 826747b715Smrg// XXX: identical to x_cvt_vptr_to_uint ? 836747b715Smrg#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) 844642e01fSmrg 854642e01fSmrgvoid 864642e01fSmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state) 874642e01fSmrg{ 884642e01fSmrg RootlessWindowRec *winRec; 894642e01fSmrg 904642e01fSmrg if (pWin == NULL) return; 914642e01fSmrg 924642e01fSmrg winRec = WINREC (pWin); 934642e01fSmrg if (winRec == NULL) return; 944642e01fSmrg 954642e01fSmrg winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); 964642e01fSmrg winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); 974642e01fSmrg pWin->rootlessUnhittable = winRec->is_offscreen; 984642e01fSmrg} 994642e01fSmrg 1004642e01fSmrgvoid RootlessNativeWindowMoved (WindowPtr pWin) { 1014642e01fSmrg xp_box bounds; 1024642e01fSmrg int sx, sy, err; 1034642e01fSmrg XID vlist[2]; 1044642e01fSmrg Mask mask; 1054642e01fSmrg ClientPtr pClient; 1064642e01fSmrg RootlessWindowRec *winRec; 1074642e01fSmrg 1084642e01fSmrg winRec = WINREC(pWin); 1094642e01fSmrg 1104642e01fSmrg if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return; 1114642e01fSmrg 1126747b715Smrg sx = pWin->drawable.pScreen->x + darwinMainScreenX; 1136747b715Smrg sy = pWin->drawable.pScreen->y + darwinMainScreenY; 1144642e01fSmrg 1154642e01fSmrg /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ 1164642e01fSmrg vlist[0] = (INT16) bounds.x1 - sx; 1174642e01fSmrg vlist[1] = (INT16) bounds.y1 - sy; 1184642e01fSmrg mask = CWX | CWY; 1194642e01fSmrg 1204642e01fSmrg /* pretend we're the owner of the window! */ 1216747b715Smrg err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess); 1224642e01fSmrg if(err != Success) { 1234642e01fSmrg ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id); 1244642e01fSmrg return; 1254642e01fSmrg } 1264642e01fSmrg 1274642e01fSmrg /* Don't want to do anything to the physical window (avoids 1284642e01fSmrg notification-response feedback loops) */ 1294642e01fSmrg 1304642e01fSmrg no_configure_window = TRUE; 1314642e01fSmrg ConfigureWindow (pWin, mask, vlist, pClient); 1324642e01fSmrg no_configure_window = FALSE; 1334642e01fSmrg} 1344642e01fSmrg 1356747b715Smrg#endif /* __APPLE__ */ 13605b261ecSmrg 13705b261ecSmrg/* 13805b261ecSmrg * RootlessCreateWindow 13905b261ecSmrg * For now, don't create a physical window until either the window is 14005b261ecSmrg * realized, or we really need it (e.g. to attach VRAM surfaces to). 14105b261ecSmrg * Do reset the window size so it's not clipped by the root window. 14205b261ecSmrg */ 14305b261ecSmrgBool 14405b261ecSmrgRootlessCreateWindow(WindowPtr pWin) 14505b261ecSmrg{ 14605b261ecSmrg Bool result; 14705b261ecSmrg RegionRec saveRoot; 14805b261ecSmrg 1494642e01fSmrg SETWINREC(pWin, NULL); 1504642e01fSmrg dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); 15105b261ecSmrg 15205b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); 15305b261ecSmrg 15405b261ecSmrg if (!IsRoot(pWin)) { 15505b261ecSmrg /* win/border size set by DIX, not by wrapped CreateWindow, so 15605b261ecSmrg correct it here. Don't HUGE_ROOT when pWin is the root! */ 15705b261ecSmrg 15805b261ecSmrg HUGE_ROOT(pWin); 15905b261ecSmrg SetWinSize(pWin); 16005b261ecSmrg SetBorderSize(pWin); 16105b261ecSmrg } 16205b261ecSmrg 16305b261ecSmrg result = pWin->drawable.pScreen->CreateWindow(pWin); 16405b261ecSmrg 16505b261ecSmrg if (pWin->parent) { 16605b261ecSmrg NORMAL_ROOT(pWin); 16705b261ecSmrg } 16805b261ecSmrg 16905b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); 17005b261ecSmrg 17105b261ecSmrg return result; 17205b261ecSmrg} 17305b261ecSmrg 17405b261ecSmrg 17505b261ecSmrg/* 17605b261ecSmrg * RootlessDestroyFrame 17705b261ecSmrg * Destroy the physical window associated with the given window. 17805b261ecSmrg */ 17905b261ecSmrgstatic void 18005b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) 18105b261ecSmrg{ 1826747b715Smrg SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid); 18305b261ecSmrg 18405b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 1856747b715Smrg RegionUninit(&winRec->damage); 18605b261ecSmrg#endif 18705b261ecSmrg 1886747b715Smrg free(winRec); 1894642e01fSmrg SETWINREC(pWin, NULL); 19005b261ecSmrg} 19105b261ecSmrg 19205b261ecSmrg 19305b261ecSmrg/* 19405b261ecSmrg * RootlessDestroyWindow 19505b261ecSmrg * Destroy the physical window associated with the given window. 19605b261ecSmrg */ 19705b261ecSmrgBool 19805b261ecSmrgRootlessDestroyWindow(WindowPtr pWin) 19905b261ecSmrg{ 20005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 20105b261ecSmrg Bool result; 20205b261ecSmrg 20305b261ecSmrg if (winRec != NULL) { 20405b261ecSmrg RootlessDestroyFrame(pWin, winRec); 20505b261ecSmrg } 20605b261ecSmrg 20705b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); 20805b261ecSmrg result = pWin->drawable.pScreen->DestroyWindow(pWin); 20905b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); 21005b261ecSmrg 21105b261ecSmrg return result; 21205b261ecSmrg} 21305b261ecSmrg 21405b261ecSmrg 21505b261ecSmrg 21605b261ecSmrgstatic Bool 21705b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape) 21805b261ecSmrg{ 21905b261ecSmrg if (wBoundingShape(pWin) == NULL) 22005b261ecSmrg return FALSE; 22105b261ecSmrg 22205b261ecSmrg /* wBoundingShape is relative to *inner* origin of window. 22305b261ecSmrg Translate by borderWidth to get the outside-relative position. */ 22405b261ecSmrg 2256747b715Smrg RegionNull(pShape); 2266747b715Smrg RegionCopy(pShape, wBoundingShape(pWin)); 2276747b715Smrg RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth); 22805b261ecSmrg 22905b261ecSmrg return TRUE; 23005b261ecSmrg} 23105b261ecSmrg 23205b261ecSmrg 23305b261ecSmrg/* 23405b261ecSmrg * RootlessReshapeFrame 23505b261ecSmrg * Set the frame shape. 23605b261ecSmrg */ 23705b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin) 23805b261ecSmrg{ 23905b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 24005b261ecSmrg RegionRec newShape; 24105b261ecSmrg RegionPtr pShape; 24205b261ecSmrg 24305b261ecSmrg // If the window is not yet framed, do nothing 24405b261ecSmrg if (winRec == NULL) 24505b261ecSmrg return; 24605b261ecSmrg 24705b261ecSmrg if (IsRoot(pWin)) 24805b261ecSmrg return; 24905b261ecSmrg 25005b261ecSmrg RootlessStopDrawing(pWin, FALSE); 25105b261ecSmrg 25205b261ecSmrg pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; 25305b261ecSmrg 25405b261ecSmrg#ifdef ROOTLESSDEBUG 25505b261ecSmrg RL_DEBUG_MSG("reshaping..."); 25605b261ecSmrg if (pShape != NULL) { 25705b261ecSmrg RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", 2586747b715Smrg RegionNumRects(&newShape), 25905b261ecSmrg newShape.extents.x1, newShape.extents.y1, 26005b261ecSmrg newShape.extents.x2, newShape.extents.y2); 26105b261ecSmrg } else { 26205b261ecSmrg RL_DEBUG_MSG("no shape "); 26305b261ecSmrg } 26405b261ecSmrg#endif 26505b261ecSmrg 2666747b715Smrg SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape); 26705b261ecSmrg 26805b261ecSmrg if (pShape != NULL) 2696747b715Smrg RegionUninit(&newShape); 27005b261ecSmrg} 27105b261ecSmrg 27205b261ecSmrg 27305b261ecSmrg/* 27405b261ecSmrg * RootlessSetShape 27505b261ecSmrg * Shape is usually set before a window is mapped and the window will 27605b261ecSmrg * not have a frame associated with it. In this case, the frame will be 27705b261ecSmrg * shaped when the window is framed. 27805b261ecSmrg */ 27905b261ecSmrgvoid 2806747b715SmrgRootlessSetShape(WindowPtr pWin, int kind) 28105b261ecSmrg{ 28205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 28305b261ecSmrg 28405b261ecSmrg SCREEN_UNWRAP(pScreen, SetShape); 2856747b715Smrg pScreen->SetShape(pWin, kind); 28605b261ecSmrg SCREEN_WRAP(pScreen, SetShape); 28705b261ecSmrg 28805b261ecSmrg RootlessReshapeFrame(pWin); 28905b261ecSmrg} 29005b261ecSmrg 29105b261ecSmrg 29205b261ecSmrg 29305b261ecSmrg/* Disallow ParentRelative background on top-level windows 2944642e01fSmrg because the root window doesn't really have the right background. 2954642e01fSmrg */ 29605b261ecSmrgBool 29705b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) 29805b261ecSmrg{ 29905b261ecSmrg Bool result; 30005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 30105b261ecSmrg 30205b261ecSmrg RL_DEBUG_MSG("change window attributes start "); 30305b261ecSmrg 30405b261ecSmrg SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); 30505b261ecSmrg result = pScreen->ChangeWindowAttributes(pWin, vmask); 30605b261ecSmrg SCREEN_WRAP(pScreen, ChangeWindowAttributes); 30705b261ecSmrg 30805b261ecSmrg if (WINREC(pWin)) { 30905b261ecSmrg // disallow ParentRelative background state 31005b261ecSmrg if (pWin->backgroundState == ParentRelative) { 31105b261ecSmrg XID pixel = 0; 31205b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 31305b261ecSmrg } 31405b261ecSmrg } 31505b261ecSmrg 31605b261ecSmrg RL_DEBUG_MSG("change window attributes end\n"); 31705b261ecSmrg return result; 31805b261ecSmrg} 31905b261ecSmrg 32005b261ecSmrg 32105b261ecSmrg/* 32205b261ecSmrg * RootlessPositionWindow 32305b261ecSmrg * This is a hook for when DIX moves or resizes a window. 32405b261ecSmrg * Update the frame position now although the physical window is moved 32505b261ecSmrg * in RootlessMoveWindow. (x, y) are *inside* position. After this, 32605b261ecSmrg * mi and fb are expecting the pixmap to be at the new location. 32705b261ecSmrg */ 32805b261ecSmrgBool 32905b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y) 33005b261ecSmrg{ 33105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 33205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 33305b261ecSmrg Bool result; 33405b261ecSmrg 33505b261ecSmrg RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); 33605b261ecSmrg 33705b261ecSmrg if (winRec) { 33805b261ecSmrg if (winRec->is_drawing) { 33905b261ecSmrg // Reset frame's pixmap and move it to the new position. 34005b261ecSmrg int bw = wBorderWidth(pWin); 34105b261ecSmrg 34205b261ecSmrg winRec->pixmap->devPrivate.ptr = winRec->pixelData; 34305b261ecSmrg SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); 34405b261ecSmrg 34505b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 34605b261ecSmrg // Move damaged region to correspond to new window position 3476747b715Smrg if (RegionNotEmpty(&winRec->damage)) { 3486747b715Smrg RegionTranslate(&winRec->damage, 34905b261ecSmrg x - bw - winRec->x, 35005b261ecSmrg y - bw - winRec->y); 35105b261ecSmrg } 35205b261ecSmrg#endif 35305b261ecSmrg } 35405b261ecSmrg } 35505b261ecSmrg 35605b261ecSmrg SCREEN_UNWRAP(pScreen, PositionWindow); 35705b261ecSmrg result = pScreen->PositionWindow(pWin, x, y); 35805b261ecSmrg SCREEN_WRAP(pScreen, PositionWindow); 35905b261ecSmrg 36005b261ecSmrg RL_DEBUG_MSG("positionwindow end\n"); 36105b261ecSmrg return result; 36205b261ecSmrg} 36305b261ecSmrg 36405b261ecSmrg 36505b261ecSmrg/* 36605b261ecSmrg * RootlessInitializeFrame 36705b261ecSmrg * Initialize some basic attributes of the frame. Note that winRec 36805b261ecSmrg * may already have valid data in it, so don't overwrite anything 36905b261ecSmrg * valuable. 37005b261ecSmrg */ 37105b261ecSmrgstatic void 37205b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) 37305b261ecSmrg{ 37405b261ecSmrg DrawablePtr d = &pWin->drawable; 37505b261ecSmrg int bw = wBorderWidth(pWin); 37605b261ecSmrg 37705b261ecSmrg winRec->win = pWin; 37805b261ecSmrg 37905b261ecSmrg winRec->x = d->x - bw; 38005b261ecSmrg winRec->y = d->y - bw; 38105b261ecSmrg winRec->width = d->width + 2*bw; 38205b261ecSmrg winRec->height = d->height + 2*bw; 38305b261ecSmrg winRec->borderWidth = bw; 38405b261ecSmrg 38505b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 3866747b715Smrg RegionNull(&winRec->damage); 38705b261ecSmrg#endif 38805b261ecSmrg} 38905b261ecSmrg 39005b261ecSmrg/* 39105b261ecSmrg * RootlessEnsureFrame 39205b261ecSmrg * Make sure the given window is framed. If the window doesn't have a 39305b261ecSmrg * physical window associated with it, attempt to create one. If that 39405b261ecSmrg * is unsuccessful, return NULL. 39505b261ecSmrg */ 39605b261ecSmrgstatic RootlessWindowRec * 39705b261ecSmrgRootlessEnsureFrame(WindowPtr pWin) 39805b261ecSmrg{ 39905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 40005b261ecSmrg RootlessWindowRec *winRec; 40105b261ecSmrg RegionRec shape; 40205b261ecSmrg RegionPtr pShape = NULL; 40305b261ecSmrg 40405b261ecSmrg if (WINREC(pWin) != NULL) 40505b261ecSmrg return WINREC(pWin); 40605b261ecSmrg 4074642e01fSmrg if (!IsTopLevel(pWin) && !IsRoot(pWin)) 40805b261ecSmrg return NULL; 40905b261ecSmrg 41005b261ecSmrg if (pWin->drawable.class != InputOutput) 41105b261ecSmrg return NULL; 41205b261ecSmrg 4136747b715Smrg winRec = malloc(sizeof(RootlessWindowRec)); 41405b261ecSmrg 41505b261ecSmrg if (!winRec) 41605b261ecSmrg return NULL; 41705b261ecSmrg 41805b261ecSmrg RootlessInitializeFrame(pWin, winRec); 41905b261ecSmrg 42005b261ecSmrg winRec->is_drawing = FALSE; 42105b261ecSmrg winRec->is_reorder_pending = FALSE; 42205b261ecSmrg winRec->pixmap = NULL; 42305b261ecSmrg winRec->wid = NULL; 4246747b715Smrg winRec->level = 0; 42505b261ecSmrg 4264642e01fSmrg SETWINREC(pWin, winRec); 42705b261ecSmrg 42805b261ecSmrg // Set the frame's shape if the window is shaped 42905b261ecSmrg if (RootlessGetShape(pWin, &shape)) 43005b261ecSmrg pShape = &shape; 43105b261ecSmrg 43205b261ecSmrg RL_DEBUG_MSG("creating frame "); 43305b261ecSmrg 43405b261ecSmrg if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, 43505b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 43605b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 43705b261ecSmrg pShape)) 43805b261ecSmrg { 43905b261ecSmrg RL_DEBUG_MSG("implementation failed to create frame!\n"); 4406747b715Smrg free(winRec); 4414642e01fSmrg SETWINREC(pWin, NULL); 44205b261ecSmrg return NULL; 44305b261ecSmrg } 44405b261ecSmrg 4454642e01fSmrg if (pWin->drawable.depth == 8) 4464642e01fSmrg RootlessFlushWindowColormap(pWin); 4474642e01fSmrg 44805b261ecSmrg if (pShape != NULL) 4496747b715Smrg RegionUninit(&shape); 45005b261ecSmrg 45105b261ecSmrg return winRec; 45205b261ecSmrg} 45305b261ecSmrg 45405b261ecSmrg 45505b261ecSmrg/* 45605b261ecSmrg * RootlessRealizeWindow 45705b261ecSmrg * The frame is usually created here and not in CreateWindow so that 45805b261ecSmrg * windows do not eat memory until they are realized. 45905b261ecSmrg */ 46005b261ecSmrgBool 46105b261ecSmrgRootlessRealizeWindow(WindowPtr pWin) 46205b261ecSmrg{ 46305b261ecSmrg Bool result; 46405b261ecSmrg RegionRec saveRoot; 46505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 46605b261ecSmrg 46705b261ecSmrg RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); 46805b261ecSmrg 46905b261ecSmrg if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { 47005b261ecSmrg RootlessWindowRec *winRec; 47105b261ecSmrg 47205b261ecSmrg winRec = RootlessEnsureFrame(pWin); 47305b261ecSmrg if (winRec == NULL) 47405b261ecSmrg return FALSE; 47505b261ecSmrg 47605b261ecSmrg winRec->is_reorder_pending = TRUE; 47705b261ecSmrg 47805b261ecSmrg RL_DEBUG_MSG("Top level window "); 47905b261ecSmrg 48005b261ecSmrg // Disallow ParentRelative background state on top-level windows. 48105b261ecSmrg // This might have been set before the window was mapped. 48205b261ecSmrg if (pWin->backgroundState == ParentRelative) { 48305b261ecSmrg XID pixel = 0; 48405b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 48505b261ecSmrg } 48605b261ecSmrg } 48705b261ecSmrg 48805b261ecSmrg if (!IsRoot(pWin)) HUGE_ROOT(pWin); 48905b261ecSmrg SCREEN_UNWRAP(pScreen, RealizeWindow); 49005b261ecSmrg result = pScreen->RealizeWindow(pWin); 49105b261ecSmrg SCREEN_WRAP(pScreen, RealizeWindow); 49205b261ecSmrg if (!IsRoot(pWin)) NORMAL_ROOT(pWin); 49305b261ecSmrg 49405b261ecSmrg RL_DEBUG_MSG("realizewindow end\n"); 49505b261ecSmrg return result; 49605b261ecSmrg} 49705b261ecSmrg 49805b261ecSmrg 49905b261ecSmrg/* 50005b261ecSmrg * RootlessFrameForWindow 50105b261ecSmrg * Returns the frame ID for the physical window displaying the given window. 50205b261ecSmrg * If CREATE is true and the window has no frame, attempt to create one. 50305b261ecSmrg */ 50405b261ecSmrgRootlessFrameID 50505b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create) 50605b261ecSmrg{ 50705b261ecSmrg WindowPtr pTopWin; 50805b261ecSmrg RootlessWindowRec *winRec; 50905b261ecSmrg 51005b261ecSmrg pTopWin = TopLevelParent(pWin); 51105b261ecSmrg if (pTopWin == NULL) 51205b261ecSmrg return NULL; 51305b261ecSmrg 51405b261ecSmrg winRec = WINREC(pTopWin); 51505b261ecSmrg 51605b261ecSmrg if (winRec == NULL && create && pWin->drawable.class == InputOutput) { 51705b261ecSmrg winRec = RootlessEnsureFrame(pTopWin); 51805b261ecSmrg } 51905b261ecSmrg 52005b261ecSmrg if (winRec == NULL) 52105b261ecSmrg return NULL; 52205b261ecSmrg 52305b261ecSmrg return winRec->wid; 52405b261ecSmrg} 52505b261ecSmrg 52605b261ecSmrg 52705b261ecSmrg/* 52805b261ecSmrg * RootlessUnrealizeWindow 52905b261ecSmrg * Unmap the physical window. 53005b261ecSmrg */ 53105b261ecSmrgBool 53205b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin) 53305b261ecSmrg{ 53405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 53505b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 53605b261ecSmrg Bool result; 53705b261ecSmrg 53805b261ecSmrg RL_DEBUG_MSG("unrealizewindow start "); 53905b261ecSmrg 54005b261ecSmrg if (winRec) { 54105b261ecSmrg RootlessStopDrawing(pWin, FALSE); 54205b261ecSmrg 54305b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 54405b261ecSmrg 54505b261ecSmrg winRec->is_reorder_pending = FALSE; 54605b261ecSmrg } 54705b261ecSmrg 54805b261ecSmrg SCREEN_UNWRAP(pScreen, UnrealizeWindow); 54905b261ecSmrg result = pScreen->UnrealizeWindow(pWin); 55005b261ecSmrg SCREEN_WRAP(pScreen, UnrealizeWindow); 55105b261ecSmrg 55205b261ecSmrg RL_DEBUG_MSG("unrealizewindow end\n"); 55305b261ecSmrg return result; 55405b261ecSmrg} 55505b261ecSmrg 55605b261ecSmrg 55705b261ecSmrg/* 55805b261ecSmrg * RootlessReorderWindow 55905b261ecSmrg * Reorder the frame associated with the given window so that it's 56005b261ecSmrg * physically above the window below it in the X stacking order. 56105b261ecSmrg */ 56205b261ecSmrgvoid 56305b261ecSmrgRootlessReorderWindow(WindowPtr pWin) 56405b261ecSmrg{ 56505b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 56605b261ecSmrg 5674642e01fSmrg if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) { 56805b261ecSmrg WindowPtr newPrevW; 56905b261ecSmrg RootlessWindowRec *newPrev; 57005b261ecSmrg RootlessFrameID newPrevID; 57105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 57205b261ecSmrg 57305b261ecSmrg /* Check if the implementation wants the frame to not be reordered 57405b261ecSmrg even though the X11 window is restacked. This can be useful if 57505b261ecSmrg frames are ordered-in with animation so that the reordering is not 57605b261ecSmrg done until the animation is complete. */ 57705b261ecSmrg if (SCREENREC(pScreen)->imp->DoReorderWindow) { 57805b261ecSmrg if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) 57905b261ecSmrg return; 58005b261ecSmrg } 58105b261ecSmrg 58205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 58305b261ecSmrg 5846747b715Smrg /* Find the next window above this one that has a mapped frame. 5856747b715Smrg * Only include cases where the windows are in the same category of 5866747b715Smrg * hittability to ensure offscreen windows dont get restacked 5876747b715Smrg * relative to onscreen ones (but that the offscreen ones maintain 5886747b715Smrg * their stacking order if they are explicitly asked to Reorder 5896747b715Smrg */ 59005b261ecSmrg 59105b261ecSmrg newPrevW = pWin->prevSib; 5926747b715Smrg while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable)) 59305b261ecSmrg newPrevW = newPrevW->prevSib; 59405b261ecSmrg 59505b261ecSmrg newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; 59605b261ecSmrg newPrevID = newPrev != NULL ? newPrev->wid : 0; 59705b261ecSmrg 59805b261ecSmrg /* If it exists, reorder the frame above us first. */ 59905b261ecSmrg 60005b261ecSmrg if (newPrev && newPrev->is_reorder_pending) { 60105b261ecSmrg newPrev->is_reorder_pending = FALSE; 60205b261ecSmrg RootlessReorderWindow(newPrevW); 60305b261ecSmrg } 60405b261ecSmrg 60505b261ecSmrg SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); 60605b261ecSmrg } 60705b261ecSmrg} 60805b261ecSmrg 60905b261ecSmrg 61005b261ecSmrg/* 61105b261ecSmrg * RootlessRestackWindow 61205b261ecSmrg * This is a hook for when DIX changes the window stacking order. 61305b261ecSmrg * The window has already been inserted into its new position in the 61405b261ecSmrg * DIX window stack. We need to change the order of the physical 61505b261ecSmrg * window to match. 61605b261ecSmrg */ 61705b261ecSmrgvoid 61805b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) 61905b261ecSmrg{ 62005b261ecSmrg RegionRec saveRoot; 62105b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 62205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 62305b261ecSmrg 62405b261ecSmrg RL_DEBUG_MSG("restackwindow start "); 62505b261ecSmrg if (winRec) 62605b261ecSmrg RL_DEBUG_MSG("restack top level \n"); 62705b261ecSmrg 62805b261ecSmrg HUGE_ROOT(pWin); 62905b261ecSmrg SCREEN_UNWRAP(pScreen, RestackWindow); 63005b261ecSmrg 63105b261ecSmrg if (pScreen->RestackWindow) 63205b261ecSmrg pScreen->RestackWindow(pWin, pOldNextSib); 63305b261ecSmrg 63405b261ecSmrg SCREEN_WRAP(pScreen, RestackWindow); 63505b261ecSmrg NORMAL_ROOT(pWin); 63605b261ecSmrg 63705b261ecSmrg if (winRec && pWin->viewable) { 63805b261ecSmrg RootlessReorderWindow(pWin); 63905b261ecSmrg } 64005b261ecSmrg 64105b261ecSmrg RL_DEBUG_MSG("restackwindow end\n"); 64205b261ecSmrg} 64305b261ecSmrg 64405b261ecSmrg/* 64505b261ecSmrg * Specialized window copy procedures 64605b261ecSmrg */ 64705b261ecSmrg 64805b261ecSmrg// Globals needed during window resize and move. 64905b261ecSmrgstatic pointer gResizeDeathBits = NULL; 65005b261ecSmrgstatic int gResizeDeathCount = 0; 65105b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; 65205b261ecSmrgstatic BoxRec gResizeDeathBounds[2]; 65305b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; 65405b261ecSmrg 65505b261ecSmrg/* 65605b261ecSmrg * RootlessNoCopyWindow 65705b261ecSmrg * CopyWindow() that doesn't do anything. For MoveWindow() of 65805b261ecSmrg * top-level windows. 65905b261ecSmrg */ 66005b261ecSmrgstatic void 66105b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 66205b261ecSmrg RegionPtr prgnSrc) 66305b261ecSmrg{ 66405b261ecSmrg // some code expects the region to be translated 66505b261ecSmrg int dx = ptOldOrg.x - pWin->drawable.x; 66605b261ecSmrg int dy = ptOldOrg.y - pWin->drawable.y; 66705b261ecSmrg 66805b261ecSmrg RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); 66905b261ecSmrg 6706747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 67105b261ecSmrg} 67205b261ecSmrg 67305b261ecSmrg 67405b261ecSmrg/* 67505b261ecSmrg * RootlessResizeCopyWindow 67605b261ecSmrg * CopyWindow used during ResizeWindow for gravity moves. Based on 67705b261ecSmrg * fbCopyWindow. The original always draws on the root pixmap, which 67805b261ecSmrg * we don't have. Instead, draw on the parent window's pixmap. 67905b261ecSmrg * Resize version: the old location's pixels are in gResizeCopyWindowSource. 68005b261ecSmrg */ 68105b261ecSmrgstatic void 68205b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 68305b261ecSmrg RegionPtr prgnSrc) 68405b261ecSmrg{ 68505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 68605b261ecSmrg RegionRec rgnDst; 68705b261ecSmrg int dx, dy; 68805b261ecSmrg 68905b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); 69005b261ecSmrg 69105b261ecSmrg /* Don't unwrap pScreen->CopyWindow. 69205b261ecSmrg The bogus rewrap with RootlessCopyWindow causes a crash if 69305b261ecSmrg CopyWindow is called again during the same resize. */ 69405b261ecSmrg 69505b261ecSmrg if (gResizeDeathCount == 0) 69605b261ecSmrg return; 69705b261ecSmrg 69805b261ecSmrg RootlessStartDrawing(pWin); 69905b261ecSmrg 70005b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 70105b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 7026747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 7036747b715Smrg RegionNull(&rgnDst); 7046747b715Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 70505b261ecSmrg 70605b261ecSmrg if (gResizeDeathCount == 1) { 70705b261ecSmrg /* Simple case, we only have a single source pixmap. */ 70805b261ecSmrg 70905b261ecSmrg fbCopyRegion(&gResizeDeathPix[0]->drawable, 71005b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 71105b261ecSmrg &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 71205b261ecSmrg } 71305b261ecSmrg else { 71405b261ecSmrg int i; 71505b261ecSmrg RegionRec clip, clipped; 71605b261ecSmrg 71705b261ecSmrg /* More complex case, N source pixmaps (usually two). So we 71805b261ecSmrg intersect the destination with each source and copy those bits. */ 71905b261ecSmrg 72005b261ecSmrg for (i = 0; i < gResizeDeathCount; i++) { 7216747b715Smrg RegionInit(&clip, gResizeDeathBounds + 0, 1); 7226747b715Smrg RegionNull(&clipped); 7236747b715Smrg RegionIntersect(&rgnDst, &clip, &clipped); 72405b261ecSmrg 72505b261ecSmrg fbCopyRegion(&gResizeDeathPix[i]->drawable, 72605b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 72705b261ecSmrg &clipped, dx, dy, fbCopyWindowProc, 0, 0); 72805b261ecSmrg 7296747b715Smrg RegionUninit(&clipped); 7306747b715Smrg RegionUninit(&clip); 73105b261ecSmrg } 73205b261ecSmrg } 73305b261ecSmrg 73405b261ecSmrg /* Don't update - resize will update everything */ 7356747b715Smrg RegionUninit(&rgnDst); 73605b261ecSmrg 73705b261ecSmrg fbValidateDrawable(&pWin->drawable); 73805b261ecSmrg 73905b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB end\n"); 74005b261ecSmrg} 74105b261ecSmrg 74205b261ecSmrg 74305b261ecSmrg/* 74405b261ecSmrg * RootlessCopyWindow 74505b261ecSmrg * Update *new* location of window. Old location is redrawn with 7464642e01fSmrg * miPaintWindow. Cloned from fbCopyWindow. 74705b261ecSmrg * The original always draws on the root pixmap, which we don't have. 74805b261ecSmrg * Instead, draw on the parent window's pixmap. 74905b261ecSmrg */ 75005b261ecSmrgvoid 75105b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 75205b261ecSmrg{ 75305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 75405b261ecSmrg RegionRec rgnDst; 75505b261ecSmrg int dx, dy; 75605b261ecSmrg BoxPtr extents; 75705b261ecSmrg int area; 75805b261ecSmrg 75905b261ecSmrg RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); 76005b261ecSmrg 76105b261ecSmrg SCREEN_UNWRAP(pScreen, CopyWindow); 76205b261ecSmrg 76305b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 76405b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 7656747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 76605b261ecSmrg 7676747b715Smrg RegionNull(&rgnDst); 7686747b715Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 76905b261ecSmrg 7706747b715Smrg extents = RegionExtents(&rgnDst); 77105b261ecSmrg area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); 77205b261ecSmrg 77305b261ecSmrg /* If the area exceeds threshold, use the implementation's 77405b261ecSmrg accelerated version. */ 77505b261ecSmrg if (area > rootless_CopyWindow_threshold && 77605b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow) 77705b261ecSmrg { 77805b261ecSmrg RootlessWindowRec *winRec; 77905b261ecSmrg WindowPtr top; 78005b261ecSmrg 78105b261ecSmrg top = TopLevelParent(pWin); 78205b261ecSmrg if (top == NULL) { 78305b261ecSmrg RL_DEBUG_MSG("no parent\n"); 7844642e01fSmrg goto out; 78505b261ecSmrg } 78605b261ecSmrg 78705b261ecSmrg winRec = WINREC(top); 78805b261ecSmrg if (winRec == NULL) { 78905b261ecSmrg RL_DEBUG_MSG("not framed\n"); 7904642e01fSmrg goto out; 79105b261ecSmrg } 79205b261ecSmrg 79305b261ecSmrg /* Move region to window local coords */ 7946747b715Smrg RegionTranslate(&rgnDst, -winRec->x, -winRec->y); 79505b261ecSmrg 79605b261ecSmrg RootlessStopDrawing(pWin, FALSE); 79705b261ecSmrg 79805b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, 7996747b715Smrg RegionNumRects(&rgnDst), 8006747b715Smrg RegionRects(&rgnDst), 80105b261ecSmrg dx, dy); 80205b261ecSmrg } 80305b261ecSmrg else { 80405b261ecSmrg RootlessStartDrawing(pWin); 80505b261ecSmrg 80605b261ecSmrg fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, 80705b261ecSmrg 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 80805b261ecSmrg 80905b261ecSmrg /* prgnSrc has been translated to dst position */ 81005b261ecSmrg RootlessDamageRegion(pWin, prgnSrc); 81105b261ecSmrg } 81205b261ecSmrg 8134642e01fSmrgout: 8146747b715Smrg RegionUninit(&rgnDst); 81505b261ecSmrg fbValidateDrawable(&pWin->drawable); 81605b261ecSmrg 81705b261ecSmrg SCREEN_WRAP(pScreen, CopyWindow); 81805b261ecSmrg 81905b261ecSmrg RL_DEBUG_MSG("copywindowFB end\n"); 82005b261ecSmrg} 82105b261ecSmrg 82205b261ecSmrg 82305b261ecSmrg/* 82405b261ecSmrg * Window resize procedures 82505b261ecSmrg */ 82605b261ecSmrg 82705b261ecSmrgenum { 82805b261ecSmrg WIDTH_SMALLER = 1, 82905b261ecSmrg HEIGHT_SMALLER = 2, 83005b261ecSmrg}; 83105b261ecSmrg 83205b261ecSmrg 83305b261ecSmrg/* 83405b261ecSmrg * ResizeWeighting 83505b261ecSmrg * Choose gravity to avoid local copies. Do that by looking for 83605b261ecSmrg * a corner that doesn't move _relative to the screen_. 83705b261ecSmrg */ 83805b261ecSmrgstatic inline unsigned int 83905b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, 84005b261ecSmrg int newX1, int newY1, int newX2, int newY2, int newBW) 84105b261ecSmrg{ 84205b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY 84305b261ecSmrg if (newBW != oldBW) 84405b261ecSmrg return RL_GRAVITY_NONE; 84505b261ecSmrg 84605b261ecSmrg if (newX1 == oldX1 && newY1 == oldY1) 84705b261ecSmrg return RL_GRAVITY_NORTH_WEST; 84805b261ecSmrg else if (newX1 == oldX1 && newY2 == oldY2) 84905b261ecSmrg return RL_GRAVITY_SOUTH_WEST; 85005b261ecSmrg else if (newX2 == oldX2 && newY2 == oldY2) 85105b261ecSmrg return RL_GRAVITY_SOUTH_EAST; 85205b261ecSmrg else if (newX2 == oldX2 && newY1 == oldY1) 85305b261ecSmrg return RL_GRAVITY_NORTH_EAST; 85405b261ecSmrg else 85505b261ecSmrg return RL_GRAVITY_NONE; 85605b261ecSmrg#else 85705b261ecSmrg return RL_GRAVITY_NONE; 85805b261ecSmrg#endif 85905b261ecSmrg} 86005b261ecSmrg 86105b261ecSmrg 86205b261ecSmrg/* 86305b261ecSmrg * StartFrameResize 86405b261ecSmrg * Prepare to resize a top-level window. The old window's pixels are 86505b261ecSmrg * saved and the implementation is told to change the window size. 86605b261ecSmrg * (x,y,w,h) is outer frame of window (outside border) 86705b261ecSmrg */ 86805b261ecSmrgstatic Bool 86905b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity, 87005b261ecSmrg int oldX, int oldY, int oldW, int oldH, int oldBW, 87105b261ecSmrg int newX, int newY, int newW, int newH, int newBW) 87205b261ecSmrg{ 87305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 87405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 87505b261ecSmrg Bool need_window_source = FALSE, resize_after = FALSE; 87605b261ecSmrg 87705b261ecSmrg BoxRec rect; 87805b261ecSmrg int oldX2, newX2; 87905b261ecSmrg int oldY2, newY2; 88005b261ecSmrg unsigned int weight; 88105b261ecSmrg 88205b261ecSmrg oldX2 = oldX + oldW, newX2 = newX + newW; 88305b261ecSmrg oldY2 = oldY + oldH, newY2 = newY + newH; 88405b261ecSmrg 88505b261ecSmrg /* Decide which resize weighting to use */ 88605b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 88705b261ecSmrg newX, newY, newW, newH, newBW); 88805b261ecSmrg 88905b261ecSmrg /* Compute intersection between old and new rects */ 89005b261ecSmrg rect.x1 = max(oldX, newX); 89105b261ecSmrg rect.y1 = max(oldY, newY); 89205b261ecSmrg rect.x2 = min(oldX2, newX2); 89305b261ecSmrg rect.y2 = min(oldY2, newY2); 89405b261ecSmrg 89505b261ecSmrg RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); 89605b261ecSmrg RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", 89705b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 89805b261ecSmrg newX, newY, newW, newH, newBW); 89905b261ecSmrg 90005b261ecSmrg RootlessRedisplay(pWin); 90105b261ecSmrg 90205b261ecSmrg /* If gravity is true, then we need to have a way of recovering all 90305b261ecSmrg the original bits in the window for when X rearranges the contents 90405b261ecSmrg based on the various gravity settings. The obvious way is to just 90505b261ecSmrg snapshot the entire backing store before resizing it, but that 90605b261ecSmrg it slow on large windows. 90705b261ecSmrg 90805b261ecSmrg So the optimization here is to use the implementation's resize 90905b261ecSmrg weighting options (if available) to allow us to reason about what 91005b261ecSmrg is left in the backing store after the resize. We can then only 91105b261ecSmrg copy what won't be there after the resize, and do a two-stage copy 91205b261ecSmrg operation. 91305b261ecSmrg 91405b261ecSmrg Most of these optimizations are only applied when the top-left 91505b261ecSmrg corner of the window is fixed, since that's the common case. They 91605b261ecSmrg could probably be extended with some thought. */ 91705b261ecSmrg 91805b261ecSmrg gResizeDeathCount = 0; 91905b261ecSmrg 92005b261ecSmrg if (gravity && weight == RL_GRAVITY_NORTH_WEST) { 92105b261ecSmrg unsigned int code = 0; 92205b261ecSmrg 92305b261ecSmrg /* Top left corner is anchored. We never need to copy the 92405b261ecSmrg entire window. */ 92505b261ecSmrg 92605b261ecSmrg need_window_source = TRUE; 92705b261ecSmrg 92805b261ecSmrg /* These comparisons were chosen to avoid setting bits when the sizes 92905b261ecSmrg are the same. (So the fastest case automatically gets taken when 93005b261ecSmrg dimensions are unchanging.) */ 93105b261ecSmrg 93205b261ecSmrg if (newW < oldW) 93305b261ecSmrg code |= WIDTH_SMALLER; 93405b261ecSmrg if (newH < oldH) 93505b261ecSmrg code |= HEIGHT_SMALLER; 93605b261ecSmrg 93705b261ecSmrg if (((code ^ (code >> 1)) & 1) == 0) { 93805b261ecSmrg /* Both dimensions are either getting larger, or both 93905b261ecSmrg are getting smaller. No need to copy anything. */ 94005b261ecSmrg 94105b261ecSmrg if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { 94205b261ecSmrg /* Since the window is getting smaller, we can do gravity 94305b261ecSmrg repair on it with it's current size, then resize it 94405b261ecSmrg afterwards. */ 94505b261ecSmrg 94605b261ecSmrg resize_after = TRUE; 94705b261ecSmrg } 94805b261ecSmrg 94905b261ecSmrg gResizeDeathCount = 1; 95005b261ecSmrg } 95105b261ecSmrg else { 95205b261ecSmrg unsigned int copy_rowbytes, Bpp; 95305b261ecSmrg unsigned int copy_rect_width, copy_rect_height; 95405b261ecSmrg BoxRec copy_rect; 95505b261ecSmrg 95605b261ecSmrg /* We can get away with a partial copy. 'rect' is the 95705b261ecSmrg intersection between old and new bounds, so copy 95805b261ecSmrg everything to the right of or below the intersection. */ 95905b261ecSmrg 96005b261ecSmrg RootlessStartDrawing(pWin); 96105b261ecSmrg 96205b261ecSmrg if (code == WIDTH_SMALLER) { 96305b261ecSmrg copy_rect.x1 = rect.x2; 96405b261ecSmrg copy_rect.y1 = rect.y1; 96505b261ecSmrg copy_rect.x2 = oldX2; 96605b261ecSmrg copy_rect.y2 = oldY2; 96705b261ecSmrg } 96805b261ecSmrg else if (code == HEIGHT_SMALLER) { 96905b261ecSmrg copy_rect.x1 = rect.x1; 97005b261ecSmrg copy_rect.y1 = rect.y2; 97105b261ecSmrg copy_rect.x2 = oldX2; 97205b261ecSmrg copy_rect.y2 = oldY2; 97305b261ecSmrg } 97405b261ecSmrg else 9756747b715Smrg OsAbort(); 97605b261ecSmrg 97705b261ecSmrg Bpp = winRec->win->drawable.bitsPerPixel / 8; 97805b261ecSmrg copy_rect_width = copy_rect.x2 - copy_rect.x1; 97905b261ecSmrg copy_rect_height = copy_rect.y2 - copy_rect.y1; 98005b261ecSmrg copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; 9816747b715Smrg gResizeDeathBits = malloc(copy_rowbytes 98205b261ecSmrg * copy_rect_height); 98305b261ecSmrg 98405b261ecSmrg if (copy_rect_width * copy_rect_height > 98505b261ecSmrg rootless_CopyBytes_threshold && 98605b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes) 98705b261ecSmrg { 98805b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes( 98905b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 99005b261ecSmrg ((char *) winRec->pixelData) 99105b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 99205b261ecSmrg + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, 99305b261ecSmrg gResizeDeathBits, copy_rowbytes); 99405b261ecSmrg } else { 99505b261ecSmrg fbBlt((FbBits *) (winRec->pixelData 99605b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 99705b261ecSmrg + (copy_rect.x1 - oldX) * Bpp), 99805b261ecSmrg winRec->bytesPerRow / sizeof(FbBits), 0, 99905b261ecSmrg (FbBits *) gResizeDeathBits, 100005b261ecSmrg copy_rowbytes / sizeof(FbBits), 0, 100105b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 100205b261ecSmrg GXcopy, FB_ALLONES, Bpp, 0, 0); 100305b261ecSmrg } 100405b261ecSmrg 100505b261ecSmrg gResizeDeathBounds[1] = copy_rect; 100605b261ecSmrg gResizeDeathPix[1] 100705b261ecSmrg = GetScratchPixmapHeader(pScreen, copy_rect_width, 100805b261ecSmrg copy_rect_height, 100905b261ecSmrg winRec->win->drawable.depth, 101005b261ecSmrg winRec->win->drawable.bitsPerPixel, 101105b261ecSmrg winRec->bytesPerRow, 101205b261ecSmrg (void *) gResizeDeathBits); 101305b261ecSmrg 101405b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[1], 101505b261ecSmrg copy_rect.x1, copy_rect.y1); 101605b261ecSmrg 101705b261ecSmrg gResizeDeathCount = 2; 101805b261ecSmrg } 101905b261ecSmrg } 102005b261ecSmrg else if (gravity) { 102105b261ecSmrg /* The general case. Just copy everything. */ 102205b261ecSmrg 102305b261ecSmrg RootlessStartDrawing(pWin); 102405b261ecSmrg 10256747b715Smrg gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); 102605b261ecSmrg 102705b261ecSmrg memcpy(gResizeDeathBits, winRec->pixelData, 102805b261ecSmrg winRec->bytesPerRow * winRec->height); 102905b261ecSmrg 103005b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 103105b261ecSmrg gResizeDeathPix[0] 103205b261ecSmrg = GetScratchPixmapHeader(pScreen, winRec->width, 103305b261ecSmrg winRec->height, 103405b261ecSmrg winRec->win->drawable.depth, 103505b261ecSmrg winRec->win->drawable.bitsPerPixel, 103605b261ecSmrg winRec->bytesPerRow, 103705b261ecSmrg (void *) gResizeDeathBits); 103805b261ecSmrg 103905b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 104005b261ecSmrg gResizeDeathCount = 1; 104105b261ecSmrg } 104205b261ecSmrg 104305b261ecSmrg RootlessStopDrawing(pWin, FALSE); 104405b261ecSmrg 104505b261ecSmrg winRec->x = newX; 104605b261ecSmrg winRec->y = newY; 104705b261ecSmrg winRec->width = newW; 104805b261ecSmrg winRec->height = newH; 104905b261ecSmrg winRec->borderWidth = newBW; 105005b261ecSmrg 105105b261ecSmrg /* Unless both dimensions are getting smaller, Resize the frame 105205b261ecSmrg before doing gravity repair */ 105305b261ecSmrg 105405b261ecSmrg if (!resize_after) { 105505b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 105605b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 105705b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 105805b261ecSmrg newW, newH, weight); 105905b261ecSmrg } 106005b261ecSmrg 106105b261ecSmrg RootlessStartDrawing(pWin); 106205b261ecSmrg 106305b261ecSmrg /* If necessary, create a source pixmap pointing at the current 106405b261ecSmrg window bits. */ 106505b261ecSmrg 106605b261ecSmrg if (need_window_source) { 106705b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 106805b261ecSmrg gResizeDeathPix[0] 106905b261ecSmrg = GetScratchPixmapHeader(pScreen, oldW, oldH, 107005b261ecSmrg winRec->win->drawable.depth, 107105b261ecSmrg winRec->win->drawable.bitsPerPixel, 107205b261ecSmrg winRec->bytesPerRow, winRec->pixelData); 107305b261ecSmrg 107405b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 107505b261ecSmrg } 107605b261ecSmrg 107705b261ecSmrg /* Use custom CopyWindow when moving gravity bits around 107805b261ecSmrg ResizeWindow assumes the old window contents are in the same 107905b261ecSmrg pixmap, but here they're in deathPix instead. */ 108005b261ecSmrg 108105b261ecSmrg if (gravity) { 108205b261ecSmrg gResizeOldCopyWindowProc = pScreen->CopyWindow; 108305b261ecSmrg pScreen->CopyWindow = RootlessResizeCopyWindow; 108405b261ecSmrg } 108505b261ecSmrg 108605b261ecSmrg /* If we can't rely on the window server preserving the bits we 108705b261ecSmrg need in the position we need, copy the pixels in the 108805b261ecSmrg intersection from src to dst. ResizeWindow assumes these pixels 108905b261ecSmrg are already present when making gravity adjustments. pWin 109005b261ecSmrg currently has new-sized pixmap but is in old position. 109105b261ecSmrg 109205b261ecSmrg FIXME: border width change! (?) */ 109305b261ecSmrg 109405b261ecSmrg if (gravity && weight == RL_GRAVITY_NONE) { 109505b261ecSmrg PixmapPtr src, dst; 109605b261ecSmrg 109705b261ecSmrg assert(gResizeDeathCount == 1); 109805b261ecSmrg 109905b261ecSmrg src = gResizeDeathPix[0]; 110005b261ecSmrg dst = pScreen->GetWindowPixmap(pWin); 110105b261ecSmrg 110205b261ecSmrg RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", 110305b261ecSmrg rect.x1, rect.y1, rect.x2, rect.y2); 110405b261ecSmrg 110505b261ecSmrg /* rect is the intersection of the old location and new location */ 110605b261ecSmrg if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { 110705b261ecSmrg /* The window drawable still has the old frame position, which 110805b261ecSmrg means that DST doesn't actually point at the origin of our 110905b261ecSmrg physical backing store when adjusted by the drawable.x,y 111005b261ecSmrg position. So sneakily adjust it temporarily while copying.. */ 111105b261ecSmrg 111205b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 111305b261ecSmrg SetPixmapBaseToScreen(dst, newX, newY); 111405b261ecSmrg 111505b261ecSmrg fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, 111605b261ecSmrg &rect, 1, 0, 0, FALSE, FALSE, 0, 0); 111705b261ecSmrg 111805b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 111905b261ecSmrg SetPixmapBaseToScreen(dst, oldX, oldY); 112005b261ecSmrg } 112105b261ecSmrg } 112205b261ecSmrg 112305b261ecSmrg return resize_after; 112405b261ecSmrg} 112505b261ecSmrg 112605b261ecSmrg 112705b261ecSmrgstatic void 112805b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, 112905b261ecSmrg unsigned int oldW, unsigned int oldH, unsigned int oldBW, 113005b261ecSmrg int newX, int newY, unsigned int newW, unsigned int newH, 113105b261ecSmrg unsigned int newBW, Bool resize_now) 113205b261ecSmrg{ 113305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 113405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 113505b261ecSmrg int i; 113605b261ecSmrg 113705b261ecSmrg RootlessStopDrawing(pWin, FALSE); 113805b261ecSmrg 113905b261ecSmrg if (resize_now) { 114005b261ecSmrg unsigned int weight; 114105b261ecSmrg 114205b261ecSmrg /* We didn't resize anything earlier, so do it now, now that 114305b261ecSmrg we've finished gravitating the bits. */ 114405b261ecSmrg 114505b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 114605b261ecSmrg newX, newY, newW, newH, newBW); 114705b261ecSmrg 114805b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 114905b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 115005b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 115105b261ecSmrg newW, newH, weight); 115205b261ecSmrg } 115305b261ecSmrg 115405b261ecSmrg /* Redraw everything. FIXME: there must be times when we don't need 115505b261ecSmrg to do this. Perhaps when top-left weighting and no gravity? */ 115605b261ecSmrg 115705b261ecSmrg RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); 115805b261ecSmrg 115905b261ecSmrg for (i = 0; i < 2; i++) { 116005b261ecSmrg if (gResizeDeathPix[i] != NULL) { 116105b261ecSmrg FreeScratchPixmapHeader(gResizeDeathPix[i]); 116205b261ecSmrg gResizeDeathPix[i] = NULL; 116305b261ecSmrg } 116405b261ecSmrg } 116505b261ecSmrg 116605b261ecSmrg if (gResizeDeathBits != NULL) { 11676747b715Smrg free(gResizeDeathBits); 116805b261ecSmrg gResizeDeathBits = NULL; 116905b261ecSmrg } 117005b261ecSmrg 117105b261ecSmrg if (gravity) { 117205b261ecSmrg pScreen->CopyWindow = gResizeOldCopyWindowProc; 117305b261ecSmrg } 117405b261ecSmrg} 117505b261ecSmrg 117605b261ecSmrg 117705b261ecSmrg/* 117805b261ecSmrg * RootlessMoveWindow 117905b261ecSmrg * If kind==VTOther, window border is resizing (and borderWidth is 118005b261ecSmrg * already changed!!@#$) This case works like window resize, not move. 118105b261ecSmrg */ 118205b261ecSmrgvoid 118305b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 118405b261ecSmrg{ 118505b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 118605b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 118705b261ecSmrg CopyWindowProcPtr oldCopyWindowProc = NULL; 118805b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 118905b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 119005b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 119105b261ecSmrg Bool resize_after = FALSE; 119205b261ecSmrg RegionRec saveRoot; 119305b261ecSmrg 119405b261ecSmrg RL_DEBUG_MSG("movewindow start \n"); 119505b261ecSmrg 119605b261ecSmrg if (winRec) { 119705b261ecSmrg if (kind == VTMove) { 119805b261ecSmrg oldX = winRec->x; 119905b261ecSmrg oldY = winRec->y; 120005b261ecSmrg RootlessRedisplay(pWin); 120105b261ecSmrg RootlessStartDrawing(pWin); 120205b261ecSmrg } else { 120305b261ecSmrg RL_DEBUG_MSG("movewindow border resizing "); 120405b261ecSmrg 120505b261ecSmrg oldBW = winRec->borderWidth; 120605b261ecSmrg oldX = winRec->x; 120705b261ecSmrg oldY = winRec->y; 120805b261ecSmrg oldW = winRec->width; 120905b261ecSmrg oldH = winRec->height; 121005b261ecSmrg 121105b261ecSmrg newBW = wBorderWidth(pWin); 121205b261ecSmrg newX = x; 121305b261ecSmrg newY = y; 121405b261ecSmrg newW = pWin->drawable.width + 2*newBW; 121505b261ecSmrg newH = pWin->drawable.height + 2*newBW; 121605b261ecSmrg 121705b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 121805b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 121905b261ecSmrg newX, newY, newW, newH, newBW); 122005b261ecSmrg } 122105b261ecSmrg } 122205b261ecSmrg 122305b261ecSmrg HUGE_ROOT(pWin); 122405b261ecSmrg SCREEN_UNWRAP(pScreen, MoveWindow); 122505b261ecSmrg 122605b261ecSmrg if (winRec) { 122705b261ecSmrg oldCopyWindowProc = pScreen->CopyWindow; 122805b261ecSmrg pScreen->CopyWindow = RootlessNoCopyWindow; 122905b261ecSmrg } 123005b261ecSmrg pScreen->MoveWindow(pWin, x, y, pSib, kind); 123105b261ecSmrg if (winRec) { 123205b261ecSmrg pScreen->CopyWindow = oldCopyWindowProc; 123305b261ecSmrg } 123405b261ecSmrg 123505b261ecSmrg NORMAL_ROOT(pWin); 123605b261ecSmrg SCREEN_WRAP(pScreen, MoveWindow); 123705b261ecSmrg 123805b261ecSmrg if (winRec) { 123905b261ecSmrg if (kind == VTMove) { 124005b261ecSmrg winRec->x = x; 124105b261ecSmrg winRec->y = y; 124205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 124305b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 124405b261ecSmrg x + SCREEN_TO_GLOBAL_X, 124505b261ecSmrg y + SCREEN_TO_GLOBAL_Y); 124605b261ecSmrg } else { 124705b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 124805b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 124905b261ecSmrg } 125005b261ecSmrg } 125105b261ecSmrg 125205b261ecSmrg RL_DEBUG_MSG("movewindow end\n"); 125305b261ecSmrg} 125405b261ecSmrg 125505b261ecSmrg 125605b261ecSmrg/* 125705b261ecSmrg * RootlessResizeWindow 125805b261ecSmrg * Note: (x, y, w, h) as passed to this procedure don't match the frame 125905b261ecSmrg * definition. (x,y) is corner of very outer edge, *outside* border. 126005b261ecSmrg * w,h is width and height *inside* border, *ignoring* border width. 126105b261ecSmrg * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) 126205b261ecSmrg * is total rect and (x+bw, y+bw, w, h) is inner rect. 126305b261ecSmrg */ 126405b261ecSmrgvoid 126505b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y, 126605b261ecSmrg unsigned int w, unsigned int h, WindowPtr pSib) 126705b261ecSmrg{ 126805b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 126905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 127005b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 127105b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; 127205b261ecSmrg Bool resize_after = FALSE; 127305b261ecSmrg RegionRec saveRoot; 127405b261ecSmrg 127505b261ecSmrg RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); 12764642e01fSmrg 12774642e01fSmrg if(pWin->parent) { 12784642e01fSmrg if (winRec) { 12794642e01fSmrg oldBW = winRec->borderWidth; 12804642e01fSmrg oldX = winRec->x; 12814642e01fSmrg oldY = winRec->y; 12824642e01fSmrg oldW = winRec->width; 12834642e01fSmrg oldH = winRec->height; 128405b261ecSmrg 12854642e01fSmrg newBW = oldBW; 12864642e01fSmrg newX = x; 12874642e01fSmrg newY = y; 12884642e01fSmrg newW = w + 2*newBW; 12894642e01fSmrg newH = h + 2*newBW; 129005b261ecSmrg 12914642e01fSmrg resize_after = StartFrameResize(pWin, TRUE, 12924642e01fSmrg oldX, oldY, oldW, oldH, oldBW, 12934642e01fSmrg newX, newY, newW, newH, newBW); 12944642e01fSmrg } 129505b261ecSmrg 12964642e01fSmrg HUGE_ROOT(pWin); 12974642e01fSmrg SCREEN_UNWRAP(pScreen, ResizeWindow); 12984642e01fSmrg pScreen->ResizeWindow(pWin, x, y, w, h, pSib); 12994642e01fSmrg SCREEN_WRAP(pScreen, ResizeWindow); 13004642e01fSmrg NORMAL_ROOT(pWin); 13014642e01fSmrg 13024642e01fSmrg if (winRec) { 13034642e01fSmrg FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, 13044642e01fSmrg newX, newY, newW, newH, newBW, resize_after); 13054642e01fSmrg } 13064642e01fSmrg } else { 13074642e01fSmrg /* Special case for resizing the root window */ 13084642e01fSmrg BoxRec box; 13094642e01fSmrg 13104642e01fSmrg pWin->drawable.x = x; 13114642e01fSmrg pWin->drawable.y = y; 13124642e01fSmrg pWin->drawable.width = w; 13134642e01fSmrg pWin->drawable.height = h; 13144642e01fSmrg 13154642e01fSmrg box.x1 = x; box.y1 = y; 13164642e01fSmrg box.x2 = x + w; box.y2 = y + h; 13176747b715Smrg RegionUninit(&pWin->winSize); 13186747b715Smrg RegionInit(&pWin->winSize, &box, 1); 13196747b715Smrg RegionCopy(&pWin->borderSize, &pWin->winSize); 13206747b715Smrg RegionCopy(&pWin->clipList, &pWin->winSize); 13216747b715Smrg RegionCopy(&pWin->borderClip, &pWin->winSize); 13226747b715Smrg 13236747b715Smrg if (winRec) { 13246747b715Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 13256747b715Smrg x + SCREEN_TO_GLOBAL_X, 13266747b715Smrg y + SCREEN_TO_GLOBAL_Y, 13276747b715Smrg w, h, RL_GRAVITY_NONE); 13286747b715Smrg } 13294642e01fSmrg 13304642e01fSmrg miSendExposures(pWin, &pWin->borderClip, 13314642e01fSmrg pWin->drawable.x, pWin->drawable.y); 133205b261ecSmrg } 133305b261ecSmrg 133405b261ecSmrg RL_DEBUG_MSG("resizewindow end\n"); 133505b261ecSmrg} 133605b261ecSmrg 133705b261ecSmrg 133805b261ecSmrg/* 133905b261ecSmrg * RootlessRepositionWindow 134005b261ecSmrg * Called by the implementation when a window needs to be repositioned to 134105b261ecSmrg * its correct location on the screen. This routine is typically needed 134205b261ecSmrg * due to changes in the underlying window system, such as a screen layout 134305b261ecSmrg * change. 134405b261ecSmrg */ 134505b261ecSmrgvoid 134605b261ecSmrgRootlessRepositionWindow(WindowPtr pWin) 134705b261ecSmrg{ 134805b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 134905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 135005b261ecSmrg 135105b261ecSmrg if (winRec == NULL) 135205b261ecSmrg return; 135305b261ecSmrg 135405b261ecSmrg RootlessStopDrawing(pWin, FALSE); 135505b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 135605b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 135705b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y); 135805b261ecSmrg 135905b261ecSmrg RootlessReorderWindow(pWin); 136005b261ecSmrg} 136105b261ecSmrg 136205b261ecSmrg 136305b261ecSmrg/* 136405b261ecSmrg * RootlessReparentWindow 136505b261ecSmrg * Called after a window has been reparented. Generally windows are not 136605b261ecSmrg * framed until they are mapped. However, a window may be framed early by the 136705b261ecSmrg * implementation calling RootlessFrameForWindow. (e.g. this could be needed 136805b261ecSmrg * to attach a VRAM surface to it.) If the window is subsequently reparented 136905b261ecSmrg * by the window manager before being mapped, we need to give the frame to 137005b261ecSmrg * the new top-level window. 137105b261ecSmrg */ 137205b261ecSmrgvoid 137305b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 137405b261ecSmrg{ 137505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 137605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 137705b261ecSmrg WindowPtr pTopWin; 137805b261ecSmrg 137905b261ecSmrg /* Check that window is not top-level now, but used to be. */ 138005b261ecSmrg if (IsRoot(pWin) || IsRoot(pWin->parent) 138105b261ecSmrg || IsTopLevel(pWin) || winRec == NULL) 138205b261ecSmrg { 138305b261ecSmrg goto out; 138405b261ecSmrg } 138505b261ecSmrg 138605b261ecSmrg /* If the formerly top-level window has a frame, we want to give the 138705b261ecSmrg frame to its new top-level parent. If we can't do that, we'll just 138805b261ecSmrg have to jettison it... */ 138905b261ecSmrg 139005b261ecSmrg pTopWin = TopLevelParent(pWin); 139105b261ecSmrg assert(pTopWin != pWin); 13924642e01fSmrg 13934642e01fSmrg pWin->rootlessUnhittable = FALSE; 13944642e01fSmrg 13954642e01fSmrg DeleteProperty (serverClient, pWin, xa_native_window_id ()); 139605b261ecSmrg 139705b261ecSmrg if (WINREC(pTopWin) != NULL) { 139805b261ecSmrg /* We're screwed. */ 139905b261ecSmrg RootlessDestroyFrame(pWin, winRec); 140005b261ecSmrg } else { 140105b261ecSmrg if (!pTopWin->realized && pWin->realized) { 140205b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 140305b261ecSmrg } 140405b261ecSmrg 140505b261ecSmrg /* Switch the frame record from one to the other. */ 140605b261ecSmrg 14074642e01fSmrg SETWINREC(pWin, NULL); 14084642e01fSmrg SETWINREC(pTopWin, winRec); 140905b261ecSmrg 141005b261ecSmrg RootlessInitializeFrame(pTopWin, winRec); 141105b261ecSmrg RootlessReshapeFrame(pTopWin); 141205b261ecSmrg 141305b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 141405b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 141505b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 141605b261ecSmrg winRec->width, winRec->height, 141705b261ecSmrg RL_GRAVITY_NONE); 141805b261ecSmrg 141905b261ecSmrg if (SCREENREC(pScreen)->imp->SwitchWindow) { 142005b261ecSmrg SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); 142105b261ecSmrg } 142205b261ecSmrg 142305b261ecSmrg if (pTopWin->realized && !pWin->realized) 142405b261ecSmrg winRec->is_reorder_pending = TRUE; 142505b261ecSmrg } 142605b261ecSmrg 142705b261ecSmrgout: 142805b261ecSmrg if (SCREENREC(pScreen)->ReparentWindow) { 142905b261ecSmrg SCREEN_UNWRAP(pScreen, ReparentWindow); 143005b261ecSmrg pScreen->ReparentWindow(pWin, pPriorParent); 143105b261ecSmrg SCREEN_WRAP(pScreen, ReparentWindow); 143205b261ecSmrg } 143305b261ecSmrg} 143405b261ecSmrg 143505b261ecSmrg 143605b261ecSmrgvoid 14374642e01fSmrgRootlessFlushWindowColormap (WindowPtr pWin) 143805b261ecSmrg{ 14394642e01fSmrg RootlessWindowRec *winRec = WINREC (pWin); 14406747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 144105b261ecSmrg 14424642e01fSmrg if (winRec == NULL) 14434642e01fSmrg return; 144405b261ecSmrg 14454642e01fSmrg RootlessStopDrawing (pWin, FALSE); 144605b261ecSmrg 14476747b715Smrg if (SCREENREC(pScreen)->imp->UpdateColormap) 14486747b715Smrg SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); 144905b261ecSmrg} 145005b261ecSmrg 145105b261ecSmrg/* 145205b261ecSmrg * RootlessChangeBorderWidth 145305b261ecSmrg * FIXME: untested! 145405b261ecSmrg * pWin inside corner stays the same; pWin->drawable.[xy] stays the same 145505b261ecSmrg * Frame moves and resizes. 145605b261ecSmrg */ 145705b261ecSmrgvoid 145805b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) 145905b261ecSmrg{ 146005b261ecSmrg RegionRec saveRoot; 146105b261ecSmrg Bool resize_after = FALSE; 146205b261ecSmrg 146305b261ecSmrg RL_DEBUG_MSG("change border width "); 146405b261ecSmrg 146505b261ecSmrg if (width != wBorderWidth(pWin)) { 146605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 146705b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 146805b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 146905b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 147005b261ecSmrg 147105b261ecSmrg if (winRec) { 147205b261ecSmrg oldBW = winRec->borderWidth; 147305b261ecSmrg oldX = winRec->x; 147405b261ecSmrg oldY = winRec->y; 147505b261ecSmrg oldW = winRec->width; 147605b261ecSmrg oldH = winRec->height; 147705b261ecSmrg 147805b261ecSmrg newBW = width; 147905b261ecSmrg newX = pWin->drawable.x - newBW; 148005b261ecSmrg newY = pWin->drawable.y - newBW; 148105b261ecSmrg newW = pWin->drawable.width + 2*newBW; 148205b261ecSmrg newH = pWin->drawable.height + 2*newBW; 148305b261ecSmrg 148405b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 148505b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 148605b261ecSmrg newX, newY, newW, newH, newBW); 148705b261ecSmrg } 148805b261ecSmrg 148905b261ecSmrg HUGE_ROOT(pWin); 149005b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); 149105b261ecSmrg pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); 149205b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); 149305b261ecSmrg NORMAL_ROOT(pWin); 149405b261ecSmrg 149505b261ecSmrg if (winRec) { 149605b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 149705b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 149805b261ecSmrg } 149905b261ecSmrg } 150005b261ecSmrg 150105b261ecSmrg RL_DEBUG_MSG("change border width end\n"); 150205b261ecSmrg} 15034642e01fSmrg 15044642e01fSmrg/* 15054642e01fSmrg * RootlessOrderAllWindows 15064642e01fSmrg * Brings all X11 windows to the top of the window stack 15074642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus 15084642e01fSmrg */ 15094642e01fSmrgvoid 15106747b715SmrgRootlessOrderAllWindows (Bool include_unhitable) 15114642e01fSmrg{ 15124642e01fSmrg int i; 15134642e01fSmrg WindowPtr pWin; 15144642e01fSmrg 15154642e01fSmrg if (windows_hidden) 15164642e01fSmrg return; 15174642e01fSmrg 15184642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() "); 15194642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 15204642e01fSmrg if (screenInfo.screens[i] == NULL) continue; 15216747b715Smrg pWin = screenInfo.screens[i]->root; 15224642e01fSmrg if (pWin == NULL) continue; 15234642e01fSmrg 15244642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 15254642e01fSmrg if (!pWin->realized) continue; 15264642e01fSmrg if (RootlessEnsureFrame(pWin) == NULL) continue; 15276747b715Smrg if (!include_unhitable && pWin->rootlessUnhittable) continue; 15284642e01fSmrg RootlessReorderWindow (pWin); 15294642e01fSmrg } 15304642e01fSmrg } 15314642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() done"); 15324642e01fSmrg} 15334642e01fSmrg 15344642e01fSmrgvoid 15354642e01fSmrgRootlessEnableRoot (ScreenPtr pScreen) 15364642e01fSmrg{ 15374642e01fSmrg WindowPtr pRoot; 15386747b715Smrg pRoot = pScreen->root; 15394642e01fSmrg 15404642e01fSmrg RootlessEnsureFrame (pRoot); 15414642e01fSmrg (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); 15424642e01fSmrg RootlessReorderWindow (pRoot); 15434642e01fSmrg} 15444642e01fSmrg 15454642e01fSmrgvoid 15464642e01fSmrgRootlessDisableRoot (ScreenPtr pScreen) 15474642e01fSmrg{ 15484642e01fSmrg WindowPtr pRoot; 15494642e01fSmrg RootlessWindowRec *winRec; 15504642e01fSmrg 15516747b715Smrg pRoot = pScreen->root; 15524642e01fSmrg winRec = WINREC (pRoot); 15534642e01fSmrg 15544642e01fSmrg if (NULL == winRec) 15554642e01fSmrg return; 15564642e01fSmrg 15574642e01fSmrg RootlessDestroyFrame (pRoot, winRec); 15584642e01fSmrg DeleteProperty (serverClient, pRoot, xa_native_window_id ()); 15594642e01fSmrg} 15604642e01fSmrg 15614642e01fSmrgvoid 15624642e01fSmrgRootlessHideAllWindows (void) 15634642e01fSmrg{ 15644642e01fSmrg int i; 15654642e01fSmrg ScreenPtr pScreen; 15664642e01fSmrg WindowPtr pWin; 15674642e01fSmrg RootlessWindowRec *winRec; 15684642e01fSmrg 15694642e01fSmrg if (windows_hidden) 15704642e01fSmrg return; 15714642e01fSmrg 15724642e01fSmrg windows_hidden = TRUE; 15734642e01fSmrg 15744642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 15754642e01fSmrg { 15764642e01fSmrg pScreen = screenInfo.screens[i]; 15776747b715Smrg if (pScreen == NULL) 15786747b715Smrg continue; 15796747b715Smrg pWin = pScreen->root; 15806747b715Smrg if (pWin == NULL) 15814642e01fSmrg continue; 15824642e01fSmrg 15834642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 15844642e01fSmrg { 15854642e01fSmrg if (!pWin->realized) 15864642e01fSmrg continue; 15874642e01fSmrg 15884642e01fSmrg RootlessStopDrawing (pWin, FALSE); 15894642e01fSmrg 15904642e01fSmrg winRec = WINREC (pWin); 15914642e01fSmrg if (winRec != NULL) 15924642e01fSmrg { 15936747b715Smrg if (SCREENREC(pScreen)->imp->HideWindow) 15946747b715Smrg SCREENREC(pScreen)->imp->HideWindow(winRec->wid); 15954642e01fSmrg } 15964642e01fSmrg } 15974642e01fSmrg } 15984642e01fSmrg} 15994642e01fSmrg 16004642e01fSmrgvoid 16014642e01fSmrgRootlessShowAllWindows (void) 16024642e01fSmrg{ 16034642e01fSmrg int i; 16044642e01fSmrg ScreenPtr pScreen; 16054642e01fSmrg WindowPtr pWin; 16064642e01fSmrg RootlessWindowRec *winRec; 16074642e01fSmrg 16084642e01fSmrg if (!windows_hidden) 16094642e01fSmrg return; 16104642e01fSmrg 16114642e01fSmrg windows_hidden = FALSE; 16124642e01fSmrg 16134642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 16144642e01fSmrg { 16154642e01fSmrg pScreen = screenInfo.screens[i]; 16166747b715Smrg if (pScreen == NULL) 16176747b715Smrg continue; 16186747b715Smrg pWin = pScreen->root; 16196747b715Smrg if (pWin == NULL) 16204642e01fSmrg continue; 16214642e01fSmrg 16224642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 16234642e01fSmrg { 16244642e01fSmrg if (!pWin->realized) 16254642e01fSmrg continue; 16264642e01fSmrg 16274642e01fSmrg winRec = RootlessEnsureFrame (pWin); 16284642e01fSmrg if (winRec == NULL) 16294642e01fSmrg continue; 16304642e01fSmrg 16314642e01fSmrg RootlessReorderWindow (pWin); 16324642e01fSmrg } 16334642e01fSmrg 16344642e01fSmrg RootlessScreenExpose (pScreen); 16354642e01fSmrg } 16364642e01fSmrg} 16376747b715Smrg 16386747b715Smrg/* 16396747b715Smrg * SetPixmapOfAncestors 16406747b715Smrg * Set the Pixmaps on all ParentRelative windows up the ancestor chain. 16416747b715Smrg */ 16426747b715Smrgvoid 16436747b715SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin) 16446747b715Smrg{ 16456747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 16466747b715Smrg WindowPtr topWin = TopLevelParent(pWin); 16476747b715Smrg RootlessWindowRec *topWinRec = WINREC(topWin); 16486747b715Smrg 16496747b715Smrg while (pWin->backgroundState == ParentRelative) { 16506747b715Smrg if (pWin == topWin) { 16516747b715Smrg // disallow ParentRelative background state on top level 16526747b715Smrg XID pixel = 0; 16536747b715Smrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 16546747b715Smrg RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); 16556747b715Smrg break; 16566747b715Smrg } 16576747b715Smrg 16586747b715Smrg pWin = pWin->parent; 16596747b715Smrg pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); 16606747b715Smrg } 16616747b715Smrg} 16626747b715Smrg 1663