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 3635c4bbdfSmrg#include <stddef.h> /* For NULL */ 3735c4bbdfSmrg#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 7035c4bbdfSmrgDEFINE_ATOM_HELPER(xa_native_window_id, "_NATIVE_WINDOW_ID") 714642e01fSmrg 724642e01fSmrgstatic Bool windows_hidden; 7335c4bbdfSmrg 744642e01fSmrg// TODO - abstract xp functions 754642e01fSmrg 766747b715Smrg#ifdef __APPLE__ 774642e01fSmrg 786747b715Smrg// XXX: identical to x_cvt_vptr_to_uint ? 796747b715Smrg#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) 804642e01fSmrg 814642e01fSmrgvoid 8235c4bbdfSmrgRootlessNativeWindowStateChanged(WindowPtr pWin, unsigned int state) 834642e01fSmrg{ 8435c4bbdfSmrg RootlessWindowRec *winRec; 854642e01fSmrg 8635c4bbdfSmrg if (pWin == NULL) 8735c4bbdfSmrg return; 884642e01fSmrg 8935c4bbdfSmrg winRec = WINREC(pWin); 9035c4bbdfSmrg if (winRec == NULL) 9135c4bbdfSmrg return; 924642e01fSmrg 9335c4bbdfSmrg winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); 9435c4bbdfSmrg winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); 9535c4bbdfSmrg pWin->unhittable = winRec->is_offscreen; 964642e01fSmrg} 974642e01fSmrg 9835c4bbdfSmrgvoid 9935c4bbdfSmrgRootlessNativeWindowMoved(WindowPtr pWin) 10035c4bbdfSmrg{ 1014642e01fSmrg xp_box bounds; 1024642e01fSmrg int sx, sy, err; 1034642e01fSmrg XID vlist[2]; 1044642e01fSmrg Mask mask; 1054642e01fSmrg ClientPtr pClient; 1064642e01fSmrg RootlessWindowRec *winRec; 10735c4bbdfSmrg 1084642e01fSmrg winRec = WINREC(pWin); 10935c4bbdfSmrg 11035c4bbdfSmrg if (xp_get_window_bounds(MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) 11135c4bbdfSmrg return; 11235c4bbdfSmrg 1136747b715Smrg sx = pWin->drawable.pScreen->x + darwinMainScreenX; 1146747b715Smrg sy = pWin->drawable.pScreen->y + darwinMainScreenY; 11535c4bbdfSmrg 1164642e01fSmrg /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ 1174642e01fSmrg vlist[0] = (INT16) bounds.x1 - sx; 1184642e01fSmrg vlist[1] = (INT16) bounds.y1 - sy; 1194642e01fSmrg mask = CWX | CWY; 12035c4bbdfSmrg 1214642e01fSmrg /* pretend we're the owner of the window! */ 12235c4bbdfSmrg err = 12335c4bbdfSmrg dixLookupClient(&pClient, pWin->drawable.id, serverClient, 12435c4bbdfSmrg DixUnknownAccess); 12535c4bbdfSmrg if (err != Success) { 12635c4bbdfSmrg ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", 12735c4bbdfSmrg (unsigned int) pWin->drawable.id); 1284642e01fSmrg return; 1294642e01fSmrg } 13035c4bbdfSmrg 13135c4bbdfSmrg /* Don't want to do anything to the physical window (avoids 13235c4bbdfSmrg notification-response feedback loops) */ 13335c4bbdfSmrg 1344642e01fSmrg no_configure_window = TRUE; 13535c4bbdfSmrg ConfigureWindow(pWin, mask, vlist, pClient); 1364642e01fSmrg no_configure_window = FALSE; 1374642e01fSmrg} 1384642e01fSmrg 13935c4bbdfSmrg#endif /* __APPLE__ */ 14005b261ecSmrg 14105b261ecSmrg/* 14205b261ecSmrg * RootlessCreateWindow 14305b261ecSmrg * For now, don't create a physical window until either the window is 14405b261ecSmrg * realized, or we really need it (e.g. to attach VRAM surfaces to). 14505b261ecSmrg * Do reset the window size so it's not clipped by the root window. 14605b261ecSmrg */ 14705b261ecSmrgBool 14805b261ecSmrgRootlessCreateWindow(WindowPtr pWin) 14905b261ecSmrg{ 15005b261ecSmrg Bool result; 15105b261ecSmrg RegionRec saveRoot; 15205b261ecSmrg 1534642e01fSmrg SETWINREC(pWin, NULL); 1544642e01fSmrg dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); 15505b261ecSmrg 15605b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); 15705b261ecSmrg 15805b261ecSmrg if (!IsRoot(pWin)) { 15905b261ecSmrg /* win/border size set by DIX, not by wrapped CreateWindow, so 16005b261ecSmrg correct it here. Don't HUGE_ROOT when pWin is the root! */ 16105b261ecSmrg 16205b261ecSmrg HUGE_ROOT(pWin); 16305b261ecSmrg SetWinSize(pWin); 16405b261ecSmrg SetBorderSize(pWin); 16505b261ecSmrg } 16605b261ecSmrg 16705b261ecSmrg result = pWin->drawable.pScreen->CreateWindow(pWin); 16805b261ecSmrg 16905b261ecSmrg if (pWin->parent) { 17005b261ecSmrg NORMAL_ROOT(pWin); 17105b261ecSmrg } 17205b261ecSmrg 17305b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); 17405b261ecSmrg 17505b261ecSmrg return result; 17605b261ecSmrg} 17705b261ecSmrg 17805b261ecSmrg/* 17905b261ecSmrg * RootlessDestroyFrame 18005b261ecSmrg * Destroy the physical window associated with the given window. 18105b261ecSmrg */ 18205b261ecSmrgstatic void 18305b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) 18405b261ecSmrg{ 1856747b715Smrg SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid); 1866747b715Smrg free(winRec); 1874642e01fSmrg SETWINREC(pWin, NULL); 18805b261ecSmrg} 18905b261ecSmrg 19005b261ecSmrg/* 19105b261ecSmrg * RootlessDestroyWindow 19205b261ecSmrg * Destroy the physical window associated with the given window. 19305b261ecSmrg */ 19405b261ecSmrgBool 19505b261ecSmrgRootlessDestroyWindow(WindowPtr pWin) 19605b261ecSmrg{ 19705b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 19805b261ecSmrg Bool result; 19905b261ecSmrg 20005b261ecSmrg if (winRec != NULL) { 20105b261ecSmrg RootlessDestroyFrame(pWin, winRec); 20205b261ecSmrg } 20305b261ecSmrg 20405b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); 20505b261ecSmrg result = pWin->drawable.pScreen->DestroyWindow(pWin); 20605b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); 20705b261ecSmrg 20805b261ecSmrg return result; 20905b261ecSmrg} 21005b261ecSmrg 21105b261ecSmrgstatic Bool 21205b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape) 21305b261ecSmrg{ 21405b261ecSmrg if (wBoundingShape(pWin) == NULL) 21505b261ecSmrg return FALSE; 21605b261ecSmrg 21705b261ecSmrg /* wBoundingShape is relative to *inner* origin of window. 21805b261ecSmrg Translate by borderWidth to get the outside-relative position. */ 21905b261ecSmrg 2206747b715Smrg RegionNull(pShape); 2216747b715Smrg RegionCopy(pShape, wBoundingShape(pWin)); 2226747b715Smrg RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth); 22305b261ecSmrg 22405b261ecSmrg return TRUE; 22505b261ecSmrg} 22605b261ecSmrg 22705b261ecSmrg/* 22805b261ecSmrg * RootlessReshapeFrame 22905b261ecSmrg * Set the frame shape. 23005b261ecSmrg */ 23135c4bbdfSmrgstatic void 23235c4bbdfSmrgRootlessReshapeFrame(WindowPtr pWin) 23305b261ecSmrg{ 23405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 23505b261ecSmrg RegionRec newShape; 23605b261ecSmrg RegionPtr pShape; 23705b261ecSmrg 23805b261ecSmrg // If the window is not yet framed, do nothing 23905b261ecSmrg if (winRec == NULL) 24005b261ecSmrg return; 24105b261ecSmrg 24205b261ecSmrg if (IsRoot(pWin)) 24305b261ecSmrg return; 24405b261ecSmrg 24505b261ecSmrg RootlessStopDrawing(pWin, FALSE); 24605b261ecSmrg 24705b261ecSmrg pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; 24805b261ecSmrg 24905b261ecSmrg#ifdef ROOTLESSDEBUG 25005b261ecSmrg RL_DEBUG_MSG("reshaping..."); 25105b261ecSmrg if (pShape != NULL) { 25205b261ecSmrg RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", 2536747b715Smrg RegionNumRects(&newShape), 25405b261ecSmrg newShape.extents.x1, newShape.extents.y1, 25505b261ecSmrg newShape.extents.x2, newShape.extents.y2); 25635c4bbdfSmrg } 25735c4bbdfSmrg else { 25805b261ecSmrg RL_DEBUG_MSG("no shape "); 25905b261ecSmrg } 26005b261ecSmrg#endif 26105b261ecSmrg 2626747b715Smrg SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape); 26305b261ecSmrg 26405b261ecSmrg if (pShape != NULL) 2656747b715Smrg RegionUninit(&newShape); 26605b261ecSmrg} 26705b261ecSmrg 26805b261ecSmrg/* 26905b261ecSmrg * RootlessSetShape 27005b261ecSmrg * Shape is usually set before a window is mapped and the window will 27105b261ecSmrg * not have a frame associated with it. In this case, the frame will be 27205b261ecSmrg * shaped when the window is framed. 27305b261ecSmrg */ 27405b261ecSmrgvoid 2756747b715SmrgRootlessSetShape(WindowPtr pWin, int kind) 27605b261ecSmrg{ 27705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 27805b261ecSmrg 27905b261ecSmrg SCREEN_UNWRAP(pScreen, SetShape); 2806747b715Smrg pScreen->SetShape(pWin, kind); 28105b261ecSmrg SCREEN_WRAP(pScreen, SetShape); 28205b261ecSmrg 28305b261ecSmrg RootlessReshapeFrame(pWin); 28405b261ecSmrg} 28505b261ecSmrg 28605b261ecSmrg/* Disallow ParentRelative background on top-level windows 2874642e01fSmrg because the root window doesn't really have the right background. 2884642e01fSmrg */ 28905b261ecSmrgBool 29005b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) 29105b261ecSmrg{ 29205b261ecSmrg Bool result; 29305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 29405b261ecSmrg 29505b261ecSmrg RL_DEBUG_MSG("change window attributes start "); 29605b261ecSmrg 29705b261ecSmrg SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); 29805b261ecSmrg result = pScreen->ChangeWindowAttributes(pWin, vmask); 29905b261ecSmrg SCREEN_WRAP(pScreen, ChangeWindowAttributes); 30005b261ecSmrg 30105b261ecSmrg if (WINREC(pWin)) { 30205b261ecSmrg // disallow ParentRelative background state 30305b261ecSmrg if (pWin->backgroundState == ParentRelative) { 30405b261ecSmrg XID pixel = 0; 30535c4bbdfSmrg 30605b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 30705b261ecSmrg } 30805b261ecSmrg } 30905b261ecSmrg 31005b261ecSmrg RL_DEBUG_MSG("change window attributes end\n"); 31105b261ecSmrg return result; 31205b261ecSmrg} 31305b261ecSmrg 31405b261ecSmrg/* 31505b261ecSmrg * RootlessPositionWindow 31605b261ecSmrg * This is a hook for when DIX moves or resizes a window. 31705b261ecSmrg * Update the frame position now although the physical window is moved 31805b261ecSmrg * in RootlessMoveWindow. (x, y) are *inside* position. After this, 31905b261ecSmrg * mi and fb are expecting the pixmap to be at the new location. 32005b261ecSmrg */ 32105b261ecSmrgBool 32205b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y) 32305b261ecSmrg{ 32405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 32505b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 32605b261ecSmrg Bool result; 32705b261ecSmrg 32805b261ecSmrg RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); 32905b261ecSmrg 33005b261ecSmrg if (winRec) { 33105b261ecSmrg if (winRec->is_drawing) { 33205b261ecSmrg // Reset frame's pixmap and move it to the new position. 33305b261ecSmrg int bw = wBorderWidth(pWin); 33405b261ecSmrg 33505b261ecSmrg winRec->pixmap->devPrivate.ptr = winRec->pixelData; 33605b261ecSmrg SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); 33705b261ecSmrg } 33805b261ecSmrg } 33905b261ecSmrg 34005b261ecSmrg SCREEN_UNWRAP(pScreen, PositionWindow); 34105b261ecSmrg result = pScreen->PositionWindow(pWin, x, y); 34205b261ecSmrg SCREEN_WRAP(pScreen, PositionWindow); 34305b261ecSmrg 34405b261ecSmrg RL_DEBUG_MSG("positionwindow end\n"); 34505b261ecSmrg return result; 34605b261ecSmrg} 34705b261ecSmrg 34805b261ecSmrg/* 34905b261ecSmrg * RootlessInitializeFrame 35005b261ecSmrg * Initialize some basic attributes of the frame. Note that winRec 35105b261ecSmrg * may already have valid data in it, so don't overwrite anything 35205b261ecSmrg * valuable. 35305b261ecSmrg */ 35405b261ecSmrgstatic void 35535c4bbdfSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec * winRec) 35605b261ecSmrg{ 35705b261ecSmrg DrawablePtr d = &pWin->drawable; 35805b261ecSmrg int bw = wBorderWidth(pWin); 35905b261ecSmrg 36005b261ecSmrg winRec->win = pWin; 36105b261ecSmrg 36205b261ecSmrg winRec->x = d->x - bw; 36305b261ecSmrg winRec->y = d->y - bw; 36435c4bbdfSmrg winRec->width = d->width + 2 * bw; 36535c4bbdfSmrg winRec->height = d->height + 2 * bw; 36605b261ecSmrg winRec->borderWidth = bw; 36705b261ecSmrg} 36805b261ecSmrg 36905b261ecSmrg/* 37005b261ecSmrg * RootlessEnsureFrame 37105b261ecSmrg * Make sure the given window is framed. If the window doesn't have a 37205b261ecSmrg * physical window associated with it, attempt to create one. If that 37305b261ecSmrg * is unsuccessful, return NULL. 37405b261ecSmrg */ 37505b261ecSmrgstatic RootlessWindowRec * 37605b261ecSmrgRootlessEnsureFrame(WindowPtr pWin) 37705b261ecSmrg{ 37805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 37905b261ecSmrg RootlessWindowRec *winRec; 38005b261ecSmrg RegionRec shape; 38105b261ecSmrg RegionPtr pShape = NULL; 38205b261ecSmrg 38305b261ecSmrg if (WINREC(pWin) != NULL) 38405b261ecSmrg return WINREC(pWin); 38505b261ecSmrg 3864642e01fSmrg if (!IsTopLevel(pWin) && !IsRoot(pWin)) 38705b261ecSmrg return NULL; 38805b261ecSmrg 38905b261ecSmrg if (pWin->drawable.class != InputOutput) 39005b261ecSmrg return NULL; 39105b261ecSmrg 3926747b715Smrg winRec = malloc(sizeof(RootlessWindowRec)); 39305b261ecSmrg 39405b261ecSmrg if (!winRec) 39505b261ecSmrg return NULL; 39605b261ecSmrg 39705b261ecSmrg RootlessInitializeFrame(pWin, winRec); 39805b261ecSmrg 39905b261ecSmrg winRec->is_drawing = FALSE; 40005b261ecSmrg winRec->is_reorder_pending = FALSE; 40105b261ecSmrg winRec->pixmap = NULL; 40205b261ecSmrg winRec->wid = NULL; 4036747b715Smrg winRec->level = 0; 40405b261ecSmrg 4054642e01fSmrg SETWINREC(pWin, winRec); 40605b261ecSmrg 40705b261ecSmrg // Set the frame's shape if the window is shaped 40805b261ecSmrg if (RootlessGetShape(pWin, &shape)) 40905b261ecSmrg pShape = &shape; 41005b261ecSmrg 41105b261ecSmrg RL_DEBUG_MSG("creating frame "); 41205b261ecSmrg 41305b261ecSmrg if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, 41405b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 41505b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 41635c4bbdfSmrg pShape)) { 41705b261ecSmrg RL_DEBUG_MSG("implementation failed to create frame!\n"); 4186747b715Smrg free(winRec); 4194642e01fSmrg SETWINREC(pWin, NULL); 42005b261ecSmrg return NULL; 42105b261ecSmrg } 42205b261ecSmrg 4234642e01fSmrg if (pWin->drawable.depth == 8) 42435c4bbdfSmrg RootlessFlushWindowColormap(pWin); 4254642e01fSmrg 42605b261ecSmrg if (pShape != NULL) 4276747b715Smrg RegionUninit(&shape); 42805b261ecSmrg 42905b261ecSmrg return winRec; 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; 46135c4bbdfSmrg 46205b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 46305b261ecSmrg } 46405b261ecSmrg } 46505b261ecSmrg 46635c4bbdfSmrg if (!IsRoot(pWin)) 46735c4bbdfSmrg HUGE_ROOT(pWin); 46805b261ecSmrg SCREEN_UNWRAP(pScreen, RealizeWindow); 46905b261ecSmrg result = pScreen->RealizeWindow(pWin); 47005b261ecSmrg SCREEN_WRAP(pScreen, RealizeWindow); 47135c4bbdfSmrg if (!IsRoot(pWin)) 47235c4bbdfSmrg NORMAL_ROOT(pWin); 47305b261ecSmrg 47405b261ecSmrg RL_DEBUG_MSG("realizewindow end\n"); 47505b261ecSmrg return result; 47605b261ecSmrg} 47705b261ecSmrg 47805b261ecSmrg/* 47905b261ecSmrg * RootlessFrameForWindow 48035c4bbdfSmrg * Returns the frame ID for the physical window displaying the given window. 48105b261ecSmrg * If CREATE is true and the window has no frame, attempt to create one. 48205b261ecSmrg */ 48305b261ecSmrgRootlessFrameID 48405b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create) 48505b261ecSmrg{ 48605b261ecSmrg WindowPtr pTopWin; 48705b261ecSmrg RootlessWindowRec *winRec; 48805b261ecSmrg 48905b261ecSmrg pTopWin = TopLevelParent(pWin); 49005b261ecSmrg if (pTopWin == NULL) 49105b261ecSmrg return NULL; 49205b261ecSmrg 49305b261ecSmrg winRec = WINREC(pTopWin); 49405b261ecSmrg 49505b261ecSmrg if (winRec == NULL && create && pWin->drawable.class == InputOutput) { 49605b261ecSmrg winRec = RootlessEnsureFrame(pTopWin); 49705b261ecSmrg } 49805b261ecSmrg 49905b261ecSmrg if (winRec == NULL) 50005b261ecSmrg return NULL; 50105b261ecSmrg 50205b261ecSmrg return winRec->wid; 50305b261ecSmrg} 50405b261ecSmrg 50505b261ecSmrg/* 50605b261ecSmrg * RootlessUnrealizeWindow 50705b261ecSmrg * Unmap the physical window. 50805b261ecSmrg */ 50905b261ecSmrgBool 51005b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin) 51105b261ecSmrg{ 51205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 51305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 51405b261ecSmrg Bool result; 51505b261ecSmrg 51605b261ecSmrg RL_DEBUG_MSG("unrealizewindow start "); 51705b261ecSmrg 51805b261ecSmrg if (winRec) { 51905b261ecSmrg RootlessStopDrawing(pWin, FALSE); 52005b261ecSmrg 52105b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 52205b261ecSmrg 52305b261ecSmrg winRec->is_reorder_pending = FALSE; 52405b261ecSmrg } 52505b261ecSmrg 52605b261ecSmrg SCREEN_UNWRAP(pScreen, UnrealizeWindow); 52705b261ecSmrg result = pScreen->UnrealizeWindow(pWin); 52805b261ecSmrg SCREEN_WRAP(pScreen, UnrealizeWindow); 52905b261ecSmrg 53005b261ecSmrg RL_DEBUG_MSG("unrealizewindow end\n"); 53105b261ecSmrg return result; 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 54435c4bbdfSmrg if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && 54535c4bbdfSmrg !windows_hidden) { 54605b261ecSmrg WindowPtr newPrevW; 54705b261ecSmrg RootlessWindowRec *newPrev; 54805b261ecSmrg RootlessFrameID newPrevID; 54905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 55005b261ecSmrg 55105b261ecSmrg /* Check if the implementation wants the frame to not be reordered 55205b261ecSmrg even though the X11 window is restacked. This can be useful if 55305b261ecSmrg frames are ordered-in with animation so that the reordering is not 55405b261ecSmrg done until the animation is complete. */ 55505b261ecSmrg if (SCREENREC(pScreen)->imp->DoReorderWindow) { 55605b261ecSmrg if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) 55705b261ecSmrg return; 55805b261ecSmrg } 55905b261ecSmrg 56005b261ecSmrg RootlessStopDrawing(pWin, FALSE); 56105b261ecSmrg 56235c4bbdfSmrg /* Find the next window above this one that has a mapped frame. 5636747b715Smrg * Only include cases where the windows are in the same category of 564ed6184dfSmrg * hittability to ensure offscreen windows don't get restacked 5656747b715Smrg * relative to onscreen ones (but that the offscreen ones maintain 566ed6184dfSmrg * their stacking order if they are explicitly asked to Reorder). 5676747b715Smrg */ 56805b261ecSmrg 56905b261ecSmrg newPrevW = pWin->prevSib; 57035c4bbdfSmrg while (newPrevW && 57135c4bbdfSmrg (WINREC(newPrevW) == NULL || !newPrevW->realized || 57235c4bbdfSmrg newPrevW->unhittable != pWin->unhittable)) 57305b261ecSmrg newPrevW = newPrevW->prevSib; 57405b261ecSmrg 57505b261ecSmrg newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; 57605b261ecSmrg newPrevID = newPrev != NULL ? newPrev->wid : 0; 57705b261ecSmrg 57805b261ecSmrg /* If it exists, reorder the frame above us first. */ 57905b261ecSmrg 58005b261ecSmrg if (newPrev && newPrev->is_reorder_pending) { 58105b261ecSmrg newPrev->is_reorder_pending = FALSE; 58205b261ecSmrg RootlessReorderWindow(newPrevW); 58305b261ecSmrg } 58405b261ecSmrg 58505b261ecSmrg SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); 58605b261ecSmrg } 58705b261ecSmrg} 58805b261ecSmrg 58905b261ecSmrg/* 59005b261ecSmrg * RootlessRestackWindow 59105b261ecSmrg * This is a hook for when DIX changes the window stacking order. 59205b261ecSmrg * The window has already been inserted into its new position in the 59305b261ecSmrg * DIX window stack. We need to change the order of the physical 59405b261ecSmrg * window to match. 59505b261ecSmrg */ 59605b261ecSmrgvoid 59705b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) 59805b261ecSmrg{ 59905b261ecSmrg RegionRec saveRoot; 60005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 60105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 60205b261ecSmrg 60305b261ecSmrg RL_DEBUG_MSG("restackwindow start "); 60405b261ecSmrg if (winRec) 60505b261ecSmrg RL_DEBUG_MSG("restack top level \n"); 60605b261ecSmrg 60705b261ecSmrg HUGE_ROOT(pWin); 60805b261ecSmrg SCREEN_UNWRAP(pScreen, RestackWindow); 60905b261ecSmrg 61005b261ecSmrg if (pScreen->RestackWindow) 61105b261ecSmrg pScreen->RestackWindow(pWin, pOldNextSib); 61205b261ecSmrg 61305b261ecSmrg SCREEN_WRAP(pScreen, RestackWindow); 61405b261ecSmrg NORMAL_ROOT(pWin); 61505b261ecSmrg 61605b261ecSmrg if (winRec && pWin->viewable) { 61705b261ecSmrg RootlessReorderWindow(pWin); 61805b261ecSmrg } 61905b261ecSmrg 62005b261ecSmrg RL_DEBUG_MSG("restackwindow end\n"); 62105b261ecSmrg} 62205b261ecSmrg 62305b261ecSmrg/* 62405b261ecSmrg * Specialized window copy procedures 62505b261ecSmrg */ 62605b261ecSmrg 62705b261ecSmrg// Globals needed during window resize and move. 62835c4bbdfSmrgstatic void *gResizeDeathBits = NULL; 62905b261ecSmrgstatic int gResizeDeathCount = 0; 63035c4bbdfSmrgstatic PixmapPtr gResizeDeathPix[2] = { NULL, NULL }; 63135c4bbdfSmrg 63205b261ecSmrgstatic BoxRec gResizeDeathBounds[2]; 63305b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; 63405b261ecSmrg 63505b261ecSmrg/* 63605b261ecSmrg * RootlessNoCopyWindow 63705b261ecSmrg * CopyWindow() that doesn't do anything. For MoveWindow() of 63805b261ecSmrg * top-level windows. 63905b261ecSmrg */ 64005b261ecSmrgstatic void 64135c4bbdfSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 64205b261ecSmrg{ 64305b261ecSmrg // some code expects the region to be translated 64405b261ecSmrg int dx = ptOldOrg.x - pWin->drawable.x; 64505b261ecSmrg int dy = ptOldOrg.y - pWin->drawable.y; 64605b261ecSmrg 64705b261ecSmrg RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); 64805b261ecSmrg 6496747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 65005b261ecSmrg} 65105b261ecSmrg 65205b261ecSmrg/* 65305b261ecSmrg * RootlessResizeCopyWindow 65405b261ecSmrg * CopyWindow used during ResizeWindow for gravity moves. Based on 65505b261ecSmrg * fbCopyWindow. The original always draws on the root pixmap, which 65605b261ecSmrg * we don't have. Instead, draw on the parent window's pixmap. 65705b261ecSmrg * Resize version: the old location's pixels are in gResizeCopyWindowSource. 65805b261ecSmrg */ 65905b261ecSmrgstatic void 66005b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 66105b261ecSmrg RegionPtr prgnSrc) 66205b261ecSmrg{ 66305b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 66435c4bbdfSmrg RegionRec rgnDst; 66535c4bbdfSmrg int dx, dy; 66605b261ecSmrg 66705b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); 66805b261ecSmrg 66905b261ecSmrg /* Don't unwrap pScreen->CopyWindow. 67005b261ecSmrg The bogus rewrap with RootlessCopyWindow causes a crash if 67105b261ecSmrg CopyWindow is called again during the same resize. */ 67205b261ecSmrg 67305b261ecSmrg if (gResizeDeathCount == 0) 67405b261ecSmrg return; 67505b261ecSmrg 67605b261ecSmrg RootlessStartDrawing(pWin); 67705b261ecSmrg 67805b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 67905b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 6806747b715Smrg RegionTranslate(prgnSrc, -dx, -dy); 6816747b715Smrg RegionNull(&rgnDst); 6826747b715Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 68305b261ecSmrg 68405b261ecSmrg if (gResizeDeathCount == 1) { 68505b261ecSmrg /* Simple case, we only have a single source pixmap. */ 68605b261ecSmrg 68735c4bbdfSmrg miCopyRegion(&gResizeDeathPix[0]->drawable, 68805b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 68905b261ecSmrg &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 69005b261ecSmrg } 69105b261ecSmrg else { 69205b261ecSmrg int i; 69305b261ecSmrg RegionRec clip, clipped; 69405b261ecSmrg 69505b261ecSmrg /* More complex case, N source pixmaps (usually two). So we 69605b261ecSmrg intersect the destination with each source and copy those bits. */ 69705b261ecSmrg 69805b261ecSmrg for (i = 0; i < gResizeDeathCount; i++) { 6996747b715Smrg RegionInit(&clip, gResizeDeathBounds + 0, 1); 7006747b715Smrg RegionNull(&clipped); 7016747b715Smrg RegionIntersect(&rgnDst, &clip, &clipped); 70205b261ecSmrg 70335c4bbdfSmrg miCopyRegion(&gResizeDeathPix[i]->drawable, 70405b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 70505b261ecSmrg &clipped, dx, dy, fbCopyWindowProc, 0, 0); 70605b261ecSmrg 7076747b715Smrg RegionUninit(&clipped); 7086747b715Smrg RegionUninit(&clip); 70905b261ecSmrg } 71005b261ecSmrg } 71105b261ecSmrg 71205b261ecSmrg /* Don't update - resize will update everything */ 7136747b715Smrg RegionUninit(&rgnDst); 71405b261ecSmrg 71505b261ecSmrg fbValidateDrawable(&pWin->drawable); 71605b261ecSmrg 71705b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB end\n"); 71805b261ecSmrg} 71905b261ecSmrg 72005b261ecSmrg/* 72105b261ecSmrg * RootlessCopyWindow 72205b261ecSmrg * Update *new* location of window. Old location is redrawn with 72335c4bbdfSmrg * PaintWindow. 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; 73135c4bbdfSmrg RegionRec rgnDst; 73235c4bbdfSmrg 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 && 75335c4bbdfSmrg SCREENREC(pScreen)->imp->CopyWindow) { 75405b261ecSmrg RootlessWindowRec *winRec; 75505b261ecSmrg WindowPtr top; 75605b261ecSmrg 75705b261ecSmrg top = TopLevelParent(pWin); 75805b261ecSmrg if (top == NULL) { 75905b261ecSmrg RL_DEBUG_MSG("no parent\n"); 7604642e01fSmrg goto out; 76105b261ecSmrg } 76205b261ecSmrg 76305b261ecSmrg winRec = WINREC(top); 76405b261ecSmrg if (winRec == NULL) { 76505b261ecSmrg RL_DEBUG_MSG("not framed\n"); 7664642e01fSmrg goto out; 76705b261ecSmrg } 76805b261ecSmrg 76905b261ecSmrg /* Move region to window local coords */ 7706747b715Smrg RegionTranslate(&rgnDst, -winRec->x, -winRec->y); 77105b261ecSmrg 77205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 77305b261ecSmrg 77405b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, 7756747b715Smrg RegionNumRects(&rgnDst), 77635c4bbdfSmrg RegionRects(&rgnDst), dx, dy); 77705b261ecSmrg } 77805b261ecSmrg else { 77905b261ecSmrg RootlessStartDrawing(pWin); 78005b261ecSmrg 78135c4bbdfSmrg miCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, 78205b261ecSmrg 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 78305b261ecSmrg 78405b261ecSmrg /* prgnSrc has been translated to dst position */ 78505b261ecSmrg RootlessDamageRegion(pWin, prgnSrc); 78605b261ecSmrg } 78705b261ecSmrg 78835c4bbdfSmrg out: 7896747b715Smrg RegionUninit(&rgnDst); 79005b261ecSmrg fbValidateDrawable(&pWin->drawable); 79105b261ecSmrg 79205b261ecSmrg SCREEN_WRAP(pScreen, CopyWindow); 79305b261ecSmrg 79405b261ecSmrg RL_DEBUG_MSG("copywindowFB end\n"); 79505b261ecSmrg} 79605b261ecSmrg 79735c4bbdfSmrgvoid 79835c4bbdfSmrgRootlessPaintWindow(WindowPtr pWin, RegionPtr prgn, int what) 79935c4bbdfSmrg{ 80035c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 80135c4bbdfSmrg 80235c4bbdfSmrg if (IsFramedWindow(pWin)) { 80335c4bbdfSmrg RootlessStartDrawing(pWin); 80435c4bbdfSmrg RootlessDamageRegion(pWin, prgn); 80535c4bbdfSmrg 80635c4bbdfSmrg if (pWin->backgroundState == ParentRelative) { 80735c4bbdfSmrg if ((what == PW_BACKGROUND) || 80835c4bbdfSmrg (what == PW_BORDER && !pWin->borderIsPixel)) 80935c4bbdfSmrg RootlessSetPixmapOfAncestors(pWin); 81035c4bbdfSmrg } 81135c4bbdfSmrg } 81235c4bbdfSmrg 81335c4bbdfSmrg SCREEN_UNWRAP(pScreen, PaintWindow); 81435c4bbdfSmrg pScreen->PaintWindow(pWin, prgn, what); 81535c4bbdfSmrg SCREEN_WRAP(pScreen, PaintWindow); 81635c4bbdfSmrg} 81705b261ecSmrg 81805b261ecSmrg/* 81905b261ecSmrg * Window resize procedures 82005b261ecSmrg */ 82105b261ecSmrg 82205b261ecSmrgenum { 82305b261ecSmrg WIDTH_SMALLER = 1, 82405b261ecSmrg HEIGHT_SMALLER = 2, 82505b261ecSmrg}; 82605b261ecSmrg 82705b261ecSmrg/* 82805b261ecSmrg * ResizeWeighting 82905b261ecSmrg * Choose gravity to avoid local copies. Do that by looking for 83005b261ecSmrg * a corner that doesn't move _relative to the screen_. 83105b261ecSmrg */ 83205b261ecSmrgstatic inline unsigned int 83305b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, 83405b261ecSmrg int newX1, int newY1, int newX2, int newY2, int newBW) 83505b261ecSmrg{ 83605b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY 83705b261ecSmrg if (newBW != oldBW) 83805b261ecSmrg return RL_GRAVITY_NONE; 83905b261ecSmrg 84005b261ecSmrg if (newX1 == oldX1 && newY1 == oldY1) 84105b261ecSmrg return RL_GRAVITY_NORTH_WEST; 84205b261ecSmrg else if (newX1 == oldX1 && newY2 == oldY2) 84305b261ecSmrg return RL_GRAVITY_SOUTH_WEST; 84405b261ecSmrg else if (newX2 == oldX2 && newY2 == oldY2) 84505b261ecSmrg return RL_GRAVITY_SOUTH_EAST; 84605b261ecSmrg else if (newX2 == oldX2 && newY1 == oldY1) 84705b261ecSmrg return RL_GRAVITY_NORTH_EAST; 84805b261ecSmrg else 84905b261ecSmrg return RL_GRAVITY_NONE; 85005b261ecSmrg#else 85105b261ecSmrg return RL_GRAVITY_NONE; 85205b261ecSmrg#endif 85305b261ecSmrg} 85405b261ecSmrg 85505b261ecSmrg/* 85605b261ecSmrg * StartFrameResize 85705b261ecSmrg * Prepare to resize a top-level window. The old window's pixels are 85805b261ecSmrg * saved and the implementation is told to change the window size. 85905b261ecSmrg * (x,y,w,h) is outer frame of window (outside border) 86005b261ecSmrg */ 86105b261ecSmrgstatic Bool 86205b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity, 86305b261ecSmrg int oldX, int oldY, int oldW, int oldH, int oldBW, 86405b261ecSmrg int newX, int newY, int newW, int newH, int newBW) 86505b261ecSmrg{ 86605b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 86705b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 86805b261ecSmrg Bool need_window_source = FALSE, resize_after = FALSE; 86905b261ecSmrg 87005b261ecSmrg BoxRec rect; 87105b261ecSmrg int oldX2, newX2; 87205b261ecSmrg int oldY2, newY2; 87305b261ecSmrg unsigned int weight; 87405b261ecSmrg 87505b261ecSmrg oldX2 = oldX + oldW, newX2 = newX + newW; 87605b261ecSmrg oldY2 = oldY + oldH, newY2 = newY + newH; 87705b261ecSmrg 87805b261ecSmrg /* Decide which resize weighting to use */ 87905b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 88005b261ecSmrg newX, newY, newW, newH, newBW); 88105b261ecSmrg 88205b261ecSmrg /* Compute intersection between old and new rects */ 88305b261ecSmrg rect.x1 = max(oldX, newX); 88405b261ecSmrg rect.y1 = max(oldY, newY); 88505b261ecSmrg rect.x2 = min(oldX2, newX2); 88605b261ecSmrg rect.y2 = min(oldY2, newY2); 88705b261ecSmrg 88805b261ecSmrg RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); 88905b261ecSmrg RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", 89035c4bbdfSmrg oldX, oldY, oldW, oldH, oldBW, newX, newY, newW, newH, newBW); 89105b261ecSmrg 89205b261ecSmrg RootlessRedisplay(pWin); 89305b261ecSmrg 89405b261ecSmrg /* If gravity is true, then we need to have a way of recovering all 89505b261ecSmrg the original bits in the window for when X rearranges the contents 89605b261ecSmrg based on the various gravity settings. The obvious way is to just 89705b261ecSmrg snapshot the entire backing store before resizing it, but that 89805b261ecSmrg it slow on large windows. 89905b261ecSmrg 90005b261ecSmrg So the optimization here is to use the implementation's resize 90105b261ecSmrg weighting options (if available) to allow us to reason about what 90205b261ecSmrg is left in the backing store after the resize. We can then only 90305b261ecSmrg copy what won't be there after the resize, and do a two-stage copy 90405b261ecSmrg operation. 90505b261ecSmrg 90605b261ecSmrg Most of these optimizations are only applied when the top-left 90705b261ecSmrg corner of the window is fixed, since that's the common case. They 90805b261ecSmrg could probably be extended with some thought. */ 90905b261ecSmrg 91005b261ecSmrg gResizeDeathCount = 0; 91105b261ecSmrg 91205b261ecSmrg if (gravity && weight == RL_GRAVITY_NORTH_WEST) { 91305b261ecSmrg unsigned int code = 0; 91405b261ecSmrg 91505b261ecSmrg /* Top left corner is anchored. We never need to copy the 91605b261ecSmrg entire window. */ 91705b261ecSmrg 91805b261ecSmrg need_window_source = TRUE; 91905b261ecSmrg 92005b261ecSmrg /* These comparisons were chosen to avoid setting bits when the sizes 92135c4bbdfSmrg are the same. (So the fastest case automatically gets taken when 92235c4bbdfSmrg dimensions are unchanging.) */ 92305b261ecSmrg 92405b261ecSmrg if (newW < oldW) 92505b261ecSmrg code |= WIDTH_SMALLER; 92605b261ecSmrg if (newH < oldH) 92705b261ecSmrg code |= HEIGHT_SMALLER; 92805b261ecSmrg 92905b261ecSmrg if (((code ^ (code >> 1)) & 1) == 0) { 93005b261ecSmrg /* Both dimensions are either getting larger, or both 93105b261ecSmrg are getting smaller. No need to copy anything. */ 93205b261ecSmrg 93305b261ecSmrg if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { 93405b261ecSmrg /* Since the window is getting smaller, we can do gravity 935ed6184dfSmrg repair on it with its current size, then resize it 93605b261ecSmrg afterwards. */ 93705b261ecSmrg 93805b261ecSmrg resize_after = TRUE; 93905b261ecSmrg } 94005b261ecSmrg 94105b261ecSmrg gResizeDeathCount = 1; 94205b261ecSmrg } 94305b261ecSmrg else { 94405b261ecSmrg unsigned int copy_rowbytes, Bpp; 94505b261ecSmrg unsigned int copy_rect_width, copy_rect_height; 94605b261ecSmrg BoxRec copy_rect; 94705b261ecSmrg 94805b261ecSmrg /* We can get away with a partial copy. 'rect' is the 94905b261ecSmrg intersection between old and new bounds, so copy 95005b261ecSmrg everything to the right of or below the intersection. */ 95105b261ecSmrg 95205b261ecSmrg RootlessStartDrawing(pWin); 95305b261ecSmrg 95405b261ecSmrg if (code == WIDTH_SMALLER) { 95505b261ecSmrg copy_rect.x1 = rect.x2; 95605b261ecSmrg copy_rect.y1 = rect.y1; 95705b261ecSmrg copy_rect.x2 = oldX2; 95805b261ecSmrg copy_rect.y2 = oldY2; 95905b261ecSmrg } 96005b261ecSmrg else if (code == HEIGHT_SMALLER) { 96105b261ecSmrg copy_rect.x1 = rect.x1; 96205b261ecSmrg copy_rect.y1 = rect.y2; 96305b261ecSmrg copy_rect.x2 = oldX2; 96405b261ecSmrg copy_rect.y2 = oldY2; 96505b261ecSmrg } 96605b261ecSmrg else 9676747b715Smrg OsAbort(); 96805b261ecSmrg 96905b261ecSmrg Bpp = winRec->win->drawable.bitsPerPixel / 8; 97005b261ecSmrg copy_rect_width = copy_rect.x2 - copy_rect.x1; 97105b261ecSmrg copy_rect_height = copy_rect.y2 - copy_rect.y1; 97205b261ecSmrg copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; 97335c4bbdfSmrg gResizeDeathBits = xallocarray(copy_rowbytes, copy_rect_height); 97405b261ecSmrg 97505b261ecSmrg if (copy_rect_width * copy_rect_height > 97635c4bbdfSmrg rootless_CopyBytes_threshold && 97735c4bbdfSmrg SCREENREC(pScreen)->imp->CopyBytes) { 97835c4bbdfSmrg SCREENREC(pScreen)->imp->CopyBytes(copy_rect_width * Bpp, 97935c4bbdfSmrg copy_rect_height, 98035c4bbdfSmrg ((char *) winRec->pixelData) 98135c4bbdfSmrg + 98235c4bbdfSmrg ((copy_rect.y1 - 98335c4bbdfSmrg oldY) * 98435c4bbdfSmrg winRec->bytesPerRow) 98535c4bbdfSmrg + (copy_rect.x1 - 98635c4bbdfSmrg oldX) * Bpp, 98735c4bbdfSmrg winRec->bytesPerRow, 98835c4bbdfSmrg gResizeDeathBits, 98935c4bbdfSmrg copy_rowbytes); 99035c4bbdfSmrg } 99135c4bbdfSmrg else { 99205b261ecSmrg fbBlt((FbBits *) (winRec->pixelData 99335c4bbdfSmrg + 99435c4bbdfSmrg ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 99535c4bbdfSmrg + (copy_rect.x1 - oldX) * Bpp), 99605b261ecSmrg winRec->bytesPerRow / sizeof(FbBits), 0, 99705b261ecSmrg (FbBits *) gResizeDeathBits, 99835c4bbdfSmrg copy_rowbytes / sizeof(FbBits), 0, copy_rect_width * Bpp, 99935c4bbdfSmrg copy_rect_height, GXcopy, FB_ALLONES, Bpp, 0, 0); 100005b261ecSmrg } 100105b261ecSmrg 100205b261ecSmrg gResizeDeathBounds[1] = copy_rect; 100305b261ecSmrg gResizeDeathPix[1] 100405b261ecSmrg = GetScratchPixmapHeader(pScreen, copy_rect_width, 100505b261ecSmrg copy_rect_height, 100605b261ecSmrg winRec->win->drawable.depth, 100705b261ecSmrg winRec->win->drawable.bitsPerPixel, 100805b261ecSmrg winRec->bytesPerRow, 100905b261ecSmrg (void *) gResizeDeathBits); 101005b261ecSmrg 101105b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[1], 101205b261ecSmrg copy_rect.x1, copy_rect.y1); 101305b261ecSmrg 101405b261ecSmrg gResizeDeathCount = 2; 101505b261ecSmrg } 101605b261ecSmrg } 101705b261ecSmrg else if (gravity) { 101805b261ecSmrg /* The general case. Just copy everything. */ 101905b261ecSmrg 102005b261ecSmrg RootlessStartDrawing(pWin); 102105b261ecSmrg 102235c4bbdfSmrg gResizeDeathBits = xallocarray(winRec->bytesPerRow, winRec->height); 102305b261ecSmrg 102405b261ecSmrg memcpy(gResizeDeathBits, winRec->pixelData, 102505b261ecSmrg winRec->bytesPerRow * winRec->height); 102605b261ecSmrg 102735c4bbdfSmrg gResizeDeathBounds[0] = (BoxRec) { 102835c4bbdfSmrg oldX, oldY, oldX2, oldY2}; 102905b261ecSmrg gResizeDeathPix[0] 103005b261ecSmrg = GetScratchPixmapHeader(pScreen, winRec->width, 103105b261ecSmrg winRec->height, 103205b261ecSmrg winRec->win->drawable.depth, 103305b261ecSmrg winRec->win->drawable.bitsPerPixel, 103405b261ecSmrg winRec->bytesPerRow, 103505b261ecSmrg (void *) gResizeDeathBits); 103605b261ecSmrg 103705b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 103805b261ecSmrg gResizeDeathCount = 1; 103905b261ecSmrg } 104005b261ecSmrg 104105b261ecSmrg RootlessStopDrawing(pWin, FALSE); 104205b261ecSmrg 104305b261ecSmrg winRec->x = newX; 104405b261ecSmrg winRec->y = newY; 104505b261ecSmrg winRec->width = newW; 104605b261ecSmrg winRec->height = newH; 104705b261ecSmrg winRec->borderWidth = newBW; 104805b261ecSmrg 104905b261ecSmrg /* Unless both dimensions are getting smaller, Resize the frame 105005b261ecSmrg before doing gravity repair */ 105105b261ecSmrg 105205b261ecSmrg if (!resize_after) { 105305b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 105405b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 105505b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 105605b261ecSmrg newW, newH, weight); 105705b261ecSmrg } 105805b261ecSmrg 105905b261ecSmrg RootlessStartDrawing(pWin); 106005b261ecSmrg 106105b261ecSmrg /* If necessary, create a source pixmap pointing at the current 106205b261ecSmrg window bits. */ 106305b261ecSmrg 106405b261ecSmrg if (need_window_source) { 106535c4bbdfSmrg gResizeDeathBounds[0] = (BoxRec) { 106635c4bbdfSmrg oldX, oldY, oldX2, oldY2}; 106705b261ecSmrg gResizeDeathPix[0] 106805b261ecSmrg = GetScratchPixmapHeader(pScreen, oldW, oldH, 106905b261ecSmrg winRec->win->drawable.depth, 107005b261ecSmrg winRec->win->drawable.bitsPerPixel, 107105b261ecSmrg winRec->bytesPerRow, winRec->pixelData); 107205b261ecSmrg 107305b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 107405b261ecSmrg } 107505b261ecSmrg 107605b261ecSmrg /* Use custom CopyWindow when moving gravity bits around 107705b261ecSmrg ResizeWindow assumes the old window contents are in the same 107805b261ecSmrg pixmap, but here they're in deathPix instead. */ 107905b261ecSmrg 108005b261ecSmrg if (gravity) { 108105b261ecSmrg gResizeOldCopyWindowProc = pScreen->CopyWindow; 108205b261ecSmrg pScreen->CopyWindow = RootlessResizeCopyWindow; 108305b261ecSmrg } 108405b261ecSmrg 108505b261ecSmrg /* If we can't rely on the window server preserving the bits we 108605b261ecSmrg need in the position we need, copy the pixels in the 108705b261ecSmrg intersection from src to dst. ResizeWindow assumes these pixels 108805b261ecSmrg are already present when making gravity adjustments. pWin 108905b261ecSmrg currently has new-sized pixmap but is in old position. 109005b261ecSmrg 109105b261ecSmrg FIXME: border width change! (?) */ 109205b261ecSmrg 109305b261ecSmrg if (gravity && weight == RL_GRAVITY_NONE) { 109405b261ecSmrg PixmapPtr src, dst; 109505b261ecSmrg 109605b261ecSmrg assert(gResizeDeathCount == 1); 109705b261ecSmrg 109805b261ecSmrg src = gResizeDeathPix[0]; 109905b261ecSmrg dst = pScreen->GetWindowPixmap(pWin); 110005b261ecSmrg 110105b261ecSmrg RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", 110205b261ecSmrg rect.x1, rect.y1, rect.x2, rect.y2); 110305b261ecSmrg 110405b261ecSmrg /* rect is the intersection of the old location and new location */ 110505b261ecSmrg if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { 110605b261ecSmrg /* The window drawable still has the old frame position, which 110705b261ecSmrg means that DST doesn't actually point at the origin of our 110805b261ecSmrg physical backing store when adjusted by the drawable.x,y 110905b261ecSmrg position. So sneakily adjust it temporarily while copying.. */ 111005b261ecSmrg 111105b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 111205b261ecSmrg SetPixmapBaseToScreen(dst, newX, newY); 111305b261ecSmrg 111405b261ecSmrg fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, 111505b261ecSmrg &rect, 1, 0, 0, FALSE, FALSE, 0, 0); 111605b261ecSmrg 111705b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 111805b261ecSmrg SetPixmapBaseToScreen(dst, oldX, oldY); 111905b261ecSmrg } 112005b261ecSmrg } 112105b261ecSmrg 112205b261ecSmrg return resize_after; 112305b261ecSmrg} 112405b261ecSmrg 112505b261ecSmrgstatic void 112605b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, 112705b261ecSmrg unsigned int oldW, unsigned int oldH, unsigned int oldBW, 112805b261ecSmrg int newX, int newY, unsigned int newW, unsigned int newH, 112905b261ecSmrg unsigned int newBW, Bool resize_now) 113005b261ecSmrg{ 113105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 113205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 113305b261ecSmrg int i; 113405b261ecSmrg 113505b261ecSmrg RootlessStopDrawing(pWin, FALSE); 113605b261ecSmrg 113705b261ecSmrg if (resize_now) { 113805b261ecSmrg unsigned int weight; 113905b261ecSmrg 114005b261ecSmrg /* We didn't resize anything earlier, so do it now, now that 114105b261ecSmrg we've finished gravitating the bits. */ 114205b261ecSmrg 114305b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 114405b261ecSmrg newX, newY, newW, newH, newBW); 114505b261ecSmrg 114605b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 114705b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 114805b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 114905b261ecSmrg newW, newH, weight); 115005b261ecSmrg } 115105b261ecSmrg 115205b261ecSmrg /* Redraw everything. FIXME: there must be times when we don't need 115305b261ecSmrg to do this. Perhaps when top-left weighting and no gravity? */ 115405b261ecSmrg 115505b261ecSmrg RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); 115605b261ecSmrg 115705b261ecSmrg for (i = 0; i < 2; i++) { 115805b261ecSmrg if (gResizeDeathPix[i] != NULL) { 115905b261ecSmrg FreeScratchPixmapHeader(gResizeDeathPix[i]); 116005b261ecSmrg gResizeDeathPix[i] = NULL; 116105b261ecSmrg } 116205b261ecSmrg } 116305b261ecSmrg 11649ace9065Smrg free(gResizeDeathBits); 11659ace9065Smrg gResizeDeathBits = NULL; 116605b261ecSmrg 116705b261ecSmrg if (gravity) { 116805b261ecSmrg pScreen->CopyWindow = gResizeOldCopyWindowProc; 116905b261ecSmrg } 117005b261ecSmrg} 117105b261ecSmrg 117205b261ecSmrg/* 117305b261ecSmrg * RootlessMoveWindow 117405b261ecSmrg * If kind==VTOther, window border is resizing (and borderWidth is 117505b261ecSmrg * already changed!!@#$) This case works like window resize, not move. 117605b261ecSmrg */ 117705b261ecSmrgvoid 117805b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 117905b261ecSmrg{ 118005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 118105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 118205b261ecSmrg CopyWindowProcPtr oldCopyWindowProc = NULL; 118305b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 118405b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 118505b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 118605b261ecSmrg Bool resize_after = FALSE; 118705b261ecSmrg RegionRec saveRoot; 118805b261ecSmrg 118905b261ecSmrg RL_DEBUG_MSG("movewindow start \n"); 119005b261ecSmrg 119105b261ecSmrg if (winRec) { 119205b261ecSmrg if (kind == VTMove) { 119305b261ecSmrg oldX = winRec->x; 119405b261ecSmrg oldY = winRec->y; 119505b261ecSmrg RootlessRedisplay(pWin); 119605b261ecSmrg RootlessStartDrawing(pWin); 119735c4bbdfSmrg } 119835c4bbdfSmrg else { 119905b261ecSmrg RL_DEBUG_MSG("movewindow border resizing "); 120005b261ecSmrg 120105b261ecSmrg oldBW = winRec->borderWidth; 120205b261ecSmrg oldX = winRec->x; 120305b261ecSmrg oldY = winRec->y; 120405b261ecSmrg oldW = winRec->width; 120505b261ecSmrg oldH = winRec->height; 120605b261ecSmrg 120705b261ecSmrg newBW = wBorderWidth(pWin); 120805b261ecSmrg newX = x; 120905b261ecSmrg newY = y; 121035c4bbdfSmrg newW = pWin->drawable.width + 2 * newBW; 121135c4bbdfSmrg newH = pWin->drawable.height + 2 * newBW; 121205b261ecSmrg 121305b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 121405b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 121505b261ecSmrg newX, newY, newW, newH, newBW); 121605b261ecSmrg } 121705b261ecSmrg } 121805b261ecSmrg 121905b261ecSmrg HUGE_ROOT(pWin); 122005b261ecSmrg SCREEN_UNWRAP(pScreen, MoveWindow); 122105b261ecSmrg 122205b261ecSmrg if (winRec) { 122305b261ecSmrg oldCopyWindowProc = pScreen->CopyWindow; 122405b261ecSmrg pScreen->CopyWindow = RootlessNoCopyWindow; 122505b261ecSmrg } 122605b261ecSmrg pScreen->MoveWindow(pWin, x, y, pSib, kind); 122705b261ecSmrg if (winRec) { 122805b261ecSmrg pScreen->CopyWindow = oldCopyWindowProc; 122905b261ecSmrg } 123005b261ecSmrg 123105b261ecSmrg NORMAL_ROOT(pWin); 123205b261ecSmrg SCREEN_WRAP(pScreen, MoveWindow); 123305b261ecSmrg 123405b261ecSmrg if (winRec) { 123505b261ecSmrg if (kind == VTMove) { 123605b261ecSmrg winRec->x = x; 123705b261ecSmrg winRec->y = y; 123805b261ecSmrg RootlessStopDrawing(pWin, FALSE); 123905b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 124005b261ecSmrg x + SCREEN_TO_GLOBAL_X, 124105b261ecSmrg y + SCREEN_TO_GLOBAL_Y); 124235c4bbdfSmrg } 124335c4bbdfSmrg else { 124405b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 124505b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 124605b261ecSmrg } 124705b261ecSmrg } 124805b261ecSmrg 124905b261ecSmrg RL_DEBUG_MSG("movewindow end\n"); 125005b261ecSmrg} 125105b261ecSmrg 125205b261ecSmrg/* 125305b261ecSmrg * RootlessResizeWindow 125405b261ecSmrg * Note: (x, y, w, h) as passed to this procedure don't match the frame 125505b261ecSmrg * definition. (x,y) is corner of very outer edge, *outside* border. 125605b261ecSmrg * w,h is width and height *inside* border, *ignoring* border width. 125705b261ecSmrg * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) 125805b261ecSmrg * is total rect and (x+bw, y+bw, w, h) is inner rect. 125905b261ecSmrg */ 126005b261ecSmrgvoid 126105b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y, 126205b261ecSmrg unsigned int w, unsigned int h, WindowPtr pSib) 126305b261ecSmrg{ 126405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 126505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 126605b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 126705b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; 126805b261ecSmrg Bool resize_after = FALSE; 126905b261ecSmrg RegionRec saveRoot; 127005b261ecSmrg 127105b261ecSmrg RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); 127235c4bbdfSmrg 127335c4bbdfSmrg if (pWin->parent) { 12744642e01fSmrg if (winRec) { 12754642e01fSmrg oldBW = winRec->borderWidth; 12764642e01fSmrg oldX = winRec->x; 12774642e01fSmrg oldY = winRec->y; 12784642e01fSmrg oldW = winRec->width; 12794642e01fSmrg oldH = winRec->height; 128005b261ecSmrg 12814642e01fSmrg newBW = oldBW; 12824642e01fSmrg newX = x; 12834642e01fSmrg newY = y; 128435c4bbdfSmrg newW = w + 2 * newBW; 128535c4bbdfSmrg newH = h + 2 * newBW; 128605b261ecSmrg 12874642e01fSmrg resize_after = StartFrameResize(pWin, TRUE, 12884642e01fSmrg oldX, oldY, oldW, oldH, oldBW, 12894642e01fSmrg newX, newY, newW, newH, newBW); 12904642e01fSmrg } 129105b261ecSmrg 12924642e01fSmrg HUGE_ROOT(pWin); 12934642e01fSmrg SCREEN_UNWRAP(pScreen, ResizeWindow); 12944642e01fSmrg pScreen->ResizeWindow(pWin, x, y, w, h, pSib); 12954642e01fSmrg SCREEN_WRAP(pScreen, ResizeWindow); 12964642e01fSmrg NORMAL_ROOT(pWin); 12974642e01fSmrg 12984642e01fSmrg if (winRec) { 12994642e01fSmrg FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, 13004642e01fSmrg newX, newY, newW, newH, newBW, resize_after); 13014642e01fSmrg } 130235c4bbdfSmrg } 130335c4bbdfSmrg else { 13044642e01fSmrg /* Special case for resizing the root window */ 13054642e01fSmrg BoxRec box; 13064642e01fSmrg 13074642e01fSmrg pWin->drawable.x = x; 13084642e01fSmrg pWin->drawable.y = y; 13094642e01fSmrg pWin->drawable.width = w; 13104642e01fSmrg pWin->drawable.height = h; 13114642e01fSmrg 131235c4bbdfSmrg box.x1 = x; 131335c4bbdfSmrg box.y1 = y; 131435c4bbdfSmrg box.x2 = x + w; 131535c4bbdfSmrg box.y2 = y + h; 13166747b715Smrg RegionUninit(&pWin->winSize); 13176747b715Smrg RegionInit(&pWin->winSize, &box, 1); 13186747b715Smrg RegionCopy(&pWin->borderSize, &pWin->winSize); 13196747b715Smrg RegionCopy(&pWin->clipList, &pWin->winSize); 13206747b715Smrg RegionCopy(&pWin->borderClip, &pWin->winSize); 13216747b715Smrg 13226747b715Smrg if (winRec) { 13236747b715Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 13246747b715Smrg x + SCREEN_TO_GLOBAL_X, 13256747b715Smrg y + SCREEN_TO_GLOBAL_Y, 13266747b715Smrg w, h, RL_GRAVITY_NONE); 13276747b715Smrg } 13284642e01fSmrg 13294642e01fSmrg miSendExposures(pWin, &pWin->borderClip, 133035c4bbdfSmrg pWin->drawable.x, pWin->drawable.y); 133105b261ecSmrg } 133205b261ecSmrg 133305b261ecSmrg RL_DEBUG_MSG("resizewindow end\n"); 133405b261ecSmrg} 133505b261ecSmrg 133605b261ecSmrg/* 133705b261ecSmrg * RootlessRepositionWindow 133805b261ecSmrg * Called by the implementation when a window needs to be repositioned to 133905b261ecSmrg * its correct location on the screen. This routine is typically needed 134005b261ecSmrg * due to changes in the underlying window system, such as a screen layout 134105b261ecSmrg * change. 134205b261ecSmrg */ 134305b261ecSmrgvoid 134405b261ecSmrgRootlessRepositionWindow(WindowPtr pWin) 134505b261ecSmrg{ 134605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 134705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 134805b261ecSmrg 134905b261ecSmrg if (winRec == NULL) 135005b261ecSmrg return; 135105b261ecSmrg 135205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 135305b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 135405b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 135505b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y); 135605b261ecSmrg 135705b261ecSmrg RootlessReorderWindow(pWin); 135805b261ecSmrg} 135905b261ecSmrg 136005b261ecSmrg/* 136105b261ecSmrg * RootlessReparentWindow 136205b261ecSmrg * Called after a window has been reparented. Generally windows are not 136305b261ecSmrg * framed until they are mapped. However, a window may be framed early by the 136405b261ecSmrg * implementation calling RootlessFrameForWindow. (e.g. this could be needed 136505b261ecSmrg * to attach a VRAM surface to it.) If the window is subsequently reparented 136605b261ecSmrg * by the window manager before being mapped, we need to give the frame to 136705b261ecSmrg * the new top-level window. 136805b261ecSmrg */ 136905b261ecSmrgvoid 137005b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 137105b261ecSmrg{ 137205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 137305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 137405b261ecSmrg WindowPtr pTopWin; 137505b261ecSmrg 137605b261ecSmrg /* Check that window is not top-level now, but used to be. */ 137705b261ecSmrg if (IsRoot(pWin) || IsRoot(pWin->parent) 137835c4bbdfSmrg || IsTopLevel(pWin) || winRec == NULL) { 137905b261ecSmrg goto out; 138005b261ecSmrg } 138105b261ecSmrg 138205b261ecSmrg /* If the formerly top-level window has a frame, we want to give the 138305b261ecSmrg frame to its new top-level parent. If we can't do that, we'll just 138405b261ecSmrg have to jettison it... */ 138505b261ecSmrg 138605b261ecSmrg pTopWin = TopLevelParent(pWin); 138705b261ecSmrg assert(pTopWin != pWin); 138835c4bbdfSmrg 138935c4bbdfSmrg pWin->unhittable = FALSE; 139035c4bbdfSmrg 139135c4bbdfSmrg DeleteProperty(serverClient, pWin, xa_native_window_id()); 139205b261ecSmrg 139305b261ecSmrg if (WINREC(pTopWin) != NULL) { 139405b261ecSmrg /* We're screwed. */ 139505b261ecSmrg RootlessDestroyFrame(pWin, winRec); 139635c4bbdfSmrg } 139735c4bbdfSmrg else { 139805b261ecSmrg if (!pTopWin->realized && pWin->realized) { 139905b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 140005b261ecSmrg } 140105b261ecSmrg 140205b261ecSmrg /* Switch the frame record from one to the other. */ 140305b261ecSmrg 14044642e01fSmrg SETWINREC(pWin, NULL); 14054642e01fSmrg SETWINREC(pTopWin, winRec); 140605b261ecSmrg 140705b261ecSmrg RootlessInitializeFrame(pTopWin, winRec); 140805b261ecSmrg RootlessReshapeFrame(pTopWin); 140905b261ecSmrg 141005b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 141105b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 141205b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 141305b261ecSmrg winRec->width, winRec->height, 141405b261ecSmrg RL_GRAVITY_NONE); 141505b261ecSmrg 141605b261ecSmrg if (SCREENREC(pScreen)->imp->SwitchWindow) { 141705b261ecSmrg SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); 141805b261ecSmrg } 141905b261ecSmrg 142005b261ecSmrg if (pTopWin->realized && !pWin->realized) 142105b261ecSmrg winRec->is_reorder_pending = TRUE; 142205b261ecSmrg } 142305b261ecSmrg 142435c4bbdfSmrg out: 142505b261ecSmrg if (SCREENREC(pScreen)->ReparentWindow) { 142605b261ecSmrg SCREEN_UNWRAP(pScreen, ReparentWindow); 142705b261ecSmrg pScreen->ReparentWindow(pWin, pPriorParent); 142805b261ecSmrg SCREEN_WRAP(pScreen, ReparentWindow); 142905b261ecSmrg } 143005b261ecSmrg} 143105b261ecSmrg 143205b261ecSmrgvoid 143335c4bbdfSmrgRootlessFlushWindowColormap(WindowPtr pWin) 143405b261ecSmrg{ 143535c4bbdfSmrg RootlessWindowRec *winRec = WINREC(pWin); 143635c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 143705b261ecSmrg 143835c4bbdfSmrg if (winRec == NULL) 143935c4bbdfSmrg return; 144005b261ecSmrg 144135c4bbdfSmrg RootlessStopDrawing(pWin, FALSE); 144205b261ecSmrg 144335c4bbdfSmrg if (SCREENREC(pScreen)->imp->UpdateColormap) 144435c4bbdfSmrg SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); 144505b261ecSmrg} 144605b261ecSmrg 144705b261ecSmrg/* 144805b261ecSmrg * RootlessChangeBorderWidth 144905b261ecSmrg * FIXME: untested! 145005b261ecSmrg * pWin inside corner stays the same; pWin->drawable.[xy] stays the same 145105b261ecSmrg * Frame moves and resizes. 145205b261ecSmrg */ 145305b261ecSmrgvoid 145405b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) 145505b261ecSmrg{ 145605b261ecSmrg RegionRec saveRoot; 145705b261ecSmrg Bool resize_after = FALSE; 145805b261ecSmrg 145905b261ecSmrg RL_DEBUG_MSG("change border width "); 146005b261ecSmrg 146105b261ecSmrg if (width != wBorderWidth(pWin)) { 146205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 146305b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 146405b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 146505b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 146605b261ecSmrg 146705b261ecSmrg if (winRec) { 146805b261ecSmrg oldBW = winRec->borderWidth; 146905b261ecSmrg oldX = winRec->x; 147005b261ecSmrg oldY = winRec->y; 147105b261ecSmrg oldW = winRec->width; 147205b261ecSmrg oldH = winRec->height; 147305b261ecSmrg 147405b261ecSmrg newBW = width; 147505b261ecSmrg newX = pWin->drawable.x - newBW; 147605b261ecSmrg newY = pWin->drawable.y - newBW; 147735c4bbdfSmrg newW = pWin->drawable.width + 2 * newBW; 147835c4bbdfSmrg newH = pWin->drawable.height + 2 * newBW; 147905b261ecSmrg 148005b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 148105b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 148205b261ecSmrg newX, newY, newW, newH, newBW); 148305b261ecSmrg } 148405b261ecSmrg 148505b261ecSmrg HUGE_ROOT(pWin); 148605b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); 148705b261ecSmrg pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); 148805b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); 148905b261ecSmrg NORMAL_ROOT(pWin); 149005b261ecSmrg 149105b261ecSmrg if (winRec) { 149205b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 149305b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 149405b261ecSmrg } 149505b261ecSmrg } 149605b261ecSmrg 149705b261ecSmrg RL_DEBUG_MSG("change border width end\n"); 149805b261ecSmrg} 14994642e01fSmrg 15004642e01fSmrg/* 15014642e01fSmrg * RootlessOrderAllWindows 15024642e01fSmrg * Brings all X11 windows to the top of the window stack 15034642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus 15044642e01fSmrg */ 15054642e01fSmrgvoid 150635c4bbdfSmrgRootlessOrderAllWindows(Bool include_unhitable) 15074642e01fSmrg{ 15084642e01fSmrg int i; 15094642e01fSmrg WindowPtr pWin; 15104642e01fSmrg 15114642e01fSmrg if (windows_hidden) 151235c4bbdfSmrg return; 15134642e01fSmrg 15144642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() "); 15154642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 151635c4bbdfSmrg if (screenInfo.screens[i] == NULL) 151735c4bbdfSmrg continue; 151835c4bbdfSmrg pWin = screenInfo.screens[i]->root; 151935c4bbdfSmrg if (pWin == NULL) 152035c4bbdfSmrg continue; 152135c4bbdfSmrg 152235c4bbdfSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 152335c4bbdfSmrg if (!pWin->realized) 152435c4bbdfSmrg continue; 152535c4bbdfSmrg if (RootlessEnsureFrame(pWin) == NULL) 152635c4bbdfSmrg continue; 152735c4bbdfSmrg if (!include_unhitable && pWin->unhittable) 152835c4bbdfSmrg continue; 152935c4bbdfSmrg RootlessReorderWindow(pWin); 153035c4bbdfSmrg } 15314642e01fSmrg } 15324642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() done"); 15334642e01fSmrg} 15344642e01fSmrg 15354642e01fSmrgvoid 153635c4bbdfSmrgRootlessEnableRoot(ScreenPtr pScreen) 15374642e01fSmrg{ 15384642e01fSmrg WindowPtr pRoot; 153935c4bbdfSmrg 15406747b715Smrg pRoot = pScreen->root; 154135c4bbdfSmrg 154235c4bbdfSmrg RootlessEnsureFrame(pRoot); 15434642e01fSmrg (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); 154435c4bbdfSmrg RootlessReorderWindow(pRoot); 15454642e01fSmrg} 15464642e01fSmrg 15474642e01fSmrgvoid 154835c4bbdfSmrgRootlessDisableRoot(ScreenPtr pScreen) 15494642e01fSmrg{ 15504642e01fSmrg WindowPtr pRoot; 15514642e01fSmrg RootlessWindowRec *winRec; 15524642e01fSmrg 15536747b715Smrg pRoot = pScreen->root; 155435c4bbdfSmrg winRec = WINREC(pRoot); 15554642e01fSmrg 15564642e01fSmrg if (NULL == winRec) 155735c4bbdfSmrg return; 155835c4bbdfSmrg 155935c4bbdfSmrg RootlessDestroyFrame(pRoot, winRec); 156035c4bbdfSmrg DeleteProperty(serverClient, pRoot, xa_native_window_id()); 15614642e01fSmrg} 15624642e01fSmrg 15634642e01fSmrgvoid 156435c4bbdfSmrgRootlessHideAllWindows(void) 15654642e01fSmrg{ 15664642e01fSmrg int i; 15674642e01fSmrg ScreenPtr pScreen; 15684642e01fSmrg WindowPtr pWin; 15694642e01fSmrg RootlessWindowRec *winRec; 157035c4bbdfSmrg 15714642e01fSmrg if (windows_hidden) 15724642e01fSmrg return; 157335c4bbdfSmrg 15744642e01fSmrg windows_hidden = TRUE; 157535c4bbdfSmrg 157635c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 15774642e01fSmrg pScreen = screenInfo.screens[i]; 157835c4bbdfSmrg if (pScreen == NULL) 157935c4bbdfSmrg continue; 158035c4bbdfSmrg pWin = pScreen->root; 158135c4bbdfSmrg if (pWin == NULL) 15824642e01fSmrg continue; 158335c4bbdfSmrg 158435c4bbdfSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 15854642e01fSmrg if (!pWin->realized) 15864642e01fSmrg continue; 158735c4bbdfSmrg 158835c4bbdfSmrg RootlessStopDrawing(pWin, FALSE); 158935c4bbdfSmrg 159035c4bbdfSmrg winRec = WINREC(pWin); 159135c4bbdfSmrg if (winRec != NULL) { 159235c4bbdfSmrg if (SCREENREC(pScreen)->imp->HideWindow) 159335c4bbdfSmrg SCREENREC(pScreen)->imp->HideWindow(winRec->wid); 15944642e01fSmrg } 15954642e01fSmrg } 15964642e01fSmrg } 15974642e01fSmrg} 15984642e01fSmrg 15994642e01fSmrgvoid 160035c4bbdfSmrgRootlessShowAllWindows(void) 16014642e01fSmrg{ 16024642e01fSmrg int i; 16034642e01fSmrg ScreenPtr pScreen; 16044642e01fSmrg WindowPtr pWin; 16054642e01fSmrg RootlessWindowRec *winRec; 160635c4bbdfSmrg 16074642e01fSmrg if (!windows_hidden) 16084642e01fSmrg return; 160935c4bbdfSmrg 16104642e01fSmrg windows_hidden = FALSE; 161135c4bbdfSmrg 161235c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 16134642e01fSmrg pScreen = screenInfo.screens[i]; 161435c4bbdfSmrg if (pScreen == NULL) 161535c4bbdfSmrg continue; 161635c4bbdfSmrg pWin = pScreen->root; 161735c4bbdfSmrg if (pWin == NULL) 16184642e01fSmrg continue; 161935c4bbdfSmrg 162035c4bbdfSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 16214642e01fSmrg if (!pWin->realized) 16224642e01fSmrg continue; 162335c4bbdfSmrg 162435c4bbdfSmrg winRec = RootlessEnsureFrame(pWin); 16254642e01fSmrg if (winRec == NULL) 16264642e01fSmrg continue; 162735c4bbdfSmrg 162835c4bbdfSmrg RootlessReorderWindow(pWin); 16294642e01fSmrg } 163035c4bbdfSmrg 163135c4bbdfSmrg RootlessScreenExpose(pScreen); 16324642e01fSmrg } 16334642e01fSmrg} 16346747b715Smrg 16356747b715Smrg/* 16366747b715Smrg * SetPixmapOfAncestors 16376747b715Smrg * Set the Pixmaps on all ParentRelative windows up the ancestor chain. 16386747b715Smrg */ 16396747b715Smrgvoid 16406747b715SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin) 16416747b715Smrg{ 16426747b715Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 16436747b715Smrg WindowPtr topWin = TopLevelParent(pWin); 16446747b715Smrg RootlessWindowRec *topWinRec = WINREC(topWin); 164535c4bbdfSmrg 16466747b715Smrg while (pWin->backgroundState == ParentRelative) { 16476747b715Smrg if (pWin == topWin) { 16486747b715Smrg // disallow ParentRelative background state on top level 16496747b715Smrg XID pixel = 0; 165035c4bbdfSmrg 16516747b715Smrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 16526747b715Smrg RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); 16536747b715Smrg break; 16546747b715Smrg } 165535c4bbdfSmrg 16566747b715Smrg pWin = pWin->parent; 16576747b715Smrg pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); 16586747b715Smrg } 16596747b715Smrg} 1660