2 * Rootless window management
5 * Copyright (c) 2001 Greg Parker. All Rights Reserved.
6 * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
7 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
27 * Except as contained in this notice, the name(s) of the above copyright
28 * holders shall not be used in advertising or otherwise to promote the sale,
29 * use or other dealings in this Software without prior written authorization.
31 /* Portions of this file are based on fbwindow.c, which contains the
32 * following copyright:
34 * Copyright © 1998 Keith Packard
36 /* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c,v 1.11 2002/09/28 00:43:39 torrey Exp $ */
38 #include "rootless-common.h"
39 #include "rootless-window.h"
44 #define _APPLEWM_SERVER_
45 #include "applewmstr.h"
48 #include "propertyst.h"
51 #include "panoramiX.h"
52 #include "panoramiXsrv.h"
55 #include <X11/Xatom.h>
58 #define DEFINE_ATOM_HELPER(func,atom_name) \
59 static Atom func (void) { \
60 static unsigned int generation; \
62 if (generation != serverGeneration) { \
63 generation = serverGeneration; \
64 atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
69 DEFINE_ATOM_HELPER (xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
70 DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
71 DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
73 /* Maps xp_window_id -> AquaWindowRec */
74 static x_hash_table *window_hash;
75 static pthread_mutex_t window_hash_mutex;
77 static Bool no_configure_window;
78 static Bool windows_hidden;
80 static const int normal_window_levels[AppleWMNumWindowLevels+1] = {
81 0, 3, 4, 5, LONG_MIN + 30, LONG_MIN + 29,
83 static const int rooted_window_levels[AppleWMNumWindowLevels+1] = {
84 202, 203, 204, 205, 201, 200
87 static inline xp_error
88 configure_window (xp_window_id id, unsigned int mask,
89 const xp_window_changes *values)
91 if (!no_configure_window)
92 return xp_configure_window (id, mask, values);
97 static inline unsigned long
98 current_time_in_seconds (void)
102 t += currentTime.milliseconds / 1000;
103 t += currentTime.months * 4294967;
109 rootlessHasRoot (ScreenPtr pScreen)
111 return WINREC (WindowTable[pScreen->myNum]) != NULL;
115 RootlessNativeWindowStateChanged (xp_window_id id, unsigned int state)
118 RootlessWindowRec *winRec;
120 pWin = RootlessGetXWindow (id);
124 winRec = WINREC (pWin);
128 winRec->is_offscreen = (state & XP_WINDOW_STATE_OFFSCREEN) != 0;
129 winRec->is_obscured = (state & XP_WINDOW_STATE_OBSCURED) != 0;
132 pWin->rootlessUnhittable = winRec->is_offscreen;
137 RootlessNativeWindowMoved (xp_window_id id)
146 pWin = RootlessGetXWindow (id);
150 if (xp_get_window_bounds (id, &bounds) != Success)
153 sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX;
154 sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY;
156 /* Fake up a ConfigureWindow packet to resize the window to the
159 vlist[0] = (INT16) bounds.x1 - sx;
160 vlist[1] = (INT16) bounds.y1 - sy;
163 /* pretend we're the owner of the window! */
164 client = LookupClient (pWin->drawable.id, NullClient);
166 /* Don't want to do anything to the physical window (avoids
167 notification-response feedback loops) */
169 no_configure_window = TRUE;
170 ConfigureWindow (pWin, mask, vlist, client);
171 no_configure_window = FALSE;
174 /* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
176 set_screen_origin (WindowPtr pWin)
183 /* FIXME: move this to an extension? */
185 data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
186 + darwinMainScreenX);
187 data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
188 + darwinMainScreenY);
190 ChangeWindowProperty (pWin, xa_native_screen_origin (), XA_INTEGER,
191 32, PropModeReplace, 2, data, TRUE);
194 /* For now, don't create a physical window until either the window is
195 realized, or we really need it (e.g. to attach VRAM surfaces to).
196 Do reset the window size so it's not clipped by the root window. */
198 RootlessCreateWindow (WindowPtr pWin)
203 SCREEN_UNWRAP (pWin->drawable.pScreen, CreateWindow);
207 /* win/border size set by DIX, not by wrapped CreateWindow, so
208 correct it here. Don't HUGE_ROOT when pWin is the root! */
212 SetBorderSize (pWin);
216 set_screen_origin (pWin);
219 result = pWin->drawable.pScreen->CreateWindow (pWin);
224 SCREEN_WRAP (pWin->drawable.pScreen, CreateWindow);
229 /* Destroy the physical window associated with the given window */
231 rootlessDestroyFrame (WindowPtr pWin, RootlessWindowRec *winRec)
233 RootlessStopDrawing (pWin, FALSE);
235 pthread_mutex_lock (&window_hash_mutex);
236 x_hash_table_remove (window_hash, (void *) winRec->wid);
237 pthread_mutex_unlock (&window_hash_mutex);
239 xp_destroy_window (winRec->wid);
242 WINREC (pWin) = NULL;
246 RootlessDestroyWindow (WindowPtr pWin)
248 RootlessWindowRec *winRec = WINREC(pWin);
252 rootlessDestroyFrame (pWin, winRec);
254 /* winRec is gone now */
256 SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
258 result = pWin->drawable.pScreen->DestroyWindow (pWin);
260 SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
267 RootlessGetShape (WindowPtr pWin, RegionPtr pShape)
269 if (wBoundingShape (pWin) == NULL)
272 /* wBoundingShape is relative to *inner* origin of window.
273 Translate by borderWidth to get the outside-relative position. */
275 REGION_INIT (pScreen, pShape, NullBox, 0);
276 REGION_COPY (pScreen, pShape, wBoundingShape (pWin));
277 REGION_TRANSLATE (pScreen, pShape, pWin->borderWidth, pWin->borderWidth);
282 /* boundingShape = outside border (like borderClip)
283 clipShape = inside border (like clipList)
284 Both are in window-local coordinates
285 We only care about boundingShape (FIXME true?)
287 RootlessReallySetShape is used in several places other than SetShape.
288 Most importantly, SetShape is often called on unmapped windows, so we
289 have to wait until the window is mapped to reshape the frame. */
291 rootlessSetShape (WindowPtr pWin)
293 RootlessWindowRec *winRec = WINREC (pWin);
297 xp_window_changes wc;
302 RootlessStopDrawing (pWin, FALSE);
304 pShape = RootlessGetShape (pWin, &newShape) ? &newShape : NULL;
306 RL_DEBUG_MSG("reshaping...");
307 RL_DEBUG_MSG("numrects %d, extents %d %d %d %d\n",
308 REGION_NUM_RECTS(&newShape),
309 newShape.extents.x1, newShape.extents.y1,
310 newShape.extents.x2, newShape.extents.y2);
312 RootlessDisableUpdate (pWin);
316 wc.shape_nrects = REGION_NUM_RECTS (pShape);
317 wc.shape_rects = REGION_RECTS (pShape);
321 wc.shape_nrects = -1;
322 wc.shape_rects = NULL;
325 wc.shape_tx = wc.shape_ty = 0;
327 configure_window (winRec->wid, XP_SHAPE, &wc);
330 REGION_UNINIT(pScreen, &newShape);
334 RootlessSetShape (WindowPtr pWin)
336 ScreenPtr pScreen = pWin->drawable.pScreen;
338 SCREEN_UNWRAP (pScreen, SetShape);
340 pScreen->SetShape (pWin);
342 SCREEN_WRAP (pScreen, SetShape);
344 rootlessSetShape (pWin);
348 /* Disallow ParentRelative background on top-level windows
349 because the root window doesn't really have the right background
350 and fb will try to draw on the root instead of on the window.
351 ParentRelative prevention is also in PaintWindowBackground/Border()
352 so it is no longer really needed here. */
354 RootlessChangeWindowAttributes (WindowPtr pWin, unsigned long vmask)
357 ScreenPtr pScreen = pWin->drawable.pScreen;
359 RL_DEBUG_MSG("change window attributes start\n");
361 SCREEN_UNWRAP (pScreen, ChangeWindowAttributes);
363 result = pScreen->ChangeWindowAttributes (pWin, vmask);
365 SCREEN_WRAP (pScreen, ChangeWindowAttributes);
367 if (WINREC (pWin) != NULL)
369 /* disallow ParentRelative background state */
371 if (pWin->backgroundState == ParentRelative)
374 ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
378 RL_DEBUG_MSG("change window attributes end\n");
382 /* This is a hook for when DIX moves or resizes a window.
383 Update the frame position now. (x, y) are *inside* position.
384 After this, mi and fb are expecting the pixmap to be at the new location. */
386 RootlessPositionWindow (WindowPtr pWin, int x, int y)
388 ScreenPtr pScreen = pWin->drawable.pScreen;
389 RootlessWindowRec *winRec = WINREC (pWin);
392 RL_DEBUG_MSG("positionwindow start (win 0x%x)\n", pWin);
396 if (winRec->is_drawing)
398 /* Reset frame's pixmap and move it to the new position. */
399 int bw = wBorderWidth (pWin);
401 winRec->pixmap->devPrivate.ptr = winRec->data;
402 TranslatePixmapBase (winRec->pixmap, - (x - bw), - (y - bw));
406 SCREEN_UNWRAP (pScreen, PositionWindow);
408 result = pScreen->PositionWindow (pWin, x, y);
410 SCREEN_WRAP(pScreen, PositionWindow);
412 RL_DEBUG_MSG("positionwindow end\n");
416 /* Initialize some basic attributes of the frame. Note that winRec
417 may already have valid data in it, so don't overwrite anything
420 rootlessInitializeFrame (WindowPtr pWin, RootlessWindowRec *winRec)
422 DrawablePtr d = &pWin->drawable;
423 int bw = wBorderWidth (pWin);
427 winRec->x = d->x - bw;
428 winRec->y = d->y - bw;
429 winRec->width = d->width + 2*bw;
430 winRec->height = d->height + 2*bw;
431 winRec->borderWidth = bw;
435 rootlessSetNativeProperty (RootlessWindowRec *winRec)
438 unsigned int native_id;
441 err = xp_get_native_window (winRec->wid, &native_id);
444 /* FIXME: move this to an extension? */
447 ChangeWindowProperty (winRec->win, xa_native_window_id (),
448 XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
453 rootlessColormapCallback (void *data, int first_color,
454 int n_colors, uint32_t *colors)
456 return (RootlessResolveColormap (data, first_color, n_colors, colors)
457 ? XP_Success : XP_BadMatch);
460 /* If the given window doesn't have a physical window associated with it,
461 attempt to create one. If that's unsuccessful, return null. */
462 static RootlessWindowRec *
463 rootlessEnsureFrame (WindowPtr pWin)
465 ScreenPtr pScreen = pWin->drawable.pScreen;
466 RootlessWindowRec *winRec;
468 RegionPtr pShape = NULL;
470 xp_window_changes wc;
475 if (WINREC (pWin) != NULL)
476 return WINREC (pWin);
478 if (pWin->drawable.class != InputOutput)
481 winRec = xalloc (sizeof(RootlessWindowRec));
486 rootlessInitializeFrame (pWin, winRec);
488 winRec->is_drawing = FALSE;
489 winRec->pixmap = NULL;
491 winRec->is_update_disabled = FALSE;
492 winRec->is_reorder_pending = FALSE;
493 winRec->level = !IsRoot (pWin) ? 0 : AppleWMNumWindowLevels;
494 WINREC(pWin) = winRec;
497 if (RootlessGetShape (pWin, &shape))
501 sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
502 sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
506 wc.x = sx + winRec->x;
507 wc.y = sy + winRec->y;
508 wc.width = winRec->width;
509 wc.height = winRec->height;
510 wc.bit_gravity = XP_GRAVITY_NONE;
513 if (pWin->drawable.depth == 8)
515 wc.depth = XP_DEPTH_INDEX8;
516 wc.colormap = rootlessColormapCallback;
517 wc.colormap_data = pScreen;
520 else if (pWin->drawable.depth == 15)
521 wc.depth = XP_DEPTH_RGB555;
522 else if (pWin->drawable.depth == 24)
523 wc.depth = XP_DEPTH_ARGB8888;
525 wc.depth = XP_DEPTH_NIL;
530 wc.shape_nrects = REGION_NUM_RECTS (pShape);
531 wc.shape_rects = REGION_RECTS (pShape);
532 wc.shape_tx = wc.shape_ty = 0;
536 if (!rootlessHasRoot (pScreen))
537 wc.window_level = normal_window_levels[winRec->level];
539 wc.window_level = rooted_window_levels[winRec->level];
540 mask |= XP_WINDOW_LEVEL;
542 err = xp_create_window (mask, &wc, &winRec->wid);
550 if (window_hash == NULL)
552 window_hash = x_hash_table_new (NULL, NULL, NULL, NULL);
553 pthread_mutex_init (&window_hash_mutex, NULL);
556 pthread_mutex_lock (&window_hash_mutex);
557 x_hash_table_insert (window_hash, (void *) winRec->wid, winRec);
558 pthread_mutex_unlock (&window_hash_mutex);
560 rootlessSetNativeProperty (winRec);
563 REGION_UNINIT (pScreen, &shape);
568 /* The frame is usually created here and not in CreateWindow so that
569 windows do not eat memory until they are realized. */
571 RootlessRealizeWindow(WindowPtr pWin)
575 ScreenPtr pScreen = pWin->drawable.pScreen;
578 RL_DEBUG_MSG("realizewindow start (win 0x%x)\n", pWin);
580 if (IsTopLevel (pWin) && pWin->drawable.class == InputOutput)
582 RootlessWindowRec *winRec;
584 winRec = rootlessEnsureFrame (pWin);
588 winRec->is_reorder_pending = TRUE;
590 /* Disallow ParentRelative background state on top-level windows.
591 This might have been set before the window was mapped. */
593 if (pWin->backgroundState == ParentRelative)
596 ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
600 if (!IsRoot(pWin)) HUGE_ROOT(pWin);
601 SCREEN_UNWRAP (pScreen, RealizeWindow);
603 result = pScreen->RealizeWindow (pWin);
605 SCREEN_WRAP (pScreen, RealizeWindow);
606 if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
608 RL_DEBUG_MSG("realizewindow end\n");
613 RootlessEnableRoot (ScreenPtr pScreen)
616 pRoot = WindowTable[pScreen->myNum];
618 rootlessEnsureFrame (pRoot);
619 (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
620 RootlessReorderWindow (pRoot);
624 RootlessDisableRoot (ScreenPtr pScreen)
627 RootlessWindowRec *winRec;
629 pRoot = WindowTable[pScreen->myNum];
630 winRec = WINREC (pRoot);
634 rootlessDestroyFrame (pRoot, winRec);
635 DeleteProperty (pRoot, xa_native_window_id ());
640 RootlessHideAllWindows (void)
645 RootlessWindowRec *winRec;
646 xp_window_changes wc;
651 windows_hidden = TRUE;
653 for (i = 0; i < screenInfo.numScreens; i++)
655 pScreen = screenInfo.screens[i];
656 pWin = WindowTable[i];
657 if (pScreen == NULL || pWin == NULL)
660 for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
665 RootlessStopDrawing (pWin, FALSE);
667 winRec = WINREC (pWin);
670 wc.stack_mode = XP_UNMAPPED;
672 configure_window (winRec->wid, XP_STACKING, &wc);
679 RootlessShowAllWindows (void)
684 RootlessWindowRec *winRec;
689 windows_hidden = FALSE;
691 for (i = 0; i < screenInfo.numScreens; i++)
693 pScreen = screenInfo.screens[i];
694 pWin = WindowTable[i];
695 if (pScreen == NULL || pWin == NULL)
698 for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
703 winRec = rootlessEnsureFrame (pWin);
707 RootlessReorderWindow (pWin);
710 RootlessScreenExpose (pScreen);
715 RootlessSetWindowLevel (WindowPtr pWin, int level)
717 RootlessWindowRec *winRec;
718 xp_window_changes wc;
720 winRec = WINREC (pWin);
721 if (!IsTopLevel (pWin) || winRec == NULL || winRec->level == level)
724 RootlessStopDrawing (pWin, FALSE);
726 winRec->level = level;
728 if (!rootlessHasRoot (pWin->drawable.pScreen))
729 wc.window_level = normal_window_levels[level];
731 wc.window_level = rooted_window_levels[level];
733 configure_window (winRec->wid, XP_WINDOW_LEVEL, &wc);
736 /* Return the id of the physical window displaying the given window. If
737 CREATE is true and the window has no frame, attempt to create one. */
739 RootlessGetPhysicalWindow (WindowPtr pWin, Bool create)
741 RootlessWindowRec *winRec;
743 if (TopLevelParent (pWin) == NULL)
746 winRec = WINREC (pWin);
748 if (winRec == NULL && create && !IsRoot (pWin)
749 && pWin->drawable.class == InputOutput)
751 rootlessEnsureFrame (pWin);
752 winRec = WINREC (pWin);
761 /* Given the id of a physical window, try to find the top-level (or root)
762 X window that it represents. */
764 RootlessGetXWindow (xp_window_id wid)
766 RootlessWindowRec *winRec;
768 if (window_hash == NULL)
771 winRec = x_hash_table_lookup (window_hash, (void *) wid, NULL);
773 return winRec != NULL ? winRec->win : NULL;
776 /* Number is an appkit window number. Returns true if X is displaying
777 a window with that number. */
779 RootlessKnowsWindowNumber (int number)
784 /* need to lock, since this function can be called by any thread */
786 if (window_hash == NULL)
789 pthread_mutex_lock (&window_hash_mutex);
791 if (xp_lookup_native_window (number, &wid))
792 ret = RootlessGetXWindow (wid) != NULL;
796 pthread_mutex_unlock (&window_hash_mutex);
802 RootlessUnrealizeWindow (WindowPtr pWin)
804 ScreenPtr pScreen = pWin->drawable.pScreen;
805 RootlessWindowRec *winRec = WINREC(pWin);
806 xp_window_changes wc;
809 RL_DEBUG_MSG("unrealizewindow start\n");
813 RootlessStopDrawing (pWin, FALSE);
815 wc.stack_mode = XP_UNMAPPED;
818 configure_window (winRec->wid, XP_STACKING, &wc);
820 winRec->unrealize_time = current_time_in_seconds ();
821 winRec->is_reorder_pending = FALSE;
823 RootlessReenableUpdate (pWin);
826 SCREEN_UNWRAP (pScreen, UnrealizeWindow);
828 result = pScreen->UnrealizeWindow (pWin);
830 SCREEN_WRAP (pScreen, UnrealizeWindow);
832 RL_DEBUG_MSG ("unrealizewindow end\n");
837 RootlessReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
839 ScreenPtr pScreen = pWin->drawable.pScreen;
840 RootlessWindowRec *winRec = WINREC (pWin);
844 if (IsRoot (pWin) || IsRoot (pWin->parent)
845 || IsTopLevel (pWin) || winRec == NULL)
850 /* If the window is moving upwards towards the root has a frame,
851 we want to try to move it onto its new toplevel parent. If we
852 can't do that, we'll just have to jettison it.. */
854 pTopWin = TopLevelParent (pWin);
855 assert (pTopWin != pWin);
857 pWin->rootlessUnhittable = FALSE;
859 DeleteProperty (pWin, xa_native_window_id ());
861 if (WINREC (pTopWin) != NULL)
864 rootlessDestroyFrame (pWin, winRec);
868 xp_window_changes wc;
871 if (!pTopWin->realized && pWin->realized)
873 wc.stack_mode = XP_UNMAPPED;
876 RootlessStopDrawing (pWin, FALSE);
877 configure_window (winRec->wid, XP_STACKING, &wc);
880 /* Switch the frame record from one to the other. */
882 WINREC (pWin) = NULL;
883 WINREC (pTopWin) = winRec;
885 rootlessInitializeFrame (pTopWin, winRec);
886 rootlessSetShape (pTopWin);
888 sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
889 sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
891 wc.x = sx + winRec->x;
892 wc.y = sy + winRec->y;
893 wc.width = winRec->width;
894 wc.height = winRec->height;
895 wc.bit_gravity = XP_GRAVITY_NONE;
897 RootlessStopDrawing (pWin, FALSE);
898 configure_window (winRec->wid, XP_BOUNDS, &wc);
900 rootlessSetNativeProperty (winRec);
902 if (pTopWin->realized && !pWin->realized)
903 winRec->is_reorder_pending = TRUE;
907 /* Reorder the window associated with the given frame so that it's
908 physically above the window below it in the X stacking order. */
910 RootlessReorderWindow (WindowPtr pWin)
912 RootlessWindowRec *winRec = WINREC (pWin);
914 if (pWin->realized && winRec != NULL
915 && !winRec->is_reorder_pending && !windows_hidden)
918 RootlessWindowRec *newPrev;
919 xp_window_changes wc;
923 /* quartz-wm sets the _APPLE_NO_ORDER_IN property on windows
924 that are being genie-restored from the Dock. We want them to
925 be mapped but remain ordered-out until the animation
926 completes (when the Dock will order them in) */
928 atom = xa_apple_no_order_in ();
929 for (prop = wUserProps (pWin); prop != NULL; prop = prop->next)
931 if (prop->propertyName == atom && prop->type == atom)
935 RootlessStopDrawing (pWin, FALSE);
939 wc.stack_mode = XP_MAPPED_BELOW;
944 /* Find the next window above this one that has a mapped frame. */
946 newPrevW = pWin->prevSib;
948 && (WINREC (newPrevW) == NULL || !newPrevW->realized))
950 newPrevW = newPrevW->prevSib;
953 newPrev = newPrevW != NULL ? WINREC (newPrevW) : NULL;
955 /* Then either stack ourselves below it if it exists, or raise
956 ourselves above everything otherwise. */
960 wc.stack_mode = XP_MAPPED_ABOVE;
965 if (newPrev->is_reorder_pending)
967 newPrev->is_reorder_pending = FALSE;
968 RootlessReorderWindow (newPrevW);
971 wc.stack_mode = XP_MAPPED_BELOW;
972 wc.sibling = newPrev->wid;
976 configure_window (winRec->wid, XP_STACKING, &wc);
981 RootlessRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
984 RootlessWindowRec *winRec = WINREC (pWin);
985 ScreenPtr pScreen = pWin->drawable.pScreen;
987 RL_DEBUG_MSG("restackwindow start\n");
989 RL_DEBUG_MSG("restack top level \n");
992 SCREEN_UNWRAP(pScreen, RestackWindow);
994 if (pScreen->RestackWindow != NULL)
995 pScreen->RestackWindow (pWin, pOldNextSib);
997 SCREEN_WRAP(pScreen, RestackWindow);
1000 if (winRec != NULL && pWin->viewable)
1001 RootlessReorderWindow (pWin);
1003 RL_DEBUG_MSG("restackwindow end\n");
1007 * Specialized window copy procedures
1010 /* Globals needed during window resize and move. */
1011 static pointer gResizeDeathBits = NULL;
1012 static int gResizeDeathCount;
1013 static PixmapPtr gResizeDeathPix[2];
1014 static BoxRec gResizeDeathBounds[2];
1015 static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
1017 /* CopyWindow () that doesn't do anything. For MoveWindow() of
1018 top-level windows. */
1020 RootlessNoCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
1022 /* Some code expects the region to be translated */
1024 int dx = ptOldOrg.x - pWin->drawable.x;
1025 int dy = ptOldOrg.y - pWin->drawable.y;
1027 REGION_TRANSLATE (pWin->drawable.pScreen, prgnSrc, -dx, -dy);
1030 /* CopyWindow used during ResizeWindow for gravity moves. (from fbCopyWindow)
1031 The original always draws on the root pixmap (which we don't have).
1032 Instead, draw on the parent window's pixmap.
1033 Resize version: the old location's pixels are in gResizeCopyWindowSource */
1035 RootlessResizeCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg,
1038 ScreenPtr pScreen = pWin->drawable.pScreen;
1042 RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x)\n", pWin);
1044 /* Don't unwrap pScreen->CopyWindow.
1045 The bogus rewrap with RootlessCopyWindow causes a crash if
1046 CopyWindow is called again during the same resize. */
1048 if (gResizeDeathCount == 0)
1051 RootlessStartDrawing (pWin);
1053 dx = ptOldOrg.x - pWin->drawable.x;
1054 dy = ptOldOrg.y - pWin->drawable.y;
1055 REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
1056 REGION_INIT (pScreen, &rgnDst, NullBox, 0);
1057 REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
1059 if (gResizeDeathCount == 1)
1061 /* Simple case, we only have a single source pixmap. */
1063 fbCopyRegion (&gResizeDeathPix[0]->drawable,
1064 &pScreen->GetWindowPixmap(pWin)->drawable, 0,
1065 &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
1070 RegionRec clip, clipped;
1072 /* More complex case, N source pixmaps (usually two). So we
1073 intersect the destination with each source and copy those bits. */
1075 for (i = 0; i < gResizeDeathCount; i++)
1077 REGION_INIT (pScreen, &clip, gResizeDeathBounds + 0, 1);
1078 REGION_INIT (pScreen, &clipped, NullBox, 0);
1079 REGION_INTERSECT (pScreen, &rgnDst, &clip, &clipped);
1081 fbCopyRegion (&gResizeDeathPix[i]->drawable,
1082 &pScreen->GetWindowPixmap(pWin)->drawable, 0,
1083 &clipped, dx, dy, fbCopyWindowProc, 0, 0);
1085 REGION_UNINIT (pScreen, &clipped);
1086 REGION_UNINIT (pScreen, &clip);
1090 /* Don't update - resize will update everything */
1091 REGION_UNINIT (pScreen, &rgnDst);
1093 fbValidateDrawable (&pWin->drawable);
1095 RL_DEBUG_MSG("resizecopywindowFB end\n");
1098 /* Update *new* location of window. Old location is redrawn with
1099 PaintWindowBackground/Border. Cloned from fbCopyWindow
1100 The original always draws on the root pixmap (which we don't have).
1101 Instead, draw on the parent window's pixmap. */
1103 RootlessCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
1105 ScreenPtr pScreen = pWin->drawable.pScreen;
1106 RootlessWindowRec *winRec;
1114 RL_DEBUG_MSG("copywindowFB start (win 0x%x)\n", pWin);
1116 top = TopLevelParent (pWin);
1119 RL_DEBUG_MSG("no parent\n");
1123 winRec = WINREC(top);
1126 RL_DEBUG_MSG("not framed\n");
1130 SCREEN_UNWRAP (pScreen, CopyWindow);
1132 dx = ptOldOrg.x - pWin->drawable.x;
1133 dy = ptOldOrg.y - pWin->drawable.y;
1134 REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
1136 REGION_INIT (pScreen, &rgnDst, NullBox, 0);
1137 REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
1139 extents = REGION_EXTENTS (pScreen, &rgnDst);
1140 area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
1142 if (area > xp_scroll_area_threshold)
1144 /* Move region to window local coords */
1145 REGION_TRANSLATE (pScreen, &rgnDst, -winRec->x, -winRec->y);
1147 RootlessStopDrawing (pWin, FALSE);
1149 xp_copy_window (winRec->wid, winRec->wid,
1150 REGION_NUM_RECTS (&rgnDst),
1151 REGION_RECTS (&rgnDst), dx, dy);
1155 RootlessStartDrawing (pWin);
1157 fbCopyRegion ((DrawablePtr) pWin, (DrawablePtr) pWin,
1158 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
1160 /* prgnSrc has been translated to dst position */
1161 RootlessDamageRegion(pWin, prgnSrc);
1164 REGION_UNINIT (pScreen, &rgnDst);
1165 fbValidateDrawable (&pWin->drawable);
1167 SCREEN_WRAP (pScreen, CopyWindow);
1169 RL_DEBUG_MSG("copywindowFB end\n");
1173 * Window resize procedures
1181 /* Compute which directions the window is resizing in. */
1182 static inline unsigned int
1183 resize_code (int oldX, int oldY, int oldW, int oldH,
1184 int newX, int newY, int newW, int newH)
1186 unsigned int code = 0;
1188 /* These comparisons were chosen to avoid setting bits when the sizes
1189 are the same. (So the fastest case automatically gets taken when
1190 dimensions are unchanging.) */
1193 code |= WIDTH_SMALLER;
1196 code |= HEIGHT_SMALLER;
1201 static inline unsigned int
1202 resize_weighting (int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
1203 int newX1, int newY1, int newX2, int newY2, int newBW)
1205 /* Choose gravity to avoid local copies. Do that by looking for
1206 a corner that doesn't move _relative to the screen_ */
1209 return XP_GRAVITY_NONE;
1211 if (newX1 == oldX1 && newY1 == oldY1)
1212 return XP_GRAVITY_NORTH_WEST;
1213 else if (newX1 == oldX1 && newY2 == oldY2)
1214 return XP_GRAVITY_SOUTH_WEST;
1215 else if (newX2 == oldX2 && newY2 == oldY2)
1216 return XP_GRAVITY_SOUTH_EAST;
1217 else if (newX2 == oldX2 && newY1 == oldY1)
1218 return XP_GRAVITY_NORTH_EAST;
1220 return XP_GRAVITY_NONE;
1223 /* Resize the given window to its new position and size. */
1225 resize_frame (ScreenPtr pScreen, WindowPtr pWin,
1226 RootlessWindowRec *winRec, int gravity)
1229 xp_window_changes wc;
1231 sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
1232 sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
1234 wc.x = sx + winRec->x;
1235 wc.y = sy + winRec->y;
1236 wc.width = winRec->width;
1237 wc.height = winRec->height;
1238 wc.bit_gravity = gravity;
1240 /* It's unlikely that being async will save us anything here.
1241 But it can't hurt. */
1243 configure_window (winRec->wid, XP_BOUNDS, &wc);
1246 /* Prepare to resize a top-level window. The old window's pixels are
1247 saved and the implementation is told to change the window size.
1248 (x,y,w,h) is outer frame of window (outside border) */
1250 StartFrameResize (WindowPtr pWin, Bool gravity,
1251 int oldX, int oldY, int oldW, int oldH, int oldBW,
1252 int newX, int newY, int newW, int newH, int newBW)
1254 ScreenPtr pScreen = pWin->drawable.pScreen;
1255 RootlessWindowRec *winRec = WINREC(pWin);
1256 Bool need_window_source = FALSE, resize_after = FALSE;
1258 BoxRec rect, copy_rect;
1261 unsigned int weight;
1263 oldX2 = oldX + oldW, newX2 = newX + newW;
1264 oldY2 = oldY + oldH, newY2 = newY + newH;
1266 /* Decide which resize weighting to use */
1267 weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
1268 newX, newY, newW, newH, newBW);
1270 /* Compute intersection between old and new rects */
1271 rect.x1 = max(oldX, newX);
1272 rect.y1 = max(oldY, newY);
1273 rect.x2 = min(oldX2, newX2);
1274 rect.y2 = min(oldY2, newY2);
1276 RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
1277 RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n",
1278 oldX, oldY, oldW, oldH, oldBW,
1279 newX, newY, newW, newH, newBW);
1281 RootlessDisableUpdate (pWin);
1282 RootlessRedisplay (pWin);
1284 /* If gravity is true, then we need to have a way of recovering all
1285 the original bits in the window for when X rearranges the contents
1286 based on the various gravity settings. The obvious way is to just
1287 snapshot the entire backing store before resizing it, but that
1288 it slow on large windows.
1290 So the optimization here is to use CG's resize weighting options
1291 to allow us to reason about what is left in the backing store
1292 after the resize. We can then only copy what won't be there after
1293 the resize, and do a two-stage copy operation.
1295 Most of these optimizations are only applied when the top-left
1296 corner of the window is fixed, since that's the common case. They
1297 could probably be extended with some thought. */
1299 gResizeDeathCount = 0;
1301 if (gravity && weight == XP_GRAVITY_NORTH_WEST)
1305 /* Top left corner is anchored. We never need to copy the
1308 need_window_source = TRUE;
1310 code = resize_code (oldX, oldY, oldW, oldH,
1311 newX, newY, newW, newH);
1313 if (((code ^ (code >> 1)) & 1) == 0)
1315 /* Both dimensions are either getting larger, or both
1316 are getting smaller. No need to copy anything. */
1318 if (code == (WIDTH_SMALLER | HEIGHT_SMALLER))
1320 /* Since the window is getting smaller, we can do gravity
1321 repair on it with it's current size, then resize it
1324 resize_after = TRUE;
1327 gResizeDeathCount = 1;
1331 unsigned int copy_rowbytes, Bpp;
1333 /* We can get away with a partial copy. 'rect' is the
1334 intersection between old and new bounds, so copy
1335 everything to the right of or below the intersection. */
1337 RootlessStartDrawing (pWin);
1339 if (code == WIDTH_SMALLER)
1341 copy_rect.x1 = rect.x2;
1342 copy_rect.y1 = rect.y1;
1343 copy_rect.x2 = oldX2;
1344 copy_rect.y2 = oldY2;
1346 else if (code == HEIGHT_SMALLER)
1348 copy_rect.x1 = rect.x1;
1349 copy_rect.y1 = rect.y2;
1350 copy_rect.x2 = oldX2;
1351 copy_rect.y2 = oldY2;
1356 Bpp = winRec->win->drawable.bitsPerPixel / 8;
1357 copy_rowbytes = (((copy_rect.x2 - copy_rect.x1) * Bpp) + 31) & ~31;
1358 gResizeDeathBits = xalloc (copy_rowbytes
1359 * (copy_rect.y2 - copy_rect.y1));
1361 xp_copy_bytes ((copy_rect.x2 - copy_rect.x1) * Bpp,
1362 copy_rect.y2 - copy_rect.y1, ((char *) winRec->data)
1363 + ((copy_rect.y1 - oldY) * winRec->rowbytes)
1364 + (copy_rect.x1 - oldX) * Bpp, winRec->rowbytes,
1365 gResizeDeathBits, copy_rowbytes);
1367 gResizeDeathBounds[1] = copy_rect;
1369 = GetScratchPixmapHeader(pScreen, copy_rect.x2 - copy_rect.x1,
1370 copy_rect.y2 - copy_rect.y1,
1371 winRec->win->drawable.depth,
1372 winRec->win->drawable.bitsPerPixel,
1374 (void *) gResizeDeathBits);
1376 TranslatePixmapBase (gResizeDeathPix[1],
1377 -copy_rect.x1, -copy_rect.y1);
1379 gResizeDeathCount = 2;
1384 /* The general case. Just copy everything. */
1386 RootlessStartDrawing (pWin);
1388 gResizeDeathBits = xalloc(winRec->rowbytes * winRec->height);
1390 memcpy(gResizeDeathBits, winRec->data,
1391 winRec->rowbytes * winRec->height);
1393 gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
1395 = GetScratchPixmapHeader(pScreen, winRec->width,
1397 winRec->win->drawable.depth,
1398 winRec->win->drawable.bitsPerPixel,
1400 (void *) gResizeDeathBits);
1402 TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
1403 gResizeDeathCount = 1;
1406 RootlessStopDrawing (pWin, FALSE);
1410 winRec->width = newW;
1411 winRec->height = newH;
1412 winRec->borderWidth = newBW;
1414 /* Unless both dimensions are getting smaller, Resize the frame
1415 before doing gravity repair */
1418 resize_frame (pScreen, pWin, winRec, weight);
1420 RootlessStartDrawing(pWin);
1422 /* If necessary, create a source pixmap pointing at the current
1425 if (need_window_source)
1427 gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
1429 = GetScratchPixmapHeader (pScreen, oldW, oldH,
1430 winRec->win->drawable.depth,
1431 winRec->win->drawable.bitsPerPixel,
1432 winRec->rowbytes, winRec->data);
1434 TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
1437 /* Use custom CopyWindow when moving gravity bits around
1438 ResizeWindow assumes the old window contents are in the same
1439 pixmap, but here they're in deathPix instead. */
1443 gResizeOldCopyWindowProc = pScreen->CopyWindow;
1444 pScreen->CopyWindow = RootlessResizeCopyWindow;
1447 /* If we can't rely on the window server preserving the bits we
1448 need in the position we need, copy the pixels in the
1449 intersection from src to dst. ResizeWindow assumes these pixels
1450 are already present when making gravity adjustments. pWin
1451 currently has new-sized pixmap but is in old position.
1453 FIXME: border width change! (?) */
1455 if (gravity && weight == XP_GRAVITY_NONE)
1459 assert (gResizeDeathCount == 1);
1461 src = gResizeDeathPix[0];
1462 dst = pScreen->GetWindowPixmap(pWin);
1464 RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
1465 rect.x1, rect.y1, rect.x2, rect.y2);
1467 /* rect is the intersection of the old location and new location */
1468 if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL)
1472 /* The window drawable still has the old frame position, which
1473 means that DST doesn't actually point at the origin of our
1474 physical backing store when adjusted by the drawable.x,y
1475 position. So sneakily adjust it temporarily while copying.. */
1479 TranslatePixmapBase (dst, -dx, -dy);
1481 fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
1482 &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
1484 TranslatePixmapBase (dst, dx, dy);
1488 return resize_after;
1492 FinishFrameResize (WindowPtr pWin, Bool gravity, int oldX, int oldY,
1493 unsigned int oldW, unsigned int oldH, unsigned int oldBW,
1494 int newX, int newY, unsigned int newW, unsigned int newH,
1495 unsigned int newBW, Bool resize_now)
1497 ScreenPtr pScreen = pWin->drawable.pScreen;
1498 RootlessWindowRec *winRec = WINREC(pWin);
1502 RootlessStopDrawing (pWin, FALSE);
1506 unsigned int weight;
1508 /* We didn't resize anything earlier, so do it now, now that
1509 we've finished gravitating the bits. */
1511 weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
1512 newX, newY, newW, newH, newBW);
1514 resize_frame (pScreen, pWin, winRec, weight);
1517 /* Redraw everything. FIXME: there must be times when we don't need
1518 to do this. Perhaps when top-left weighting and no gravity? */
1522 box.x2 = winRec->width;
1523 box.y2 = winRec->height;
1525 xp_mark_window (winRec->wid, 1, &box, 0, 0);
1527 for (i = 0; i < 2; i++)
1529 if (gResizeDeathPix[i] != NULL)
1531 FreeScratchPixmapHeader (gResizeDeathPix[i]);
1532 gResizeDeathPix[i] = NULL;
1536 if (gResizeDeathBits != NULL)
1538 xfree (gResizeDeathBits);
1539 gResizeDeathBits = NULL;
1543 pScreen->CopyWindow = gResizeOldCopyWindowProc;
1546 /* If kind==VTOther, window border is resizing (and borderWidth is
1547 already changed!!@#$) This case works like window resize, not move. */
1549 RootlessMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
1551 RootlessWindowRec *winRec = WINREC(pWin);
1552 ScreenPtr pScreen = pWin->drawable.pScreen;
1553 CopyWindowProcPtr oldCopyWindowProc = NULL;
1555 int oldX = 0, oldY = 0;
1556 unsigned int oldW = 0, oldH = 0, oldBW = 0;
1557 int newX = 0, newY = 0;
1558 unsigned int newW = 0, newH = 0, newBW = 0;
1560 Bool resize_after = FALSE;
1563 RL_DEBUG_MSG("movewindow start \n");
1571 RootlessRedisplay (pWin);
1572 RootlessStartDrawing (pWin);
1576 RL_DEBUG_MSG("movewindow border resizing ");
1578 oldBW = winRec->borderWidth;
1581 oldW = winRec->width;
1582 oldH = winRec->height;
1584 newBW = wBorderWidth (pWin);
1587 newW = pWin->drawable.width + 2*newBW;
1588 newH = pWin->drawable.height + 2*newBW;
1590 resize_after = StartFrameResize (pWin, FALSE,
1591 oldX, oldY, oldW, oldH, oldBW,
1592 newX, newY, newW, newH, newBW);
1597 SCREEN_UNWRAP (pScreen, MoveWindow);
1599 oldCopyWindowProc = pScreen->CopyWindow;
1602 pScreen->CopyWindow = RootlessNoCopyWindow;
1604 pScreen->MoveWindow (pWin, x, y, pSib, kind);
1607 pScreen->CopyWindow = oldCopyWindowProc;
1610 SCREEN_WRAP (pScreen, MoveWindow);
1616 xp_window_changes wc;
1619 RootlessStopDrawing (pWin, FALSE);
1624 sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
1625 sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
1627 wc.x = sx + winRec->x;
1628 wc.y = sy + winRec->y;
1630 configure_window (winRec->wid, XP_ORIGIN, &wc);
1634 FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
1635 newX, newY, newW, newH, newBW, resize_after);
1639 RL_DEBUG_MSG("movewindow end\n");
1643 /* Note: (x, y, w, h) as passed to this procedure don't match the frame
1644 definition. (x,y) is corner of very outer edge, *outside* border
1645 w,h is width and height *inside* border, *ignoring* border width
1646 The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
1647 is total rect (x+bw, y+bw, w, h) is inner rect */
1649 RootlessResizeWindow (WindowPtr pWin, int x, int y,
1650 unsigned int w, unsigned int h, WindowPtr pSib)
1652 RootlessWindowRec *winRec = WINREC(pWin);
1653 ScreenPtr pScreen = pWin->drawable.pScreen;
1656 int oldX = 0, oldY = 0;
1657 unsigned int oldW = 0, oldH = 0, oldBW = 0;
1658 int newX = 0, newY = 0;
1659 unsigned int newW = 0, newH = 0, newBW = 0;
1661 Bool resize_after = FALSE;
1663 RL_DEBUG_MSG("resizewindow start (win 0x%x)\n", pWin);
1667 oldBW = winRec->borderWidth;
1670 oldW = winRec->width;
1671 oldH = winRec->height;
1679 resize_after = StartFrameResize (pWin, TRUE,
1680 oldX, oldY, oldW, oldH, oldBW,
1681 newX, newY, newW, newH, newBW);
1685 SCREEN_UNWRAP (pScreen, ResizeWindow);
1689 pScreen->ResizeWindow (pWin, x, y, w, h, pSib);
1695 /* mi won't resize the root. So do it ourselves... */
1697 pWin->drawable.x = x;
1698 pWin->drawable.y = y;
1699 pWin->drawable.width = w;
1700 pWin->drawable.height = h;
1702 box.x1 = x; box.y1 = y;
1703 box.x2 = x + w; box.y2 = y + h;
1704 REGION_UNINIT (pScreen, &pWin->winSize);
1705 REGION_INIT (pScreen, &pWin->winSize, &box, 1);
1706 REGION_COPY (pScreen, &pWin->borderSize, &pWin->winSize);
1707 REGION_COPY (pScreen, &pWin->clipList, &pWin->winSize);
1708 REGION_COPY (pScreen, &pWin->borderClip, &pWin->winSize);
1710 miSendExposures (pWin, &pWin->borderClip,
1711 pWin->drawable.x, pWin->drawable.y);
1714 SCREEN_WRAP (pScreen, ResizeWindow);
1719 FinishFrameResize (pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
1720 newX, newY, newW, newH, newBW, resize_after);
1723 RL_DEBUG_MSG("resizewindow end\n");
1727 RootlessRepositionWindow (WindowPtr pWin)
1729 RootlessWindowRec *winRec = WINREC (pWin);
1730 ScreenPtr pScreen = pWin->drawable.pScreen;
1731 xp_window_changes wc;
1735 set_screen_origin (pWin);
1740 RootlessStopDrawing (pWin, FALSE);
1742 sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
1743 sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
1745 wc.x = sx + winRec->x;
1746 wc.y = sy + winRec->y;
1748 if (!rootlessHasRoot (pScreen))
1749 wc.window_level = normal_window_levels[winRec->level];
1751 wc.window_level = rooted_window_levels[winRec->level];
1753 configure_window (winRec->wid, XP_ORIGIN | XP_WINDOW_LEVEL, &wc);
1755 RootlessReorderWindow (pWin);
1759 RootlessFlushWindowColormap (WindowPtr pWin)
1761 RootlessWindowRec *winRec = WINREC (pWin);
1762 xp_window_changes wc;
1767 RootlessStopDrawing (pWin, FALSE);
1769 /* This is how we tell xp that the colormap may have changed. */
1771 wc.colormap = rootlessColormapCallback;
1772 wc.colormap_data = pWin->drawable.pScreen;
1774 configure_window (winRec->wid, XP_COLORMAP, &wc);
1777 /* Set the Pixmaps on all ParentRelative windows up the ancestor chain. */
1779 SetPixmapOfAncestors (WindowPtr pWin)
1781 ScreenPtr pScreen = pWin->drawable.pScreen;
1782 WindowPtr topWin = TopLevelParent (pWin);
1783 RootlessWindowRec *topWinRec = WINREC (topWin);
1786 while (pWin->backgroundState == ParentRelative)
1790 /* disallow ParentRelative background state on top level */
1793 ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
1795 RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
1799 pWin = pWin->parent;
1800 pScreen->SetWindowPixmap (pWin, topWinRec->pixmap);
1804 /* RootlessPaintWindowBackground
1805 Paint the window background while filling in the alpha channel
1808 RootlessPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
1810 ScreenPtr pScreen = pWin->drawable.pScreen;
1812 SCREEN_UNWRAP (pScreen, PaintWindowBackground);
1814 RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i)\n",
1815 pWin, IsFramedWindow(pWin));
1817 if (IsFramedWindow (pWin))
1819 /* Don't bother trying to paint the surface background.. */
1820 rootlessNoDRIDrawing++;
1822 RootlessStartDrawing (pWin);
1823 RootlessDamageRegion (pWin, pRegion);
1825 /* For ParentRelative windows, we have to make sure the window
1826 pixmap is set correctly all the way up the ancestor chain. */
1828 if (pWin->backgroundState == ParentRelative)
1829 SetPixmapOfAncestors (pWin);
1831 pScreen->PaintWindowBackground (pWin, pRegion, what);
1833 rootlessNoDRIDrawing--;
1836 SCREEN_WRAP (pScreen, PaintWindowBackground);
1838 RL_DEBUG_MSG("paintwindowbackground end\n");
1842 /* RootlessPaintWindowBorder
1843 Paint the window border while filling in the alpha channel with all on. */
1845 RootlessPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what)
1847 SCREEN_UNWRAP (pWin->drawable.pScreen, PaintWindowBorder);
1849 RL_DEBUG_MSG("paintwindowborder start (win 0x%x)\n", pWin);
1851 if (IsFramedWindow (pWin))
1853 RootlessStartDrawing (pWin);
1854 RootlessDamageRegion (pWin, pRegion);
1856 /* For ParentRelative windows with tiled borders, we have to make
1857 sure the window pixmap is set correctly all the way up the
1860 if (!pWin->borderIsPixel && pWin->backgroundState == ParentRelative)
1861 SetPixmapOfAncestors (pWin);
1864 pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
1866 SCREEN_WRAP (pWin->drawable.pScreen, PaintWindowBorder);
1868 RL_DEBUG_MSG("paintwindowborder end\n");
1873 pWin inside corner stays the same; pWin->drawable.[xy] stays the same
1874 frame moves and resizes */
1876 RootlessChangeBorderWidth (WindowPtr pWin, unsigned int width)
1879 Bool resize_after = FALSE;
1881 RL_DEBUG_MSG("change border width\n");
1883 if ((int) width != wBorderWidth (pWin))
1885 RootlessWindowRec *winRec = WINREC(pWin);
1887 int oldX = 0, oldY = 0, newX = 0, newY = 0;
1888 unsigned int oldW = 0, oldH = 0, oldBW = 0;
1889 unsigned int newW = 0, newH = 0, newBW = 0;
1893 oldBW = winRec->borderWidth;
1896 oldW = winRec->width;
1897 oldH = winRec->height;
1900 newX = pWin->drawable.x - newBW;
1901 newY = pWin->drawable.y - newBW;
1902 newW = pWin->drawable.width + 2*newBW;
1903 newH = pWin->drawable.height + 2*newBW;
1905 resize_after = StartFrameResize (pWin, FALSE,
1906 oldX, oldY, oldW, oldH, oldBW,
1907 newX, newY, newW, newH, newBW);
1911 SCREEN_UNWRAP (pWin->drawable.pScreen, ChangeBorderWidth);
1913 pWin->drawable.pScreen->ChangeBorderWidth (pWin, width);
1915 SCREEN_WRAP (pWin->drawable.pScreen, ChangeBorderWidth);
1920 FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
1921 newX, newY, newW, newH, newBW, resize_after);
1925 RL_DEBUG_MSG("change border width end\n");
1929 * RootlessFillRegionTiled
1930 * Fill using a tile while leaving the alpha channel untouched.
1931 * Based on fbfillRegionTiled.
1934 RootlessFillRegionTiled(
1935 DrawablePtr pDrawable,
1942 int dstXoff, dstYoff;
1944 FbStride tileStride;
1946 int tileXoff, tileYoff; /* XXX assumed to be zero */
1947 int tileWidth, tileHeight;
1948 int n = REGION_NUM_RECTS(pRegion);
1949 BoxPtr pbox = REGION_RECTS(pRegion);
1950 int xRot = pDrawable->x;
1951 int yRot = pDrawable->y;
1955 if(!noPanoramiXExtension)
1957 int index = pDrawable->pScreen->myNum;
1958 if(&WindowTable[index]->drawable == pDrawable)
1960 xRot -= panoramiXdataPtr[index].x;
1961 yRot -= panoramiXdataPtr[index].y;
1965 fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
1966 fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp,
1967 tileXoff, tileYoff);
1968 tileWidth = pTile->drawable.width;
1969 tileHeight = pTile->drawable.height;
1972 planeMask = FB_ALLONES & ~RootlessAlphaMask(dstBpp);
1976 fbTile (dst + (pbox->y1 + dstYoff) * dstStride,
1978 (pbox->x1 + dstXoff) * dstBpp,
1979 (pbox->x2 - pbox->x1) * dstBpp,
1980 pbox->y2 - pbox->y1,
1995 * RootlessPaintWindow
1996 * Paint the window while filling in the alpha channel with all on.
1997 * We can't use fbPaintWindow because it zeros the alpha channel.
2000 RootlessPaintWindow(
2008 switch (pWin->backgroundState) {
2011 case ParentRelative:
2013 pWin = pWin->parent;
2014 } while (pWin->backgroundState == ParentRelative);
2015 (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
2018 case BackgroundPixmap:
2019 RootlessFillRegionTiled (&pWin->drawable,
2021 pWin->background.pixmap);
2023 case BackgroundPixel:
2025 Pixel pixel = pWin->background.pixel |
2026 RootlessAlphaMask(pWin->drawable.bitsPerPixel);
2027 fbFillRegionSolid (&pWin->drawable, pRegion, 0,
2028 fbReplicatePixel (pixel,
2029 pWin->drawable.bitsPerPixel));
2035 if (pWin->borderIsPixel)
2037 Pixel pixel = pWin->border.pixel |
2038 RootlessAlphaMask(pWin->drawable.bitsPerPixel);
2039 fbFillRegionSolid (&pWin->drawable, pRegion, 0,
2040 fbReplicatePixel (pixel,
2041 pWin->drawable.bitsPerPixel));
2046 for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative;
2047 pBgWin = pBgWin->parent);
2049 RootlessFillRegionTiled (&pBgWin->drawable,
2051 pWin->border.pixmap);
2055 fbValidateDrawable (&pWin->drawable);