+++ /dev/null
-/*
- * Rootless window management
- */
-/*
- * Copyright (c) 2001 Greg Parker. All Rights Reserved.
- * Copyright (c) 2002 Torrey T. Lyons. All Rights Reserved.
- * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name(s) of the above copyright
- * holders shall not be used in advertising or otherwise to promote the sale,
- * use or other dealings in this Software without prior written authorization.
- */
-/* Portions of this file are based on fbwindow.c, which contains the
- * following copyright:
- *
- * Copyright © 1998 Keith Packard
- */
-/* $XFree86: xc/programs/Xserver/hw/darwin/quartz/rootlessWindow.c,v 1.11 2002/09/28 00:43:39 torrey Exp $ */
-
-#include "rootless-common.h"
-#include "rootless-window.h"
-#include "darwin.h"
-#include "Xplugin.h"
-#include "x-hash.h"
-#include "x-list.h"
-#define _APPLEWM_SERVER_
-#include "applewmstr.h"
-
-#include "fb.h"
-#include "propertyst.h"
-
-#ifdef PANORAMIX
-#include "panoramiX.h"
-#include "panoramiXsrv.h"
-#endif
-
-#include <X11/Xatom.h>
-#include <pthread.h>
-
-#define DEFINE_ATOM_HELPER(func,atom_name) \
-static Atom func (void) { \
- static unsigned int generation; \
- static Atom atom; \
- if (generation != serverGeneration) { \
- generation = serverGeneration; \
- atom = MakeAtom (atom_name, strlen (atom_name), TRUE); \
- } \
- return atom; \
-}
-
-DEFINE_ATOM_HELPER (xa_native_screen_origin, "_NATIVE_SCREEN_ORIGIN")
-DEFINE_ATOM_HELPER (xa_native_window_id, "_NATIVE_WINDOW_ID")
-DEFINE_ATOM_HELPER (xa_apple_no_order_in, "_APPLE_NO_ORDER_IN")
-
-/* Maps xp_window_id -> AquaWindowRec */
-static x_hash_table *window_hash;
-static pthread_mutex_t window_hash_mutex;
-
-static Bool no_configure_window;
-static Bool windows_hidden;
-
-static const int normal_window_levels[AppleWMNumWindowLevels+1] = {
- 0, 3, 4, 5, LONG_MIN + 30, LONG_MIN + 29,
-};
-static const int rooted_window_levels[AppleWMNumWindowLevels+1] = {
- 202, 203, 204, 205, 201, 200
-};
-
-static inline xp_error
-configure_window (xp_window_id id, unsigned int mask,
- const xp_window_changes *values)
-{
- if (!no_configure_window)
- return xp_configure_window (id, mask, values);
- else
- return XP_Success;
-}
-
-static inline unsigned long
-current_time_in_seconds (void)
-{
- unsigned long t = 0;
-
- t += currentTime.milliseconds / 1000;
- t += currentTime.months * 4294967;
-
- return t;
-}
-
-static inline Bool
-rootlessHasRoot (ScreenPtr pScreen)
-{
- return WINREC (WindowTable[pScreen->myNum]) != NULL;
-}
-
-void
-RootlessNativeWindowStateChanged (xp_window_id id, unsigned int state)
-{
- WindowPtr pWin;
- RootlessWindowRec *winRec;
-
- pWin = RootlessGetXWindow (id);
- if (pWin == NULL)
- return;
-
- winRec = WINREC (pWin);
- if (winRec == NULL)
- return;
-
- winRec->is_offscreen = (state & XP_WINDOW_STATE_OFFSCREEN) != 0;
- winRec->is_obscured = (state & XP_WINDOW_STATE_OBSCURED) != 0;
-
-#ifdef ROOTLESS
- pWin->rootlessUnhittable = winRec->is_offscreen;
-#endif
-}
-
-void
-RootlessNativeWindowMoved (xp_window_id id)
-{
- WindowPtr pWin;
- xp_box bounds;
- int sx, sy;
- XID vlist[2];
- Mask mask;
- ClientPtr client;
-
- pWin = RootlessGetXWindow (id);
- if (pWin == NULL)
- return;
-
- if (xp_get_window_bounds (id, &bounds) != Success)
- return;
-
- sx = dixScreenOrigins[pWin->drawable.pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pWin->drawable.pScreen->myNum].y + darwinMainScreenY;
-
- /* Fake up a ConfigureWindow packet to resize the window to the
- current bounds. */
-
- vlist[0] = (INT16) bounds.x1 - sx;
- vlist[1] = (INT16) bounds.y1 - sy;
- mask = CWX | CWY;
-
- /* pretend we're the owner of the window! */
- client = LookupClient (pWin->drawable.id, NullClient);
-
- /* Don't want to do anything to the physical window (avoids
- notification-response feedback loops) */
-
- no_configure_window = TRUE;
- ConfigureWindow (pWin, mask, vlist, client);
- no_configure_window = FALSE;
-}
-
-/* Updates the _NATIVE_SCREEN_ORIGIN property on the given root window. */
-static void
-set_screen_origin (WindowPtr pWin)
-{
- long data[2];
-
- if (!IsRoot (pWin))
- return;
-
- /* FIXME: move this to an extension? */
-
- data[0] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].x
- + darwinMainScreenX);
- data[1] = (dixScreenOrigins[pWin->drawable.pScreen->myNum].y
- + darwinMainScreenY);
-
- ChangeWindowProperty (pWin, xa_native_screen_origin (), XA_INTEGER,
- 32, PropModeReplace, 2, data, TRUE);
-}
-
-/* For now, don't create a physical window until either the window is
- realized, or we really need it (e.g. to attach VRAM surfaces to).
- Do reset the window size so it's not clipped by the root window. */
-Bool
-RootlessCreateWindow (WindowPtr pWin)
-{
- Bool result;
- RegionRec saveRoot;
-
- SCREEN_UNWRAP (pWin->drawable.pScreen, CreateWindow);
-
- if (!IsRoot (pWin))
- {
- /* win/border size set by DIX, not by wrapped CreateWindow, so
- correct it here. Don't HUGE_ROOT when pWin is the root! */
-
- HUGE_ROOT (pWin);
- SetWinSize (pWin);
- SetBorderSize (pWin);
- }
- else
- {
- set_screen_origin (pWin);
- }
-
- result = pWin->drawable.pScreen->CreateWindow (pWin);
-
- if (pWin->parent)
- NORMAL_ROOT (pWin);
-
- SCREEN_WRAP (pWin->drawable.pScreen, CreateWindow);
-
- return result;
-}
-
-/* Destroy the physical window associated with the given window */
-static void
-rootlessDestroyFrame (WindowPtr pWin, RootlessWindowRec *winRec)
-{
- RootlessStopDrawing (pWin, FALSE);
-
- pthread_mutex_lock (&window_hash_mutex);
- x_hash_table_remove (window_hash, (void *) winRec->wid);
- pthread_mutex_unlock (&window_hash_mutex);
-
- xp_destroy_window (winRec->wid);
-
- xfree (winRec);
- WINREC (pWin) = NULL;
-}
-
-Bool
-RootlessDestroyWindow (WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- Bool result;
-
- if (winRec != NULL)
- rootlessDestroyFrame (pWin, winRec);
-
- /* winRec is gone now */
-
- SCREEN_UNWRAP(pWin->drawable.pScreen, DestroyWindow);
-
- result = pWin->drawable.pScreen->DestroyWindow (pWin);
-
- SCREEN_WRAP(pWin->drawable.pScreen, DestroyWindow);
-
- return result;
-}
-
-#ifdef SHAPE
-static Bool
-RootlessGetShape (WindowPtr pWin, RegionPtr pShape)
-{
- if (wBoundingShape (pWin) == NULL)
- return FALSE;
-
- /* wBoundingShape is relative to *inner* origin of window.
- Translate by borderWidth to get the outside-relative position. */
-
- REGION_INIT (pScreen, pShape, NullBox, 0);
- REGION_COPY (pScreen, pShape, wBoundingShape (pWin));
- REGION_TRANSLATE (pScreen, pShape, pWin->borderWidth, pWin->borderWidth);
-
- return TRUE;
-}
-
-/* boundingShape = outside border (like borderClip)
- clipShape = inside border (like clipList)
- Both are in window-local coordinates
- We only care about boundingShape (FIXME true?)
-
- RootlessReallySetShape is used in several places other than SetShape.
- Most importantly, SetShape is often called on unmapped windows, so we
- have to wait until the window is mapped to reshape the frame. */
-static void
-rootlessSetShape (WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC (pWin);
-
- RegionRec newShape;
- RegionPtr pShape;
- xp_window_changes wc;
-
- if (winRec == NULL)
- return;
-
- RootlessStopDrawing (pWin, FALSE);
-
- pShape = RootlessGetShape (pWin, &newShape) ? &newShape : NULL;
-
- RL_DEBUG_MSG("reshaping...");
- RL_DEBUG_MSG("numrects %d, extents %d %d %d %d\n",
- REGION_NUM_RECTS(&newShape),
- newShape.extents.x1, newShape.extents.y1,
- newShape.extents.x2, newShape.extents.y2);
-
- RootlessDisableUpdate (pWin);
-
- if (pShape != NULL)
- {
- wc.shape_nrects = REGION_NUM_RECTS (pShape);
- wc.shape_rects = REGION_RECTS (pShape);
- }
- else
- {
- wc.shape_nrects = -1;
- wc.shape_rects = NULL;
- }
-
- wc.shape_tx = wc.shape_ty = 0;
-
- configure_window (winRec->wid, XP_SHAPE, &wc);
-
- if (pShape != NULL)
- REGION_UNINIT(pScreen, &newShape);
-}
-
-void
-RootlessSetShape (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- SCREEN_UNWRAP (pScreen, SetShape);
-
- pScreen->SetShape (pWin);
-
- SCREEN_WRAP (pScreen, SetShape);
-
- rootlessSetShape (pWin);
-}
-#endif
-
-/* Disallow ParentRelative background on top-level windows
- because the root window doesn't really have the right background
- and fb will try to draw on the root instead of on the window.
- ParentRelative prevention is also in PaintWindowBackground/Border()
- so it is no longer really needed here. */
-Bool
-RootlessChangeWindowAttributes (WindowPtr pWin, unsigned long vmask)
-{
- Bool result;
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- RL_DEBUG_MSG("change window attributes start\n");
-
- SCREEN_UNWRAP (pScreen, ChangeWindowAttributes);
-
- result = pScreen->ChangeWindowAttributes (pWin, vmask);
-
- SCREEN_WRAP (pScreen, ChangeWindowAttributes);
-
- if (WINREC (pWin) != NULL)
- {
- /* disallow ParentRelative background state */
-
- if (pWin->backgroundState == ParentRelative)
- {
- XID pixel = 0;
- ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
- }
- }
-
- RL_DEBUG_MSG("change window attributes end\n");
- return result;
-}
-
-/* This is a hook for when DIX moves or resizes a window.
- Update the frame position now. (x, y) are *inside* position.
- After this, mi and fb are expecting the pixmap to be at the new location. */
-Bool
-RootlessPositionWindow (WindowPtr pWin, int x, int y)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC (pWin);
- Bool result;
-
- RL_DEBUG_MSG("positionwindow start (win 0x%x)\n", pWin);
-
- if (winRec != NULL)
- {
- if (winRec->is_drawing)
- {
- /* Reset frame's pixmap and move it to the new position. */
- int bw = wBorderWidth (pWin);
-
- winRec->pixmap->devPrivate.ptr = winRec->data;
- TranslatePixmapBase (winRec->pixmap, - (x - bw), - (y - bw));
- }
- }
-
- SCREEN_UNWRAP (pScreen, PositionWindow);
-
- result = pScreen->PositionWindow (pWin, x, y);
-
- SCREEN_WRAP(pScreen, PositionWindow);
-
- RL_DEBUG_MSG("positionwindow end\n");
- return result;
-}
-
-/* Initialize some basic attributes of the frame. Note that winRec
- may already have valid data in it, so don't overwrite anything
- valuable. */
-static void
-rootlessInitializeFrame (WindowPtr pWin, RootlessWindowRec *winRec)
-{
- DrawablePtr d = &pWin->drawable;
- int bw = wBorderWidth (pWin);
-
- winRec->win = pWin;
-
- winRec->x = d->x - bw;
- winRec->y = d->y - bw;
- winRec->width = d->width + 2*bw;
- winRec->height = d->height + 2*bw;
- winRec->borderWidth = bw;
-}
-
-static void
-rootlessSetNativeProperty (RootlessWindowRec *winRec)
-{
- xp_error err;
- unsigned int native_id;
- long data;
-
- err = xp_get_native_window (winRec->wid, &native_id);
- if (err == Success)
- {
- /* FIXME: move this to an extension? */
-
- data = native_id;
- ChangeWindowProperty (winRec->win, xa_native_window_id (),
- XA_INTEGER, 32, PropModeReplace, 1, &data, TRUE);
- }
-}
-
-static xp_error
-rootlessColormapCallback (void *data, int first_color,
- int n_colors, uint32_t *colors)
-{
- return (RootlessResolveColormap (data, first_color, n_colors, colors)
- ? XP_Success : XP_BadMatch);
-}
-
-/* If the given window doesn't have a physical window associated with it,
- attempt to create one. If that's unsuccessful, return null. */
-static RootlessWindowRec *
-rootlessEnsureFrame (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec;
- RegionRec shape;
- RegionPtr pShape = NULL;
-
- xp_window_changes wc;
- unsigned int mask;
- xp_error err;
- int sx, sy;
-
- if (WINREC (pWin) != NULL)
- return WINREC (pWin);
-
- if (pWin->drawable.class != InputOutput)
- return NULL;
-
- winRec = xalloc (sizeof(RootlessWindowRec));
-
- if (!winRec)
- return NULL;
-
- rootlessInitializeFrame (pWin, winRec);
-
- winRec->is_drawing = FALSE;
- winRec->pixmap = NULL;
- winRec->wid = 0;
- winRec->is_update_disabled = FALSE;
- winRec->is_reorder_pending = FALSE;
- winRec->level = !IsRoot (pWin) ? 0 : AppleWMNumWindowLevels;
- WINREC(pWin) = winRec;
-
-#ifdef SHAPE
- if (RootlessGetShape (pWin, &shape))
- pShape = &shape;
-#endif
-
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
-
- mask = 0;
-
- wc.x = sx + winRec->x;
- wc.y = sy + winRec->y;
- wc.width = winRec->width;
- wc.height = winRec->height;
- wc.bit_gravity = XP_GRAVITY_NONE;
- mask |= XP_BOUNDS;
-
- if (pWin->drawable.depth == 8)
- {
- wc.depth = XP_DEPTH_INDEX8;
- wc.colormap = rootlessColormapCallback;
- wc.colormap_data = pScreen;
- mask |= XP_COLORMAP;
- }
- else if (pWin->drawable.depth == 15)
- wc.depth = XP_DEPTH_RGB555;
- else if (pWin->drawable.depth == 24)
- wc.depth = XP_DEPTH_ARGB8888;
- else
- wc.depth = XP_DEPTH_NIL;
- mask |= XP_DEPTH;
-
- if (pShape != NULL)
- {
- wc.shape_nrects = REGION_NUM_RECTS (pShape);
- wc.shape_rects = REGION_RECTS (pShape);
- wc.shape_tx = wc.shape_ty = 0;
- mask |= XP_SHAPE;
- }
-
- if (!rootlessHasRoot (pScreen))
- wc.window_level = normal_window_levels[winRec->level];
- else
- wc.window_level = rooted_window_levels[winRec->level];
- mask |= XP_WINDOW_LEVEL;
-
- err = xp_create_window (mask, &wc, &winRec->wid);
-
- if (err != Success)
- {
- xfree (winRec);
- return NULL;
- }
-
- if (window_hash == NULL)
- {
- window_hash = x_hash_table_new (NULL, NULL, NULL, NULL);
- pthread_mutex_init (&window_hash_mutex, NULL);
- }
-
- pthread_mutex_lock (&window_hash_mutex);
- x_hash_table_insert (window_hash, (void *) winRec->wid, winRec);
- pthread_mutex_unlock (&window_hash_mutex);
-
- rootlessSetNativeProperty (winRec);
-
- if (pShape != NULL)
- REGION_UNINIT (pScreen, &shape);
-
- return winRec;
-}
-
-/* The frame is usually created here and not in CreateWindow so that
- windows do not eat memory until they are realized. */
-Bool
-RootlessRealizeWindow(WindowPtr pWin)
-{
- Bool result = FALSE;
- RegionRec saveRoot;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- XID pixel;
-
- RL_DEBUG_MSG("realizewindow start (win 0x%x)\n", pWin);
-
- if (IsTopLevel (pWin) && pWin->drawable.class == InputOutput)
- {
- RootlessWindowRec *winRec;
-
- winRec = rootlessEnsureFrame (pWin);
- if (winRec == NULL)
- return NULL;
-
- winRec->is_reorder_pending = TRUE;
-
- /* Disallow ParentRelative background state on top-level windows.
- This might have been set before the window was mapped. */
-
- if (pWin->backgroundState == ParentRelative)
- {
- pixel = 0;
- ChangeWindowAttributes (pWin, CWBackPixel, &pixel, serverClient);
- }
- }
-
- if (!IsRoot(pWin)) HUGE_ROOT(pWin);
- SCREEN_UNWRAP (pScreen, RealizeWindow);
-
- result = pScreen->RealizeWindow (pWin);
-
- SCREEN_WRAP (pScreen, RealizeWindow);
- if (!IsRoot(pWin)) NORMAL_ROOT(pWin);
-
- RL_DEBUG_MSG("realizewindow end\n");
- return result;
-}
-
-void
-RootlessEnableRoot (ScreenPtr pScreen)
-{
- WindowPtr pRoot;
- pRoot = WindowTable[pScreen->myNum];
-
- rootlessEnsureFrame (pRoot);
- (*pScreen->ClearToBackground) (pRoot, 0, 0, 0, 0, TRUE);
- RootlessReorderWindow (pRoot);
-}
-
-void
-RootlessDisableRoot (ScreenPtr pScreen)
-{
- WindowPtr pRoot;
- RootlessWindowRec *winRec;
-
- pRoot = WindowTable[pScreen->myNum];
- winRec = WINREC (pRoot);
-
- if (winRec != NULL)
- {
- rootlessDestroyFrame (pRoot, winRec);
- DeleteProperty (pRoot, xa_native_window_id ());
- }
-}
-
-void
-RootlessHideAllWindows (void)
-{
- int i;
- ScreenPtr pScreen;
- WindowPtr pWin;
- RootlessWindowRec *winRec;
- xp_window_changes wc;
-
- if (windows_hidden)
- return;
-
- windows_hidden = TRUE;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
- pWin = WindowTable[i];
- if (pScreen == NULL || pWin == NULL)
- continue;
-
- for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
- {
- if (!pWin->realized)
- continue;
-
- RootlessStopDrawing (pWin, FALSE);
-
- winRec = WINREC (pWin);
- if (winRec != NULL)
- {
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
- configure_window (winRec->wid, XP_STACKING, &wc);
- }
- }
- }
-}
-
-void
-RootlessShowAllWindows (void)
-{
- int i;
- ScreenPtr pScreen;
- WindowPtr pWin;
- RootlessWindowRec *winRec;
-
- if (!windows_hidden)
- return;
-
- windows_hidden = FALSE;
-
- for (i = 0; i < screenInfo.numScreens; i++)
- {
- pScreen = screenInfo.screens[i];
- pWin = WindowTable[i];
- if (pScreen == NULL || pWin == NULL)
- continue;
-
- for (pWin = pWin->firstChild; pWin != NULL; pWin = pWin->nextSib)
- {
- if (!pWin->realized)
- continue;
-
- winRec = rootlessEnsureFrame (pWin);
- if (winRec == NULL)
- continue;
-
- RootlessReorderWindow (pWin);
- }
-
- RootlessScreenExpose (pScreen);
- }
-}
-
-void
-RootlessSetWindowLevel (WindowPtr pWin, int level)
-{
- RootlessWindowRec *winRec;
- xp_window_changes wc;
-
- winRec = WINREC (pWin);
- if (!IsTopLevel (pWin) || winRec == NULL || winRec->level == level)
- return;
-
- RootlessStopDrawing (pWin, FALSE);
-
- winRec->level = level;
-
- if (!rootlessHasRoot (pWin->drawable.pScreen))
- wc.window_level = normal_window_levels[level];
- else
- wc.window_level = rooted_window_levels[level];
-
- configure_window (winRec->wid, XP_WINDOW_LEVEL, &wc);
-}
-
-/* Return the id of the physical window displaying the given window. If
- CREATE is true and the window has no frame, attempt to create one. */
-xp_window_id
-RootlessGetPhysicalWindow (WindowPtr pWin, Bool create)
-{
- RootlessWindowRec *winRec;
-
- if (TopLevelParent (pWin) == NULL)
- return 0;
-
- winRec = WINREC (pWin);
-
- if (winRec == NULL && create && !IsRoot (pWin)
- && pWin->drawable.class == InputOutput)
- {
- rootlessEnsureFrame (pWin);
- winRec = WINREC (pWin);
- }
-
- if (winRec == NULL)
- return 0;
-
- return winRec->wid;
-}
-
-/* Given the id of a physical window, try to find the top-level (or root)
- X window that it represents. */
-WindowPtr
-RootlessGetXWindow (xp_window_id wid)
-{
- RootlessWindowRec *winRec;
-
- if (window_hash == NULL)
- return NULL;
-
- winRec = x_hash_table_lookup (window_hash, (void *) wid, NULL);
-
- return winRec != NULL ? winRec->win : NULL;
-}
-
-/* Number is an appkit window number. Returns true if X is displaying
- a window with that number. */
-int
-RootlessKnowsWindowNumber (int number)
-{
- Bool ret;
- xp_window_id wid;
-
- /* need to lock, since this function can be called by any thread */
-
- if (window_hash == NULL)
- return FALSE;
-
- pthread_mutex_lock (&window_hash_mutex);
-
- if (xp_lookup_native_window (number, &wid))
- ret = RootlessGetXWindow (wid) != NULL;
- else
- ret = FALSE;
-
- pthread_mutex_unlock (&window_hash_mutex);
-
- return ret;
-}
-
-Bool
-RootlessUnrealizeWindow (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- xp_window_changes wc;
- Bool result;
-
- RL_DEBUG_MSG("unrealizewindow start\n");
-
- if (winRec != NULL)
- {
- RootlessStopDrawing (pWin, FALSE);
-
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
-
- configure_window (winRec->wid, XP_STACKING, &wc);
-
- winRec->unrealize_time = current_time_in_seconds ();
- winRec->is_reorder_pending = FALSE;
-
- RootlessReenableUpdate (pWin);
- }
-
- SCREEN_UNWRAP (pScreen, UnrealizeWindow);
-
- result = pScreen->UnrealizeWindow (pWin);
-
- SCREEN_WRAP (pScreen, UnrealizeWindow);
-
- RL_DEBUG_MSG ("unrealizewindow end\n");
- return result;
-}
-
-void
-RootlessReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC (pWin);
-
- WindowPtr pTopWin;
-
- if (IsRoot (pWin) || IsRoot (pWin->parent)
- || IsTopLevel (pWin) || winRec == NULL)
- {
- return;
- }
-
- /* If the window is moving upwards towards the root has a frame,
- we want to try to move it onto its new toplevel parent. If we
- can't do that, we'll just have to jettison it.. */
-
- pTopWin = TopLevelParent (pWin);
- assert (pTopWin != pWin);
-
- pWin->rootlessUnhittable = FALSE;
-
- DeleteProperty (pWin, xa_native_window_id ());
-
- if (WINREC (pTopWin) != NULL)
- {
- /* We're screwed. */
- rootlessDestroyFrame (pWin, winRec);
- }
- else
- {
- xp_window_changes wc;
- int sx, sy;
-
- if (!pTopWin->realized && pWin->realized)
- {
- wc.stack_mode = XP_UNMAPPED;
- wc.sibling = 0;
-
- RootlessStopDrawing (pWin, FALSE);
- configure_window (winRec->wid, XP_STACKING, &wc);
- }
-
- /* Switch the frame record from one to the other. */
-
- WINREC (pWin) = NULL;
- WINREC (pTopWin) = winRec;
-
- rootlessInitializeFrame (pTopWin, winRec);
- rootlessSetShape (pTopWin);
-
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
-
- wc.x = sx + winRec->x;
- wc.y = sy + winRec->y;
- wc.width = winRec->width;
- wc.height = winRec->height;
- wc.bit_gravity = XP_GRAVITY_NONE;
-
- RootlessStopDrawing (pWin, FALSE);
- configure_window (winRec->wid, XP_BOUNDS, &wc);
-
- rootlessSetNativeProperty (winRec);
-
- if (pTopWin->realized && !pWin->realized)
- winRec->is_reorder_pending = TRUE;
- }
-}
-
-/* Reorder the window associated with the given frame so that it's
- physically above the window below it in the X stacking order. */
-void
-RootlessReorderWindow (WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC (pWin);
-
- if (pWin->realized && winRec != NULL
- && !winRec->is_reorder_pending && !windows_hidden)
- {
- WindowPtr newPrevW;
- RootlessWindowRec *newPrev;
- xp_window_changes wc;
- Atom atom;
- PropertyPtr prop;
-
- /* quartz-wm sets the _APPLE_NO_ORDER_IN property on windows
- that are being genie-restored from the Dock. We want them to
- be mapped but remain ordered-out until the animation
- completes (when the Dock will order them in) */
-
- atom = xa_apple_no_order_in ();
- for (prop = wUserProps (pWin); prop != NULL; prop = prop->next)
- {
- if (prop->propertyName == atom && prop->type == atom)
- return;
- }
-
- RootlessStopDrawing (pWin, FALSE);
-
- if (IsRoot (pWin))
- {
- wc.stack_mode = XP_MAPPED_BELOW;
- wc.sibling = 0;
- }
- else
- {
- /* Find the next window above this one that has a mapped frame. */
-
- newPrevW = pWin->prevSib;
- while (newPrevW
- && (WINREC (newPrevW) == NULL || !newPrevW->realized))
- {
- newPrevW = newPrevW->prevSib;
- }
-
- newPrev = newPrevW != NULL ? WINREC (newPrevW) : NULL;
-
- /* Then either stack ourselves below it if it exists, or raise
- ourselves above everything otherwise. */
-
- if (newPrev == NULL)
- {
- wc.stack_mode = XP_MAPPED_ABOVE;
- wc.sibling = 0;
- }
- else
- {
- if (newPrev->is_reorder_pending)
- {
- newPrev->is_reorder_pending = FALSE;
- RootlessReorderWindow (newPrevW);
- }
-
- wc.stack_mode = XP_MAPPED_BELOW;
- wc.sibling = newPrev->wid;
- }
- }
-
- configure_window (winRec->wid, XP_STACKING, &wc);
- }
-}
-
-void
-RootlessRestackWindow (WindowPtr pWin, WindowPtr pOldNextSib)
-{
- RegionRec saveRoot;
- RootlessWindowRec *winRec = WINREC (pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- RL_DEBUG_MSG("restackwindow start\n");
- if (winRec != NULL)
- RL_DEBUG_MSG("restack top level \n");
-
- HUGE_ROOT(pWin);
- SCREEN_UNWRAP(pScreen, RestackWindow);
-
- if (pScreen->RestackWindow != NULL)
- pScreen->RestackWindow (pWin, pOldNextSib);
-
- SCREEN_WRAP(pScreen, RestackWindow);
- NORMAL_ROOT(pWin);
-
- if (winRec != NULL && pWin->viewable)
- RootlessReorderWindow (pWin);
-
- RL_DEBUG_MSG("restackwindow end\n");
-}
-
-/*
- * Specialized window copy procedures
- */
-
-/* Globals needed during window resize and move. */
-static pointer gResizeDeathBits = NULL;
-static int gResizeDeathCount;
-static PixmapPtr gResizeDeathPix[2];
-static BoxRec gResizeDeathBounds[2];
-static CopyWindowProcPtr gResizeOldCopyWindowProc = NULL;
-
-/* CopyWindow () that doesn't do anything. For MoveWindow() of
- top-level windows. */
-static void
-RootlessNoCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- /* Some code expects the region to be translated */
-
- int dx = ptOldOrg.x - pWin->drawable.x;
- int dy = ptOldOrg.y - pWin->drawable.y;
-
- REGION_TRANSLATE (pWin->drawable.pScreen, prgnSrc, -dx, -dy);
-}
-
-/* CopyWindow used during ResizeWindow for gravity moves. (from fbCopyWindow)
- The original always draws on the root pixmap (which we don't have).
- Instead, draw on the parent window's pixmap.
- Resize version: the old location's pixels are in gResizeCopyWindowSource */
-static void
-RootlessResizeCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg,
- RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RegionRec rgnDst;
- int dx, dy;
-
- RL_DEBUG_MSG("resizecopywindowFB start (win 0x%x)\n", pWin);
-
- /* Don't unwrap pScreen->CopyWindow.
- The bogus rewrap with RootlessCopyWindow causes a crash if
- CopyWindow is called again during the same resize. */
-
- if (gResizeDeathCount == 0)
- return;
-
- RootlessStartDrawing (pWin);
-
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
- REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
- REGION_INIT (pScreen, &rgnDst, NullBox, 0);
- REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
-
- if (gResizeDeathCount == 1)
- {
- /* Simple case, we only have a single source pixmap. */
-
- fbCopyRegion (&gResizeDeathPix[0]->drawable,
- &pScreen->GetWindowPixmap(pWin)->drawable, 0,
- &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
- }
- else
- {
- int i;
- RegionRec clip, clipped;
-
- /* More complex case, N source pixmaps (usually two). So we
- intersect the destination with each source and copy those bits. */
-
- for (i = 0; i < gResizeDeathCount; i++)
- {
- REGION_INIT (pScreen, &clip, gResizeDeathBounds + 0, 1);
- REGION_INIT (pScreen, &clipped, NullBox, 0);
- REGION_INTERSECT (pScreen, &rgnDst, &clip, &clipped);
-
- fbCopyRegion (&gResizeDeathPix[i]->drawable,
- &pScreen->GetWindowPixmap(pWin)->drawable, 0,
- &clipped, dx, dy, fbCopyWindowProc, 0, 0);
-
- REGION_UNINIT (pScreen, &clipped);
- REGION_UNINIT (pScreen, &clip);
- }
- }
-
- /* Don't update - resize will update everything */
- REGION_UNINIT (pScreen, &rgnDst);
-
- fbValidateDrawable (&pWin->drawable);
-
- RL_DEBUG_MSG("resizecopywindowFB end\n");
-}
-
-/* Update *new* location of window. Old location is redrawn with
- PaintWindowBackground/Border. Cloned from fbCopyWindow
- The original always draws on the root pixmap (which we don't have).
- Instead, draw on the parent window's pixmap. */
-void
-RootlessCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec;
- WindowPtr top;
-
- RegionRec rgnDst;
- int dx, dy;
- BoxPtr extents;
- unsigned int area;
-
- RL_DEBUG_MSG("copywindowFB start (win 0x%x)\n", pWin);
-
- top = TopLevelParent (pWin);
- if (top == NULL)
- {
- RL_DEBUG_MSG("no parent\n");
- return;
- }
-
- winRec = WINREC(top);
- if (winRec == NULL)
- {
- RL_DEBUG_MSG("not framed\n");
- return;
- }
-
- SCREEN_UNWRAP (pScreen, CopyWindow);
-
- dx = ptOldOrg.x - pWin->drawable.x;
- dy = ptOldOrg.y - pWin->drawable.y;
- REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
-
- REGION_INIT (pScreen, &rgnDst, NullBox, 0);
- REGION_INTERSECT (pScreen, &rgnDst, &pWin->borderClip, prgnSrc);
-
- extents = REGION_EXTENTS (pScreen, &rgnDst);
- area = (extents->x2 - extents->x1) * (extents->y2 - extents->y1);
-
- if (area > xp_scroll_area_threshold)
- {
- /* Move region to window local coords */
- REGION_TRANSLATE (pScreen, &rgnDst, -winRec->x, -winRec->y);
-
- RootlessStopDrawing (pWin, FALSE);
-
- xp_copy_window (winRec->wid, winRec->wid,
- REGION_NUM_RECTS (&rgnDst),
- REGION_RECTS (&rgnDst), dx, dy);
- }
- else
- {
- RootlessStartDrawing (pWin);
-
- fbCopyRegion ((DrawablePtr) pWin, (DrawablePtr) pWin,
- 0, &rgnDst, dx, dy, fbCopyWindowProc, 0, 0);
-
- /* prgnSrc has been translated to dst position */
- RootlessDamageRegion(pWin, prgnSrc);
- }
-
- REGION_UNINIT (pScreen, &rgnDst);
- fbValidateDrawable (&pWin->drawable);
-
- SCREEN_WRAP (pScreen, CopyWindow);
-
- RL_DEBUG_MSG("copywindowFB end\n");
-}
-
-/*
- * Window resize procedures
- */
-
-enum {
- WIDTH_SMALLER = 1,
- HEIGHT_SMALLER = 2,
-};
-
-/* Compute which directions the window is resizing in. */
-static inline unsigned int
-resize_code (int oldX, int oldY, int oldW, int oldH,
- int newX, int newY, int newW, int newH)
-{
- unsigned int code = 0;
-
- /* These comparisons were chosen to avoid setting bits when the sizes
- are the same. (So the fastest case automatically gets taken when
- dimensions are unchanging.) */
-
- if (newW < oldW)
- code |= WIDTH_SMALLER;
-
- if (newH < oldH)
- code |= HEIGHT_SMALLER;
-
- return code;
-}
-
-static inline unsigned int
-resize_weighting (int oldX1, int oldY1, int oldX2, int oldY2, int oldBW,
- int newX1, int newY1, int newX2, int newY2, int newBW)
-{
- /* Choose gravity to avoid local copies. Do that by looking for
- a corner that doesn't move _relative to the screen_ */
-
- if (newBW != oldBW)
- return XP_GRAVITY_NONE;
-
- if (newX1 == oldX1 && newY1 == oldY1)
- return XP_GRAVITY_NORTH_WEST;
- else if (newX1 == oldX1 && newY2 == oldY2)
- return XP_GRAVITY_SOUTH_WEST;
- else if (newX2 == oldX2 && newY2 == oldY2)
- return XP_GRAVITY_SOUTH_EAST;
- else if (newX2 == oldX2 && newY1 == oldY1)
- return XP_GRAVITY_NORTH_EAST;
- else
- return XP_GRAVITY_NONE;
-}
-
-/* Resize the given window to its new position and size. */
-static void
-resize_frame (ScreenPtr pScreen, WindowPtr pWin,
- RootlessWindowRec *winRec, int gravity)
-{
- int sx, sy;
- xp_window_changes wc;
-
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
-
- wc.x = sx + winRec->x;
- wc.y = sy + winRec->y;
- wc.width = winRec->width;
- wc.height = winRec->height;
- wc.bit_gravity = gravity;
-
- /* It's unlikely that being async will save us anything here.
- But it can't hurt. */
-
- configure_window (winRec->wid, XP_BOUNDS, &wc);
-}
-
-/* Prepare to resize a top-level window. The old window's pixels are
- saved and the implementation is told to change the window size.
- (x,y,w,h) is outer frame of window (outside border) */
-static Bool
-StartFrameResize (WindowPtr pWin, Bool gravity,
- int oldX, int oldY, int oldW, int oldH, int oldBW,
- int newX, int newY, int newW, int newH, int newBW)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- Bool need_window_source = FALSE, resize_after = FALSE;
-
- BoxRec rect, copy_rect;
- int oldX2, newX2;
- int oldY2, newY2;
- unsigned int weight;
-
- oldX2 = oldX + oldW, newX2 = newX + newW;
- oldY2 = oldY + oldH, newY2 = newY + newH;
-
- /* Decide which resize weighting to use */
- weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
-
- /* Compute intersection between old and new rects */
- rect.x1 = max(oldX, newX);
- rect.y1 = max(oldY, newY);
- rect.x2 = min(oldX2, newX2);
- rect.y2 = min(oldY2, newY2);
-
- RL_DEBUG_MSG("RESIZE TOPLEVEL WINDOW with gravity %i ", gravity);
- RL_DEBUG_MSG("%d %d %d %d %d %d %d %d %d %d\n",
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
-
- RootlessDisableUpdate (pWin);
- RootlessRedisplay (pWin);
-
- /* If gravity is true, then we need to have a way of recovering all
- the original bits in the window for when X rearranges the contents
- based on the various gravity settings. The obvious way is to just
- snapshot the entire backing store before resizing it, but that
- it slow on large windows.
-
- So the optimization here is to use CG's resize weighting options
- to allow us to reason about what is left in the backing store
- after the resize. We can then only copy what won't be there after
- the resize, and do a two-stage copy operation.
-
- Most of these optimizations are only applied when the top-left
- corner of the window is fixed, since that's the common case. They
- could probably be extended with some thought. */
-
- gResizeDeathCount = 0;
-
- if (gravity && weight == XP_GRAVITY_NORTH_WEST)
- {
- unsigned int code;
-
- /* Top left corner is anchored. We never need to copy the
- entire window. */
-
- need_window_source = TRUE;
-
- code = resize_code (oldX, oldY, oldW, oldH,
- newX, newY, newW, newH);
-
- if (((code ^ (code >> 1)) & 1) == 0)
- {
- /* Both dimensions are either getting larger, or both
- are getting smaller. No need to copy anything. */
-
- if (code == (WIDTH_SMALLER | HEIGHT_SMALLER))
- {
- /* Since the window is getting smaller, we can do gravity
- repair on it with it's current size, then resize it
- afterwards. */
-
- resize_after = TRUE;
- }
-
- gResizeDeathCount = 1;
- }
- else
- {
- unsigned int copy_rowbytes, Bpp;
-
- /* We can get away with a partial copy. 'rect' is the
- intersection between old and new bounds, so copy
- everything to the right of or below the intersection. */
-
- RootlessStartDrawing (pWin);
-
- if (code == WIDTH_SMALLER)
- {
- copy_rect.x1 = rect.x2;
- copy_rect.y1 = rect.y1;
- copy_rect.x2 = oldX2;
- copy_rect.y2 = oldY2;
- }
- else if (code == HEIGHT_SMALLER)
- {
- copy_rect.x1 = rect.x1;
- copy_rect.y1 = rect.y2;
- copy_rect.x2 = oldX2;
- copy_rect.y2 = oldY2;
- }
- else
- abort ();
-
- Bpp = winRec->win->drawable.bitsPerPixel / 8;
- copy_rowbytes = (((copy_rect.x2 - copy_rect.x1) * Bpp) + 31) & ~31;
- gResizeDeathBits = xalloc (copy_rowbytes
- * (copy_rect.y2 - copy_rect.y1));
-
- xp_copy_bytes ((copy_rect.x2 - copy_rect.x1) * Bpp,
- copy_rect.y2 - copy_rect.y1, ((char *) winRec->data)
- + ((copy_rect.y1 - oldY) * winRec->rowbytes)
- + (copy_rect.x1 - oldX) * Bpp, winRec->rowbytes,
- gResizeDeathBits, copy_rowbytes);
-
- gResizeDeathBounds[1] = copy_rect;
- gResizeDeathPix[1]
- = GetScratchPixmapHeader(pScreen, copy_rect.x2 - copy_rect.x1,
- copy_rect.y2 - copy_rect.y1,
- winRec->win->drawable.depth,
- winRec->win->drawable.bitsPerPixel,
- winRec->rowbytes,
- (void *) gResizeDeathBits);
-
- TranslatePixmapBase (gResizeDeathPix[1],
- -copy_rect.x1, -copy_rect.y1);
-
- gResizeDeathCount = 2;
- }
- }
- else if (gravity)
- {
- /* The general case. Just copy everything. */
-
- RootlessStartDrawing (pWin);
-
- gResizeDeathBits = xalloc(winRec->rowbytes * winRec->height);
-
- memcpy(gResizeDeathBits, winRec->data,
- winRec->rowbytes * winRec->height);
-
- gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
- gResizeDeathPix[0]
- = GetScratchPixmapHeader(pScreen, winRec->width,
- winRec->height,
- winRec->win->drawable.depth,
- winRec->win->drawable.bitsPerPixel,
- winRec->rowbytes,
- (void *) gResizeDeathBits);
-
- TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
- gResizeDeathCount = 1;
- }
-
- RootlessStopDrawing (pWin, FALSE);
-
- winRec->x = newX;
- winRec->y = newY;
- winRec->width = newW;
- winRec->height = newH;
- winRec->borderWidth = newBW;
-
- /* Unless both dimensions are getting smaller, Resize the frame
- before doing gravity repair */
-
- if (!resize_after)
- resize_frame (pScreen, pWin, winRec, weight);
-
- RootlessStartDrawing(pWin);
-
- /* If necessary, create a source pixmap pointing at the current
- window bits. */
-
- if (need_window_source)
- {
- gResizeDeathBounds[0] = (BoxRec) {oldX, oldY, oldX2, oldY2};
- gResizeDeathPix[0]
- = GetScratchPixmapHeader (pScreen, oldW, oldH,
- winRec->win->drawable.depth,
- winRec->win->drawable.bitsPerPixel,
- winRec->rowbytes, winRec->data);
-
- TranslatePixmapBase (gResizeDeathPix[0], -oldX, -oldY);
- }
-
- /* Use custom CopyWindow when moving gravity bits around
- ResizeWindow assumes the old window contents are in the same
- pixmap, but here they're in deathPix instead. */
-
- if (gravity)
- {
- gResizeOldCopyWindowProc = pScreen->CopyWindow;
- pScreen->CopyWindow = RootlessResizeCopyWindow;
- }
-
- /* If we can't rely on the window server preserving the bits we
- need in the position we need, copy the pixels in the
- intersection from src to dst. ResizeWindow assumes these pixels
- are already present when making gravity adjustments. pWin
- currently has new-sized pixmap but is in old position.
-
- FIXME: border width change! (?) */
-
- if (gravity && weight == XP_GRAVITY_NONE)
- {
- PixmapPtr src, dst;
-
- assert (gResizeDeathCount == 1);
-
- src = gResizeDeathPix[0];
- dst = pScreen->GetWindowPixmap(pWin);
-
- RL_DEBUG_MSG("Resize copy rect %d %d %d %d\n",
- rect.x1, rect.y1, rect.x2, rect.y2);
-
- /* rect is the intersection of the old location and new location */
- if (BOX_NOT_EMPTY(rect) && src != NULL && dst != NULL)
- {
- int dx, dy;
-
- /* The window drawable still has the old frame position, which
- means that DST doesn't actually point at the origin of our
- physical backing store when adjusted by the drawable.x,y
- position. So sneakily adjust it temporarily while copying.. */
-
- dx = newX - oldX;
- dy = newY - oldY;
- TranslatePixmapBase (dst, -dx, -dy);
-
- fbCopyWindowProc(&src->drawable, &dst->drawable, NULL,
- &rect, 1, 0, 0, FALSE, FALSE, 0, 0);
-
- TranslatePixmapBase (dst, dx, dy);
- }
- }
-
- return resize_after;
-}
-
-static void
-FinishFrameResize (WindowPtr pWin, Bool gravity, int oldX, int oldY,
- unsigned int oldW, unsigned int oldH, unsigned int oldBW,
- int newX, int newY, unsigned int newW, unsigned int newH,
- unsigned int newBW, Bool resize_now)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RootlessWindowRec *winRec = WINREC(pWin);
- BoxRec box;
- int i;
-
- RootlessStopDrawing (pWin, FALSE);
-
- if (resize_now)
- {
- unsigned int weight;
-
- /* We didn't resize anything earlier, so do it now, now that
- we've finished gravitating the bits. */
-
- weight = resize_weighting (oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
-
- resize_frame (pScreen, pWin, winRec, weight);
- }
-
- /* Redraw everything. FIXME: there must be times when we don't need
- to do this. Perhaps when top-left weighting and no gravity? */
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = winRec->width;
- box.y2 = winRec->height;
-
- xp_mark_window (winRec->wid, 1, &box, 0, 0);
-
- for (i = 0; i < 2; i++)
- {
- if (gResizeDeathPix[i] != NULL)
- {
- FreeScratchPixmapHeader (gResizeDeathPix[i]);
- gResizeDeathPix[i] = NULL;
- }
- }
-
- if (gResizeDeathBits != NULL)
- {
- xfree (gResizeDeathBits);
- gResizeDeathBits = NULL;
- }
-
- if (gravity)
- pScreen->CopyWindow = gResizeOldCopyWindowProc;
-}
-
-/* If kind==VTOther, window border is resizing (and borderWidth is
- already changed!!@#$) This case works like window resize, not move. */
-void
-RootlessMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
- CopyWindowProcPtr oldCopyWindowProc = NULL;
-
- int oldX = 0, oldY = 0;
- unsigned int oldW = 0, oldH = 0, oldBW = 0;
- int newX = 0, newY = 0;
- unsigned int newW = 0, newH = 0, newBW = 0;
-
- Bool resize_after = FALSE;
- RegionRec saveRoot;
-
- RL_DEBUG_MSG("movewindow start \n");
-
- if (winRec != NULL)
- {
- if (kind == VTMove)
- {
- oldX = winRec->x;
- oldY = winRec->y;
- RootlessRedisplay (pWin);
- RootlessStartDrawing (pWin);
- }
- else
- {
- RL_DEBUG_MSG("movewindow border resizing ");
-
- oldBW = winRec->borderWidth;
- oldX = winRec->x;
- oldY = winRec->y;
- oldW = winRec->width;
- oldH = winRec->height;
-
- newBW = wBorderWidth (pWin);
- newX = x;
- newY = y;
- newW = pWin->drawable.width + 2*newBW;
- newH = pWin->drawable.height + 2*newBW;
-
- resize_after = StartFrameResize (pWin, FALSE,
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
- }
- }
-
- HUGE_ROOT (pWin);
- SCREEN_UNWRAP (pScreen, MoveWindow);
-
- oldCopyWindowProc = pScreen->CopyWindow;
-
- if (winRec != NULL)
- pScreen->CopyWindow = RootlessNoCopyWindow;
-
- pScreen->MoveWindow (pWin, x, y, pSib, kind);
-
- if (winRec != NULL)
- pScreen->CopyWindow = oldCopyWindowProc;
-
- NORMAL_ROOT (pWin);
- SCREEN_WRAP (pScreen, MoveWindow);
-
- if (winRec != NULL)
- {
- if (kind == VTMove)
- {
- xp_window_changes wc;
- int sx, sy;
-
- RootlessStopDrawing (pWin, FALSE);
-
- winRec->x = x;
- winRec->y = y;
-
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
-
- wc.x = sx + winRec->x;
- wc.y = sy + winRec->y;
-
- configure_window (winRec->wid, XP_ORIGIN, &wc);
- }
- else
- {
- FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW, resize_after);
- }
- }
-
- RL_DEBUG_MSG("movewindow end\n");
-}
-
-
-/* Note: (x, y, w, h) as passed to this procedure don't match the frame
- definition. (x,y) is corner of very outer edge, *outside* border
- w,h is width and height *inside* border, *ignoring* border width
- The rect (x, y, w, h) doesn't mean anything. (x, y, w+2*bw, h+2*bw)
- is total rect (x+bw, y+bw, w, h) is inner rect */
-void
-RootlessResizeWindow (WindowPtr pWin, int x, int y,
- unsigned int w, unsigned int h, WindowPtr pSib)
-{
- RootlessWindowRec *winRec = WINREC(pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
- RegionRec saveRoot;
-
- int oldX = 0, oldY = 0;
- unsigned int oldW = 0, oldH = 0, oldBW = 0;
- int newX = 0, newY = 0;
- unsigned int newW = 0, newH = 0, newBW = 0;
-
- Bool resize_after = FALSE;
-
- RL_DEBUG_MSG("resizewindow start (win 0x%x)\n", pWin);
-
- if (winRec != NULL)
- {
- oldBW = winRec->borderWidth;
- oldX = winRec->x;
- oldY = winRec->y;
- oldW = winRec->width;
- oldH = winRec->height;
-
- newBW = oldBW;
- newX = x;
- newY = y;
- newW = w + 2*newBW;
- newH = h + 2*newBW;
-
- resize_after = StartFrameResize (pWin, TRUE,
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
- }
-
- HUGE_ROOT (pWin);
- SCREEN_UNWRAP (pScreen, ResizeWindow);
-
- if (!IsRoot (pWin))
- {
- pScreen->ResizeWindow (pWin, x, y, w, h, pSib);
- }
- else
- {
- BoxRec box;
-
- /* mi won't resize the root. So do it ourselves... */
-
- pWin->drawable.x = x;
- pWin->drawable.y = y;
- pWin->drawable.width = w;
- pWin->drawable.height = h;
-
- box.x1 = x; box.y1 = y;
- box.x2 = x + w; box.y2 = y + h;
- REGION_UNINIT (pScreen, &pWin->winSize);
- REGION_INIT (pScreen, &pWin->winSize, &box, 1);
- REGION_COPY (pScreen, &pWin->borderSize, &pWin->winSize);
- REGION_COPY (pScreen, &pWin->clipList, &pWin->winSize);
- REGION_COPY (pScreen, &pWin->borderClip, &pWin->winSize);
-
- miSendExposures (pWin, &pWin->borderClip,
- pWin->drawable.x, pWin->drawable.y);
- }
-
- SCREEN_WRAP (pScreen, ResizeWindow);
- NORMAL_ROOT (pWin);
-
- if (winRec != NULL)
- {
- FinishFrameResize (pWin, TRUE, oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW, resize_after);
- }
-
- RL_DEBUG_MSG("resizewindow end\n");
-}
-
-void
-RootlessRepositionWindow (WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC (pWin);
- ScreenPtr pScreen = pWin->drawable.pScreen;
- xp_window_changes wc;
- int sx, sy;
-
- if (IsRoot (pWin))
- set_screen_origin (pWin);
-
- if (winRec == NULL)
- return;
-
- RootlessStopDrawing (pWin, FALSE);
-
- sx = dixScreenOrigins[pScreen->myNum].x + darwinMainScreenX;
- sy = dixScreenOrigins[pScreen->myNum].y + darwinMainScreenY;
-
- wc.x = sx + winRec->x;
- wc.y = sy + winRec->y;
-
- if (!rootlessHasRoot (pScreen))
- wc.window_level = normal_window_levels[winRec->level];
- else
- wc.window_level = rooted_window_levels[winRec->level];
-
- configure_window (winRec->wid, XP_ORIGIN | XP_WINDOW_LEVEL, &wc);
-
- RootlessReorderWindow (pWin);
-}
-
-void
-RootlessFlushWindowColormap (WindowPtr pWin)
-{
- RootlessWindowRec *winRec = WINREC (pWin);
- xp_window_changes wc;
-
- if (winRec == NULL)
- return;
-
- RootlessStopDrawing (pWin, FALSE);
-
- /* This is how we tell xp that the colormap may have changed. */
-
- wc.colormap = rootlessColormapCallback;
- wc.colormap_data = pWin->drawable.pScreen;
-
- configure_window (winRec->wid, XP_COLORMAP, &wc);
-}
-
-/* Set the Pixmaps on all ParentRelative windows up the ancestor chain. */
-static void
-SetPixmapOfAncestors (WindowPtr pWin)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- WindowPtr topWin = TopLevelParent (pWin);
- RootlessWindowRec *topWinRec = WINREC (topWin);
- XID pixel;
-
- while (pWin->backgroundState == ParentRelative)
- {
- if (pWin == topWin)
- {
- /* disallow ParentRelative background state on top level */
-
- pixel = 0;
- ChangeWindowAttributes(pWin, CWBackPixel, &pixel, serverClient);
-
- RL_DEBUG_MSG("Cleared ParentRelative on 0x%x.\n", pWin);
- break;
- }
-
- pWin = pWin->parent;
- pScreen->SetWindowPixmap (pWin, topWinRec->pixmap);
- }
-}
-
-/* RootlessPaintWindowBackground
- Paint the window background while filling in the alpha channel
- with all on. */
-void
-RootlessPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
-
- SCREEN_UNWRAP (pScreen, PaintWindowBackground);
-
- RL_DEBUG_MSG("paintwindowbackground start (win 0x%x, framed %i)\n",
- pWin, IsFramedWindow(pWin));
-
- if (IsFramedWindow (pWin))
- {
- /* Don't bother trying to paint the surface background.. */
- rootlessNoDRIDrawing++;
-
- RootlessStartDrawing (pWin);
- RootlessDamageRegion (pWin, pRegion);
-
- /* For ParentRelative windows, we have to make sure the window
- pixmap is set correctly all the way up the ancestor chain. */
-
- if (pWin->backgroundState == ParentRelative)
- SetPixmapOfAncestors (pWin);
-
- pScreen->PaintWindowBackground (pWin, pRegion, what);
-
- rootlessNoDRIDrawing--;
- }
-
- SCREEN_WRAP (pScreen, PaintWindowBackground);
-
- RL_DEBUG_MSG("paintwindowbackground end\n");
-}
-
-
-/* RootlessPaintWindowBorder
- Paint the window border while filling in the alpha channel with all on. */
-void
-RootlessPaintWindowBorder (WindowPtr pWin, RegionPtr pRegion, int what)
-{
- SCREEN_UNWRAP (pWin->drawable.pScreen, PaintWindowBorder);
-
- RL_DEBUG_MSG("paintwindowborder start (win 0x%x)\n", pWin);
-
- if (IsFramedWindow (pWin))
- {
- RootlessStartDrawing (pWin);
- RootlessDamageRegion (pWin, pRegion);
-
- /* For ParentRelative windows with tiled borders, we have to make
- sure the window pixmap is set correctly all the way up the
- ancestor chain. */
-
- if (!pWin->borderIsPixel && pWin->backgroundState == ParentRelative)
- SetPixmapOfAncestors (pWin);
- }
-
- pWin->drawable.pScreen->PaintWindowBorder (pWin, pRegion, what);
-
- SCREEN_WRAP (pWin->drawable.pScreen, PaintWindowBorder);
-
- RL_DEBUG_MSG("paintwindowborder end\n");
-}
-
-
-/* FIXME: untested!
- pWin inside corner stays the same; pWin->drawable.[xy] stays the same
- frame moves and resizes */
-void
-RootlessChangeBorderWidth (WindowPtr pWin, unsigned int width)
-{
- RegionRec saveRoot;
- Bool resize_after = FALSE;
-
- RL_DEBUG_MSG("change border width\n");
-
- if ((int) width != wBorderWidth (pWin))
- {
- RootlessWindowRec *winRec = WINREC(pWin);
-
- int oldX = 0, oldY = 0, newX = 0, newY = 0;
- unsigned int oldW = 0, oldH = 0, oldBW = 0;
- unsigned int newW = 0, newH = 0, newBW = 0;
-
- if (winRec != NULL)
- {
- oldBW = winRec->borderWidth;
- oldX = winRec->x;
- oldY = winRec->y;
- oldW = winRec->width;
- oldH = winRec->height;
-
- newBW = width;
- newX = pWin->drawable.x - newBW;
- newY = pWin->drawable.y - newBW;
- newW = pWin->drawable.width + 2*newBW;
- newH = pWin->drawable.height + 2*newBW;
-
- resize_after = StartFrameResize (pWin, FALSE,
- oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW);
- }
-
- HUGE_ROOT (pWin);
- SCREEN_UNWRAP (pWin->drawable.pScreen, ChangeBorderWidth);
-
- pWin->drawable.pScreen->ChangeBorderWidth (pWin, width);
-
- SCREEN_WRAP (pWin->drawable.pScreen, ChangeBorderWidth);
- NORMAL_ROOT (pWin);
-
- if (winRec != NULL)
- {
- FinishFrameResize (pWin, FALSE, oldX, oldY, oldW, oldH, oldBW,
- newX, newY, newW, newH, newBW, resize_after);
- }
- }
-
- RL_DEBUG_MSG("change border width end\n");
-}
-
-/*
- * RootlessFillRegionTiled
- * Fill using a tile while leaving the alpha channel untouched.
- * Based on fbfillRegionTiled.
- */
-static void
-RootlessFillRegionTiled(
- DrawablePtr pDrawable,
- RegionPtr pRegion,
- PixmapPtr pTile)
-{
- FbBits *dst;
- FbStride dstStride;
- int dstBpp;
- int dstXoff, dstYoff;
- FbBits *tile;
- FbStride tileStride;
- int tileBpp;
- int tileXoff, tileYoff; /* XXX assumed to be zero */
- int tileWidth, tileHeight;
- int n = REGION_NUM_RECTS(pRegion);
- BoxPtr pbox = REGION_RECTS(pRegion);
- int xRot = pDrawable->x;
- int yRot = pDrawable->y;
- FbBits planeMask;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension)
- {
- int index = pDrawable->pScreen->myNum;
- if(&WindowTable[index]->drawable == pDrawable)
- {
- xRot -= panoramiXdataPtr[index].x;
- yRot -= panoramiXdataPtr[index].y;
- }
- }
-#endif
- fbGetDrawable (pDrawable, dst, dstStride, dstBpp, dstXoff, dstYoff);
- fbGetDrawable (&pTile->drawable, tile, tileStride, tileBpp,
- tileXoff, tileYoff);
- tileWidth = pTile->drawable.width;
- tileHeight = pTile->drawable.height;
- xRot += dstXoff;
- yRot += dstYoff;
- planeMask = FB_ALLONES & ~RootlessAlphaMask(dstBpp);
-
- while (n--)
- {
- fbTile (dst + (pbox->y1 + dstYoff) * dstStride,
- dstStride,
- (pbox->x1 + dstXoff) * dstBpp,
- (pbox->x2 - pbox->x1) * dstBpp,
- pbox->y2 - pbox->y1,
- tile,
- tileStride,
- tileWidth * dstBpp,
- tileHeight,
- GXcopy,
- planeMask,
- dstBpp,
- xRot * dstBpp,
- yRot - pbox->y1);
- pbox++;
- }
-}
-
-/*
- * RootlessPaintWindow
- * Paint the window while filling in the alpha channel with all on.
- * We can't use fbPaintWindow because it zeros the alpha channel.
- */
-void
-RootlessPaintWindow(
- WindowPtr pWin,
- RegionPtr pRegion,
- int what)
-{
- switch (what) {
- case PW_BACKGROUND:
-
- switch (pWin->backgroundState) {
- case None:
- break;
- case ParentRelative:
- do {
- pWin = pWin->parent;
- } while (pWin->backgroundState == ParentRelative);
- (*pWin->drawable.pScreen->PaintWindowBackground)(pWin, pRegion,
- what);
- break;
- case BackgroundPixmap:
- RootlessFillRegionTiled (&pWin->drawable,
- pRegion,
- pWin->background.pixmap);
- break;
- case BackgroundPixel:
- {
- Pixel pixel = pWin->background.pixel |
- RootlessAlphaMask(pWin->drawable.bitsPerPixel);
- fbFillRegionSolid (&pWin->drawable, pRegion, 0,
- fbReplicatePixel (pixel,
- pWin->drawable.bitsPerPixel));
- break;
- }
- }
- break;
- case PW_BORDER:
- if (pWin->borderIsPixel)
- {
- Pixel pixel = pWin->border.pixel |
- RootlessAlphaMask(pWin->drawable.bitsPerPixel);
- fbFillRegionSolid (&pWin->drawable, pRegion, 0,
- fbReplicatePixel (pixel,
- pWin->drawable.bitsPerPixel));
- }
- else
- {
- WindowPtr pBgWin;
- for (pBgWin = pWin; pBgWin->backgroundState == ParentRelative;
- pBgWin = pBgWin->parent);
-
- RootlessFillRegionTiled (&pBgWin->drawable,
- pRegion,
- pWin->border.pixmap);
- }
- break;
- }
- fbValidateDrawable (&pWin->drawable);
-}