1706f2543Smrg/* 2706f2543Smrg * Rootless window management 3706f2543Smrg */ 4706f2543Smrg/* 5706f2543Smrg * Copyright (c) 2001 Greg Parker. All Rights Reserved. 6706f2543Smrg * Copyright (c) 2002-2004 Torrey T. Lyons. All Rights Reserved. 7706f2543Smrg * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. 8706f2543Smrg * 9706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 10706f2543Smrg * copy of this software and associated documentation files (the "Software"), 11706f2543Smrg * to deal in the Software without restriction, including without limitation 12706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 14706f2543Smrg * Software is furnished to do so, subject to the following conditions: 15706f2543Smrg * 16706f2543Smrg * The above copyright notice and this permission notice shall be included in 17706f2543Smrg * all copies or substantial portions of the Software. 18706f2543Smrg * 19706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20706f2543Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22706f2543Smrg * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 23706f2543Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24706f2543Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25706f2543Smrg * DEALINGS IN THE SOFTWARE. 26706f2543Smrg * 27706f2543Smrg * Except as contained in this notice, the name(s) of the above copyright 28706f2543Smrg * holders shall not be used in advertising or otherwise to promote the sale, 29706f2543Smrg * use or other dealings in this Software without prior written authorization. 30706f2543Smrg */ 31706f2543Smrg 32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H 33706f2543Smrg#include <dix-config.h> 34706f2543Smrg#endif 35706f2543Smrg 36706f2543Smrg#include <stddef.h> /* For NULL */ 37706f2543Smrg#include <limits.h> /* For CHAR_BIT */ 38706f2543Smrg#include <assert.h> 39706f2543Smrg#include <X11/Xatom.h> 40706f2543Smrg#ifdef __APPLE__ 41706f2543Smrg#include <Xplugin.h> 42706f2543Smrg#include "mi.h" 43706f2543Smrg#include "pixmapstr.h" 44706f2543Smrg#include "windowstr.h" 45706f2543Smrg//#include <X11/extensions/applewm.h> 46706f2543Smrgextern int darwinMainScreenX, darwinMainScreenY; 47706f2543Smrgextern Bool no_configure_window; 48706f2543Smrg#endif 49706f2543Smrg#include "fb.h" 50706f2543Smrg 51706f2543Smrg#include "rootlessCommon.h" 52706f2543Smrg#include "rootlessWindow.h" 53706f2543Smrg 54706f2543Smrg#define SCREEN_TO_GLOBAL_X \ 55706f2543Smrg (pScreen->x + rootlessGlobalOffsetX) 56706f2543Smrg#define SCREEN_TO_GLOBAL_Y \ 57706f2543Smrg (pScreen->y + rootlessGlobalOffsetY) 58706f2543Smrg 59706f2543Smrg#define DEFINE_ATOM_HELPER(func,atom_name) \ 60706f2543Smrg static Atom func (void) { \ 61706f2543Smrg static unsigned int generation = 0; \ 62706f2543Smrg static Atom atom; \ 63706f2543Smrg if (generation != serverGeneration) { \ 64706f2543Smrg generation = serverGeneration; \ 65706f2543Smrg atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \ 66706f2543Smrg } \ 67706f2543Smrg return atom; \ 68706f2543Smrg } 69706f2543Smrg 70706f2543SmrgDEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID") 71706f2543Smrg 72706f2543Smrgstatic Bool windows_hidden; 73706f2543Smrg// TODO - abstract xp functions 74706f2543Smrg 75706f2543Smrg#ifdef __APPLE__ 76706f2543Smrg 77706f2543Smrg// XXX: identical to x_cvt_vptr_to_uint ? 78706f2543Smrg#define MAKE_WINDOW_ID(x) ((xp_window_id)((size_t)(x))) 79706f2543Smrg 80706f2543Smrgvoid 81706f2543SmrgRootlessNativeWindowStateChanged (WindowPtr pWin, unsigned int state) 82706f2543Smrg{ 83706f2543Smrg RootlessWindowRec *winRec; 84706f2543Smrg 85706f2543Smrg if (pWin == NULL) return; 86706f2543Smrg 87706f2543Smrg winRec = WINREC (pWin); 88706f2543Smrg if (winRec == NULL) return; 89706f2543Smrg 90706f2543Smrg winRec->is_offscreen = ((state & XP_WINDOW_STATE_OFFSCREEN) != 0); 91706f2543Smrg winRec->is_obscured = ((state & XP_WINDOW_STATE_OBSCURED) != 0); 92706f2543Smrg pWin->rootlessUnhittable = winRec->is_offscreen; 93706f2543Smrg} 94706f2543Smrg 95706f2543Smrgvoid RootlessNativeWindowMoved (WindowPtr pWin) { 96706f2543Smrg xp_box bounds; 97706f2543Smrg int sx, sy, err; 98706f2543Smrg XID vlist[2]; 99706f2543Smrg Mask mask; 100706f2543Smrg ClientPtr pClient; 101706f2543Smrg RootlessWindowRec *winRec; 102706f2543Smrg 103706f2543Smrg winRec = WINREC(pWin); 104706f2543Smrg 105706f2543Smrg if (xp_get_window_bounds (MAKE_WINDOW_ID(winRec->wid), &bounds) != Success) return; 106706f2543Smrg 107706f2543Smrg sx = pWin->drawable.pScreen->x + darwinMainScreenX; 108706f2543Smrg sy = pWin->drawable.pScreen->y + darwinMainScreenY; 109706f2543Smrg 110706f2543Smrg /* Fake up a ConfigureWindow packet to resize the window to the current bounds. */ 111706f2543Smrg vlist[0] = (INT16) bounds.x1 - sx; 112706f2543Smrg vlist[1] = (INT16) bounds.y1 - sy; 113706f2543Smrg mask = CWX | CWY; 114706f2543Smrg 115706f2543Smrg /* pretend we're the owner of the window! */ 116706f2543Smrg err = dixLookupClient(&pClient, pWin->drawable.id, serverClient, DixUnknownAccess); 117706f2543Smrg if(err != Success) { 118706f2543Smrg ErrorF("RootlessNativeWindowMoved(): Failed to lookup window: 0x%x\n", (unsigned int)pWin->drawable.id); 119706f2543Smrg return; 120706f2543Smrg } 121706f2543Smrg 122706f2543Smrg /* Don't want to do anything to the physical window (avoids 123706f2543Smrg notification-response feedback loops) */ 124706f2543Smrg 125706f2543Smrg no_configure_window = TRUE; 126706f2543Smrg ConfigureWindow (pWin, mask, vlist, pClient); 127706f2543Smrg no_configure_window = FALSE; 128706f2543Smrg} 129706f2543Smrg 130706f2543Smrg#endif /* __APPLE__ */ 131706f2543Smrg 132706f2543Smrg/* 133706f2543Smrg * RootlessCreateWindow 134706f2543Smrg * For now, don't create a physical window until either the window is 135706f2543Smrg * realized, or we really need it (e.g. to attach VRAM surfaces to). 136706f2543Smrg * Do reset the window size so it's not clipped by the root window. 137706f2543Smrg */ 138706f2543SmrgBool 139706f2543SmrgRootlessCreateWindow(WindowPtr pWin) 140706f2543Smrg{ 141706f2543Smrg Bool result; 142706f2543Smrg RegionRec saveRoot; 143706f2543Smrg 144706f2543Smrg SETWINREC(pWin, NULL); 145706f2543Smrg dixSetPrivate(&pWin->devPrivates, rootlessWindowOldPixmapPrivateKey, NULL); 146706f2543Smrg 147706f2543Smrg SCREEN_UNWRAP(pWin->drawable.pScreen, CreateWindow); 148706f2543Smrg 149706f2543Smrg if (!IsRoot(pWin)) { 150706f2543Smrg /* win/border size set by DIX, not by wrapped CreateWindow, so 151706f2543Smrg correct it here. Don't HUGE_ROOT when pWin is the root! */ 152706f2543Smrg 153706f2543Smrg HUGE_ROOT(pWin); 154706f2543Smrg SetWinSize(pWin); 155706f2543Smrg SetBorderSize(pWin); 156706f2543Smrg } 157706f2543Smrg 158706f2543Smrg result = pWin->drawable.pScreen->CreateWindow(pWin); 159706f2543Smrg 160706f2543Smrg if (pWin->parent) { 161706f2543Smrg NORMAL_ROOT(pWin); 162706f2543Smrg } 163706f2543Smrg 164706f2543Smrg SCREEN_WRAP(pWin->drawable.pScreen, CreateWindow); 165706f2543Smrg 166706f2543Smrg return result; 167706f2543Smrg} 168706f2543Smrg 169706f2543Smrg 170706f2543Smrg/* 171706f2543Smrg * RootlessDestroyFrame 172706f2543Smrg * Destroy the physical window associated with the given window. 173706f2543Smrg */ 174706f2543Smrgstatic void 175706f2543SmrgRootlessDestroyFrame(WindowPtr pWin, RootlessWindowPtr winRec) 176706f2543Smrg{ 177706f2543Smrg SCREENREC(pWin->drawable.pScreen)->imp->DestroyFrame(winRec->wid); 178706f2543Smrg free(winRec); 179706f2543Smrg SETWINREC(pWin, NULL); 180706f2543Smrg} 181706f2543Smrg 182706f2543Smrg 183706f2543Smrg/* 184706f2543Smrg * RootlessDestroyWindow 185706f2543Smrg * Destroy the physical window associated with the given window. 186706f2543Smrg */ 187706f2543SmrgBool 188706f2543SmrgRootlessDestroyWindow(WindowPtr pWin) 189706f2543Smrg{ 190706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 191706f2543Smrg Bool result; 192706f2543Smrg 193706f2543Smrg if (winRec != NULL) { 194706f2543Smrg RootlessDestroyFrame(pWin, winRec); 195706f2543Smrg } 196706f2543Smrg 197706f2543Smrg SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow); 198706f2543Smrg result = pWin->drawable.pScreen->DestroyWindow(pWin); 199706f2543Smrg SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow); 200706f2543Smrg 201706f2543Smrg return result; 202706f2543Smrg} 203706f2543Smrg 204706f2543Smrg 205706f2543Smrg 206706f2543Smrgstatic Bool 207706f2543SmrgRootlessGetShape(WindowPtr pWin, RegionPtr pShape) 208706f2543Smrg{ 209706f2543Smrg if (wBoundingShape(pWin) == NULL) 210706f2543Smrg return FALSE; 211706f2543Smrg 212706f2543Smrg /* wBoundingShape is relative to *inner* origin of window. 213706f2543Smrg Translate by borderWidth to get the outside-relative position. */ 214706f2543Smrg 215706f2543Smrg RegionNull(pShape); 216706f2543Smrg RegionCopy(pShape, wBoundingShape(pWin)); 217706f2543Smrg RegionTranslate(pShape, pWin->borderWidth, pWin->borderWidth); 218706f2543Smrg 219706f2543Smrg return TRUE; 220706f2543Smrg} 221706f2543Smrg 222706f2543Smrg 223706f2543Smrg/* 224706f2543Smrg * RootlessReshapeFrame 225706f2543Smrg * Set the frame shape. 226706f2543Smrg */ 227706f2543Smrgstatic void RootlessReshapeFrame(WindowPtr pWin) 228706f2543Smrg{ 229706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 230706f2543Smrg RegionRec newShape; 231706f2543Smrg RegionPtr pShape; 232706f2543Smrg 233706f2543Smrg // If the window is not yet framed, do nothing 234706f2543Smrg if (winRec == NULL) 235706f2543Smrg return; 236706f2543Smrg 237706f2543Smrg if (IsRoot(pWin)) 238706f2543Smrg return; 239706f2543Smrg 240706f2543Smrg RootlessStopDrawing(pWin, FALSE); 241706f2543Smrg 242706f2543Smrg pShape = RootlessGetShape(pWin, &newShape) ? &newShape : NULL; 243706f2543Smrg 244706f2543Smrg#ifdef ROOTLESSDEBUG 245706f2543Smrg RL_DEBUG_MSG("reshaping..."); 246706f2543Smrg if (pShape != NULL) { 247706f2543Smrg RL_DEBUG_MSG("numrects %d, extents %d %d %d %d ", 248706f2543Smrg RegionNumRects(&newShape), 249706f2543Smrg newShape.extents.x1, newShape.extents.y1, 250706f2543Smrg newShape.extents.x2, newShape.extents.y2); 251706f2543Smrg } else { 252706f2543Smrg RL_DEBUG_MSG("no shape "); 253706f2543Smrg } 254706f2543Smrg#endif 255706f2543Smrg 256706f2543Smrg SCREENREC(pWin->drawable.pScreen)->imp->ReshapeFrame(winRec->wid, pShape); 257706f2543Smrg 258706f2543Smrg if (pShape != NULL) 259706f2543Smrg RegionUninit(&newShape); 260706f2543Smrg} 261706f2543Smrg 262706f2543Smrg 263706f2543Smrg/* 264706f2543Smrg * RootlessSetShape 265706f2543Smrg * Shape is usually set before a window is mapped and the window will 266706f2543Smrg * not have a frame associated with it. In this case, the frame will be 267706f2543Smrg * shaped when the window is framed. 268706f2543Smrg */ 269706f2543Smrgvoid 270706f2543SmrgRootlessSetShape(WindowPtr pWin, int kind) 271706f2543Smrg{ 272706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 273706f2543Smrg 274706f2543Smrg SCREEN_UNWRAP(pScreen, SetShape); 275706f2543Smrg pScreen->SetShape(pWin, kind); 276706f2543Smrg SCREEN_WRAP(pScreen, SetShape); 277706f2543Smrg 278706f2543Smrg RootlessReshapeFrame(pWin); 279706f2543Smrg} 280706f2543Smrg 281706f2543Smrg 282706f2543Smrg 283706f2543Smrg/* Disallow ParentRelative background on top-level windows 284706f2543Smrg because the root window doesn't really have the right background. 285706f2543Smrg */ 286706f2543SmrgBool 287706f2543SmrgRootlessChangeWindowAttributes(WindowPtr pWin, unsigned long vmask) 288706f2543Smrg{ 289706f2543Smrg Bool result; 290706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 291706f2543Smrg 292706f2543Smrg RL_DEBUG_MSG("change window attributes start "); 293706f2543Smrg 294706f2543Smrg SCREEN_UNWRAP(pScreen, ChangeWindowAttributes); 295706f2543Smrg result = pScreen->ChangeWindowAttributes(pWin, vmask); 296706f2543Smrg SCREEN_WRAP(pScreen, ChangeWindowAttributes); 297706f2543Smrg 298706f2543Smrg if (WINREC(pWin)) { 299706f2543Smrg // disallow ParentRelative background state 300706f2543Smrg if (pWin->backgroundState == ParentRelative) { 301706f2543Smrg XID pixel = 0; 302706f2543Smrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 303706f2543Smrg } 304706f2543Smrg } 305706f2543Smrg 306706f2543Smrg RL_DEBUG_MSG("change window attributes end\n"); 307706f2543Smrg return result; 308706f2543Smrg} 309706f2543Smrg 310706f2543Smrg 311706f2543Smrg/* 312706f2543Smrg * RootlessPositionWindow 313706f2543Smrg * This is a hook for when DIX moves or resizes a window. 314706f2543Smrg * Update the frame position now although the physical window is moved 315706f2543Smrg * in RootlessMoveWindow. (x, y) are *inside* position. After this, 316706f2543Smrg * mi and fb are expecting the pixmap to be at the new location. 317706f2543Smrg */ 318706f2543SmrgBool 319706f2543SmrgRootlessPositionWindow(WindowPtr pWin, int x, int y) 320706f2543Smrg{ 321706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 322706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 323706f2543Smrg Bool result; 324706f2543Smrg 325706f2543Smrg RL_DEBUG_MSG("positionwindow start (win 0x%x @ %i, %i)\n", pWin, x, y); 326706f2543Smrg 327706f2543Smrg if (winRec) { 328706f2543Smrg if (winRec->is_drawing) { 329706f2543Smrg // Reset frame's pixmap and move it to the new position. 330706f2543Smrg int bw = wBorderWidth(pWin); 331706f2543Smrg 332706f2543Smrg winRec->pixmap->devPrivate.ptr = winRec->pixelData; 333706f2543Smrg SetPixmapBaseToScreen(winRec->pixmap, x - bw, y - bw); 334706f2543Smrg } 335706f2543Smrg } 336706f2543Smrg 337706f2543Smrg SCREEN_UNWRAP(pScreen, PositionWindow); 338706f2543Smrg result = pScreen->PositionWindow(pWin, x, y); 339706f2543Smrg SCREEN_WRAP(pScreen, PositionWindow); 340706f2543Smrg 341706f2543Smrg RL_DEBUG_MSG("positionwindow end\n"); 342706f2543Smrg return result; 343706f2543Smrg} 344706f2543Smrg 345706f2543Smrg 346706f2543Smrg/* 347706f2543Smrg * RootlessInitializeFrame 348706f2543Smrg * Initialize some basic attributes of the frame. Note that winRec 349706f2543Smrg * may already have valid data in it, so don't overwrite anything 350706f2543Smrg * valuable. 351706f2543Smrg */ 352706f2543Smrgstatic void 353706f2543SmrgRootlessInitializeFrame(WindowPtr pWin, RootlessWindowRec *winRec) 354706f2543Smrg{ 355706f2543Smrg DrawablePtr d = &pWin->drawable; 356706f2543Smrg int bw = wBorderWidth(pWin); 357706f2543Smrg 358706f2543Smrg winRec->win = pWin; 359706f2543Smrg 360706f2543Smrg winRec->x = d->x - bw; 361706f2543Smrg winRec->y = d->y - bw; 362706f2543Smrg winRec->width = d->width + 2*bw; 363706f2543Smrg winRec->height = d->height + 2*bw; 364706f2543Smrg winRec->borderWidth = bw; 365706f2543Smrg} 366706f2543Smrg 367706f2543Smrg/* 368706f2543Smrg * RootlessEnsureFrame 369706f2543Smrg * Make sure the given window is framed. If the window doesn't have a 370706f2543Smrg * physical window associated with it, attempt to create one. If that 371706f2543Smrg * is unsuccessful, return NULL. 372706f2543Smrg */ 373706f2543Smrgstatic RootlessWindowRec * 374706f2543SmrgRootlessEnsureFrame(WindowPtr pWin) 375706f2543Smrg{ 376706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 377706f2543Smrg RootlessWindowRec *winRec; 378706f2543Smrg RegionRec shape; 379706f2543Smrg RegionPtr pShape = NULL; 380706f2543Smrg 381706f2543Smrg if (WINREC(pWin) != NULL) 382706f2543Smrg return WINREC(pWin); 383706f2543Smrg 384706f2543Smrg if (!IsTopLevel(pWin) && !IsRoot(pWin)) 385706f2543Smrg return NULL; 386706f2543Smrg 387706f2543Smrg if (pWin->drawable.class != InputOutput) 388706f2543Smrg return NULL; 389706f2543Smrg 390706f2543Smrg winRec = malloc(sizeof(RootlessWindowRec)); 391706f2543Smrg 392706f2543Smrg if (!winRec) 393706f2543Smrg return NULL; 394706f2543Smrg 395706f2543Smrg RootlessInitializeFrame(pWin, winRec); 396706f2543Smrg 397706f2543Smrg winRec->is_drawing = FALSE; 398706f2543Smrg winRec->is_reorder_pending = FALSE; 399706f2543Smrg winRec->pixmap = NULL; 400706f2543Smrg winRec->wid = NULL; 401706f2543Smrg winRec->level = 0; 402706f2543Smrg 403706f2543Smrg SETWINREC(pWin, winRec); 404706f2543Smrg 405706f2543Smrg // Set the frame's shape if the window is shaped 406706f2543Smrg if (RootlessGetShape(pWin, &shape)) 407706f2543Smrg pShape = &shape; 408706f2543Smrg 409706f2543Smrg RL_DEBUG_MSG("creating frame "); 410706f2543Smrg 411706f2543Smrg if (!SCREENREC(pScreen)->imp->CreateFrame(winRec, pScreen, 412706f2543Smrg winRec->x + SCREEN_TO_GLOBAL_X, 413706f2543Smrg winRec->y + SCREEN_TO_GLOBAL_Y, 414706f2543Smrg pShape)) 415706f2543Smrg { 416706f2543Smrg RL_DEBUG_MSG("implementation failed to create frame!\n"); 417706f2543Smrg free(winRec); 418706f2543Smrg SETWINREC(pWin, NULL); 419706f2543Smrg return NULL; 420706f2543Smrg } 421706f2543Smrg 422706f2543Smrg if (pWin->drawable.depth == 8) 423706f2543Smrg RootlessFlushWindowColormap(pWin); 424706f2543Smrg 425706f2543Smrg if (pShape != NULL) 426706f2543Smrg RegionUninit(&shape); 427706f2543Smrg 428706f2543Smrg return winRec; 429706f2543Smrg} 430706f2543Smrg 431706f2543Smrg 432706f2543Smrg/* 433706f2543Smrg * RootlessRealizeWindow 434706f2543Smrg * The frame is usually created here and not in CreateWindow so that 435706f2543Smrg * windows do not eat memory until they are realized. 436706f2543Smrg */ 437706f2543SmrgBool 438706f2543SmrgRootlessRealizeWindow(WindowPtr pWin) 439706f2543Smrg{ 440706f2543Smrg Bool result; 441706f2543Smrg RegionRec saveRoot; 442706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 443706f2543Smrg 444706f2543Smrg RL_DEBUG_MSG("realizewindow start (win 0x%x) ", pWin); 445706f2543Smrg 446706f2543Smrg if ((IsTopLevel(pWin) && pWin->drawable.class == InputOutput)) { 447706f2543Smrg RootlessWindowRec *winRec; 448706f2543Smrg 449706f2543Smrg winRec = RootlessEnsureFrame(pWin); 450706f2543Smrg if (winRec == NULL) 451706f2543Smrg return FALSE; 452706f2543Smrg 453706f2543Smrg winRec->is_reorder_pending = TRUE; 454706f2543Smrg 455706f2543Smrg RL_DEBUG_MSG("Top level window "); 456706f2543Smrg 457706f2543Smrg // Disallow ParentRelative background state on top-level windows. 458706f2543Smrg // This might have been set before the window was mapped. 459706f2543Smrg if (pWin->backgroundState == ParentRelative) { 460706f2543Smrg XID pixel = 0; 461706f2543Smrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 462706f2543Smrg } 463706f2543Smrg } 464706f2543Smrg 465706f2543Smrg if (!IsRoot(pWin)) HUGE_ROOT(pWin); 466706f2543Smrg SCREEN_UNWRAP(pScreen, RealizeWindow); 467706f2543Smrg result = pScreen->RealizeWindow(pWin); 468706f2543Smrg SCREEN_WRAP(pScreen, RealizeWindow); 469706f2543Smrg if (!IsRoot(pWin)) NORMAL_ROOT(pWin); 470706f2543Smrg 471706f2543Smrg RL_DEBUG_MSG("realizewindow end\n"); 472706f2543Smrg return result; 473706f2543Smrg} 474706f2543Smrg 475706f2543Smrg 476706f2543Smrg/* 477706f2543Smrg * RootlessFrameForWindow 478706f2543Smrg * Returns the frame ID for the physical window displaying the given window. 479706f2543Smrg * If CREATE is true and the window has no frame, attempt to create one. 480706f2543Smrg */ 481706f2543SmrgRootlessFrameID 482706f2543SmrgRootlessFrameForWindow(WindowPtr pWin, Bool create) 483706f2543Smrg{ 484706f2543Smrg WindowPtr pTopWin; 485706f2543Smrg RootlessWindowRec *winRec; 486706f2543Smrg 487706f2543Smrg pTopWin = TopLevelParent(pWin); 488706f2543Smrg if (pTopWin == NULL) 489706f2543Smrg return NULL; 490706f2543Smrg 491706f2543Smrg winRec = WINREC(pTopWin); 492706f2543Smrg 493706f2543Smrg if (winRec == NULL && create && pWin->drawable.class == InputOutput) { 494706f2543Smrg winRec = RootlessEnsureFrame(pTopWin); 495706f2543Smrg } 496706f2543Smrg 497706f2543Smrg if (winRec == NULL) 498706f2543Smrg return NULL; 499706f2543Smrg 500706f2543Smrg return winRec->wid; 501706f2543Smrg} 502706f2543Smrg 503706f2543Smrg 504706f2543Smrg/* 505706f2543Smrg * RootlessUnrealizeWindow 506706f2543Smrg * Unmap the physical window. 507706f2543Smrg */ 508706f2543SmrgBool 509706f2543SmrgRootlessUnrealizeWindow(WindowPtr pWin) 510706f2543Smrg{ 511706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 512706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 513706f2543Smrg Bool result; 514706f2543Smrg 515706f2543Smrg RL_DEBUG_MSG("unrealizewindow start "); 516706f2543Smrg 517706f2543Smrg if (winRec) { 518706f2543Smrg RootlessStopDrawing(pWin, FALSE); 519706f2543Smrg 520706f2543Smrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 521706f2543Smrg 522706f2543Smrg winRec->is_reorder_pending = FALSE; 523706f2543Smrg } 524706f2543Smrg 525706f2543Smrg SCREEN_UNWRAP(pScreen, UnrealizeWindow); 526706f2543Smrg result = pScreen->UnrealizeWindow(pWin); 527706f2543Smrg SCREEN_WRAP(pScreen, UnrealizeWindow); 528706f2543Smrg 529706f2543Smrg RL_DEBUG_MSG("unrealizewindow end\n"); 530706f2543Smrg return result; 531706f2543Smrg} 532706f2543Smrg 533706f2543Smrg 534706f2543Smrg/* 535706f2543Smrg * RootlessReorderWindow 536706f2543Smrg * Reorder the frame associated with the given window so that it's 537706f2543Smrg * physically above the window below it in the X stacking order. 538706f2543Smrg */ 539706f2543Smrgvoid 540706f2543SmrgRootlessReorderWindow(WindowPtr pWin) 541706f2543Smrg{ 542706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 543706f2543Smrg 544706f2543Smrg if (pWin->realized && winRec != NULL && !winRec->is_reorder_pending && !windows_hidden) { 545706f2543Smrg WindowPtr newPrevW; 546706f2543Smrg RootlessWindowRec *newPrev; 547706f2543Smrg RootlessFrameID newPrevID; 548706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 549706f2543Smrg 550706f2543Smrg /* Check if the implementation wants the frame to not be reordered 551706f2543Smrg even though the X11 window is restacked. This can be useful if 552706f2543Smrg frames are ordered-in with animation so that the reordering is not 553706f2543Smrg done until the animation is complete. */ 554706f2543Smrg if (SCREENREC(pScreen)->imp->DoReorderWindow) { 555706f2543Smrg if (!SCREENREC(pScreen)->imp->DoReorderWindow(winRec)) 556706f2543Smrg return; 557706f2543Smrg } 558706f2543Smrg 559706f2543Smrg RootlessStopDrawing(pWin, FALSE); 560706f2543Smrg 561706f2543Smrg /* Find the next window above this one that has a mapped frame. 562706f2543Smrg * Only include cases where the windows are in the same category of 563706f2543Smrg * hittability to ensure offscreen windows dont get restacked 564706f2543Smrg * relative to onscreen ones (but that the offscreen ones maintain 565706f2543Smrg * their stacking order if they are explicitly asked to Reorder 566706f2543Smrg */ 567706f2543Smrg 568706f2543Smrg newPrevW = pWin->prevSib; 569706f2543Smrg while (newPrevW && (WINREC(newPrevW) == NULL || !newPrevW->realized || newPrevW->rootlessUnhittable != pWin->rootlessUnhittable)) 570706f2543Smrg newPrevW = newPrevW->prevSib; 571706f2543Smrg 572706f2543Smrg newPrev = newPrevW != NULL ? WINREC(newPrevW) : NULL; 573706f2543Smrg newPrevID = newPrev != NULL ? newPrev->wid : 0; 574706f2543Smrg 575706f2543Smrg /* If it exists, reorder the frame above us first. */ 576706f2543Smrg 577706f2543Smrg if (newPrev && newPrev->is_reorder_pending) { 578706f2543Smrg newPrev->is_reorder_pending = FALSE; 579706f2543Smrg RootlessReorderWindow(newPrevW); 580706f2543Smrg } 581706f2543Smrg 582706f2543Smrg SCREENREC(pScreen)->imp->RestackFrame(winRec->wid, newPrevID); 583706f2543Smrg } 584706f2543Smrg} 585706f2543Smrg 586706f2543Smrg 587706f2543Smrg/* 588706f2543Smrg * RootlessRestackWindow 589706f2543Smrg * This is a hook for when DIX changes the window stacking order. 590706f2543Smrg * The window has already been inserted into its new position in the 591706f2543Smrg * DIX window stack. We need to change the order of the physical 592706f2543Smrg * window to match. 593706f2543Smrg */ 594706f2543Smrgvoid 595706f2543SmrgRootlessRestackWindow(WindowPtr pWin, WindowPtr pOldNextSib) 596706f2543Smrg{ 597706f2543Smrg RegionRec saveRoot; 598706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 599706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 600706f2543Smrg 601706f2543Smrg RL_DEBUG_MSG("restackwindow start "); 602706f2543Smrg if (winRec) 603706f2543Smrg RL_DEBUG_MSG("restack top level \n"); 604706f2543Smrg 605706f2543Smrg HUGE_ROOT(pWin); 606706f2543Smrg SCREEN_UNWRAP(pScreen, RestackWindow); 607706f2543Smrg 608706f2543Smrg if (pScreen->RestackWindow) 609706f2543Smrg pScreen->RestackWindow(pWin, pOldNextSib); 610706f2543Smrg 611706f2543Smrg SCREEN_WRAP(pScreen, RestackWindow); 612706f2543Smrg NORMAL_ROOT(pWin); 613706f2543Smrg 614706f2543Smrg if (winRec && pWin->viewable) { 615706f2543Smrg RootlessReorderWindow(pWin); 616706f2543Smrg } 617706f2543Smrg 618706f2543Smrg RL_DEBUG_MSG("restackwindow end\n"); 619706f2543Smrg} 620706f2543Smrg 621706f2543Smrg/* 622706f2543Smrg * Specialized window copy procedures 623706f2543Smrg */ 624706f2543Smrg 625706f2543Smrg// Globals needed during window resize and move. 626706f2543Smrgstatic pointer gResizeDeathBits = NULL; 627706f2543Smrgstatic int gResizeDeathCount = 0; 628706f2543Smrgstatic PixmapPtr gResizeDeathPix[2] = {NULL, NULL}; 629706f2543Smrgstatic BoxRec gResizeDeathBounds[2]; 630706f2543Smrgstatic CopyWindowProcPtr gResizeOldCopyWindowProc = NULL; 631706f2543Smrg 632706f2543Smrg/* 633706f2543Smrg * RootlessNoCopyWindow 634706f2543Smrg * CopyWindow() that doesn't do anything. For MoveWindow() of 635706f2543Smrg * top-level windows. 636706f2543Smrg */ 637706f2543Smrgstatic void 638706f2543SmrgRootlessNoCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 639706f2543Smrg RegionPtr prgnSrc) 640706f2543Smrg{ 641706f2543Smrg // some code expects the region to be translated 642706f2543Smrg int dx = ptOldOrg.x - pWin->drawable.x; 643706f2543Smrg int dy = ptOldOrg.y - pWin->drawable.y; 644706f2543Smrg 645706f2543Smrg RL_DEBUG_MSG("ROOTLESSNOCOPYWINDOW "); 646706f2543Smrg 647706f2543Smrg RegionTranslate(prgnSrc, -dx, -dy); 648706f2543Smrg} 649706f2543Smrg 650706f2543Smrg 651706f2543Smrg/* 652706f2543Smrg * RootlessResizeCopyWindow 653706f2543Smrg * CopyWindow used during ResizeWindow for gravity moves. Based on 654706f2543Smrg * fbCopyWindow. The original always draws on the root pixmap, which 655706f2543Smrg * we don't have. Instead, draw on the parent window's pixmap. 656706f2543Smrg * Resize version: the old location's pixels are in gResizeCopyWindowSource. 657706f2543Smrg */ 658706f2543Smrgstatic void 659706f2543SmrgRootlessResizeCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, 660706f2543Smrg RegionPtr prgnSrc) 661706f2543Smrg{ 662706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 663706f2543Smrg RegionRec rgnDst; 664706f2543Smrg int dx, dy; 665706f2543Smrg 666706f2543Smrg RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x) ", pWin); 667706f2543Smrg 668706f2543Smrg /* Don't unwrap pScreen->CopyWindow. 669706f2543Smrg The bogus rewrap with RootlessCopyWindow causes a crash if 670706f2543Smrg CopyWindow is called again during the same resize. */ 671706f2543Smrg 672706f2543Smrg if (gResizeDeathCount == 0) 673706f2543Smrg return; 674706f2543Smrg 675706f2543Smrg RootlessStartDrawing(pWin); 676706f2543Smrg 677706f2543Smrg dx = ptOldOrg.x - pWin->drawable.x; 678706f2543Smrg dy = ptOldOrg.y - pWin->drawable.y; 679706f2543Smrg RegionTranslate(prgnSrc, -dx, -dy); 680706f2543Smrg RegionNull(&rgnDst); 681706f2543Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 682706f2543Smrg 683706f2543Smrg if (gResizeDeathCount == 1) { 684706f2543Smrg /* Simple case, we only have a single source pixmap. */ 685706f2543Smrg 686706f2543Smrg fbCopyRegion(&gResizeDeathPix[0]->drawable, 687706f2543Smrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 688706f2543Smrg &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 689706f2543Smrg } 690706f2543Smrg else { 691706f2543Smrg int i; 692706f2543Smrg RegionRec clip, clipped; 693706f2543Smrg 694706f2543Smrg /* More complex case, N source pixmaps (usually two). So we 695706f2543Smrg intersect the destination with each source and copy those bits. */ 696706f2543Smrg 697706f2543Smrg for (i = 0; i < gResizeDeathCount; i++) { 698706f2543Smrg RegionInit(&clip, gResizeDeathBounds + 0, 1); 699706f2543Smrg RegionNull(&clipped); 700706f2543Smrg RegionIntersect(&rgnDst, &clip, &clipped); 701706f2543Smrg 702706f2543Smrg fbCopyRegion(&gResizeDeathPix[i]->drawable, 703706f2543Smrg &pScreen->GetWindowPixmap(pWin)->drawable, 0, 704706f2543Smrg &clipped, dx, dy, fbCopyWindowProc, 0, 0); 705706f2543Smrg 706706f2543Smrg RegionUninit(&clipped); 707706f2543Smrg RegionUninit(&clip); 708706f2543Smrg } 709706f2543Smrg } 710706f2543Smrg 711706f2543Smrg /* Don't update - resize will update everything */ 712706f2543Smrg RegionUninit(&rgnDst); 713706f2543Smrg 714706f2543Smrg fbValidateDrawable(&pWin->drawable); 715706f2543Smrg 716706f2543Smrg RL_DEBUG_MSG("resizecopywindowFB end\n"); 717706f2543Smrg} 718706f2543Smrg 719706f2543Smrg 720706f2543Smrg/* 721706f2543Smrg * RootlessCopyWindow 722706f2543Smrg * Update *new* location of window. Old location is redrawn with 723706f2543Smrg * miPaintWindow. Cloned from fbCopyWindow. 724706f2543Smrg * The original always draws on the root pixmap, which we don't have. 725706f2543Smrg * Instead, draw on the parent window's pixmap. 726706f2543Smrg */ 727706f2543Smrgvoid 728706f2543SmrgRootlessCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) 729706f2543Smrg{ 730706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 731706f2543Smrg RegionRec rgnDst; 732706f2543Smrg int dx, dy; 733706f2543Smrg BoxPtr extents; 734706f2543Smrg int area; 735706f2543Smrg 736706f2543Smrg RL_DEBUG_MSG("copywindowFB start (win 0x%x) ", pWin); 737706f2543Smrg 738706f2543Smrg SCREEN_UNWRAP(pScreen, CopyWindow); 739706f2543Smrg 740706f2543Smrg dx = ptOldOrg.x - pWin->drawable.x; 741706f2543Smrg dy = ptOldOrg.y - pWin->drawable.y; 742706f2543Smrg RegionTranslate(prgnSrc, -dx, -dy); 743706f2543Smrg 744706f2543Smrg RegionNull(&rgnDst); 745706f2543Smrg RegionIntersect(&rgnDst, &pWin->borderClip, prgnSrc); 746706f2543Smrg 747706f2543Smrg extents = RegionExtents(&rgnDst); 748706f2543Smrg area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1); 749706f2543Smrg 750706f2543Smrg /* If the area exceeds threshold, use the implementation's 751706f2543Smrg accelerated version. */ 752706f2543Smrg if (area > rootless_CopyWindow_threshold && 753706f2543Smrg SCREENREC(pScreen)->imp->CopyWindow) 754706f2543Smrg { 755706f2543Smrg RootlessWindowRec *winRec; 756706f2543Smrg WindowPtr top; 757706f2543Smrg 758706f2543Smrg top = TopLevelParent(pWin); 759706f2543Smrg if (top == NULL) { 760706f2543Smrg RL_DEBUG_MSG("no parent\n"); 761706f2543Smrg goto out; 762706f2543Smrg } 763706f2543Smrg 764706f2543Smrg winRec = WINREC(top); 765706f2543Smrg if (winRec == NULL) { 766706f2543Smrg RL_DEBUG_MSG("not framed\n"); 767706f2543Smrg goto out; 768706f2543Smrg } 769706f2543Smrg 770706f2543Smrg /* Move region to window local coords */ 771706f2543Smrg RegionTranslate(&rgnDst, -winRec->x, -winRec->y); 772706f2543Smrg 773706f2543Smrg RootlessStopDrawing(pWin, FALSE); 774706f2543Smrg 775706f2543Smrg SCREENREC(pScreen)->imp->CopyWindow(winRec->wid, 776706f2543Smrg RegionNumRects(&rgnDst), 777706f2543Smrg RegionRects(&rgnDst), 778706f2543Smrg dx, dy); 779706f2543Smrg } 780706f2543Smrg else { 781706f2543Smrg RootlessStartDrawing(pWin); 782706f2543Smrg 783706f2543Smrg fbCopyRegion((DrawablePtr) pWin, (DrawablePtr) pWin, 784706f2543Smrg 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0); 785706f2543Smrg 786706f2543Smrg /* prgnSrc has been translated to dst position */ 787706f2543Smrg RootlessDamageRegion(pWin, prgnSrc); 788706f2543Smrg } 789706f2543Smrg 790706f2543Smrgout: 791706f2543Smrg RegionUninit(&rgnDst); 792706f2543Smrg fbValidateDrawable(&pWin->drawable); 793706f2543Smrg 794706f2543Smrg SCREEN_WRAP(pScreen, CopyWindow); 795706f2543Smrg 796706f2543Smrg RL_DEBUG_MSG("copywindowFB end\n"); 797706f2543Smrg} 798706f2543Smrg 799706f2543Smrg 800706f2543Smrg/* 801706f2543Smrg * Window resize procedures 802706f2543Smrg */ 803706f2543Smrg 804706f2543Smrgenum { 805706f2543Smrg WIDTH_SMALLER = 1, 806706f2543Smrg HEIGHT_SMALLER = 2, 807706f2543Smrg}; 808706f2543Smrg 809706f2543Smrg 810706f2543Smrg/* 811706f2543Smrg * ResizeWeighting 812706f2543Smrg * Choose gravity to avoid local copies. Do that by looking for 813706f2543Smrg * a corner that doesn't move _relative to the screen_. 814706f2543Smrg */ 815706f2543Smrgstatic inline unsigned int 816706f2543SmrgResizeWeighting(int oldX1, int oldY1, int oldX2, int oldY2, int oldBW, 817706f2543Smrg int newX1, int newY1, int newX2, int newY2, int newBW) 818706f2543Smrg{ 819706f2543Smrg#ifdef ROOTLESS_RESIZE_GRAVITY 820706f2543Smrg if (newBW != oldBW) 821706f2543Smrg return RL_GRAVITY_NONE; 822706f2543Smrg 823706f2543Smrg if (newX1 == oldX1 && newY1 == oldY1) 824706f2543Smrg return RL_GRAVITY_NORTH_WEST; 825706f2543Smrg else if (newX1 == oldX1 && newY2 == oldY2) 826706f2543Smrg return RL_GRAVITY_SOUTH_WEST; 827706f2543Smrg else if (newX2 == oldX2 && newY2 == oldY2) 828706f2543Smrg return RL_GRAVITY_SOUTH_EAST; 829706f2543Smrg else if (newX2 == oldX2 && newY1 == oldY1) 830706f2543Smrg return RL_GRAVITY_NORTH_EAST; 831706f2543Smrg else 832706f2543Smrg return RL_GRAVITY_NONE; 833706f2543Smrg#else 834706f2543Smrg return RL_GRAVITY_NONE; 835706f2543Smrg#endif 836706f2543Smrg} 837706f2543Smrg 838706f2543Smrg 839706f2543Smrg/* 840706f2543Smrg * StartFrameResize 841706f2543Smrg * Prepare to resize a top-level window. The old window's pixels are 842706f2543Smrg * saved and the implementation is told to change the window size. 843706f2543Smrg * (x,y,w,h) is outer frame of window (outside border) 844706f2543Smrg */ 845706f2543Smrgstatic Bool 846706f2543SmrgStartFrameResize(WindowPtr pWin, Bool gravity, 847706f2543Smrg int oldX, int oldY, int oldW, int oldH, int oldBW, 848706f2543Smrg int newX, int newY, int newW, int newH, int newBW) 849706f2543Smrg{ 850706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 851706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 852706f2543Smrg Bool need_window_source = FALSE, resize_after = FALSE; 853706f2543Smrg 854706f2543Smrg BoxRec rect; 855706f2543Smrg int oldX2, newX2; 856706f2543Smrg int oldY2, newY2; 857706f2543Smrg unsigned int weight; 858706f2543Smrg 859706f2543Smrg oldX2 = oldX + oldW, newX2 = newX + newW; 860706f2543Smrg oldY2 = oldY + oldH, newY2 = newY + newH; 861706f2543Smrg 862706f2543Smrg /* Decide which resize weighting to use */ 863706f2543Smrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 864706f2543Smrg newX, newY, newW, newH, newBW); 865706f2543Smrg 866706f2543Smrg /* Compute intersection between old and new rects */ 867706f2543Smrg rect.x1 = max(oldX, newX); 868706f2543Smrg rect.y1 = max(oldY, newY); 869706f2543Smrg rect.x2 = min(oldX2, newX2); 870706f2543Smrg rect.y2 = min(oldY2, newY2); 871706f2543Smrg 872706f2543Smrg RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity); 873706f2543Smrg RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n", 874706f2543Smrg oldX, oldY, oldW, oldH, oldBW, 875706f2543Smrg newX, newY, newW, newH, newBW); 876706f2543Smrg 877706f2543Smrg RootlessRedisplay(pWin); 878706f2543Smrg 879706f2543Smrg /* If gravity is true, then we need to have a way of recovering all 880706f2543Smrg the original bits in the window for when X rearranges the contents 881706f2543Smrg based on the various gravity settings. The obvious way is to just 882706f2543Smrg snapshot the entire backing store before resizing it, but that 883706f2543Smrg it slow on large windows. 884706f2543Smrg 885706f2543Smrg So the optimization here is to use the implementation's resize 886706f2543Smrg weighting options (if available) to allow us to reason about what 887706f2543Smrg is left in the backing store after the resize. We can then only 888706f2543Smrg copy what won't be there after the resize, and do a two-stage copy 889706f2543Smrg operation. 890706f2543Smrg 891706f2543Smrg Most of these optimizations are only applied when the top-left 892706f2543Smrg corner of the window is fixed, since that's the common case. They 893706f2543Smrg could probably be extended with some thought. */ 894706f2543Smrg 895706f2543Smrg gResizeDeathCount = 0; 896706f2543Smrg 897706f2543Smrg if (gravity && weight == RL_GRAVITY_NORTH_WEST) { 898706f2543Smrg unsigned int code = 0; 899706f2543Smrg 900706f2543Smrg /* Top left corner is anchored. We never need to copy the 901706f2543Smrg entire window. */ 902706f2543Smrg 903706f2543Smrg need_window_source = TRUE; 904706f2543Smrg 905706f2543Smrg /* These comparisons were chosen to avoid setting bits when the sizes 906706f2543Smrg are the same. (So the fastest case automatically gets taken when 907706f2543Smrg dimensions are unchanging.) */ 908706f2543Smrg 909706f2543Smrg if (newW < oldW) 910706f2543Smrg code |= WIDTH_SMALLER; 911706f2543Smrg if (newH < oldH) 912706f2543Smrg code |= HEIGHT_SMALLER; 913706f2543Smrg 914706f2543Smrg if (((code ^ (code >> 1)) & 1) == 0) { 915706f2543Smrg /* Both dimensions are either getting larger, or both 916706f2543Smrg are getting smaller. No need to copy anything. */ 917706f2543Smrg 918706f2543Smrg if (code == (WIDTH_SMALLER | HEIGHT_SMALLER)) { 919706f2543Smrg /* Since the window is getting smaller, we can do gravity 920706f2543Smrg repair on it with it's current size, then resize it 921706f2543Smrg afterwards. */ 922706f2543Smrg 923706f2543Smrg resize_after = TRUE; 924706f2543Smrg } 925706f2543Smrg 926706f2543Smrg gResizeDeathCount = 1; 927706f2543Smrg } 928706f2543Smrg else { 929706f2543Smrg unsigned int copy_rowbytes, Bpp; 930706f2543Smrg unsigned int copy_rect_width, copy_rect_height; 931706f2543Smrg BoxRec copy_rect; 932706f2543Smrg 933706f2543Smrg /* We can get away with a partial copy. 'rect' is the 934706f2543Smrg intersection between old and new bounds, so copy 935706f2543Smrg everything to the right of or below the intersection. */ 936706f2543Smrg 937706f2543Smrg RootlessStartDrawing(pWin); 938706f2543Smrg 939706f2543Smrg if (code == WIDTH_SMALLER) { 940706f2543Smrg copy_rect.x1 = rect.x2; 941706f2543Smrg copy_rect.y1 = rect.y1; 942706f2543Smrg copy_rect.x2 = oldX2; 943706f2543Smrg copy_rect.y2 = oldY2; 944706f2543Smrg } 945706f2543Smrg else if (code == HEIGHT_SMALLER) { 946706f2543Smrg copy_rect.x1 = rect.x1; 947706f2543Smrg copy_rect.y1 = rect.y2; 948706f2543Smrg copy_rect.x2 = oldX2; 949706f2543Smrg copy_rect.y2 = oldY2; 950706f2543Smrg } 951706f2543Smrg else 952706f2543Smrg OsAbort(); 953706f2543Smrg 954706f2543Smrg Bpp = winRec->win->drawable.bitsPerPixel / 8; 955706f2543Smrg copy_rect_width = copy_rect.x2 - copy_rect.x1; 956706f2543Smrg copy_rect_height = copy_rect.y2 - copy_rect.y1; 957706f2543Smrg copy_rowbytes = ((copy_rect_width * Bpp) + 31) & ~31; 958706f2543Smrg gResizeDeathBits = malloc(copy_rowbytes 959706f2543Smrg * copy_rect_height); 960706f2543Smrg 961706f2543Smrg if (copy_rect_width * copy_rect_height > 962706f2543Smrg rootless_CopyBytes_threshold && 963706f2543Smrg SCREENREC(pScreen)->imp->CopyBytes) 964706f2543Smrg { 965706f2543Smrg SCREENREC(pScreen)->imp->CopyBytes( 966706f2543Smrg copy_rect_width * Bpp, copy_rect_height, 967706f2543Smrg ((char *) winRec->pixelData) 968706f2543Smrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 969706f2543Smrg + (copy_rect.x1 - oldX) * Bpp, winRec->bytesPerRow, 970706f2543Smrg gResizeDeathBits, copy_rowbytes); 971706f2543Smrg } else { 972706f2543Smrg fbBlt((FbBits *) (winRec->pixelData 973706f2543Smrg + ((copy_rect.y1 - oldY) * winRec->bytesPerRow) 974706f2543Smrg + (copy_rect.x1 - oldX) * Bpp), 975706f2543Smrg winRec->bytesPerRow / sizeof(FbBits), 0, 976706f2543Smrg (FbBits *) gResizeDeathBits, 977706f2543Smrg copy_rowbytes / sizeof(FbBits), 0, 978706f2543Smrg copy_rect_width * Bpp, copy_rect_height, 979706f2543Smrg GXcopy, FB_ALLONES, Bpp, 0, 0); 980706f2543Smrg } 981706f2543Smrg 982706f2543Smrg gResizeDeathBounds[1] = copy_rect; 983706f2543Smrg gResizeDeathPix[1] 984706f2543Smrg = GetScratchPixmapHeader(pScreen, copy_rect_width, 985706f2543Smrg copy_rect_height, 986706f2543Smrg winRec->win->drawable.depth, 987706f2543Smrg winRec->win->drawable.bitsPerPixel, 988706f2543Smrg winRec->bytesPerRow, 989706f2543Smrg (void *) gResizeDeathBits); 990706f2543Smrg 991706f2543Smrg SetPixmapBaseToScreen(gResizeDeathPix[1], 992706f2543Smrg copy_rect.x1, copy_rect.y1); 993706f2543Smrg 994706f2543Smrg gResizeDeathCount = 2; 995706f2543Smrg } 996706f2543Smrg } 997706f2543Smrg else if (gravity) { 998706f2543Smrg /* The general case. Just copy everything. */ 999706f2543Smrg 1000706f2543Smrg RootlessStartDrawing(pWin); 1001706f2543Smrg 1002706f2543Smrg gResizeDeathBits = malloc(winRec->bytesPerRow * winRec->height); 1003706f2543Smrg 1004706f2543Smrg memcpy(gResizeDeathBits, winRec->pixelData, 1005706f2543Smrg winRec->bytesPerRow * winRec->height); 1006706f2543Smrg 1007706f2543Smrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 1008706f2543Smrg gResizeDeathPix[0] 1009706f2543Smrg = GetScratchPixmapHeader(pScreen, winRec->width, 1010706f2543Smrg winRec->height, 1011706f2543Smrg winRec->win->drawable.depth, 1012706f2543Smrg winRec->win->drawable.bitsPerPixel, 1013706f2543Smrg winRec->bytesPerRow, 1014706f2543Smrg (void *) gResizeDeathBits); 1015706f2543Smrg 1016706f2543Smrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 1017706f2543Smrg gResizeDeathCount = 1; 1018706f2543Smrg } 1019706f2543Smrg 1020706f2543Smrg RootlessStopDrawing(pWin, FALSE); 1021706f2543Smrg 1022706f2543Smrg winRec->x = newX; 1023706f2543Smrg winRec->y = newY; 1024706f2543Smrg winRec->width = newW; 1025706f2543Smrg winRec->height = newH; 1026706f2543Smrg winRec->borderWidth = newBW; 1027706f2543Smrg 1028706f2543Smrg /* Unless both dimensions are getting smaller, Resize the frame 1029706f2543Smrg before doing gravity repair */ 1030706f2543Smrg 1031706f2543Smrg if (!resize_after) { 1032706f2543Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 1033706f2543Smrg newX + SCREEN_TO_GLOBAL_X, 1034706f2543Smrg newY + SCREEN_TO_GLOBAL_Y, 1035706f2543Smrg newW, newH, weight); 1036706f2543Smrg } 1037706f2543Smrg 1038706f2543Smrg RootlessStartDrawing(pWin); 1039706f2543Smrg 1040706f2543Smrg /* If necessary, create a source pixmap pointing at the current 1041706f2543Smrg window bits. */ 1042706f2543Smrg 1043706f2543Smrg if (need_window_source) { 1044706f2543Smrg gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2}; 1045706f2543Smrg gResizeDeathPix[0] 1046706f2543Smrg = GetScratchPixmapHeader(pScreen, oldW, oldH, 1047706f2543Smrg winRec->win->drawable.depth, 1048706f2543Smrg winRec->win->drawable.bitsPerPixel, 1049706f2543Smrg winRec->bytesPerRow, winRec->pixelData); 1050706f2543Smrg 1051706f2543Smrg SetPixmapBaseToScreen(gResizeDeathPix[0], oldX, oldY); 1052706f2543Smrg } 1053706f2543Smrg 1054706f2543Smrg /* Use custom CopyWindow when moving gravity bits around 1055706f2543Smrg ResizeWindow assumes the old window contents are in the same 1056706f2543Smrg pixmap, but here they're in deathPix instead. */ 1057706f2543Smrg 1058706f2543Smrg if (gravity) { 1059706f2543Smrg gResizeOldCopyWindowProc = pScreen->CopyWindow; 1060706f2543Smrg pScreen->CopyWindow = RootlessResizeCopyWindow; 1061706f2543Smrg } 1062706f2543Smrg 1063706f2543Smrg /* If we can't rely on the window server preserving the bits we 1064706f2543Smrg need in the position we need, copy the pixels in the 1065706f2543Smrg intersection from src to dst. ResizeWindow assumes these pixels 1066706f2543Smrg are already present when making gravity adjustments. pWin 1067706f2543Smrg currently has new-sized pixmap but is in old position. 1068706f2543Smrg 1069706f2543Smrg FIXME: border width change! (?) */ 1070706f2543Smrg 1071706f2543Smrg if (gravity && weight == RL_GRAVITY_NONE) { 1072706f2543Smrg PixmapPtr src, dst; 1073706f2543Smrg 1074706f2543Smrg assert(gResizeDeathCount == 1); 1075706f2543Smrg 1076706f2543Smrg src = gResizeDeathPix[0]; 1077706f2543Smrg dst = pScreen->GetWindowPixmap(pWin); 1078706f2543Smrg 1079706f2543Smrg RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n", 1080706f2543Smrg rect.x1, rect.y1, rect.x2, rect.y2); 1081706f2543Smrg 1082706f2543Smrg /* rect is the intersection of the old location and new location */ 1083706f2543Smrg if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL) { 1084706f2543Smrg /* The window drawable still has the old frame position, which 1085706f2543Smrg means that DST doesn't actually point at the origin of our 1086706f2543Smrg physical backing store when adjusted by the drawable.x,y 1087706f2543Smrg position. So sneakily adjust it temporarily while copying.. */ 1088706f2543Smrg 1089706f2543Smrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 1090706f2543Smrg SetPixmapBaseToScreen(dst, newX, newY); 1091706f2543Smrg 1092706f2543Smrg fbCopyWindowProc(&src->drawable, &dst->drawable, NULL, 1093706f2543Smrg &rect, 1, 0, 0, FALSE, FALSE, 0, 0); 1094706f2543Smrg 1095706f2543Smrg ((PixmapPtr) dst)->devPrivate.ptr = winRec->pixelData; 1096706f2543Smrg SetPixmapBaseToScreen(dst, oldX, oldY); 1097706f2543Smrg } 1098706f2543Smrg } 1099706f2543Smrg 1100706f2543Smrg return resize_after; 1101706f2543Smrg} 1102706f2543Smrg 1103706f2543Smrg 1104706f2543Smrgstatic void 1105706f2543SmrgFinishFrameResize(WindowPtr pWin, Bool gravity, int oldX, int oldY, 1106706f2543Smrg unsigned int oldW, unsigned int oldH, unsigned int oldBW, 1107706f2543Smrg int newX, int newY, unsigned int newW, unsigned int newH, 1108706f2543Smrg unsigned int newBW, Bool resize_now) 1109706f2543Smrg{ 1110706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1111706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 1112706f2543Smrg int i; 1113706f2543Smrg 1114706f2543Smrg RootlessStopDrawing(pWin, FALSE); 1115706f2543Smrg 1116706f2543Smrg if (resize_now) { 1117706f2543Smrg unsigned int weight; 1118706f2543Smrg 1119706f2543Smrg /* We didn't resize anything earlier, so do it now, now that 1120706f2543Smrg we've finished gravitating the bits. */ 1121706f2543Smrg 1122706f2543Smrg weight = ResizeWeighting(oldX, oldY, oldW, oldH, oldBW, 1123706f2543Smrg newX, newY, newW, newH, newBW); 1124706f2543Smrg 1125706f2543Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 1126706f2543Smrg newX + SCREEN_TO_GLOBAL_X, 1127706f2543Smrg newY + SCREEN_TO_GLOBAL_Y, 1128706f2543Smrg newW, newH, weight); 1129706f2543Smrg } 1130706f2543Smrg 1131706f2543Smrg /* Redraw everything. FIXME: there must be times when we don't need 1132706f2543Smrg to do this. Perhaps when top-left weighting and no gravity? */ 1133706f2543Smrg 1134706f2543Smrg RootlessDamageRect(pWin, -newBW, -newBW, newW, newH); 1135706f2543Smrg 1136706f2543Smrg for (i = 0; i < 2; i++) { 1137706f2543Smrg if (gResizeDeathPix[i] != NULL) { 1138706f2543Smrg FreeScratchPixmapHeader(gResizeDeathPix[i]); 1139706f2543Smrg gResizeDeathPix[i] = NULL; 1140706f2543Smrg } 1141706f2543Smrg } 1142706f2543Smrg 1143706f2543Smrg free(gResizeDeathBits); 1144706f2543Smrg gResizeDeathBits = NULL; 1145706f2543Smrg 1146706f2543Smrg if (gravity) { 1147706f2543Smrg pScreen->CopyWindow = gResizeOldCopyWindowProc; 1148706f2543Smrg } 1149706f2543Smrg} 1150706f2543Smrg 1151706f2543Smrg 1152706f2543Smrg/* 1153706f2543Smrg * RootlessMoveWindow 1154706f2543Smrg * If kind==VTOther, window border is resizing (and borderWidth is 1155706f2543Smrg * already changed!!@#$) This case works like window resize, not move. 1156706f2543Smrg */ 1157706f2543Smrgvoid 1158706f2543SmrgRootlessMoveWindow(WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) 1159706f2543Smrg{ 1160706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 1161706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1162706f2543Smrg CopyWindowProcPtr oldCopyWindowProc = NULL; 1163706f2543Smrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 1164706f2543Smrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 1165706f2543Smrg unsigned int newW = 0, newH = 0, newBW = 0; 1166706f2543Smrg Bool resize_after = FALSE; 1167706f2543Smrg RegionRec saveRoot; 1168706f2543Smrg 1169706f2543Smrg RL_DEBUG_MSG("movewindow start \n"); 1170706f2543Smrg 1171706f2543Smrg if (winRec) { 1172706f2543Smrg if (kind == VTMove) { 1173706f2543Smrg oldX = winRec->x; 1174706f2543Smrg oldY = winRec->y; 1175706f2543Smrg RootlessRedisplay(pWin); 1176706f2543Smrg RootlessStartDrawing(pWin); 1177706f2543Smrg } else { 1178706f2543Smrg RL_DEBUG_MSG("movewindow border resizing "); 1179706f2543Smrg 1180706f2543Smrg oldBW = winRec->borderWidth; 1181706f2543Smrg oldX = winRec->x; 1182706f2543Smrg oldY = winRec->y; 1183706f2543Smrg oldW = winRec->width; 1184706f2543Smrg oldH = winRec->height; 1185706f2543Smrg 1186706f2543Smrg newBW = wBorderWidth(pWin); 1187706f2543Smrg newX = x; 1188706f2543Smrg newY = y; 1189706f2543Smrg newW = pWin->drawable.width + 2*newBW; 1190706f2543Smrg newH = pWin->drawable.height + 2*newBW; 1191706f2543Smrg 1192706f2543Smrg resize_after = StartFrameResize(pWin, FALSE, 1193706f2543Smrg oldX, oldY, oldW, oldH, oldBW, 1194706f2543Smrg newX, newY, newW, newH, newBW); 1195706f2543Smrg } 1196706f2543Smrg } 1197706f2543Smrg 1198706f2543Smrg HUGE_ROOT(pWin); 1199706f2543Smrg SCREEN_UNWRAP(pScreen, MoveWindow); 1200706f2543Smrg 1201706f2543Smrg if (winRec) { 1202706f2543Smrg oldCopyWindowProc = pScreen->CopyWindow; 1203706f2543Smrg pScreen->CopyWindow = RootlessNoCopyWindow; 1204706f2543Smrg } 1205706f2543Smrg pScreen->MoveWindow(pWin, x, y, pSib, kind); 1206706f2543Smrg if (winRec) { 1207706f2543Smrg pScreen->CopyWindow = oldCopyWindowProc; 1208706f2543Smrg } 1209706f2543Smrg 1210706f2543Smrg NORMAL_ROOT(pWin); 1211706f2543Smrg SCREEN_WRAP(pScreen, MoveWindow); 1212706f2543Smrg 1213706f2543Smrg if (winRec) { 1214706f2543Smrg if (kind == VTMove) { 1215706f2543Smrg winRec->x = x; 1216706f2543Smrg winRec->y = y; 1217706f2543Smrg RootlessStopDrawing(pWin, FALSE); 1218706f2543Smrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 1219706f2543Smrg x + SCREEN_TO_GLOBAL_X, 1220706f2543Smrg y + SCREEN_TO_GLOBAL_Y); 1221706f2543Smrg } else { 1222706f2543Smrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 1223706f2543Smrg newX, newY, newW, newH, newBW, resize_after); 1224706f2543Smrg } 1225706f2543Smrg } 1226706f2543Smrg 1227706f2543Smrg RL_DEBUG_MSG("movewindow end\n"); 1228706f2543Smrg} 1229706f2543Smrg 1230706f2543Smrg 1231706f2543Smrg/* 1232706f2543Smrg * RootlessResizeWindow 1233706f2543Smrg * Note: (x, y, w, h) as passed to this procedure don't match the frame 1234706f2543Smrg * definition. (x,y) is corner of very outer edge, *outside* border. 1235706f2543Smrg * w,h is width and height *inside* border, *ignoring* border width. 1236706f2543Smrg * The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw) 1237706f2543Smrg * is total rect and (x+bw, y+bw, w, h) is inner rect. 1238706f2543Smrg */ 1239706f2543Smrgvoid 1240706f2543SmrgRootlessResizeWindow(WindowPtr pWin, int x, int y, 1241706f2543Smrg unsigned int w, unsigned int h, WindowPtr pSib) 1242706f2543Smrg{ 1243706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 1244706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1245706f2543Smrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 1246706f2543Smrg unsigned int oldW = 0, oldH = 0, oldBW = 0, newW = 0, newH = 0, newBW = 0; 1247706f2543Smrg Bool resize_after = FALSE; 1248706f2543Smrg RegionRec saveRoot; 1249706f2543Smrg 1250706f2543Smrg RL_DEBUG_MSG("resizewindow start (win 0x%x) ", pWin); 1251706f2543Smrg 1252706f2543Smrg if(pWin->parent) { 1253706f2543Smrg if (winRec) { 1254706f2543Smrg oldBW = winRec->borderWidth; 1255706f2543Smrg oldX = winRec->x; 1256706f2543Smrg oldY = winRec->y; 1257706f2543Smrg oldW = winRec->width; 1258706f2543Smrg oldH = winRec->height; 1259706f2543Smrg 1260706f2543Smrg newBW = oldBW; 1261706f2543Smrg newX = x; 1262706f2543Smrg newY = y; 1263706f2543Smrg newW = w + 2*newBW; 1264706f2543Smrg newH = h + 2*newBW; 1265706f2543Smrg 1266706f2543Smrg resize_after = StartFrameResize(pWin, TRUE, 1267706f2543Smrg oldX, oldY, oldW, oldH, oldBW, 1268706f2543Smrg newX, newY, newW, newH, newBW); 1269706f2543Smrg } 1270706f2543Smrg 1271706f2543Smrg HUGE_ROOT(pWin); 1272706f2543Smrg SCREEN_UNWRAP(pScreen, ResizeWindow); 1273706f2543Smrg pScreen->ResizeWindow(pWin, x, y, w, h, pSib); 1274706f2543Smrg SCREEN_WRAP(pScreen, ResizeWindow); 1275706f2543Smrg NORMAL_ROOT(pWin); 1276706f2543Smrg 1277706f2543Smrg if (winRec) { 1278706f2543Smrg FinishFrameResize(pWin, TRUE, oldX, oldY, oldW, oldH, oldBW, 1279706f2543Smrg newX, newY, newW, newH, newBW, resize_after); 1280706f2543Smrg } 1281706f2543Smrg } else { 1282706f2543Smrg /* Special case for resizing the root window */ 1283706f2543Smrg BoxRec box; 1284706f2543Smrg 1285706f2543Smrg pWin->drawable.x = x; 1286706f2543Smrg pWin->drawable.y = y; 1287706f2543Smrg pWin->drawable.width = w; 1288706f2543Smrg pWin->drawable.height = h; 1289706f2543Smrg 1290706f2543Smrg box.x1 = x; box.y1 = y; 1291706f2543Smrg box.x2 = x + w; box.y2 = y + h; 1292706f2543Smrg RegionUninit(&pWin->winSize); 1293706f2543Smrg RegionInit(&pWin->winSize, &box, 1); 1294706f2543Smrg RegionCopy(&pWin->borderSize, &pWin->winSize); 1295706f2543Smrg RegionCopy(&pWin->clipList, &pWin->winSize); 1296706f2543Smrg RegionCopy(&pWin->borderClip, &pWin->winSize); 1297706f2543Smrg 1298706f2543Smrg if (winRec) { 1299706f2543Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 1300706f2543Smrg x + SCREEN_TO_GLOBAL_X, 1301706f2543Smrg y + SCREEN_TO_GLOBAL_Y, 1302706f2543Smrg w, h, RL_GRAVITY_NONE); 1303706f2543Smrg } 1304706f2543Smrg 1305706f2543Smrg miSendExposures(pWin, &pWin->borderClip, 1306706f2543Smrg pWin->drawable.x, pWin->drawable.y); 1307706f2543Smrg } 1308706f2543Smrg 1309706f2543Smrg RL_DEBUG_MSG("resizewindow end\n"); 1310706f2543Smrg} 1311706f2543Smrg 1312706f2543Smrg 1313706f2543Smrg/* 1314706f2543Smrg * RootlessRepositionWindow 1315706f2543Smrg * Called by the implementation when a window needs to be repositioned to 1316706f2543Smrg * its correct location on the screen. This routine is typically needed 1317706f2543Smrg * due to changes in the underlying window system, such as a screen layout 1318706f2543Smrg * change. 1319706f2543Smrg */ 1320706f2543Smrgvoid 1321706f2543SmrgRootlessRepositionWindow(WindowPtr pWin) 1322706f2543Smrg{ 1323706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 1324706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1325706f2543Smrg 1326706f2543Smrg if (winRec == NULL) 1327706f2543Smrg return; 1328706f2543Smrg 1329706f2543Smrg RootlessStopDrawing(pWin, FALSE); 1330706f2543Smrg SCREENREC(pScreen)->imp->MoveFrame(winRec->wid, pScreen, 1331706f2543Smrg winRec->x + SCREEN_TO_GLOBAL_X, 1332706f2543Smrg winRec->y + SCREEN_TO_GLOBAL_Y); 1333706f2543Smrg 1334706f2543Smrg RootlessReorderWindow(pWin); 1335706f2543Smrg} 1336706f2543Smrg 1337706f2543Smrg 1338706f2543Smrg/* 1339706f2543Smrg * RootlessReparentWindow 1340706f2543Smrg * Called after a window has been reparented. Generally windows are not 1341706f2543Smrg * framed until they are mapped. However, a window may be framed early by the 1342706f2543Smrg * implementation calling RootlessFrameForWindow. (e.g. this could be needed 1343706f2543Smrg * to attach a VRAM surface to it.) If the window is subsequently reparented 1344706f2543Smrg * by the window manager before being mapped, we need to give the frame to 1345706f2543Smrg * the new top-level window. 1346706f2543Smrg */ 1347706f2543Smrgvoid 1348706f2543SmrgRootlessReparentWindow(WindowPtr pWin, WindowPtr pPriorParent) 1349706f2543Smrg{ 1350706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1351706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 1352706f2543Smrg WindowPtr pTopWin; 1353706f2543Smrg 1354706f2543Smrg /* Check that window is not top-level now, but used to be. */ 1355706f2543Smrg if (IsRoot(pWin) || IsRoot(pWin->parent) 1356706f2543Smrg || IsTopLevel(pWin) || winRec == NULL) 1357706f2543Smrg { 1358706f2543Smrg goto out; 1359706f2543Smrg } 1360706f2543Smrg 1361706f2543Smrg /* If the formerly top-level window has a frame, we want to give the 1362706f2543Smrg frame to its new top-level parent. If we can't do that, we'll just 1363706f2543Smrg have to jettison it... */ 1364706f2543Smrg 1365706f2543Smrg pTopWin = TopLevelParent(pWin); 1366706f2543Smrg assert(pTopWin != pWin); 1367706f2543Smrg 1368706f2543Smrg pWin->rootlessUnhittable = FALSE; 1369706f2543Smrg 1370706f2543Smrg DeleteProperty (serverClient, pWin, xa_native_window_id ()); 1371706f2543Smrg 1372706f2543Smrg if (WINREC(pTopWin) != NULL) { 1373706f2543Smrg /* We're screwed. */ 1374706f2543Smrg RootlessDestroyFrame(pWin, winRec); 1375706f2543Smrg } else { 1376706f2543Smrg if (!pTopWin->realized && pWin->realized) { 1377706f2543Smrg SCREENREC(pScreen)->imp->UnmapFrame(winRec->wid); 1378706f2543Smrg } 1379706f2543Smrg 1380706f2543Smrg /* Switch the frame record from one to the other. */ 1381706f2543Smrg 1382706f2543Smrg SETWINREC(pWin, NULL); 1383706f2543Smrg SETWINREC(pTopWin, winRec); 1384706f2543Smrg 1385706f2543Smrg RootlessInitializeFrame(pTopWin, winRec); 1386706f2543Smrg RootlessReshapeFrame(pTopWin); 1387706f2543Smrg 1388706f2543Smrg SCREENREC(pScreen)->imp->ResizeFrame(winRec->wid, pScreen, 1389706f2543Smrg winRec->x + SCREEN_TO_GLOBAL_X, 1390706f2543Smrg winRec->y + SCREEN_TO_GLOBAL_Y, 1391706f2543Smrg winRec->width, winRec->height, 1392706f2543Smrg RL_GRAVITY_NONE); 1393706f2543Smrg 1394706f2543Smrg if (SCREENREC(pScreen)->imp->SwitchWindow) { 1395706f2543Smrg SCREENREC(pScreen)->imp->SwitchWindow(winRec, pWin); 1396706f2543Smrg } 1397706f2543Smrg 1398706f2543Smrg if (pTopWin->realized && !pWin->realized) 1399706f2543Smrg winRec->is_reorder_pending = TRUE; 1400706f2543Smrg } 1401706f2543Smrg 1402706f2543Smrgout: 1403706f2543Smrg if (SCREENREC(pScreen)->ReparentWindow) { 1404706f2543Smrg SCREEN_UNWRAP(pScreen, ReparentWindow); 1405706f2543Smrg pScreen->ReparentWindow(pWin, pPriorParent); 1406706f2543Smrg SCREEN_WRAP(pScreen, ReparentWindow); 1407706f2543Smrg } 1408706f2543Smrg} 1409706f2543Smrg 1410706f2543Smrg 1411706f2543Smrgvoid 1412706f2543SmrgRootlessFlushWindowColormap (WindowPtr pWin) 1413706f2543Smrg{ 1414706f2543Smrg RootlessWindowRec *winRec = WINREC (pWin); 1415706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1416706f2543Smrg 1417706f2543Smrg if (winRec == NULL) 1418706f2543Smrg return; 1419706f2543Smrg 1420706f2543Smrg RootlessStopDrawing (pWin, FALSE); 1421706f2543Smrg 1422706f2543Smrg if (SCREENREC(pScreen)->imp->UpdateColormap) 1423706f2543Smrg SCREENREC(pScreen)->imp->UpdateColormap(winRec->wid, pScreen); 1424706f2543Smrg} 1425706f2543Smrg 1426706f2543Smrg/* 1427706f2543Smrg * RootlessChangeBorderWidth 1428706f2543Smrg * FIXME: untested! 1429706f2543Smrg * pWin inside corner stays the same; pWin->drawable.[xy] stays the same 1430706f2543Smrg * Frame moves and resizes. 1431706f2543Smrg */ 1432706f2543Smrgvoid 1433706f2543SmrgRootlessChangeBorderWidth(WindowPtr pWin, unsigned int width) 1434706f2543Smrg{ 1435706f2543Smrg RegionRec saveRoot; 1436706f2543Smrg Bool resize_after = FALSE; 1437706f2543Smrg 1438706f2543Smrg RL_DEBUG_MSG("change border width "); 1439706f2543Smrg 1440706f2543Smrg if (width != wBorderWidth(pWin)) { 1441706f2543Smrg RootlessWindowRec *winRec = WINREC(pWin); 1442706f2543Smrg int oldX = 0, oldY = 0, newX = 0, newY = 0; 1443706f2543Smrg unsigned int oldW = 0, oldH = 0, oldBW = 0; 1444706f2543Smrg unsigned int newW = 0, newH = 0, newBW = 0; 1445706f2543Smrg 1446706f2543Smrg if (winRec) { 1447706f2543Smrg oldBW = winRec->borderWidth; 1448706f2543Smrg oldX = winRec->x; 1449706f2543Smrg oldY = winRec->y; 1450706f2543Smrg oldW = winRec->width; 1451706f2543Smrg oldH = winRec->height; 1452706f2543Smrg 1453706f2543Smrg newBW = width; 1454706f2543Smrg newX = pWin->drawable.x - newBW; 1455706f2543Smrg newY = pWin->drawable.y - newBW; 1456706f2543Smrg newW = pWin->drawable.width + 2*newBW; 1457706f2543Smrg newH = pWin->drawable.height + 2*newBW; 1458706f2543Smrg 1459706f2543Smrg resize_after = StartFrameResize(pWin, FALSE, 1460706f2543Smrg oldX, oldY, oldW, oldH, oldBW, 1461706f2543Smrg newX, newY, newW, newH, newBW); 1462706f2543Smrg } 1463706f2543Smrg 1464706f2543Smrg HUGE_ROOT(pWin); 1465706f2543Smrg SCREEN_UNWRAP(pWin->drawable.pScreen, ChangeBorderWidth); 1466706f2543Smrg pWin->drawable.pScreen->ChangeBorderWidth(pWin, width); 1467706f2543Smrg SCREEN_WRAP(pWin->drawable.pScreen, ChangeBorderWidth); 1468706f2543Smrg NORMAL_ROOT(pWin); 1469706f2543Smrg 1470706f2543Smrg if (winRec) { 1471706f2543Smrg FinishFrameResize(pWin, FALSE, oldX, oldY, oldW, oldH, oldBW, 1472706f2543Smrg newX, newY, newW, newH, newBW, resize_after); 1473706f2543Smrg } 1474706f2543Smrg } 1475706f2543Smrg 1476706f2543Smrg RL_DEBUG_MSG("change border width end\n"); 1477706f2543Smrg} 1478706f2543Smrg 1479706f2543Smrg/* 1480706f2543Smrg * RootlessOrderAllWindows 1481706f2543Smrg * Brings all X11 windows to the top of the window stack 1482706f2543Smrg * (i.e in front of Aqua windows) -- called when X11.app is given focus 1483706f2543Smrg */ 1484706f2543Smrgvoid 1485706f2543SmrgRootlessOrderAllWindows (Bool include_unhitable) 1486706f2543Smrg{ 1487706f2543Smrg int i; 1488706f2543Smrg WindowPtr pWin; 1489706f2543Smrg 1490706f2543Smrg if (windows_hidden) 1491706f2543Smrg return; 1492706f2543Smrg 1493706f2543Smrg RL_DEBUG_MSG("RootlessOrderAllWindows() "); 1494706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) { 1495706f2543Smrg if (screenInfo.screens[i] == NULL) continue; 1496706f2543Smrg pWin = screenInfo.screens[i]->root; 1497706f2543Smrg if (pWin == NULL) continue; 1498706f2543Smrg 1499706f2543Smrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) { 1500706f2543Smrg if (!pWin->realized) continue; 1501706f2543Smrg if (RootlessEnsureFrame(pWin) == NULL) continue; 1502706f2543Smrg if (!include_unhitable && pWin->rootlessUnhittable) continue; 1503706f2543Smrg RootlessReorderWindow (pWin); 1504706f2543Smrg } 1505706f2543Smrg } 1506706f2543Smrg RL_DEBUG_MSG("RootlessOrderAllWindows() done"); 1507706f2543Smrg} 1508706f2543Smrg 1509706f2543Smrgvoid 1510706f2543SmrgRootlessEnableRoot (ScreenPtr pScreen) 1511706f2543Smrg{ 1512706f2543Smrg WindowPtr pRoot; 1513706f2543Smrg pRoot = pScreen->root; 1514706f2543Smrg 1515706f2543Smrg RootlessEnsureFrame (pRoot); 1516706f2543Smrg (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE); 1517706f2543Smrg RootlessReorderWindow (pRoot); 1518706f2543Smrg} 1519706f2543Smrg 1520706f2543Smrgvoid 1521706f2543SmrgRootlessDisableRoot (ScreenPtr pScreen) 1522706f2543Smrg{ 1523706f2543Smrg WindowPtr pRoot; 1524706f2543Smrg RootlessWindowRec *winRec; 1525706f2543Smrg 1526706f2543Smrg pRoot = pScreen->root; 1527706f2543Smrg winRec = WINREC (pRoot); 1528706f2543Smrg 1529706f2543Smrg if (NULL == winRec) 1530706f2543Smrg return; 1531706f2543Smrg 1532706f2543Smrg RootlessDestroyFrame (pRoot, winRec); 1533706f2543Smrg DeleteProperty (serverClient, pRoot, xa_native_window_id ()); 1534706f2543Smrg} 1535706f2543Smrg 1536706f2543Smrgvoid 1537706f2543SmrgRootlessHideAllWindows (void) 1538706f2543Smrg{ 1539706f2543Smrg int i; 1540706f2543Smrg ScreenPtr pScreen; 1541706f2543Smrg WindowPtr pWin; 1542706f2543Smrg RootlessWindowRec *winRec; 1543706f2543Smrg 1544706f2543Smrg if (windows_hidden) 1545706f2543Smrg return; 1546706f2543Smrg 1547706f2543Smrg windows_hidden = TRUE; 1548706f2543Smrg 1549706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 1550706f2543Smrg { 1551706f2543Smrg pScreen = screenInfo.screens[i]; 1552706f2543Smrg if (pScreen == NULL) 1553706f2543Smrg continue; 1554706f2543Smrg pWin = pScreen->root; 1555706f2543Smrg if (pWin == NULL) 1556706f2543Smrg continue; 1557706f2543Smrg 1558706f2543Smrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 1559706f2543Smrg { 1560706f2543Smrg if (!pWin->realized) 1561706f2543Smrg continue; 1562706f2543Smrg 1563706f2543Smrg RootlessStopDrawing (pWin, FALSE); 1564706f2543Smrg 1565706f2543Smrg winRec = WINREC (pWin); 1566706f2543Smrg if (winRec != NULL) 1567706f2543Smrg { 1568706f2543Smrg if (SCREENREC(pScreen)->imp->HideWindow) 1569706f2543Smrg SCREENREC(pScreen)->imp->HideWindow(winRec->wid); 1570706f2543Smrg } 1571706f2543Smrg } 1572706f2543Smrg } 1573706f2543Smrg} 1574706f2543Smrg 1575706f2543Smrgvoid 1576706f2543SmrgRootlessShowAllWindows (void) 1577706f2543Smrg{ 1578706f2543Smrg int i; 1579706f2543Smrg ScreenPtr pScreen; 1580706f2543Smrg WindowPtr pWin; 1581706f2543Smrg RootlessWindowRec *winRec; 1582706f2543Smrg 1583706f2543Smrg if (!windows_hidden) 1584706f2543Smrg return; 1585706f2543Smrg 1586706f2543Smrg windows_hidden = FALSE; 1587706f2543Smrg 1588706f2543Smrg for (i = 0; i < screenInfo.numScreens; i++) 1589706f2543Smrg { 1590706f2543Smrg pScreen = screenInfo.screens[i]; 1591706f2543Smrg if (pScreen == NULL) 1592706f2543Smrg continue; 1593706f2543Smrg pWin = pScreen->root; 1594706f2543Smrg if (pWin == NULL) 1595706f2543Smrg continue; 1596706f2543Smrg 1597706f2543Smrg for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib) 1598706f2543Smrg { 1599706f2543Smrg if (!pWin->realized) 1600706f2543Smrg continue; 1601706f2543Smrg 1602706f2543Smrg winRec = RootlessEnsureFrame (pWin); 1603706f2543Smrg if (winRec == NULL) 1604706f2543Smrg continue; 1605706f2543Smrg 1606706f2543Smrg RootlessReorderWindow (pWin); 1607706f2543Smrg } 1608706f2543Smrg 1609706f2543Smrg RootlessScreenExpose (pScreen); 1610706f2543Smrg } 1611706f2543Smrg} 1612706f2543Smrg 1613706f2543Smrg/* 1614706f2543Smrg * SetPixmapOfAncestors 1615706f2543Smrg * Set the Pixmaps on all ParentRelative windows up the ancestor chain. 1616706f2543Smrg */ 1617706f2543Smrgvoid 1618706f2543SmrgRootlessSetPixmapOfAncestors(WindowPtr pWin) 1619706f2543Smrg{ 1620706f2543Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 1621706f2543Smrg WindowPtr topWin = TopLevelParent(pWin); 1622706f2543Smrg RootlessWindowRec *topWinRec = WINREC(topWin); 1623706f2543Smrg 1624706f2543Smrg while (pWin->backgroundState == ParentRelative) { 1625706f2543Smrg if (pWin == topWin) { 1626706f2543Smrg // disallow ParentRelative background state on top level 1627706f2543Smrg XID pixel = 0; 1628706f2543Smrg ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient); 1629706f2543Smrg RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin); 1630706f2543Smrg break; 1631706f2543Smrg } 1632706f2543Smrg 1633706f2543Smrg pWin = pWin->parent; 1634706f2543Smrg pScreen->SetWindowPixmap(pWin, topWinRec->pixmap); 1635706f2543Smrg } 1636706f2543Smrg} 1637706f2543Smrg 1638