rootlessWindow.c revision 4642e01f
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#ifdef __APPLE__ 404642e01fSmrg//#include <X11/Xlib.h> 414642e01fSmrg#include <X11/Xatom.h> 424642e01fSmrg#include "mi.h" 434642e01fSmrg#include "pixmapstr.h" 444642e01fSmrg#include "windowstr.h" 454642e01fSmrg#include <Xplugin.h> 464642e01fSmrg//#include <X11/extensions/applewm.h> 474642e01fSmrgextern int darwinMainScreenX, darwinMainScreenY; 484642e01fSmrg#endif 494642e01fSmrg#include "fb.h" 504642e01fSmrg 514642e01fSmrg#define AppleWMNumWindowLevels 5 5205b261ecSmrg 5305b261ecSmrg#include "rootlessCommon.h" 5405b261ecSmrg#include "rootlessWindow.h" 5505b261ecSmrg 5605b261ecSmrg#ifdef ROOTLESS_GLOBAL_COORDS 5705b261ecSmrg#define SCREEN_TO_GLOBAL_X \ 5805b261ecSmrg (dixScreenOrigins[pScreen->myNum].x + rootlessGlobalOffsetX) 5905b261ecSmrg#define SCREEN_TO_GLOBAL_Y \ 6005b261ecSmrg (dixScreenOrigins[pScreen->myNum].y + rootlessGlobalOffsetY) 6105b261ecSmrg#else 6205b261ecSmrg#define SCREEN_TO_GLOBAL_X 0 6305b261ecSmrg#define SCREEN_TO_GLOBAL_Y 0 6405b261ecSmrg#endif 6505b261ecSmrg 664642e01fSmrg#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) 674642e01fSmrg 684642e01fSmrg#define DEFINE_ATOM_HELPER(func,atom_name) \ 694642e01fSmrg static Atom func (void) { \ 704642e01fSmrg static unsigned int generation = 0; \ 714642e01fSmrg static Atom atom; \ 724642e01fSmrg if (generation != serverGeneration) { \ 734642e01fSmrg generation = serverGeneration; \ 744642e01fSmrg atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ 754642e01fSmrg } \ 764642e01fSmrg return atom; \ 774642e01fSmrg } 784642e01fSmrg 794642e01fSmrgDEFINE_ATOM_HELPER (xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN") 804642e01fSmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID") 814642e01fSmrgDEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN") 824642e01fSmrg 834642e01fSmrgstatic Bool no_configure_window; 844642e01fSmrgstatic Bool windows_hidden; 854642e01fSmrg// TODO - abstract xp functions 864642e01fSmrg 874642e01fSmrgstatic inline int 884642e01fSmrgconfigure_window (xp_window_id id, unsigned int mask, 894642e01fSmrg const xp_window_changes *values) 904642e01fSmrg{ 914642e01fSmrg if (!no_configure_window) 924642e01fSmrg return xp_configure_window (id, mask, values); 934642e01fSmrg else 944642e01fSmrg return XP_Success; 954642e01fSmrg} 964642e01fSmrg 974642e01fSmrg/*static inline unsigned long 984642e01fSmrgcurrent_time_in_seconds (void) 994642e01fSmrg{ 1004642e01fSmrg unsigned long t = 0; 1014642e01fSmrg 1024642e01fSmrg t += currentTime.milliseconds / 1000; 1034642e01fSmrg t += currentTime.months * 4294967; 1044642e01fSmrg 1054642e01fSmrg return t; 1064642e01fSmrg } */ 1074642e01fSmrg 1084642e01fSmrgstatic inline Bool 1094642e01fSmrgrootlessHasRoot (ScreenPtr pScreen) 1104642e01fSmrg{ 1114642e01fSmrg return WINREC (WindowTable[pScreen->myNum]) != NULL; 1124642e01fSmrg} 1134642e01fSmrg 1144642e01fSmrgvoid 1154642e01fSmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state) 1164642e01fSmrg{ 1174642e01fSmrg RootlessWindowRec *winRec; 1184642e01fSmrg 1194642e01fSmrg if (pWin == NULL) return; 1204642e01fSmrg 1214642e01fSmrg winRec = WINREC (pWin); 1224642e01fSmrg if (winRec == NULL) return; 1234642e01fSmrg 1244642e01fSmrg winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); 1254642e01fSmrg winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); 1264642e01fSmrg pWin->rootlessUnhittable = winRec->is_offscreen; 1274642e01fSmrg} 1284642e01fSmrg 1294642e01fSmrgvoid RootlessNativeWindowMoved (WindowPtr pWin) { 1304642e01fSmrg xp_box bounds; 1314642e01fSmrg int sx, sy, err; 1324642e01fSmrg XID vlist[2]; 1334642e01fSmrg Mask mask; 1344642e01fSmrg ClientPtr pClient; 1354642e01fSmrg RootlessWindowRec *winRec; 1364642e01fSmrg 1374642e01fSmrg winRec = WINREC(pWin); 1384642e01fSmrg 1394642e01fSmrg if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return; 1404642e01fSmrg 1414642e01fSmrg sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX; 1424642e01fSmrg sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY; 1434642e01fSmrg 1444642e01fSmrg /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ 1454642e01fSmrg vlist[0] = (INT16) bounds.x1 - sx; 1464642e01fSmrg vlist[1] = (INT16) bounds.y1 - sy; 1474642e01fSmrg mask = CWX | CWY; 1484642e01fSmrg 1494642e01fSmrg /* pretend we're the owner of the window! */ 1504642e01fSmrg err = dixLookupClient(&pClient, pWin->drawable.id, NullClient, DixUnknownAccess); 1514642e01fSmrg if(err != Success) { 1524642e01fSmrg ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id); 1534642e01fSmrg return; 1544642e01fSmrg } 1554642e01fSmrg 1564642e01fSmrg /* Don't want to do anything to the physical window (avoids 1574642e01fSmrg notification-response feedback loops) */ 1584642e01fSmrg 1594642e01fSmrg no_configure_window = TRUE; 1604642e01fSmrg ConfigureWindow (pWin, mask, vlist, pClient); 1614642e01fSmrg no_configure_window = FALSE; 1624642e01fSmrg} 1634642e01fSmrg 1644642e01fSmrg/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */ 1654642e01fSmrgstatic void 1664642e01fSmrgset_screen_origin (WindowPtr pWin) 1674642e01fSmrg{ 1684642e01fSmrg long data[2]; 1694642e01fSmrg 1704642e01fSmrg if (!IsRoot (pWin)) 1714642e01fSmrg return; 1724642e01fSmrg 1734642e01fSmrg /* FIXME: move this to an extension? */ 1744642e01fSmrg 1754642e01fSmrg data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x 1764642e01fSmrg + darwinMainScreenX); 1774642e01fSmrg data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y 1784642e01fSmrg + darwinMainScreenY); 1794642e01fSmrg 1804642e01fSmrg dixChangeWindowProperty(serverClient, pWin, xa_native_screen_origin(), 1814642e01fSmrg XA_INTEGER, 32, PropModeReplace, 2, data, TRUE); 1824642e01fSmrg} 18305b261ecSmrg 18405b261ecSmrg/* 18505b261ecSmrg * RootlessCreateWindow 18605b261ecSmrg * For now, don't create a physical window until either the window is 18705b261ecSmrg * realized, or we really need it (e.g. to attach VRAM surfaces to). 18805b261ecSmrg * Do reset the window size so it's not clipped by the root window. 18905b261ecSmrg */ 19005b261ecSmrgBool 19105b261ecSmrgRootlessCreateWindow(WindowPtr pWin) 19205b261ecSmrg{ 19305b261ecSmrg Bool result; 19405b261ecSmrg RegionRec saveRoot; 19505b261ecSmrg 1964642e01fSmrg SETWINREC(pWin, NULL); 1974642e01fSmrg dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); 19805b261ecSmrg 19905b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); 20005b261ecSmrg 20105b261ecSmrg if (!IsRoot(pWin)) { 20205b261ecSmrg /* win/border size set by DIX, not by wrapped CreateWindow, so 20305b261ecSmrg correct it here. Don't HUGE_ROOT when pWin is the root! */ 20405b261ecSmrg 20505b261ecSmrg HUGE_ROOT(pWin); 20605b261ecSmrg SetWinSize(pWin); 20705b261ecSmrg SetBorderSize(pWin); 20805b261ecSmrg } 20905b261ecSmrg 21005b261ecSmrg result = pWin->drawable.pScreen->CreateWindow(pWin); 21105b261ecSmrg 21205b261ecSmrg if (pWin->parent) { 21305b261ecSmrg NORMAL_ROOT(pWin); 21405b261ecSmrg } 21505b261ecSmrg 21605b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); 21705b261ecSmrg 21805b261ecSmrg return result; 21905b261ecSmrg} 22005b261ecSmrg 22105b261ecSmrg 22205b261ecSmrg/* 22305b261ecSmrg * RootlessDestroyFrame 22405b261ecSmrg * Destroy the physical window associated with the given window. 22505b261ecSmrg */ 22605b261ecSmrgstatic void 22705b261ecSmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) 22805b261ecSmrg{ 22905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 23005b261ecSmrg 23105b261ecSmrg SCREENREC(pScreen)->imp->DestroyFrame(winRec->wid); 23205b261ecSmrg 23305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 23405b261ecSmrg REGION_UNINIT(pScreen, &winRec->damage); 23505b261ecSmrg#endif 23605b261ecSmrg 23705b261ecSmrg xfree(winRec); 2384642e01fSmrg SETWINREC(pWin, NULL); 23905b261ecSmrg} 24005b261ecSmrg 24105b261ecSmrg 24205b261ecSmrg/* 24305b261ecSmrg * RootlessDestroyWindow 24405b261ecSmrg * Destroy the physical window associated with the given window. 24505b261ecSmrg */ 24605b261ecSmrgBool 24705b261ecSmrgRootlessDestroyWindow(WindowPtr pWin) 24805b261ecSmrg{ 24905b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 25005b261ecSmrg Bool result; 25105b261ecSmrg 25205b261ecSmrg if (winRec != NULL) { 25305b261ecSmrg RootlessDestroyFrame(pWin, winRec); 25405b261ecSmrg } 25505b261ecSmrg 25605b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); 25705b261ecSmrg result = pWin->drawable.pScreen->DestroyWindow(pWin); 25805b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); 25905b261ecSmrg 26005b261ecSmrg return result; 26105b261ecSmrg} 26205b261ecSmrg 26305b261ecSmrg 26405b261ecSmrg 26505b261ecSmrgstatic Bool 26605b261ecSmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape) 26705b261ecSmrg{ 26805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 26905b261ecSmrg 2704642e01fSmrg /* 2714642e01fSmrg * Avoid a warning. 2724642e01fSmrg * REGION_NULL and the other macros don't actually seem to use pScreen. 2734642e01fSmrg */ 2744642e01fSmrg (void)pScreen; 2754642e01fSmrg 27605b261ecSmrg if (wBoundingShape(pWin) == NULL) 27705b261ecSmrg return FALSE; 27805b261ecSmrg 27905b261ecSmrg /* wBoundingShape is relative to *inner* origin of window. 28005b261ecSmrg Translate by borderWidth to get the outside-relative position. */ 28105b261ecSmrg 28205b261ecSmrg REGION_NULL(pScreen, pShape); 28305b261ecSmrg REGION_COPY(pScreen, pShape, wBoundingShape(pWin)); 28405b261ecSmrg REGION_TRANSLATE(pScreen, pShape, pWin->borderWidth, pWin->borderWidth); 28505b261ecSmrg 28605b261ecSmrg return TRUE; 28705b261ecSmrg} 28805b261ecSmrg 28905b261ecSmrg 29005b261ecSmrg/* 29105b261ecSmrg * RootlessReshapeFrame 29205b261ecSmrg * Set the frame shape. 29305b261ecSmrg */ 29405b261ecSmrgstatic void RootlessReshapeFrame(WindowPtr pWin) 29505b261ecSmrg{ 29605b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 29705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 29805b261ecSmrg RegionRec newShape; 29905b261ecSmrg RegionPtr pShape; 30005b261ecSmrg 30105b261ecSmrg // If the window is not yet framed, do nothing 30205b261ecSmrg if (winRec == NULL) 30305b261ecSmrg return; 30405b261ecSmrg 30505b261ecSmrg if (IsRoot(pWin)) 30605b261ecSmrg return; 30705b261ecSmrg 30805b261ecSmrg RootlessStopDrawing(pWin, FALSE); 30905b261ecSmrg 31005b261ecSmrg pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; 31105b261ecSmrg 31205b261ecSmrg#ifdef ROOTLESSDEBUG 31305b261ecSmrg RL_DEBUG_MSG("reshaping..."); 31405b261ecSmrg if (pShape != NULL) { 31505b261ecSmrg RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", 31605b261ecSmrg REGION_NUM_RECTS(&newShape), 31705b261ecSmrg newShape.extents.x1, newShape.extents.y1, 31805b261ecSmrg newShape.extents.x2, newShape.extents.y2); 31905b261ecSmrg } else { 32005b261ecSmrg RL_DEBUG_MSG("no shape "); 32105b261ecSmrg } 32205b261ecSmrg#endif 32305b261ecSmrg 32405b261ecSmrg SCREENREC(pScreen)->imp->ReshapeFrame(winRec->wid, pShape); 32505b261ecSmrg 32605b261ecSmrg if (pShape != NULL) 32705b261ecSmrg REGION_UNINIT(pScreen, &newShape); 32805b261ecSmrg} 32905b261ecSmrg 33005b261ecSmrg 33105b261ecSmrg/* 33205b261ecSmrg * RootlessSetShape 33305b261ecSmrg * Shape is usually set before a window is mapped and the window will 33405b261ecSmrg * not have a frame associated with it. In this case, the frame will be 33505b261ecSmrg * shaped when the window is framed. 33605b261ecSmrg */ 33705b261ecSmrgvoid 33805b261ecSmrgRootlessSetShape(WindowPtr pWin) 33905b261ecSmrg{ 34005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 34105b261ecSmrg 34205b261ecSmrg SCREEN_UNWRAP(pScreen, SetShape); 34305b261ecSmrg pScreen->SetShape(pWin); 34405b261ecSmrg SCREEN_WRAP(pScreen, SetShape); 34505b261ecSmrg 34605b261ecSmrg RootlessReshapeFrame(pWin); 34705b261ecSmrg} 34805b261ecSmrg 34905b261ecSmrg 35005b261ecSmrg 35105b261ecSmrg/* Disallow ParentRelative background on top-level windows 3524642e01fSmrg because the root window doesn't really have the right background. 3534642e01fSmrg */ 35405b261ecSmrgBool 35505b261ecSmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) 35605b261ecSmrg{ 35705b261ecSmrg Bool result; 35805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 35905b261ecSmrg 36005b261ecSmrg RL_DEBUG_MSG("change window attributes start "); 36105b261ecSmrg 36205b261ecSmrg SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); 36305b261ecSmrg result = pScreen->ChangeWindowAttributes(pWin, vmask); 36405b261ecSmrg SCREEN_WRAP(pScreen, ChangeWindowAttributes); 36505b261ecSmrg 36605b261ecSmrg if (WINREC(pWin)) { 36705b261ecSmrg // disallow ParentRelative background state 36805b261ecSmrg if (pWin->backgroundState == ParentRelative) { 36905b261ecSmrg XID pixel = 0; 37005b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 37105b261ecSmrg } 37205b261ecSmrg } 37305b261ecSmrg 37405b261ecSmrg RL_DEBUG_MSG("change window attributes end\n"); 37505b261ecSmrg return result; 37605b261ecSmrg} 37705b261ecSmrg 37805b261ecSmrg 37905b261ecSmrg/* 38005b261ecSmrg * RootlessPositionWindow 38105b261ecSmrg * This is a hook for when DIX moves or resizes a window. 38205b261ecSmrg * Update the frame position now although the physical window is moved 38305b261ecSmrg * in RootlessMoveWindow. (x, y) are *inside* position. After this, 38405b261ecSmrg * mi and fb are expecting the pixmap to be at the new location. 38505b261ecSmrg */ 38605b261ecSmrgBool 38705b261ecSmrgRootlessPositionWindow(WindowPtr pWin, int x, int y) 38805b261ecSmrg{ 38905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 39005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 39105b261ecSmrg Bool result; 39205b261ecSmrg 39305b261ecSmrg RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); 39405b261ecSmrg 39505b261ecSmrg if (winRec) { 39605b261ecSmrg if (winRec->is_drawing) { 39705b261ecSmrg // Reset frame's pixmap and move it to the new position. 39805b261ecSmrg int bw = wBorderWidth(pWin); 39905b261ecSmrg 40005b261ecSmrg winRec->pixmap->devPrivate.ptr = winRec->pixelData; 40105b261ecSmrg SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); 40205b261ecSmrg 40305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 40405b261ecSmrg // Move damaged region to correspond to new window position 40505b261ecSmrg if (REGION_NOTEMPTY(pScreen, &winRec->damage)) { 40605b261ecSmrg REGION_TRANSLATE(pScreen, &winRec->damage, 40705b261ecSmrg x - bw - winRec->x, 40805b261ecSmrg y - bw - winRec->y); 40905b261ecSmrg } 41005b261ecSmrg#endif 41105b261ecSmrg } 41205b261ecSmrg } 41305b261ecSmrg 41405b261ecSmrg SCREEN_UNWRAP(pScreen, PositionWindow); 41505b261ecSmrg result = pScreen->PositionWindow(pWin, x, y); 41605b261ecSmrg SCREEN_WRAP(pScreen, PositionWindow); 41705b261ecSmrg 41805b261ecSmrg RL_DEBUG_MSG("positionwindow end\n"); 41905b261ecSmrg return result; 42005b261ecSmrg} 42105b261ecSmrg 42205b261ecSmrg 42305b261ecSmrg/* 42405b261ecSmrg * RootlessInitializeFrame 42505b261ecSmrg * Initialize some basic attributes of the frame. Note that winRec 42605b261ecSmrg * may already have valid data in it, so don't overwrite anything 42705b261ecSmrg * valuable. 42805b261ecSmrg */ 42905b261ecSmrgstatic void 43005b261ecSmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) 43105b261ecSmrg{ 43205b261ecSmrg DrawablePtr d = &pWin->drawable; 43305b261ecSmrg int bw = wBorderWidth(pWin); 43405b261ecSmrg 43505b261ecSmrg winRec->win = pWin; 43605b261ecSmrg 43705b261ecSmrg winRec->x = d->x - bw; 43805b261ecSmrg winRec->y = d->y - bw; 43905b261ecSmrg winRec->width = d->width + 2*bw; 44005b261ecSmrg winRec->height = d->height + 2*bw; 44105b261ecSmrg winRec->borderWidth = bw; 44205b261ecSmrg 44305b261ecSmrg#ifdef ROOTLESS_TRACK_DAMAGE 44405b261ecSmrg REGION_NULL(pScreen, &winRec->damage); 44505b261ecSmrg#endif 44605b261ecSmrg} 44705b261ecSmrg 44805b261ecSmrg 4494642e01fSmrgBool 4504642e01fSmrgRootlessColormapCallback (void *data, int first_color, int n_colors, uint32_t *colors) 4514642e01fSmrg{ 4524642e01fSmrg return (RootlessResolveColormap (data, first_color, n_colors, colors) ? XP_Success : XP_BadMatch); 4534642e01fSmrg} 4544642e01fSmrg 45505b261ecSmrg/* 45605b261ecSmrg * RootlessEnsureFrame 45705b261ecSmrg * Make sure the given window is framed. If the window doesn't have a 45805b261ecSmrg * physical window associated with it, attempt to create one. If that 45905b261ecSmrg * is unsuccessful, return NULL. 46005b261ecSmrg */ 46105b261ecSmrgstatic RootlessWindowRec * 46205b261ecSmrgRootlessEnsureFrame(WindowPtr pWin) 46305b261ecSmrg{ 46405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 46505b261ecSmrg RootlessWindowRec *winRec; 46605b261ecSmrg RegionRec shape; 46705b261ecSmrg RegionPtr pShape = NULL; 46805b261ecSmrg 46905b261ecSmrg if (WINREC(pWin) != NULL) 47005b261ecSmrg return WINREC(pWin); 47105b261ecSmrg 4724642e01fSmrg if (!IsTopLevel(pWin) && !IsRoot(pWin)) 47305b261ecSmrg return NULL; 47405b261ecSmrg 47505b261ecSmrg if (pWin->drawable.class != InputOutput) 47605b261ecSmrg return NULL; 47705b261ecSmrg 47805b261ecSmrg winRec = xalloc(sizeof(RootlessWindowRec)); 47905b261ecSmrg 48005b261ecSmrg if (!winRec) 48105b261ecSmrg return NULL; 48205b261ecSmrg 48305b261ecSmrg RootlessInitializeFrame(pWin, winRec); 48405b261ecSmrg 48505b261ecSmrg winRec->is_drawing = FALSE; 48605b261ecSmrg winRec->is_reorder_pending = FALSE; 48705b261ecSmrg winRec->pixmap = NULL; 48805b261ecSmrg winRec->wid = NULL; 48905b261ecSmrg 4904642e01fSmrg SETWINREC(pWin, winRec); 49105b261ecSmrg 49205b261ecSmrg // Set the frame's shape if the window is shaped 49305b261ecSmrg if (RootlessGetShape(pWin, &shape)) 49405b261ecSmrg pShape = &shape; 49505b261ecSmrg 49605b261ecSmrg RL_DEBUG_MSG("creating frame "); 49705b261ecSmrg 49805b261ecSmrg if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, 49905b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 50005b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 50105b261ecSmrg pShape)) 50205b261ecSmrg { 50305b261ecSmrg RL_DEBUG_MSG("implementation failed to create frame!\n"); 50405b261ecSmrg xfree(winRec); 5054642e01fSmrg SETWINREC(pWin, NULL); 50605b261ecSmrg return NULL; 50705b261ecSmrg } 50805b261ecSmrg 5094642e01fSmrg if (pWin->drawable.depth == 8) 5104642e01fSmrg RootlessFlushWindowColormap(pWin); 5114642e01fSmrg 51205b261ecSmrg if (pShape != NULL) 51305b261ecSmrg REGION_UNINIT(pScreen, &shape); 51405b261ecSmrg 51505b261ecSmrg return winRec; 51605b261ecSmrg} 51705b261ecSmrg 51805b261ecSmrg 51905b261ecSmrg/* 52005b261ecSmrg * RootlessRealizeWindow 52105b261ecSmrg * The frame is usually created here and not in CreateWindow so that 52205b261ecSmrg * windows do not eat memory until they are realized. 52305b261ecSmrg */ 52405b261ecSmrgBool 52505b261ecSmrgRootlessRealizeWindow(WindowPtr pWin) 52605b261ecSmrg{ 52705b261ecSmrg Bool result; 52805b261ecSmrg RegionRec saveRoot; 52905b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 53005b261ecSmrg 53105b261ecSmrg RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); 53205b261ecSmrg 53305b261ecSmrg if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { 53405b261ecSmrg RootlessWindowRec *winRec; 53505b261ecSmrg 53605b261ecSmrg winRec = RootlessEnsureFrame(pWin); 53705b261ecSmrg if (winRec == NULL) 53805b261ecSmrg return FALSE; 53905b261ecSmrg 54005b261ecSmrg winRec->is_reorder_pending = TRUE; 54105b261ecSmrg 54205b261ecSmrg RL_DEBUG_MSG("Top level window "); 54305b261ecSmrg 54405b261ecSmrg // Disallow ParentRelative background state on top-level windows. 54505b261ecSmrg // This might have been set before the window was mapped. 54605b261ecSmrg if (pWin->backgroundState == ParentRelative) { 54705b261ecSmrg XID pixel = 0; 54805b261ecSmrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 54905b261ecSmrg } 55005b261ecSmrg } 55105b261ecSmrg 55205b261ecSmrg if (!IsRoot(pWin)) HUGE_ROOT(pWin); 55305b261ecSmrg SCREEN_UNWRAP(pScreen, RealizeWindow); 55405b261ecSmrg result = pScreen->RealizeWindow(pWin); 55505b261ecSmrg SCREEN_WRAP(pScreen, RealizeWindow); 55605b261ecSmrg if (!IsRoot(pWin)) NORMAL_ROOT(pWin); 55705b261ecSmrg 55805b261ecSmrg RL_DEBUG_MSG("realizewindow end\n"); 55905b261ecSmrg return result; 56005b261ecSmrg} 56105b261ecSmrg 56205b261ecSmrg 56305b261ecSmrg/* 56405b261ecSmrg * RootlessFrameForWindow 56505b261ecSmrg * Returns the frame ID for the physical window displaying the given window. 56605b261ecSmrg * If CREATE is true and the window has no frame, attempt to create one. 56705b261ecSmrg */ 56805b261ecSmrgRootlessFrameID 56905b261ecSmrgRootlessFrameForWindow(WindowPtr pWin, Bool create) 57005b261ecSmrg{ 57105b261ecSmrg WindowPtr pTopWin; 57205b261ecSmrg RootlessWindowRec *winRec; 57305b261ecSmrg 57405b261ecSmrg pTopWin = TopLevelParent(pWin); 57505b261ecSmrg if (pTopWin == NULL) 57605b261ecSmrg return NULL; 57705b261ecSmrg 57805b261ecSmrg winRec = WINREC(pTopWin); 57905b261ecSmrg 58005b261ecSmrg if (winRec == NULL && create && pWin->drawable.class == InputOutput) { 58105b261ecSmrg winRec = RootlessEnsureFrame(pTopWin); 58205b261ecSmrg } 58305b261ecSmrg 58405b261ecSmrg if (winRec == NULL) 58505b261ecSmrg return NULL; 58605b261ecSmrg 58705b261ecSmrg return winRec->wid; 58805b261ecSmrg} 58905b261ecSmrg 59005b261ecSmrg 59105b261ecSmrg/* 59205b261ecSmrg * RootlessUnrealizeWindow 59305b261ecSmrg * Unmap the physical window. 59405b261ecSmrg */ 59505b261ecSmrgBool 59605b261ecSmrgRootlessUnrealizeWindow(WindowPtr pWin) 59705b261ecSmrg{ 59805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 59905b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 60005b261ecSmrg Bool result; 60105b261ecSmrg 60205b261ecSmrg RL_DEBUG_MSG("unrealizewindow start "); 60305b261ecSmrg 60405b261ecSmrg if (winRec) { 60505b261ecSmrg RootlessStopDrawing(pWin, FALSE); 60605b261ecSmrg 60705b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 60805b261ecSmrg 60905b261ecSmrg winRec->is_reorder_pending = FALSE; 61005b261ecSmrg } 61105b261ecSmrg 61205b261ecSmrg SCREEN_UNWRAP(pScreen, UnrealizeWindow); 61305b261ecSmrg result = pScreen->UnrealizeWindow(pWin); 61405b261ecSmrg SCREEN_WRAP(pScreen, UnrealizeWindow); 61505b261ecSmrg 61605b261ecSmrg RL_DEBUG_MSG("unrealizewindow end\n"); 61705b261ecSmrg return result; 61805b261ecSmrg} 61905b261ecSmrg 62005b261ecSmrg 62105b261ecSmrg/* 62205b261ecSmrg * RootlessReorderWindow 62305b261ecSmrg * Reorder the frame associated with the given window so that it's 62405b261ecSmrg * physically above the window below it in the X stacking order. 62505b261ecSmrg */ 62605b261ecSmrgvoid 62705b261ecSmrgRootlessReorderWindow(WindowPtr pWin) 62805b261ecSmrg{ 62905b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 63005b261ecSmrg 6314642e01fSmrg if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) { 63205b261ecSmrg WindowPtr newPrevW; 63305b261ecSmrg RootlessWindowRec *newPrev; 63405b261ecSmrg RootlessFrameID newPrevID; 63505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 63605b261ecSmrg 63705b261ecSmrg /* Check if the implementation wants the frame to not be reordered 63805b261ecSmrg even though the X11 window is restacked. This can be useful if 63905b261ecSmrg frames are ordered-in with animation so that the reordering is not 64005b261ecSmrg done until the animation is complete. */ 64105b261ecSmrg if (SCREENREC(pScreen)->imp->DoReorderWindow) { 64205b261ecSmrg if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) 64305b261ecSmrg return; 64405b261ecSmrg } 64505b261ecSmrg 64605b261ecSmrg RootlessStopDrawing(pWin, FALSE); 64705b261ecSmrg 64805b261ecSmrg /* Find the next window above this one that has a mapped frame. */ 64905b261ecSmrg 65005b261ecSmrg newPrevW = pWin->prevSib; 65105b261ecSmrg while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized)) 65205b261ecSmrg newPrevW = newPrevW->prevSib; 65305b261ecSmrg 65405b261ecSmrg newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; 65505b261ecSmrg newPrevID = newPrev != NULL ? newPrev->wid : 0; 65605b261ecSmrg 65705b261ecSmrg /* If it exists, reorder the frame above us first. */ 65805b261ecSmrg 65905b261ecSmrg if (newPrev && newPrev->is_reorder_pending) { 66005b261ecSmrg newPrev->is_reorder_pending = FALSE; 66105b261ecSmrg RootlessReorderWindow(newPrevW); 66205b261ecSmrg } 66305b261ecSmrg 66405b261ecSmrg SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); 66505b261ecSmrg } 66605b261ecSmrg} 66705b261ecSmrg 66805b261ecSmrg 66905b261ecSmrg/* 67005b261ecSmrg * RootlessRestackWindow 67105b261ecSmrg * This is a hook for when DIX changes the window stacking order. 67205b261ecSmrg * The window has already been inserted into its new position in the 67305b261ecSmrg * DIX window stack. We need to change the order of the physical 67405b261ecSmrg * window to match. 67505b261ecSmrg */ 67605b261ecSmrgvoid 67705b261ecSmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) 67805b261ecSmrg{ 67905b261ecSmrg RegionRec saveRoot; 68005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 68105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 68205b261ecSmrg 68305b261ecSmrg RL_DEBUG_MSG("restackwindow start "); 68405b261ecSmrg if (winRec) 68505b261ecSmrg RL_DEBUG_MSG("restack top level \n"); 68605b261ecSmrg 68705b261ecSmrg HUGE_ROOT(pWin); 68805b261ecSmrg SCREEN_UNWRAP(pScreen, RestackWindow); 68905b261ecSmrg 69005b261ecSmrg if (pScreen->RestackWindow) 69105b261ecSmrg pScreen->RestackWindow(pWin, pOldNextSib); 69205b261ecSmrg 69305b261ecSmrg SCREEN_WRAP(pScreen, RestackWindow); 69405b261ecSmrg NORMAL_ROOT(pWin); 69505b261ecSmrg 69605b261ecSmrg if (winRec && pWin->viewable) { 69705b261ecSmrg RootlessReorderWindow(pWin); 69805b261ecSmrg } 69905b261ecSmrg 70005b261ecSmrg RL_DEBUG_MSG("restackwindow end\n"); 70105b261ecSmrg} 70205b261ecSmrg 70305b261ecSmrg/* 70405b261ecSmrg * Specialized window copy procedures 70505b261ecSmrg */ 70605b261ecSmrg 70705b261ecSmrg// Globals needed during window resize and move. 70805b261ecSmrgstatic pointer gResizeDeathBits = NULL; 70905b261ecSmrgstatic int gResizeDeathCount = 0; 71005b261ecSmrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; 71105b261ecSmrgstatic BoxRec gResizeDeathBounds[2]; 71205b261ecSmrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; 71305b261ecSmrg 71405b261ecSmrg/* 71505b261ecSmrg * RootlessNoCopyWindow 71605b261ecSmrg * CopyWindow() that doesn't do anything. For MoveWindow() of 71705b261ecSmrg * top-level windows. 71805b261ecSmrg */ 71905b261ecSmrgstatic void 72005b261ecSmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 72105b261ecSmrg RegionPtr prgnSrc) 72205b261ecSmrg{ 72305b261ecSmrg // some code expects the region to be translated 72405b261ecSmrg int dx = ptOldOrg.x - pWin->drawable.x; 72505b261ecSmrg int dy = ptOldOrg.y - pWin->drawable.y; 72605b261ecSmrg 72705b261ecSmrg RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); 72805b261ecSmrg 72905b261ecSmrg REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy); 73005b261ecSmrg} 73105b261ecSmrg 73205b261ecSmrg 73305b261ecSmrg/* 73405b261ecSmrg * RootlessResizeCopyWindow 73505b261ecSmrg * CopyWindow used during ResizeWindow for gravity moves. Based on 73605b261ecSmrg * fbCopyWindow. The original always draws on the root pixmap, which 73705b261ecSmrg * we don't have. Instead, draw on the parent window's pixmap. 73805b261ecSmrg * Resize version: the old location's pixels are in gResizeCopyWindowSource. 73905b261ecSmrg */ 74005b261ecSmrgstatic void 74105b261ecSmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 74205b261ecSmrg RegionPtr prgnSrc) 74305b261ecSmrg{ 74405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 74505b261ecSmrg RegionRec rgnDst; 74605b261ecSmrg int dx, dy; 74705b261ecSmrg 74805b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); 74905b261ecSmrg 75005b261ecSmrg /* Don't unwrap pScreen->CopyWindow. 75105b261ecSmrg The bogus rewrap with RootlessCopyWindow causes a crash if 75205b261ecSmrg CopyWindow is called again during the same resize. */ 75305b261ecSmrg 75405b261ecSmrg if (gResizeDeathCount == 0) 75505b261ecSmrg return; 75605b261ecSmrg 75705b261ecSmrg RootlessStartDrawing(pWin); 75805b261ecSmrg 75905b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 76005b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 76105b261ecSmrg REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); 76205b261ecSmrg REGION_NULL(pScreen, &rgnDst); 76305b261ecSmrg REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); 76405b261ecSmrg 76505b261ecSmrg if (gResizeDeathCount == 1) { 76605b261ecSmrg /* Simple case, we only have a single source pixmap. */ 76705b261ecSmrg 76805b261ecSmrg fbCopyRegion(&gResizeDeathPix[0]->drawable, 76905b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 77005b261ecSmrg &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 77105b261ecSmrg } 77205b261ecSmrg else { 77305b261ecSmrg int i; 77405b261ecSmrg RegionRec clip, clipped; 77505b261ecSmrg 77605b261ecSmrg /* More complex case, N source pixmaps (usually two). So we 77705b261ecSmrg intersect the destination with each source and copy those bits. */ 77805b261ecSmrg 77905b261ecSmrg for (i = 0; i < gResizeDeathCount; i++) { 78005b261ecSmrg REGION_INIT(pScreen, &clip, gResizeDeathBounds + 0, 1); 78105b261ecSmrg REGION_NULL(pScreen, &clipped); 78205b261ecSmrg REGION_INTERSECT(pScreen, &rgnDst, &clip, &clipped); 78305b261ecSmrg 78405b261ecSmrg fbCopyRegion(&gResizeDeathPix[i]->drawable, 78505b261ecSmrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 78605b261ecSmrg &clipped, dx, dy, fbCopyWindowProc, 0, 0); 78705b261ecSmrg 78805b261ecSmrg REGION_UNINIT(pScreen, &clipped); 78905b261ecSmrg REGION_UNINIT(pScreen, &clip); 79005b261ecSmrg } 79105b261ecSmrg } 79205b261ecSmrg 79305b261ecSmrg /* Don't update - resize will update everything */ 79405b261ecSmrg REGION_UNINIT(pScreen, &rgnDst); 79505b261ecSmrg 79605b261ecSmrg fbValidateDrawable(&pWin->drawable); 79705b261ecSmrg 79805b261ecSmrg RL_DEBUG_MSG("resizecopywindowFB end\n"); 79905b261ecSmrg} 80005b261ecSmrg 80105b261ecSmrg 80205b261ecSmrg/* 80305b261ecSmrg * RootlessCopyWindow 80405b261ecSmrg * Update *new* location of window. Old location is redrawn with 8054642e01fSmrg * miPaintWindow. Cloned from fbCopyWindow. 80605b261ecSmrg * The original always draws on the root pixmap, which we don't have. 80705b261ecSmrg * Instead, draw on the parent window's pixmap. 80805b261ecSmrg */ 80905b261ecSmrgvoid 81005b261ecSmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 81105b261ecSmrg{ 81205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 81305b261ecSmrg RegionRec rgnDst; 81405b261ecSmrg int dx, dy; 81505b261ecSmrg BoxPtr extents; 81605b261ecSmrg int area; 81705b261ecSmrg 81805b261ecSmrg RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); 81905b261ecSmrg 82005b261ecSmrg SCREEN_UNWRAP(pScreen, CopyWindow); 82105b261ecSmrg 82205b261ecSmrg dx = ptOldOrg.x - pWin->drawable.x; 82305b261ecSmrg dy = ptOldOrg.y - pWin->drawable.y; 82405b261ecSmrg REGION_TRANSLATE(pScreen, prgnSrc, -dx, -dy); 82505b261ecSmrg 82605b261ecSmrg REGION_NULL(pScreen, &rgnDst); 82705b261ecSmrg REGION_INTERSECT(pScreen, &rgnDst, &pWin->borderClip, prgnSrc); 82805b261ecSmrg 82905b261ecSmrg extents = REGION_EXTENTS(pScreen, &rgnDst); 83005b261ecSmrg area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); 83105b261ecSmrg 83205b261ecSmrg /* If the area exceeds threshold, use the implementation's 83305b261ecSmrg accelerated version. */ 83405b261ecSmrg if (area > rootless_CopyWindow_threshold && 83505b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow) 83605b261ecSmrg { 83705b261ecSmrg RootlessWindowRec *winRec; 83805b261ecSmrg WindowPtr top; 83905b261ecSmrg 84005b261ecSmrg top = TopLevelParent(pWin); 84105b261ecSmrg if (top == NULL) { 84205b261ecSmrg RL_DEBUG_MSG("no parent\n"); 8434642e01fSmrg goto out; 84405b261ecSmrg } 84505b261ecSmrg 84605b261ecSmrg winRec = WINREC(top); 84705b261ecSmrg if (winRec == NULL) { 84805b261ecSmrg RL_DEBUG_MSG("not framed\n"); 8494642e01fSmrg goto out; 85005b261ecSmrg } 85105b261ecSmrg 85205b261ecSmrg /* Move region to window local coords */ 85305b261ecSmrg REGION_TRANSLATE(pScreen, &rgnDst, -winRec->x, -winRec->y); 85405b261ecSmrg 85505b261ecSmrg RootlessStopDrawing(pWin, FALSE); 85605b261ecSmrg 85705b261ecSmrg SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, 85805b261ecSmrg REGION_NUM_RECTS(&rgnDst), 85905b261ecSmrg REGION_RECTS(&rgnDst), 86005b261ecSmrg dx, dy); 86105b261ecSmrg } 86205b261ecSmrg else { 86305b261ecSmrg RootlessStartDrawing(pWin); 86405b261ecSmrg 86505b261ecSmrg fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, 86605b261ecSmrg 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 86705b261ecSmrg 86805b261ecSmrg /* prgnSrc has been translated to dst position */ 86905b261ecSmrg RootlessDamageRegion(pWin, prgnSrc); 87005b261ecSmrg } 87105b261ecSmrg 8724642e01fSmrgout: 87305b261ecSmrg REGION_UNINIT(pScreen, &rgnDst); 87405b261ecSmrg fbValidateDrawable(&pWin->drawable); 87505b261ecSmrg 87605b261ecSmrg SCREEN_WRAP(pScreen, CopyWindow); 87705b261ecSmrg 87805b261ecSmrg RL_DEBUG_MSG("copywindowFB end\n"); 87905b261ecSmrg} 88005b261ecSmrg 88105b261ecSmrg 88205b261ecSmrg/* 88305b261ecSmrg * Window resize procedures 88405b261ecSmrg */ 88505b261ecSmrg 88605b261ecSmrgenum { 88705b261ecSmrg WIDTH_SMALLER = 1, 88805b261ecSmrg HEIGHT_SMALLER = 2, 88905b261ecSmrg}; 89005b261ecSmrg 89105b261ecSmrg 89205b261ecSmrg/* 89305b261ecSmrg * ResizeWeighting 89405b261ecSmrg * Choose gravity to avoid local copies. Do that by looking for 89505b261ecSmrg * a corner that doesn't move _relative to the screen_. 89605b261ecSmrg */ 89705b261ecSmrgstatic inline unsigned int 89805b261ecSmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, 89905b261ecSmrg int newX1, int newY1, int newX2, int newY2, int newBW) 90005b261ecSmrg{ 90105b261ecSmrg#ifdef ROOTLESS_RESIZE_GRAVITY 90205b261ecSmrg if (newBW != oldBW) 90305b261ecSmrg return RL_GRAVITY_NONE; 90405b261ecSmrg 90505b261ecSmrg if (newX1 == oldX1 && newY1 == oldY1) 90605b261ecSmrg return RL_GRAVITY_NORTH_WEST; 90705b261ecSmrg else if (newX1 == oldX1 && newY2 == oldY2) 90805b261ecSmrg return RL_GRAVITY_SOUTH_WEST; 90905b261ecSmrg else if (newX2 == oldX2 && newY2 == oldY2) 91005b261ecSmrg return RL_GRAVITY_SOUTH_EAST; 91105b261ecSmrg else if (newX2 == oldX2 && newY1 == oldY1) 91205b261ecSmrg return RL_GRAVITY_NORTH_EAST; 91305b261ecSmrg else 91405b261ecSmrg return RL_GRAVITY_NONE; 91505b261ecSmrg#else 91605b261ecSmrg return RL_GRAVITY_NONE; 91705b261ecSmrg#endif 91805b261ecSmrg} 91905b261ecSmrg 92005b261ecSmrg 92105b261ecSmrg/* 92205b261ecSmrg * StartFrameResize 92305b261ecSmrg * Prepare to resize a top-level window. The old window's pixels are 92405b261ecSmrg * saved and the implementation is told to change the window size. 92505b261ecSmrg * (x,y,w,h) is outer frame of window (outside border) 92605b261ecSmrg */ 92705b261ecSmrgstatic Bool 92805b261ecSmrgStartFrameResize(WindowPtr pWin, Bool gravity, 92905b261ecSmrg int oldX, int oldY, int oldW, int oldH, int oldBW, 93005b261ecSmrg int newX, int newY, int newW, int newH, int newBW) 93105b261ecSmrg{ 93205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 93305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 93405b261ecSmrg Bool need_window_source = FALSE, resize_after = FALSE; 93505b261ecSmrg 93605b261ecSmrg BoxRec rect; 93705b261ecSmrg int oldX2, newX2; 93805b261ecSmrg int oldY2, newY2; 93905b261ecSmrg unsigned int weight; 94005b261ecSmrg 94105b261ecSmrg oldX2 = oldX + oldW, newX2 = newX + newW; 94205b261ecSmrg oldY2 = oldY + oldH, newY2 = newY + newH; 94305b261ecSmrg 94405b261ecSmrg /* Decide which resize weighting to use */ 94505b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 94605b261ecSmrg newX, newY, newW, newH, newBW); 94705b261ecSmrg 94805b261ecSmrg /* Compute intersection between old and new rects */ 94905b261ecSmrg rect.x1 = max(oldX, newX); 95005b261ecSmrg rect.y1 = max(oldY, newY); 95105b261ecSmrg rect.x2 = min(oldX2, newX2); 95205b261ecSmrg rect.y2 = min(oldY2, newY2); 95305b261ecSmrg 95405b261ecSmrg RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); 95505b261ecSmrg RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", 95605b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 95705b261ecSmrg newX, newY, newW, newH, newBW); 95805b261ecSmrg 95905b261ecSmrg RootlessRedisplay(pWin); 96005b261ecSmrg 96105b261ecSmrg /* If gravity is true, then we need to have a way of recovering all 96205b261ecSmrg the original bits in the window for when X rearranges the contents 96305b261ecSmrg based on the various gravity settings. The obvious way is to just 96405b261ecSmrg snapshot the entire backing store before resizing it, but that 96505b261ecSmrg it slow on large windows. 96605b261ecSmrg 96705b261ecSmrg So the optimization here is to use the implementation's resize 96805b261ecSmrg weighting options (if available) to allow us to reason about what 96905b261ecSmrg is left in the backing store after the resize. We can then only 97005b261ecSmrg copy what won't be there after the resize, and do a two-stage copy 97105b261ecSmrg operation. 97205b261ecSmrg 97305b261ecSmrg Most of these optimizations are only applied when the top-left 97405b261ecSmrg corner of the window is fixed, since that's the common case. They 97505b261ecSmrg could probably be extended with some thought. */ 97605b261ecSmrg 97705b261ecSmrg gResizeDeathCount = 0; 97805b261ecSmrg 97905b261ecSmrg if (gravity && weight == RL_GRAVITY_NORTH_WEST) { 98005b261ecSmrg unsigned int code = 0; 98105b261ecSmrg 98205b261ecSmrg /* Top left corner is anchored. We never need to copy the 98305b261ecSmrg entire window. */ 98405b261ecSmrg 98505b261ecSmrg need_window_source = TRUE; 98605b261ecSmrg 98705b261ecSmrg /* These comparisons were chosen to avoid setting bits when the sizes 98805b261ecSmrg are the same. (So the fastest case automatically gets taken when 98905b261ecSmrg dimensions are unchanging.) */ 99005b261ecSmrg 99105b261ecSmrg if (newW < oldW) 99205b261ecSmrg code |= WIDTH_SMALLER; 99305b261ecSmrg if (newH < oldH) 99405b261ecSmrg code |= HEIGHT_SMALLER; 99505b261ecSmrg 99605b261ecSmrg if (((code ^ (code >> 1)) & 1) == 0) { 99705b261ecSmrg /* Both dimensions are either getting larger, or both 99805b261ecSmrg are getting smaller. No need to copy anything. */ 99905b261ecSmrg 100005b261ecSmrg if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { 100105b261ecSmrg /* Since the window is getting smaller, we can do gravity 100205b261ecSmrg repair on it with it's current size, then resize it 100305b261ecSmrg afterwards. */ 100405b261ecSmrg 100505b261ecSmrg resize_after = TRUE; 100605b261ecSmrg } 100705b261ecSmrg 100805b261ecSmrg gResizeDeathCount = 1; 100905b261ecSmrg } 101005b261ecSmrg else { 101105b261ecSmrg unsigned int copy_rowbytes, Bpp; 101205b261ecSmrg unsigned int copy_rect_width, copy_rect_height; 101305b261ecSmrg BoxRec copy_rect; 101405b261ecSmrg 101505b261ecSmrg /* We can get away with a partial copy. 'rect' is the 101605b261ecSmrg intersection between old and new bounds, so copy 101705b261ecSmrg everything to the right of or below the intersection. */ 101805b261ecSmrg 101905b261ecSmrg RootlessStartDrawing(pWin); 102005b261ecSmrg 102105b261ecSmrg if (code == WIDTH_SMALLER) { 102205b261ecSmrg copy_rect.x1 = rect.x2; 102305b261ecSmrg copy_rect.y1 = rect.y1; 102405b261ecSmrg copy_rect.x2 = oldX2; 102505b261ecSmrg copy_rect.y2 = oldY2; 102605b261ecSmrg } 102705b261ecSmrg else if (code == HEIGHT_SMALLER) { 102805b261ecSmrg copy_rect.x1 = rect.x1; 102905b261ecSmrg copy_rect.y1 = rect.y2; 103005b261ecSmrg copy_rect.x2 = oldX2; 103105b261ecSmrg copy_rect.y2 = oldY2; 103205b261ecSmrg } 103305b261ecSmrg else 103405b261ecSmrg abort(); 103505b261ecSmrg 103605b261ecSmrg Bpp = winRec->win->drawable.bitsPerPixel / 8; 103705b261ecSmrg copy_rect_width = copy_rect.x2 - copy_rect.x1; 103805b261ecSmrg copy_rect_height = copy_rect.y2 - copy_rect.y1; 103905b261ecSmrg copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; 104005b261ecSmrg gResizeDeathBits = xalloc(copy_rowbytes 104105b261ecSmrg * copy_rect_height); 104205b261ecSmrg 104305b261ecSmrg if (copy_rect_width * copy_rect_height > 104405b261ecSmrg rootless_CopyBytes_threshold && 104505b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes) 104605b261ecSmrg { 104705b261ecSmrg SCREENREC(pScreen)->imp->CopyBytes( 104805b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 104905b261ecSmrg ((char *) winRec->pixelData) 105005b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 105105b261ecSmrg + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, 105205b261ecSmrg gResizeDeathBits, copy_rowbytes); 105305b261ecSmrg } else { 105405b261ecSmrg fbBlt((FbBits *) (winRec->pixelData 105505b261ecSmrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 105605b261ecSmrg + (copy_rect.x1 - oldX) * Bpp), 105705b261ecSmrg winRec->bytesPerRow / sizeof(FbBits), 0, 105805b261ecSmrg (FbBits *) gResizeDeathBits, 105905b261ecSmrg copy_rowbytes / sizeof(FbBits), 0, 106005b261ecSmrg copy_rect_width * Bpp, copy_rect_height, 106105b261ecSmrg GXcopy, FB_ALLONES, Bpp, 0, 0); 106205b261ecSmrg } 106305b261ecSmrg 106405b261ecSmrg gResizeDeathBounds[1] = copy_rect; 106505b261ecSmrg gResizeDeathPix[1] 106605b261ecSmrg = GetScratchPixmapHeader(pScreen, copy_rect_width, 106705b261ecSmrg copy_rect_height, 106805b261ecSmrg winRec->win->drawable.depth, 106905b261ecSmrg winRec->win->drawable.bitsPerPixel, 107005b261ecSmrg winRec->bytesPerRow, 107105b261ecSmrg (void *) gResizeDeathBits); 107205b261ecSmrg 107305b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[1], 107405b261ecSmrg copy_rect.x1, copy_rect.y1); 107505b261ecSmrg 107605b261ecSmrg gResizeDeathCount = 2; 107705b261ecSmrg } 107805b261ecSmrg } 107905b261ecSmrg else if (gravity) { 108005b261ecSmrg /* The general case. Just copy everything. */ 108105b261ecSmrg 108205b261ecSmrg RootlessStartDrawing(pWin); 108305b261ecSmrg 108405b261ecSmrg gResizeDeathBits = xalloc(winRec->bytesPerRow * winRec->height); 108505b261ecSmrg 108605b261ecSmrg memcpy(gResizeDeathBits, winRec->pixelData, 108705b261ecSmrg winRec->bytesPerRow * winRec->height); 108805b261ecSmrg 108905b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 109005b261ecSmrg gResizeDeathPix[0] 109105b261ecSmrg = GetScratchPixmapHeader(pScreen, winRec->width, 109205b261ecSmrg winRec->height, 109305b261ecSmrg winRec->win->drawable.depth, 109405b261ecSmrg winRec->win->drawable.bitsPerPixel, 109505b261ecSmrg winRec->bytesPerRow, 109605b261ecSmrg (void *) gResizeDeathBits); 109705b261ecSmrg 109805b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 109905b261ecSmrg gResizeDeathCount = 1; 110005b261ecSmrg } 110105b261ecSmrg 110205b261ecSmrg RootlessStopDrawing(pWin, FALSE); 110305b261ecSmrg 110405b261ecSmrg winRec->x = newX; 110505b261ecSmrg winRec->y = newY; 110605b261ecSmrg winRec->width = newW; 110705b261ecSmrg winRec->height = newH; 110805b261ecSmrg winRec->borderWidth = newBW; 110905b261ecSmrg 111005b261ecSmrg /* Unless both dimensions are getting smaller, Resize the frame 111105b261ecSmrg before doing gravity repair */ 111205b261ecSmrg 111305b261ecSmrg if (!resize_after) { 111405b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 111505b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 111605b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 111705b261ecSmrg newW, newH, weight); 111805b261ecSmrg } 111905b261ecSmrg 112005b261ecSmrg RootlessStartDrawing(pWin); 112105b261ecSmrg 112205b261ecSmrg /* If necessary, create a source pixmap pointing at the current 112305b261ecSmrg window bits. */ 112405b261ecSmrg 112505b261ecSmrg if (need_window_source) { 112605b261ecSmrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 112705b261ecSmrg gResizeDeathPix[0] 112805b261ecSmrg = GetScratchPixmapHeader(pScreen, oldW, oldH, 112905b261ecSmrg winRec->win->drawable.depth, 113005b261ecSmrg winRec->win->drawable.bitsPerPixel, 113105b261ecSmrg winRec->bytesPerRow, winRec->pixelData); 113205b261ecSmrg 113305b261ecSmrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 113405b261ecSmrg } 113505b261ecSmrg 113605b261ecSmrg /* Use custom CopyWindow when moving gravity bits around 113705b261ecSmrg ResizeWindow assumes the old window contents are in the same 113805b261ecSmrg pixmap, but here they're in deathPix instead. */ 113905b261ecSmrg 114005b261ecSmrg if (gravity) { 114105b261ecSmrg gResizeOldCopyWindowProc = pScreen->CopyWindow; 114205b261ecSmrg pScreen->CopyWindow = RootlessResizeCopyWindow; 114305b261ecSmrg } 114405b261ecSmrg 114505b261ecSmrg /* If we can't rely on the window server preserving the bits we 114605b261ecSmrg need in the position we need, copy the pixels in the 114705b261ecSmrg intersection from src to dst. ResizeWindow assumes these pixels 114805b261ecSmrg are already present when making gravity adjustments. pWin 114905b261ecSmrg currently has new-sized pixmap but is in old position. 115005b261ecSmrg 115105b261ecSmrg FIXME: border width change! (?) */ 115205b261ecSmrg 115305b261ecSmrg if (gravity && weight == RL_GRAVITY_NONE) { 115405b261ecSmrg PixmapPtr src, dst; 115505b261ecSmrg 115605b261ecSmrg assert(gResizeDeathCount == 1); 115705b261ecSmrg 115805b261ecSmrg src = gResizeDeathPix[0]; 115905b261ecSmrg dst = pScreen->GetWindowPixmap(pWin); 116005b261ecSmrg 116105b261ecSmrg RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", 116205b261ecSmrg rect.x1, rect.y1, rect.x2, rect.y2); 116305b261ecSmrg 116405b261ecSmrg /* rect is the intersection of the old location and new location */ 116505b261ecSmrg if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { 116605b261ecSmrg /* The window drawable still has the old frame position, which 116705b261ecSmrg means that DST doesn't actually point at the origin of our 116805b261ecSmrg physical backing store when adjusted by the drawable.x,y 116905b261ecSmrg position. So sneakily adjust it temporarily while copying.. */ 117005b261ecSmrg 117105b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 117205b261ecSmrg SetPixmapBaseToScreen(dst, newX, newY); 117305b261ecSmrg 117405b261ecSmrg fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, 117505b261ecSmrg &rect, 1, 0, 0, FALSE, FALSE, 0, 0); 117605b261ecSmrg 117705b261ecSmrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 117805b261ecSmrg SetPixmapBaseToScreen(dst, oldX, oldY); 117905b261ecSmrg } 118005b261ecSmrg } 118105b261ecSmrg 118205b261ecSmrg return resize_after; 118305b261ecSmrg} 118405b261ecSmrg 118505b261ecSmrg 118605b261ecSmrgstatic void 118705b261ecSmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, 118805b261ecSmrg unsigned int oldW, unsigned int oldH, unsigned int oldBW, 118905b261ecSmrg int newX, int newY, unsigned int newW, unsigned int newH, 119005b261ecSmrg unsigned int newBW, Bool resize_now) 119105b261ecSmrg{ 119205b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 119305b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 119405b261ecSmrg int i; 119505b261ecSmrg 119605b261ecSmrg RootlessStopDrawing(pWin, FALSE); 119705b261ecSmrg 119805b261ecSmrg if (resize_now) { 119905b261ecSmrg unsigned int weight; 120005b261ecSmrg 120105b261ecSmrg /* We didn't resize anything earlier, so do it now, now that 120205b261ecSmrg we've finished gravitating the bits. */ 120305b261ecSmrg 120405b261ecSmrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 120505b261ecSmrg newX, newY, newW, newH, newBW); 120605b261ecSmrg 120705b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 120805b261ecSmrg newX + SCREEN_TO_GLOBAL_X, 120905b261ecSmrg newY + SCREEN_TO_GLOBAL_Y, 121005b261ecSmrg newW, newH, weight); 121105b261ecSmrg } 121205b261ecSmrg 121305b261ecSmrg /* Redraw everything. FIXME: there must be times when we don't need 121405b261ecSmrg to do this. Perhaps when top-left weighting and no gravity? */ 121505b261ecSmrg 121605b261ecSmrg RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); 121705b261ecSmrg 121805b261ecSmrg for (i = 0; i < 2; i++) { 121905b261ecSmrg if (gResizeDeathPix[i] != NULL) { 122005b261ecSmrg FreeScratchPixmapHeader(gResizeDeathPix[i]); 122105b261ecSmrg gResizeDeathPix[i] = NULL; 122205b261ecSmrg } 122305b261ecSmrg } 122405b261ecSmrg 122505b261ecSmrg if (gResizeDeathBits != NULL) { 122605b261ecSmrg xfree(gResizeDeathBits); 122705b261ecSmrg gResizeDeathBits = NULL; 122805b261ecSmrg } 122905b261ecSmrg 123005b261ecSmrg if (gravity) { 123105b261ecSmrg pScreen->CopyWindow = gResizeOldCopyWindowProc; 123205b261ecSmrg } 123305b261ecSmrg} 123405b261ecSmrg 123505b261ecSmrg 123605b261ecSmrg/* 123705b261ecSmrg * RootlessMoveWindow 123805b261ecSmrg * If kind==VTOther, window border is resizing (and borderWidth is 123905b261ecSmrg * already changed!!@#$) This case works like window resize, not move. 124005b261ecSmrg */ 124105b261ecSmrgvoid 124205b261ecSmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 124305b261ecSmrg{ 124405b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 124505b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 124605b261ecSmrg CopyWindowProcPtr oldCopyWindowProc = NULL; 124705b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 124805b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 124905b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 125005b261ecSmrg Bool resize_after = FALSE; 125105b261ecSmrg RegionRec saveRoot; 125205b261ecSmrg 125305b261ecSmrg RL_DEBUG_MSG("movewindow start \n"); 125405b261ecSmrg 125505b261ecSmrg if (winRec) { 125605b261ecSmrg if (kind == VTMove) { 125705b261ecSmrg oldX = winRec->x; 125805b261ecSmrg oldY = winRec->y; 125905b261ecSmrg RootlessRedisplay(pWin); 126005b261ecSmrg RootlessStartDrawing(pWin); 126105b261ecSmrg } else { 126205b261ecSmrg RL_DEBUG_MSG("movewindow border resizing "); 126305b261ecSmrg 126405b261ecSmrg oldBW = winRec->borderWidth; 126505b261ecSmrg oldX = winRec->x; 126605b261ecSmrg oldY = winRec->y; 126705b261ecSmrg oldW = winRec->width; 126805b261ecSmrg oldH = winRec->height; 126905b261ecSmrg 127005b261ecSmrg newBW = wBorderWidth(pWin); 127105b261ecSmrg newX = x; 127205b261ecSmrg newY = y; 127305b261ecSmrg newW = pWin->drawable.width + 2*newBW; 127405b261ecSmrg newH = pWin->drawable.height + 2*newBW; 127505b261ecSmrg 127605b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 127705b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 127805b261ecSmrg newX, newY, newW, newH, newBW); 127905b261ecSmrg } 128005b261ecSmrg } 128105b261ecSmrg 128205b261ecSmrg HUGE_ROOT(pWin); 128305b261ecSmrg SCREEN_UNWRAP(pScreen, MoveWindow); 128405b261ecSmrg 128505b261ecSmrg if (winRec) { 128605b261ecSmrg oldCopyWindowProc = pScreen->CopyWindow; 128705b261ecSmrg pScreen->CopyWindow = RootlessNoCopyWindow; 128805b261ecSmrg } 128905b261ecSmrg pScreen->MoveWindow(pWin, x, y, pSib, kind); 129005b261ecSmrg if (winRec) { 129105b261ecSmrg pScreen->CopyWindow = oldCopyWindowProc; 129205b261ecSmrg } 129305b261ecSmrg 129405b261ecSmrg NORMAL_ROOT(pWin); 129505b261ecSmrg SCREEN_WRAP(pScreen, MoveWindow); 129605b261ecSmrg 129705b261ecSmrg if (winRec) { 129805b261ecSmrg if (kind == VTMove) { 129905b261ecSmrg winRec->x = x; 130005b261ecSmrg winRec->y = y; 130105b261ecSmrg RootlessStopDrawing(pWin, FALSE); 130205b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 130305b261ecSmrg x + SCREEN_TO_GLOBAL_X, 130405b261ecSmrg y + SCREEN_TO_GLOBAL_Y); 130505b261ecSmrg } else { 130605b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 130705b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 130805b261ecSmrg } 130905b261ecSmrg } 131005b261ecSmrg 131105b261ecSmrg RL_DEBUG_MSG("movewindow end\n"); 131205b261ecSmrg} 131305b261ecSmrg 131405b261ecSmrg 131505b261ecSmrg/* 131605b261ecSmrg * RootlessResizeWindow 131705b261ecSmrg * Note: (x, y, w, h) as passed to this procedure don't match the frame 131805b261ecSmrg * definition. (x,y) is corner of very outer edge, *outside* border. 131905b261ecSmrg * w,h is width and height *inside* border, *ignoring* border width. 132005b261ecSmrg * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) 132105b261ecSmrg * is total rect and (x+bw, y+bw, w, h) is inner rect. 132205b261ecSmrg */ 132305b261ecSmrgvoid 132405b261ecSmrgRootlessResizeWindow(WindowPtr pWin, int x, int y, 132505b261ecSmrg unsigned int w, unsigned int h, WindowPtr pSib) 132605b261ecSmrg{ 132705b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 132805b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 132905b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 133005b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; 133105b261ecSmrg Bool resize_after = FALSE; 133205b261ecSmrg RegionRec saveRoot; 133305b261ecSmrg 133405b261ecSmrg RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); 13354642e01fSmrg 13364642e01fSmrg if(pWin->parent) { 13374642e01fSmrg if (winRec) { 13384642e01fSmrg oldBW = winRec->borderWidth; 13394642e01fSmrg oldX = winRec->x; 13404642e01fSmrg oldY = winRec->y; 13414642e01fSmrg oldW = winRec->width; 13424642e01fSmrg oldH = winRec->height; 134305b261ecSmrg 13444642e01fSmrg newBW = oldBW; 13454642e01fSmrg newX = x; 13464642e01fSmrg newY = y; 13474642e01fSmrg newW = w + 2*newBW; 13484642e01fSmrg newH = h + 2*newBW; 134905b261ecSmrg 13504642e01fSmrg resize_after = StartFrameResize(pWin, TRUE, 13514642e01fSmrg oldX, oldY, oldW, oldH, oldBW, 13524642e01fSmrg newX, newY, newW, newH, newBW); 13534642e01fSmrg } 135405b261ecSmrg 13554642e01fSmrg HUGE_ROOT(pWin); 13564642e01fSmrg SCREEN_UNWRAP(pScreen, ResizeWindow); 13574642e01fSmrg pScreen->ResizeWindow(pWin, x, y, w, h, pSib); 13584642e01fSmrg SCREEN_WRAP(pScreen, ResizeWindow); 13594642e01fSmrg NORMAL_ROOT(pWin); 13604642e01fSmrg 13614642e01fSmrg if (winRec) { 13624642e01fSmrg FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, 13634642e01fSmrg newX, newY, newW, newH, newBW, resize_after); 13644642e01fSmrg } 13654642e01fSmrg } else { 13664642e01fSmrg /* Special case for resizing the root window */ 13674642e01fSmrg BoxRec box; 13684642e01fSmrg 13694642e01fSmrg pWin->drawable.x = x; 13704642e01fSmrg pWin->drawable.y = y; 13714642e01fSmrg pWin->drawable.width = w; 13724642e01fSmrg pWin->drawable.height = h; 13734642e01fSmrg 13744642e01fSmrg box.x1 = x; box.y1 = y; 13754642e01fSmrg box.x2 = x + w; box.y2 = y + h; 13764642e01fSmrg REGION_UNINIT(pScreen, &pWin->winSize); 13774642e01fSmrg REGION_INIT(pScreen, &pWin->winSize, &box, 1); 13784642e01fSmrg REGION_COPY(pScreen, &pWin->borderSize, &pWin->winSize); 13794642e01fSmrg REGION_COPY(pScreen, &pWin->clipList, &pWin->winSize); 13804642e01fSmrg REGION_COPY(pScreen, &pWin->borderClip, &pWin->winSize); 13814642e01fSmrg 13824642e01fSmrg miSendExposures(pWin, &pWin->borderClip, 13834642e01fSmrg pWin->drawable.x, pWin->drawable.y); 138405b261ecSmrg } 138505b261ecSmrg 138605b261ecSmrg RL_DEBUG_MSG("resizewindow end\n"); 138705b261ecSmrg} 138805b261ecSmrg 138905b261ecSmrg 139005b261ecSmrg/* 139105b261ecSmrg * RootlessRepositionWindow 139205b261ecSmrg * Called by the implementation when a window needs to be repositioned to 139305b261ecSmrg * its correct location on the screen. This routine is typically needed 139405b261ecSmrg * due to changes in the underlying window system, such as a screen layout 139505b261ecSmrg * change. 139605b261ecSmrg */ 139705b261ecSmrgvoid 139805b261ecSmrgRootlessRepositionWindow(WindowPtr pWin) 139905b261ecSmrg{ 140005b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 140105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 140205b261ecSmrg 140305b261ecSmrg if (winRec == NULL) 140405b261ecSmrg return; 140505b261ecSmrg 140605b261ecSmrg RootlessStopDrawing(pWin, FALSE); 140705b261ecSmrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 140805b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 140905b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y); 141005b261ecSmrg 141105b261ecSmrg RootlessReorderWindow(pWin); 141205b261ecSmrg} 141305b261ecSmrg 141405b261ecSmrg 141505b261ecSmrg/* 141605b261ecSmrg * RootlessReparentWindow 141705b261ecSmrg * Called after a window has been reparented. Generally windows are not 141805b261ecSmrg * framed until they are mapped. However, a window may be framed early by the 141905b261ecSmrg * implementation calling RootlessFrameForWindow. (e.g. this could be needed 142005b261ecSmrg * to attach a VRAM surface to it.) If the window is subsequently reparented 142105b261ecSmrg * by the window manager before being mapped, we need to give the frame to 142205b261ecSmrg * the new top-level window. 142305b261ecSmrg */ 142405b261ecSmrgvoid 142505b261ecSmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 142605b261ecSmrg{ 142705b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 142805b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 142905b261ecSmrg WindowPtr pTopWin; 143005b261ecSmrg 143105b261ecSmrg /* Check that window is not top-level now, but used to be. */ 143205b261ecSmrg if (IsRoot(pWin) || IsRoot(pWin->parent) 143305b261ecSmrg || IsTopLevel(pWin) || winRec == NULL) 143405b261ecSmrg { 143505b261ecSmrg goto out; 143605b261ecSmrg } 143705b261ecSmrg 143805b261ecSmrg /* If the formerly top-level window has a frame, we want to give the 143905b261ecSmrg frame to its new top-level parent. If we can't do that, we'll just 144005b261ecSmrg have to jettison it... */ 144105b261ecSmrg 144205b261ecSmrg pTopWin = TopLevelParent(pWin); 144305b261ecSmrg assert(pTopWin != pWin); 14444642e01fSmrg 14454642e01fSmrg pWin->rootlessUnhittable = FALSE; 14464642e01fSmrg 14474642e01fSmrg DeleteProperty (serverClient, pWin, xa_native_window_id ()); 144805b261ecSmrg 144905b261ecSmrg if (WINREC(pTopWin) != NULL) { 145005b261ecSmrg /* We're screwed. */ 145105b261ecSmrg RootlessDestroyFrame(pWin, winRec); 145205b261ecSmrg } else { 145305b261ecSmrg if (!pTopWin->realized && pWin->realized) { 145405b261ecSmrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 145505b261ecSmrg } 145605b261ecSmrg 145705b261ecSmrg /* Switch the frame record from one to the other. */ 145805b261ecSmrg 14594642e01fSmrg SETWINREC(pWin, NULL); 14604642e01fSmrg SETWINREC(pTopWin, winRec); 146105b261ecSmrg 146205b261ecSmrg RootlessInitializeFrame(pTopWin, winRec); 146305b261ecSmrg RootlessReshapeFrame(pTopWin); 146405b261ecSmrg 146505b261ecSmrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 146605b261ecSmrg winRec->x + SCREEN_TO_GLOBAL_X, 146705b261ecSmrg winRec->y + SCREEN_TO_GLOBAL_Y, 146805b261ecSmrg winRec->width, winRec->height, 146905b261ecSmrg RL_GRAVITY_NONE); 147005b261ecSmrg 147105b261ecSmrg if (SCREENREC(pScreen)->imp->SwitchWindow) { 147205b261ecSmrg SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); 147305b261ecSmrg } 147405b261ecSmrg 147505b261ecSmrg if (pTopWin->realized && !pWin->realized) 147605b261ecSmrg winRec->is_reorder_pending = TRUE; 147705b261ecSmrg } 147805b261ecSmrg 147905b261ecSmrgout: 148005b261ecSmrg if (SCREENREC(pScreen)->ReparentWindow) { 148105b261ecSmrg SCREEN_UNWRAP(pScreen, ReparentWindow); 148205b261ecSmrg pScreen->ReparentWindow(pWin, pPriorParent); 148305b261ecSmrg SCREEN_WRAP(pScreen, ReparentWindow); 148405b261ecSmrg } 148505b261ecSmrg} 148605b261ecSmrg 148705b261ecSmrg 148805b261ecSmrgvoid 14894642e01fSmrgRootlessFlushWindowColormap (WindowPtr pWin) 149005b261ecSmrg{ 14914642e01fSmrg RootlessWindowRec *winRec = WINREC (pWin); 14924642e01fSmrg xp_window_changes wc; 149305b261ecSmrg 14944642e01fSmrg if (winRec == NULL) 14954642e01fSmrg return; 149605b261ecSmrg 14974642e01fSmrg RootlessStopDrawing (pWin, FALSE); 149805b261ecSmrg 14994642e01fSmrg /* This is how we tell xp that the colormap may have changed. */ 150005b261ecSmrg 15014642e01fSmrg wc.colormap = RootlessColormapCallback; 15024642e01fSmrg wc.colormap_data = pWin->drawable.pScreen; 150305b261ecSmrg 15044642e01fSmrg configure_window (MAKE_WINDOW_ID(winRec->wid), XP_COLORMAP, &wc); 150505b261ecSmrg} 150605b261ecSmrg 150705b261ecSmrg/* 150805b261ecSmrg * RootlessChangeBorderWidth 150905b261ecSmrg * FIXME: untested! 151005b261ecSmrg * pWin inside corner stays the same; pWin->drawable.[xy] stays the same 151105b261ecSmrg * Frame moves and resizes. 151205b261ecSmrg */ 151305b261ecSmrgvoid 151405b261ecSmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) 151505b261ecSmrg{ 151605b261ecSmrg RegionRec saveRoot; 151705b261ecSmrg Bool resize_after = FALSE; 151805b261ecSmrg 151905b261ecSmrg RL_DEBUG_MSG("change border width "); 152005b261ecSmrg 152105b261ecSmrg if (width != wBorderWidth(pWin)) { 152205b261ecSmrg RootlessWindowRec *winRec = WINREC(pWin); 152305b261ecSmrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 152405b261ecSmrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 152505b261ecSmrg unsigned int newW = 0, newH = 0, newBW = 0; 152605b261ecSmrg 152705b261ecSmrg if (winRec) { 152805b261ecSmrg oldBW = winRec->borderWidth; 152905b261ecSmrg oldX = winRec->x; 153005b261ecSmrg oldY = winRec->y; 153105b261ecSmrg oldW = winRec->width; 153205b261ecSmrg oldH = winRec->height; 153305b261ecSmrg 153405b261ecSmrg newBW = width; 153505b261ecSmrg newX = pWin->drawable.x - newBW; 153605b261ecSmrg newY = pWin->drawable.y - newBW; 153705b261ecSmrg newW = pWin->drawable.width + 2*newBW; 153805b261ecSmrg newH = pWin->drawable.height + 2*newBW; 153905b261ecSmrg 154005b261ecSmrg resize_after = StartFrameResize(pWin, FALSE, 154105b261ecSmrg oldX, oldY, oldW, oldH, oldBW, 154205b261ecSmrg newX, newY, newW, newH, newBW); 154305b261ecSmrg } 154405b261ecSmrg 154505b261ecSmrg HUGE_ROOT(pWin); 154605b261ecSmrg SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); 154705b261ecSmrg pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); 154805b261ecSmrg SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); 154905b261ecSmrg NORMAL_ROOT(pWin); 155005b261ecSmrg 155105b261ecSmrg if (winRec) { 155205b261ecSmrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 155305b261ecSmrg newX, newY, newW, newH, newBW, resize_after); 155405b261ecSmrg } 155505b261ecSmrg } 155605b261ecSmrg 155705b261ecSmrg RL_DEBUG_MSG("change border width end\n"); 155805b261ecSmrg} 15594642e01fSmrg 15604642e01fSmrg/* 15614642e01fSmrg * RootlessOrderAllWindows 15624642e01fSmrg * Brings all X11 windows to the top of the window stack 15634642e01fSmrg * (i.e in front of Aqua windows) -- called when X11.app is given focus 15644642e01fSmrg */ 15654642e01fSmrgvoid 15664642e01fSmrgRootlessOrderAllWindows (void) 15674642e01fSmrg{ 15684642e01fSmrg int i; 15694642e01fSmrg WindowPtr pWin; 15704642e01fSmrg 15714642e01fSmrg if (windows_hidden) 15724642e01fSmrg return; 15734642e01fSmrg 15744642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() "); 15754642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) { 15764642e01fSmrg if (screenInfo.screens[i] == NULL) continue; 15774642e01fSmrg pWin = WindowTable[i]; 15784642e01fSmrg if (pWin == NULL) continue; 15794642e01fSmrg 15804642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 15814642e01fSmrg if (!pWin->realized) continue; 15824642e01fSmrg if (RootlessEnsureFrame(pWin) == NULL) continue; 15834642e01fSmrg RootlessReorderWindow (pWin); 15844642e01fSmrg } 15854642e01fSmrg } 15864642e01fSmrg RL_DEBUG_MSG("RootlessOrderAllWindows() done"); 15874642e01fSmrg} 15884642e01fSmrg 15894642e01fSmrgvoid 15904642e01fSmrgRootlessEnableRoot (ScreenPtr pScreen) 15914642e01fSmrg{ 15924642e01fSmrg WindowPtr pRoot; 15934642e01fSmrg pRoot = WindowTable[pScreen->myNum]; 15944642e01fSmrg 15954642e01fSmrg RootlessEnsureFrame (pRoot); 15964642e01fSmrg (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); 15974642e01fSmrg RootlessReorderWindow (pRoot); 15984642e01fSmrg} 15994642e01fSmrg 16004642e01fSmrgvoid 16014642e01fSmrgRootlessDisableRoot (ScreenPtr pScreen) 16024642e01fSmrg{ 16034642e01fSmrg WindowPtr pRoot; 16044642e01fSmrg RootlessWindowRec *winRec; 16054642e01fSmrg 16064642e01fSmrg pRoot = WindowTable[pScreen->myNum]; 16074642e01fSmrg winRec = WINREC (pRoot); 16084642e01fSmrg 16094642e01fSmrg if (NULL == winRec) 16104642e01fSmrg return; 16114642e01fSmrg 16124642e01fSmrg RootlessDestroyFrame (pRoot, winRec); 16134642e01fSmrg /* 16144642e01fSmrg * gstaplin: I fixed the usage of this DeleteProperty so that it would compile. 16154642e01fSmrg * QUESTION: Where is this xa_native_window_id set? 16164642e01fSmrg */ 16174642e01fSmrg DeleteProperty (serverClient, pRoot, xa_native_window_id ()); 16184642e01fSmrg} 16194642e01fSmrg 16204642e01fSmrgvoid 16214642e01fSmrgRootlessHideAllWindows (void) 16224642e01fSmrg{ 16234642e01fSmrg int i; 16244642e01fSmrg ScreenPtr pScreen; 16254642e01fSmrg WindowPtr pWin; 16264642e01fSmrg RootlessWindowRec *winRec; 16274642e01fSmrg xp_window_changes wc; 16284642e01fSmrg 16294642e01fSmrg if (windows_hidden) 16304642e01fSmrg return; 16314642e01fSmrg 16324642e01fSmrg windows_hidden = TRUE; 16334642e01fSmrg 16344642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 16354642e01fSmrg { 16364642e01fSmrg pScreen = screenInfo.screens[i]; 16374642e01fSmrg pWin = WindowTable[i]; 16384642e01fSmrg if (pScreen == NULL || pWin == NULL) 16394642e01fSmrg continue; 16404642e01fSmrg 16414642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 16424642e01fSmrg { 16434642e01fSmrg if (!pWin->realized) 16444642e01fSmrg continue; 16454642e01fSmrg 16464642e01fSmrg RootlessStopDrawing (pWin, FALSE); 16474642e01fSmrg 16484642e01fSmrg winRec = WINREC (pWin); 16494642e01fSmrg if (winRec != NULL) 16504642e01fSmrg { 16514642e01fSmrg wc.stack_mode = XP_UNMAPPED; 16524642e01fSmrg wc.sibling = 0; 16534642e01fSmrg configure_window (MAKE_WINDOW_ID(winRec->wid), XP_STACKING, &wc); 16544642e01fSmrg } 16554642e01fSmrg } 16564642e01fSmrg } 16574642e01fSmrg} 16584642e01fSmrg 16594642e01fSmrgvoid 16604642e01fSmrgRootlessShowAllWindows (void) 16614642e01fSmrg{ 16624642e01fSmrg int i; 16634642e01fSmrg ScreenPtr pScreen; 16644642e01fSmrg WindowPtr pWin; 16654642e01fSmrg RootlessWindowRec *winRec; 16664642e01fSmrg 16674642e01fSmrg if (!windows_hidden) 16684642e01fSmrg return; 16694642e01fSmrg 16704642e01fSmrg windows_hidden = FALSE; 16714642e01fSmrg 16724642e01fSmrg for (i = 0; i < screenInfo.numScreens; i++) 16734642e01fSmrg { 16744642e01fSmrg pScreen = screenInfo.screens[i]; 16754642e01fSmrg pWin = WindowTable[i]; 16764642e01fSmrg if (pScreen == NULL || pWin == NULL) 16774642e01fSmrg continue; 16784642e01fSmrg 16794642e01fSmrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 16804642e01fSmrg { 16814642e01fSmrg if (!pWin->realized) 16824642e01fSmrg continue; 16834642e01fSmrg 16844642e01fSmrg winRec = RootlessEnsureFrame (pWin); 16854642e01fSmrg if (winRec == NULL) 16864642e01fSmrg continue; 16874642e01fSmrg 16884642e01fSmrg RootlessReorderWindow (pWin); 16894642e01fSmrg } 16904642e01fSmrg 16914642e01fSmrg RootlessScreenExpose (pScreen); 16924642e01fSmrg } 16934642e01fSmrg} 1694