diff options
Diffstat (limited to 'xorg-server/hw/xwin/winmultiwindowwindow.c')
-rw-r--r-- | xorg-server/hw/xwin/winmultiwindowwindow.c | 2000 |
1 files changed, 1008 insertions, 992 deletions
diff --git a/xorg-server/hw/xwin/winmultiwindowwindow.c b/xorg-server/hw/xwin/winmultiwindowwindow.c index 93434fceb..21b818b89 100644 --- a/xorg-server/hw/xwin/winmultiwindowwindow.c +++ b/xorg-server/hw/xwin/winmultiwindowwindow.c @@ -1,992 +1,1008 @@ -/*
- *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
- *Copyright (C) Colin Harrison 2005-2008
- *
- *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 XFREE86 PROJECT 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 of the XFree86 Project
- *shall not be used in advertising or otherwise to promote the sale, use
- *or other dealings in this Software without prior written authorization
- *from the XFree86 Project.
- *
- * Authors: Kensuke Matsuzaki
- * Earle F. Philhower, III
- * Harold L Hunt II
- * Colin Harrison
- */
-
-#ifdef HAVE_XWIN_CONFIG_H
-#include <xwin-config.h>
-#endif
-#include "win.h"
-#include "dixevents.h"
-#include "winmultiwindowclass.h"
-
-/*
- * Prototypes for local functions
- */
-
-void
-winCreateWindowsWindow (WindowPtr pWin);
-
-static void
-winDestroyWindowsWindow (WindowPtr pWin);
-
-static void
-winUpdateWindowsWindow (WindowPtr pWin);
-
-static void
-winFindWindow (pointer value, XID id, pointer cdata);
-
-static
-void winInitMultiWindowClass(void)
-{
- static wATOM atomXWinClass=0;
- WNDCLASSEX wcx;
-
- if (atomXWinClass==0)
- {
- /* Setup our window class */
- wcx.cbSize=sizeof(WNDCLASSEX);
- wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0);
- wcx.lpfnWndProc = winTopLevelWindowProc;
- wcx.cbClsExtra = 0;
- wcx.cbWndExtra = 0;
- wcx.hInstance = g_hInstance;
- wcx.hIcon = g_hIconX;
- wcx.hCursor = 0;
- wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
- wcx.lpszMenuName = NULL;
- wcx.lpszClassName = WINDOW_CLASS_X;
- wcx.hIconSm = g_hSmallIconX;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X);
-#endif
-
- atomXWinClass = RegisterClassEx (&wcx);
- }
-}
-
-/*
- * CreateWindow - See Porting Layer Definition - p. 37
- */
-
-Bool
-winCreateWindowMultiWindow (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG
- winTrace ("winCreateWindowMultiWindow - pWin: %p\n", pWin);
-#endif
-
- WIN_UNWRAP(CreateWindow);
- fResult = (*pScreen->CreateWindow) (pWin);
- WIN_WRAP(CreateWindow, winCreateWindowMultiWindow);
-
- /* Initialize some privates values */
- pWinPriv->hRgn = NULL;
- pWinPriv->hWnd = NULL;
- pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen);
- pWinPriv->fXKilled = FALSE;
-
- return fResult;
-}
-
-
-/*
- * DestroyWindow - See Porting Layer Definition - p. 37
- */
-
-Bool
-winDestroyWindowMultiWindow (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winDestroyWindowMultiWindow - pWin: %p\n", pWin);
-#endif
-
- WIN_UNWRAP(DestroyWindow);
- fResult = (*pScreen->DestroyWindow)(pWin);
- WIN_WRAP(DestroyWindow, winDestroyWindowMultiWindow);
-
- /* Flag that the window has been destroyed */
- pWinPriv->fXKilled = TRUE;
-
- /* Kill the MS Windows window associated with this window */
- winDestroyWindowsWindow (pWin);
-
- return fResult;
-}
-
-
-/*
- * PositionWindow - See Porting Layer Definition - p. 37
- *
- * This function adjusts the position and size of Windows window
- * with respect to the underlying X window. This is the inverse
- * of winAdjustXWindow, which adjusts X window to Windows window.
- */
-
-Bool
-winPositionWindowMultiWindow (WindowPtr pWin, int x, int y)
-{
- Bool fResult = TRUE;
- int iX, iY, iWidth, iHeight;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
- HWND hWnd = pWinPriv->hWnd;
- RECT rcNew;
- RECT rcOld;
-#if CYGMULTIWINDOW_DEBUG
- RECT rcClient;
- RECT *lpRc;
-#endif
- DWORD dwExStyle;
- DWORD dwStyle;
-
-#if CYGMULTIWINDOW_DEBUG
- winTrace ("winPositionWindowMultiWindow - pWin: %p\n", pWin);
-#endif
-
- WIN_UNWRAP(PositionWindow);
- fResult = (*pScreen->PositionWindow)(pWin, x, y);
- WIN_WRAP(PositionWindow, winPositionWindowMultiWindow);
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("winPositionWindowMultiWindow: (x, y) = (%d, %d)\n",
- x, y);
-#endif
-
- /* Bail out if the Windows window handle is bad */
- if (!hWnd)
- {
-#if CYGWINDOWING_DEBUG
- ErrorF ("\timmediately return since hWnd is NULL\n");
-#endif
- return fResult;
- }
-
- /* Get the Windows window style and extended style */
- dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE);
- dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE);
-
- /* Get the X and Y location of the X window */
- iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
- iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
-
- /* Get the height and width of the X window */
- iWidth = pWin->drawable.width;
- iHeight = pWin->drawable.height;
-
- /* Store the origin, height, and width in a rectangle structure */
- SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight);
-
-#if CYGMULTIWINDOW_DEBUG
- lpRc = &rcNew;
- ErrorF ("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n",
- GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
-#endif
-
- /*
- * Calculate the required size of the Windows window rectangle,
- * given the size of the Windows window client area.
- */
- AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle);
-
- /* Get a rectangle describing the old Windows window */
- GetWindowRect (hWnd, &rcOld);
-
-#if CYGMULTIWINDOW_DEBUG
- /* Get a rectangle describing the Windows window client area */
- GetClientRect (hWnd, &rcClient);
-
- lpRc = &rcNew;
- ErrorF ("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n",
- GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
-
- lpRc = &rcOld;
- ErrorF ("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n",
- GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
-
- lpRc = &rcClient;
- ErrorF ("(%d ms)rcClient (%d, %d)-(%d, %d)\n",
- GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom);
-#endif
-
- /* Check if the old rectangle and new rectangle are the same */
- if (!EqualRect (&rcNew, &rcOld))
- {
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winPositionWindowMultiWindow - Need to move\n");
-#endif
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top,
- rcNew.right - rcNew.left, rcNew.bottom - rcNew.top);
-#endif
- /* Change the position and dimensions of the Windows window */
- MoveWindow (hWnd,
- rcNew.left, rcNew.top,
- rcNew.right - rcNew.left, rcNew.bottom - rcNew.top,
- TRUE);
- }
- else
- {
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winPositionWindowMultiWindow - Not need to move\n");
-#endif
- }
-
- return fResult;
-}
-
-
-/*
- * ChangeWindowAttributes - See Porting Layer Definition - p. 37
- */
-
-Bool
-winChangeWindowAttributesMultiWindow (WindowPtr pWin, unsigned long mask)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin);
-#endif
-
- WIN_UNWRAP(ChangeWindowAttributes);
- fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask);
- WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesMultiWindow);
-
- /*
- * NOTE: We do not currently need to do anything here.
- */
-
- return fResult;
-}
-
-
-/*
- * UnmapWindow - See Porting Layer Definition - p. 37
- * Also referred to as UnrealizeWindow
- */
-
-Bool
-winUnmapWindowMultiWindow (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winUnmapWindowMultiWindow - pWin: %08x\n", pWin);
-#endif
-
- WIN_UNWRAP(UnrealizeWindow);
- fResult = (*pScreen->UnrealizeWindow)(pWin);
- WIN_WRAP(UnrealizeWindow, winUnmapWindowMultiWindow);
-
- /* Flag that the window has been killed */
- pWinPriv->fXKilled = TRUE;
-
- /* Destroy the Windows window associated with this X window */
- winDestroyWindowsWindow (pWin);
-
- return fResult;
-}
-
-
-/*
- * MapWindow - See Porting Layer Definition - p. 37
- * Also referred to as RealizeWindow
- */
-
-Bool
-winMapWindowMultiWindow (WindowPtr pWin)
-{
- Bool fResult = TRUE;
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winWindowPriv(pWin);
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winMapWindowMultiWindow - pWin: %08x\n", pWin);
-#endif
-
- WIN_UNWRAP(RealizeWindow);
- fResult = (*pScreen->RealizeWindow)(pWin);
- WIN_WRAP(RealizeWindow, winMapWindowMultiWindow);
-
- /* Flag that this window has not been destroyed */
- pWinPriv->fXKilled = FALSE;
-
- /* Refresh/redisplay the Windows window associated with this X window */
- winUpdateWindowsWindow (pWin);
-
- /* Update the Windows window's shape */
- winReshapeMultiWindow (pWin);
- winUpdateRgnMultiWindow (pWin);
-
- return fResult;
-}
-
-
-/*
- * ReparentWindow - See Porting Layer Definition - p. 42
- */
-
-void
-winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winReparentMultiWindow - pWin: %08x\n", pWin);
-#endif
-
- WIN_UNWRAP(ReparentWindow);
- if (pScreen->ReparentWindow)
- (*pScreen->ReparentWindow)(pWin, pPriorParent);
- WIN_WRAP(ReparentWindow, winReparentWindowMultiWindow);
-
- /* Update the Windows window associated with this X window */
- winUpdateWindowsWindow (pWin);
-}
-
-
-/*
- * RestackWindow - Shuffle the z-order of a window
- */
-
-void
-winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib)
-{
-#if 0
- WindowPtr pPrevWin;
- UINT uFlags;
- HWND hInsertAfter;
- HWND hWnd = NULL;
-#endif
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG
- winTrace ("winRestackMultiWindow - %08x\n", pWin);
-#endif
-
- WIN_UNWRAP(RestackWindow);
- if (pScreen->RestackWindow)
- (*pScreen->RestackWindow)(pWin, pOldNextSib);
- WIN_WRAP(RestackWindow, winRestackWindowMultiWindow);
-
-#if 1
- /*
- * Calling winReorderWindowsMultiWindow here means our window manager
- * (i.e. Windows Explorer) has initiative to determine Z order.
- */
- if (pWin->nextSib != pOldNextSib)
- winReorderWindowsMultiWindow ();
-#else
- /* Bail out if no window privates or window handle is invalid */
- if (!pWinPriv || !pWinPriv->hWnd)
- return;
-
- /* Get a pointer to our previous sibling window */
- pPrevWin = pWin->prevSib;
-
- /*
- * Look for a sibling window with
- * valid privates and window handle
- */
- while (pPrevWin
- && !winGetWindowPriv(pPrevWin)
- && !winGetWindowPriv(pPrevWin)->hWnd)
- pPrevWin = pPrevWin->prevSib;
-
- /* Check if we found a valid sibling */
- if (pPrevWin)
- {
- /* Valid sibling - get handle to insert window after */
- hInsertAfter = winGetWindowPriv(pPrevWin)->hWnd;
- uFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE;
-
- hWnd = GetNextWindow (pWinPriv->hWnd, GW_HWNDPREV);
-
- do
- {
- if (GetProp (hWnd, WIN_WINDOW_PROP))
- {
- if (hWnd == winGetWindowPriv(pPrevWin)->hWnd)
- {
- uFlags |= SWP_NOZORDER;
- }
- break;
- }
- hWnd = GetNextWindow (hWnd, GW_HWNDPREV);
- }
- while (hWnd);
- }
- else
- {
- /* No valid sibling - make this window the top window */
- hInsertAfter = HWND_TOP;
- uFlags = SWP_NOMOVE | SWP_NOSIZE;
- }
-
- /* Perform the restacking operation in Windows */
- SetWindowPos (pWinPriv->hWnd,
- hInsertAfter,
- 0, 0,
- 0, 0,
- uFlags);
-#endif
-}
-
-
-/*
- * winCreateWindowsWindow - Create a Windows window associated with an X window
- */
-
-void
-winCreateWindowsWindow (WindowPtr pWin)
-{
- int iX, iY;
- int iWidth;
- int iHeight;
- HWND hWnd;
- HWND hFore = NULL;
- winWindowPriv(pWin);
- HICON hIcon;
- HICON hIconSmall;
- winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv;
- WinXSizeHints hints;
- WindowPtr pDaddy;
-
- winInitMultiWindowClass();
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winCreateWindowsWindow - pWin: %08x\n", pWin);
-#endif
-
- iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN);
- iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN);
-
- iWidth = pWin->drawable.width;
- iHeight = pWin->drawable.height;
-
- /* ensure window actually ends up somewhere visible */
- if (iX > GetSystemMetrics (SM_CXVIRTUALSCREEN))
- iX = CW_USEDEFAULT;
-
- if (iY > GetSystemMetrics (SM_CYVIRTUALSCREEN))
- iY = CW_USEDEFAULT;
-
- if (winMultiWindowGetTransientFor (pWin, &pDaddy))
- {
- if (pDaddy)
- {
- hFore = GetForegroundWindow();
- if (hFore && (pDaddy != (WindowPtr)GetProp(hFore, WIN_WID_PROP))) hFore = NULL;
- }
- }
- else
- {
- /* Default positions if none specified */
- if (!winMultiWindowGetWMNormalHints(pWin, &hints))
- hints.flags = 0;
- if (!(hints.flags & (USPosition|PPosition)) &&
- !pWin->overrideRedirect)
- {
- iX = CW_USEDEFAULT;
- iY = CW_USEDEFAULT;
- }
- }
-
- /* Create the window */
- /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */
- /* CW_USEDEFAULT, change back to popup after creation */
- hWnd = CreateWindowExA (WS_EX_TOOLWINDOW, /* Extended styles */
- WINDOW_CLASS_X, /* Class name */
- WINDOW_TITLE_X, /* Window name */
- WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
- iX, /* Horizontal position */
- iY, /* Vertical position */
- iWidth, /* Right edge */
- iHeight, /* Bottom edge */
- hFore, /* Null or Parent window if transient*/
- (HMENU) NULL, /* No menu */
- GetModuleHandle (NULL), /* Instance handle */
- pWin); /* ScreenPrivates */
- if (hWnd == NULL)
- {
- ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n",
- (int) GetLastError ());
- }
- pWinPriv->hWnd = hWnd;
-
- /* Set application or .XWinrc defined Icons */
- winSelectIcons(pWin, &hIcon, &hIconSmall);
- if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon);
- if (hIconSmall) SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall);
-
- /* Change style back to popup, already placed... */
- SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
- SetWindowPos (hWnd, 0, 0, 0, 0, 0,
- SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
- /* Make sure it gets the proper system menu for a WS_POPUP, too */
- GetSystemMenu (hWnd, TRUE);
-
- /* Cause any .XWinrc menus to be added in main WNDPROC */
- PostMessage (hWnd, WM_INIT_SYS_MENU, 0, 0);
-
- SetProp (hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin));
-
- /* Flag that this Windows window handles its own activation */
- SetProp (hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0);
-
- /* Call engine-specific create window procedure */
- (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin);
-}
-
-
-Bool winInDestroyWindowsWindow = FALSE;
-/*
- * winDestroyWindowsWindow - Destroy a Windows window associated
- * with an X window
- */
-static void
-winDestroyWindowsWindow (WindowPtr pWin)
-{
- MSG msg;
- winWindowPriv(pWin);
- BOOL oldstate = winInDestroyWindowsWindow;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winDestroyWindowsWindow\n");
-#endif
-
- /* Bail out if the Windows window handle is invalid */
- if (pWinPriv->hWnd == NULL)
- return;
-
- winInDestroyWindowsWindow = TRUE;
-
- SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL);
- /* Destroy the Windows window */
- DestroyWindow (pWinPriv->hWnd);
-
- /* Null our handle to the Window so referencing it will cause an error */
- pWinPriv->hWnd = NULL;
-
- /* Process all messages on our queue */
- while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
- {
- if (g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg))
- {
- DispatchMessage (&msg);
- }
- }
-
- winInDestroyWindowsWindow = oldstate;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("-winDestroyWindowsWindow\n");
-#endif
-}
-
-
-/*
- * winUpdateWindowsWindow - Redisplay/redraw a Windows window
- * associated with an X window
- */
-
-static void
-winUpdateWindowsWindow (WindowPtr pWin)
-{
- winWindowPriv(pWin);
- HWND hWnd = pWinPriv->hWnd;
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winUpdateWindowsWindow\n");
-#endif
-
- /* Check if the Windows window's parents have been destroyed */
- if (pWin->parent != NULL
- && pWin->parent->parent == NULL
- && pWin->mapped)
- {
- /* Create the Windows window if it has been destroyed */
- if (hWnd == NULL)
- {
- winCreateWindowsWindow (pWin);
- assert (pWinPriv->hWnd != NULL);
- }
-
- /* Display the window without activating it */
- ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE);
-
- /* Send first paint message */
- UpdateWindow (pWinPriv->hWnd);
- }
- else if (hWnd != NULL)
- {
- /* Destroy the Windows window if its parents are destroyed */
- winDestroyWindowsWindow (pWin);
- assert (pWinPriv->hWnd == NULL);
- }
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("-winUpdateWindowsWindow\n");
-#endif
-}
-
-
-/*
- * winGetWindowID -
- */
-
-XID
-winGetWindowID (WindowPtr pWin)
-{
- WindowIDPairRec wi = {pWin, 0};
- ClientPtr c = wClient(pWin);
-
- /* */
- FindClientResourcesByType (c, RT_WINDOW, winFindWindow, &wi);
-
-#if CYGMULTIWINDOW_DEBUG
- ErrorF ("winGetWindowID - Window ID: %d\n", wi.id);
-#endif
-
- return wi.id;
-}
-
-
-/*
- * winFindWindow -
- */
-
-static void
-winFindWindow (pointer value, XID id, pointer cdata)
-{
- WindowIDPairPtr wi = (WindowIDPairPtr)cdata;
-
- if (value == wi->value)
- {
- wi->id = id;
- }
-}
-
-
-/*
- * winReorderWindowsMultiWindow -
- */
-
-void
-winReorderWindowsMultiWindow (void)
-{
- HWND hwnd = NULL;
- WindowPtr pWin = NULL;
- WindowPtr pWinSib = NULL;
- XID vlist[2];
- static Bool fRestacking = FALSE; /* Avoid recusive calls to this function */
- DWORD dwCurrentProcessID = GetCurrentProcessId ();
- DWORD dwWindowProcessID = 0;
-
-#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG
- winTrace ("winReorderWindowsMultiWindow\n");
-#endif
-
- if (fRestacking)
- {
- /* It is a recusive call so immediately exit */
-#if CYGWINDOWING_DEBUG
- ErrorF ("winReorderWindowsMultiWindow - "
- "exit because fRestacking == TRUE\n");
-#endif
- return;
- }
- fRestacking = TRUE;
-
- /* Loop through top level Window windows, descending in Z order */
- for ( hwnd = GetTopWindow (NULL);
- hwnd;
- hwnd = GetNextWindow (hwnd, GW_HWNDNEXT) )
- {
- /* Don't take care of other Cygwin/X process's windows */
- GetWindowThreadProcessId (hwnd, &dwWindowProcessID);
-
- if ( GetProp (hwnd, WIN_WINDOW_PROP)
- && (dwWindowProcessID == dwCurrentProcessID)
- && !IsIconic (hwnd) ) /* ignore minimized windows */
- {
- pWinSib = pWin;
- pWin = GetProp (hwnd, WIN_WINDOW_PROP);
-
- if (!pWinSib)
- { /* 1st window - raise to the top */
- vlist[0] = Above;
-
- ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin));
- }
- else
- { /* 2nd or deeper windows - just below the previous one */
- vlist[0] = winGetWindowID (pWinSib);
- vlist[1] = Below;
-
- ConfigureWindow (pWin, CWSibling | CWStackMode,
- vlist, wClient(pWin));
- }
- }
- }
-
- fRestacking = FALSE;
-}
-
-
-/*
- * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE
- */
-
-void
-winMinimizeWindow (Window id)
-{
- WindowPtr pWin;
- winPrivWinPtr pWinPriv;
-#ifdef XWIN_MULTIWINDOWEXTWM
- win32RootlessWindowPtr pRLWinPriv;
-#endif
- HWND hWnd;
- ScreenPtr pScreen = NULL;
- winPrivScreenPtr pScreenPriv = NULL;
- winScreenInfo *pScreenInfo = NULL;
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("winMinimizeWindow\n");
-#endif
-
- dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess);
- if (!pWin)
- {
- ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__);
- return;
- }
-
- pScreen = pWin->drawable.pScreen;
- if (pScreen) pScreenPriv = winGetScreenPriv(pScreen);
- if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo;
-
-#ifdef XWIN_MULTIWINDOWEXTWM
- if (pScreenPriv && pScreenInfo->fInternalWM)
- {
- pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE);
- hWnd = pRLWinPriv->hWnd;
- }
- else
-#else
- if (pScreenPriv)
-#endif
- {
- pWinPriv = winGetWindowPriv (pWin);
- hWnd = pWinPriv->hWnd;
- }
-
- ShowWindow (hWnd, SW_MINIMIZE);
-}
-
-
-/*
- * CopyWindow - See Porting Layer Definition - p. 39
- */
-void
-winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt,
- RegionPtr oldRegion)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("CopyWindowMultiWindow\n");
-#endif
- WIN_UNWRAP(CopyWindow);
- (*pScreen->CopyWindow)(pWin, oldpt, oldRegion);
- WIN_WRAP(CopyWindow, winCopyWindowMultiWindow);
-}
-
-
-/*
- * MoveWindow - See Porting Layer Definition - p. 42
- */
-void
-winMoveWindowMultiWindow (WindowPtr pWin, int x, int y,
- WindowPtr pSib, VTKind kind)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("MoveWindowMultiWindow to (%d, %d)\n", x, y);
-#endif
-
- WIN_UNWRAP(MoveWindow);
- (*pScreen->MoveWindow)(pWin, x, y, pSib, kind);
- WIN_WRAP(MoveWindow, winMoveWindowMultiWindow);
-}
-
-
-/*
- * ResizeWindow - See Porting Layer Definition - p. 42
- */
-void
-winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w,
- unsigned int h, WindowPtr pSib)
-{
- ScreenPtr pScreen = pWin->drawable.pScreen;
- winScreenPriv(pScreen);
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("ResizeWindowMultiWindow to (%d, %d) - %dx%d\n", x, y, w, h);
-#endif
- WIN_UNWRAP(ResizeWindow);
- (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib);
- WIN_WRAP(ResizeWindow, winResizeWindowMultiWindow);
-}
-
-
-/*
- * winAdjustXWindow
- *
- * Move and resize X window with respect to corresponding Windows window.
- * This is called from WM_MOVE/WM_SIZE handlers when the user performs
- * any windowing operation (move, resize, minimize, maximize, restore).
- *
- * The functionality is the inverse of winPositionWindowMultiWindow, which
- * adjusts Windows window with respect to X window.
- */
-int
-winAdjustXWindow (WindowPtr pWin, HWND hwnd)
-{
- RECT rcDraw; /* Rect made from pWin->drawable to be adjusted */
- RECT rcWin; /* The source: WindowRect from hwnd */
- DrawablePtr pDraw;
- XID vlist[4];
- LONG dX, dY, dW, dH, x, y;
- DWORD dwStyle, dwExStyle;
-
-#define WIDTH(rc) (rc.right - rc.left)
-#define HEIGHT(rc) (rc.bottom - rc.top)
-
-#if CYGWINDOWING_DEBUG
- ErrorF ("winAdjustXWindow\n");
-#endif
-
- if (IsIconic (hwnd))
- {
-#if CYGWINDOWING_DEBUG
- ErrorF ("\timmediately return because the window is iconized\n");
-#endif
- /*
- * If the Windows window is minimized, its WindowRect has
- * meaningless values so we don't adjust X window to it.
- */
- vlist[0] = 0;
- vlist[1] = 0;
- return ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin));
- }
-
- pDraw = &pWin->drawable;
-
- /* Calculate the window rect from the drawable */
- x = pDraw->x + GetSystemMetrics (SM_XVIRTUALSCREEN);
- y = pDraw->y + GetSystemMetrics (SM_YVIRTUALSCREEN);
- SetRect (&rcDraw, x, y, x + pDraw->width, y + pDraw->height);
-#ifdef CYGMULTIWINDOW_DEBUG
- winDebug("\tDrawable extend {%d, %d, %d, %d}, {%d, %d}\n",
- rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom,
- rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top);
-#endif
- dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE);
- dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE);
-#ifdef CYGMULTIWINDOW_DEBUG
- winDebug("\tWindowStyle: %08x %08x\n", dwStyle, dwExStyle);
-#endif
- AdjustWindowRectEx (&rcDraw, dwStyle, FALSE, dwExStyle);
-
- /* The source of adjust */
- GetWindowRect (hwnd, &rcWin);
-#ifdef CYGMULTIWINDOW_DEBUG
- winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n",
- rcWin.left, rcWin.top, rcWin.right, rcWin.bottom,
- rcWin.right - rcWin.left, rcWin.bottom - rcWin.top);
- winDebug("\tDraw extend {%d, %d, %d, %d}, {%d, %d}\n",
- rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom,
- rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top);
-#endif
-
- if (EqualRect (&rcDraw, &rcWin)) {
- /* Bail if no adjust is needed */
-#if CYGWINDOWING_DEBUG
- ErrorF ("\treturn because already adjusted\n");
-#endif
- return 0;
- }
-
- /* Calculate delta values */
- dX = rcWin.left - rcDraw.left;
- dY = rcWin.top - rcDraw.top;
- dW = WIDTH(rcWin) - WIDTH(rcDraw);
- dH = HEIGHT(rcWin) - HEIGHT(rcDraw);
-
- /*
- * Adjust.
- * We may only need to move (vlist[0] and [1]), or only resize
- * ([2] and [3]) but currently we set all the parameters and leave
- * the decision to ConfigureWindow. The reason is code simplicity.
- */
- vlist[0] = pDraw->x + dX - wBorderWidth(pWin);
- vlist[1] = pDraw->y + dY - wBorderWidth(pWin);
- vlist[2] = pDraw->width + dW;
- vlist[3] = pDraw->height + dH;
-#if CYGWINDOWING_DEBUG
- ErrorF ("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1],
- vlist[2], vlist[3]);
-#endif
- return ConfigureWindow (pWin, CWX | CWY | CWWidth | CWHeight,
- vlist, wClient(pWin));
-
-#undef WIDTH
-#undef HEIGHT
-}
-
+/* + *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + *Copyright (C) Colin Harrison 2005-2008 + * + *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 XFREE86 PROJECT 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 of the XFree86 Project + *shall not be used in advertising or otherwise to promote the sale, use + *or other dealings in this Software without prior written authorization + *from the XFree86 Project. + * + * Authors: Kensuke Matsuzaki + * Earle F. Philhower, III + * Harold L Hunt II + * Colin Harrison + */ + +#ifdef HAVE_XWIN_CONFIG_H +#include <xwin-config.h> +#endif +#include "win.h" +#include "dixevents.h" +#include "winmultiwindowclass.h" + +/* + * Prototypes for local functions + */ + +void +winCreateWindowsWindow (WindowPtr pWin); + +static void +winDestroyWindowsWindow (WindowPtr pWin); + +static void +winUpdateWindowsWindow (WindowPtr pWin); + +static void +winFindWindow (pointer value, XID id, pointer cdata); + +static +void winInitMultiWindowClass(void) +{ + static wATOM atomXWinClass=0; + WNDCLASSEX wcx; + + if (atomXWinClass==0) + { + /* Setup our window class */ + wcx.cbSize=sizeof(WNDCLASSEX); + wcx.style = CS_HREDRAW | CS_VREDRAW | (g_fNativeGl ? CS_OWNDC : 0); + wcx.lpfnWndProc = winTopLevelWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = g_hInstance; + wcx.hIcon = g_hIconX; + wcx.hCursor = 0; + wcx.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = WINDOW_CLASS_X; + wcx.hIconSm = g_hSmallIconX; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winCreateWindowsWindow - Creating class: %s\n", WINDOW_CLASS_X); +#endif + + atomXWinClass = RegisterClassEx (&wcx); + } +} + +/* + * CreateWindow - See Porting Layer Definition - p. 37 + */ + +Bool +winCreateWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG + winTrace ("winCreateWindowMultiWindow - pWin: %p\n", pWin); +#endif + + WIN_UNWRAP(CreateWindow); + fResult = (*pScreen->CreateWindow) (pWin); + WIN_WRAP(CreateWindow, winCreateWindowMultiWindow); + + /* Initialize some privates values */ + pWinPriv->hRgn = NULL; + pWinPriv->hWnd = NULL; + pWinPriv->pScreenPriv = winGetScreenPriv(pWin->drawable.pScreen); + pWinPriv->fXKilled = FALSE; + + return fResult; +} + + +/* + * DestroyWindow - See Porting Layer Definition - p. 37 + */ + +Bool +winDestroyWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winDestroyWindowMultiWindow - pWin: %p\n", pWin); +#endif + + WIN_UNWRAP(DestroyWindow); + fResult = (*pScreen->DestroyWindow)(pWin); + WIN_WRAP(DestroyWindow, winDestroyWindowMultiWindow); + + /* Flag that the window has been destroyed */ + pWinPriv->fXKilled = TRUE; + + /* Kill the MS Windows window associated with this window */ + winDestroyWindowsWindow (pWin); + + return fResult; +} + + +/* + * PositionWindow - See Porting Layer Definition - p. 37 + * + * This function adjusts the position and size of Windows window + * with respect to the underlying X window. This is the inverse + * of winAdjustXWindow, which adjusts X window to Windows window. + */ + +Bool +winPositionWindowMultiWindow (WindowPtr pWin, int x, int y) +{ + Bool fResult = TRUE; + int iX, iY, iWidth, iHeight; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + + HWND hWnd = pWinPriv->hWnd; + RECT rcNew; + RECT rcOld; +#if CYGMULTIWINDOW_DEBUG + RECT rcClient; + RECT *lpRc; +#endif + DWORD dwExStyle; + DWORD dwStyle; + +#if CYGMULTIWINDOW_DEBUG + winTrace ("winPositionWindowMultiWindow - pWin: %p\n", pWin); +#endif + + WIN_UNWRAP(PositionWindow); + fResult = (*pScreen->PositionWindow)(pWin, x, y); + WIN_WRAP(PositionWindow, winPositionWindowMultiWindow); + +#if CYGWINDOWING_DEBUG + ErrorF ("winPositionWindowMultiWindow: (x, y) = (%d, %d)\n", + x, y); +#endif + + /* Bail out if the Windows window handle is bad */ + if (!hWnd) + { +#if CYGWINDOWING_DEBUG + ErrorF ("\timmediately return since hWnd is NULL\n"); +#endif + return fResult; + } + + /* Get the Windows window style and extended style */ + dwExStyle = GetWindowLongPtr (hWnd, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE); + + /* Get the X and Y location of the X window */ + iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); + iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); + + /* Get the height and width of the X window */ + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* Store the origin, height, and width in a rectangle structure */ + SetRect (&rcNew, iX, iY, iX + iWidth, iY + iHeight); + +#if CYGMULTIWINDOW_DEBUG + lpRc = &rcNew; + ErrorF ("winPositionWindowMultiWindow - (%d ms)drawable (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); +#endif + + /* + * Calculate the required size of the Windows window rectangle, + * given the size of the Windows window client area. + */ + AdjustWindowRectEx (&rcNew, dwStyle, FALSE, dwExStyle); + + /* Get a rectangle describing the old Windows window */ + GetWindowRect (hWnd, &rcOld); + +#if CYGMULTIWINDOW_DEBUG + /* Get a rectangle describing the Windows window client area */ + GetClientRect (hWnd, &rcClient); + + lpRc = &rcNew; + ErrorF ("winPositionWindowMultiWindow - (%d ms)rcNew (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); + + lpRc = &rcOld; + ErrorF ("winPositionWindowMultiWindow - (%d ms)rcOld (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); + + lpRc = &rcClient; + ErrorF ("(%d ms)rcClient (%d, %d)-(%d, %d)\n", + GetTickCount (), lpRc->left, lpRc->top, lpRc->right, lpRc->bottom); +#endif + + /* Check if the old rectangle and new rectangle are the same */ + if (!EqualRect (&rcNew, &rcOld)) + { +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winPositionWindowMultiWindow - Need to move\n"); +#endif + +#if CYGWINDOWING_DEBUG + ErrorF ("\tMoveWindow to (%ld, %ld) - %ldx%ld\n", rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top); +#endif + /* Change the position and dimensions of the Windows window */ + MoveWindow (hWnd, + rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, + TRUE); + } + else + { +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winPositionWindowMultiWindow - Not need to move\n"); +#endif + } + + return fResult; +} + + +/* + * ChangeWindowAttributes - See Porting Layer Definition - p. 37 + */ + +Bool +winChangeWindowAttributesMultiWindow (WindowPtr pWin, unsigned long mask) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winChangeWindowAttributesMultiWindow - pWin: %08x\n", pWin); +#endif + + WIN_UNWRAP(ChangeWindowAttributes); + fResult = (*pScreen->ChangeWindowAttributes)(pWin, mask); + WIN_WRAP(ChangeWindowAttributes, winChangeWindowAttributesMultiWindow); + + /* + * NOTE: We do not currently need to do anything here. + */ + + return fResult; +} + + +/* + * UnmapWindow - See Porting Layer Definition - p. 37 + * Also referred to as UnrealizeWindow + */ + +Bool +winUnmapWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winUnmapWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + WIN_UNWRAP(UnrealizeWindow); + fResult = (*pScreen->UnrealizeWindow)(pWin); + WIN_WRAP(UnrealizeWindow, winUnmapWindowMultiWindow); + + /* Flag that the window has been killed */ + pWinPriv->fXKilled = TRUE; + + /* Destroy the Windows window associated with this X window */ + winDestroyWindowsWindow (pWin); + + return fResult; +} + + +/* + * MapWindow - See Porting Layer Definition - p. 37 + * Also referred to as RealizeWindow + */ + +Bool +winMapWindowMultiWindow (WindowPtr pWin) +{ + Bool fResult = TRUE; + ScreenPtr pScreen = pWin->drawable.pScreen; + winWindowPriv(pWin); + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winMapWindowMultiWindow - pWin: %08x\n", pWin); +#endif + + WIN_UNWRAP(RealizeWindow); + fResult = (*pScreen->RealizeWindow)(pWin); + WIN_WRAP(RealizeWindow, winMapWindowMultiWindow); + + /* Flag that this window has not been destroyed */ + pWinPriv->fXKilled = FALSE; + + /* Refresh/redisplay the Windows window associated with this X window */ + winUpdateWindowsWindow (pWin); + + /* Update the Windows window's shape */ + winReshapeMultiWindow (pWin); + winUpdateRgnMultiWindow (pWin); + + return fResult; +} + + +/* + * ReparentWindow - See Porting Layer Definition - p. 42 + */ + +void +winReparentWindowMultiWindow (WindowPtr pWin, WindowPtr pPriorParent) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winReparentMultiWindow - pWin: %08x\n", pWin); +#endif + + WIN_UNWRAP(ReparentWindow); + if (pScreen->ReparentWindow) + (*pScreen->ReparentWindow)(pWin, pPriorParent); + WIN_WRAP(ReparentWindow, winReparentWindowMultiWindow); + + /* Update the Windows window associated with this X window */ + winUpdateWindowsWindow (pWin); +} + + +/* + * RestackWindow - Shuffle the z-order of a window + */ + +void +winRestackWindowMultiWindow (WindowPtr pWin, WindowPtr pOldNextSib) +{ +#if 0 + WindowPtr pPrevWin; + UINT uFlags; + HWND hInsertAfter; + HWND hWnd = NULL; +#endif + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + +#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG + winTrace ("winRestackMultiWindow - %08x\n", pWin); +#endif + + WIN_UNWRAP(RestackWindow); + if (pScreen->RestackWindow) + (*pScreen->RestackWindow)(pWin, pOldNextSib); + WIN_WRAP(RestackWindow, winRestackWindowMultiWindow); + +#if 1 + /* + * Calling winReorderWindowsMultiWindow here means our window manager + * (i.e. Windows Explorer) has initiative to determine Z order. + */ + if (pWin->nextSib != pOldNextSib) + winReorderWindowsMultiWindow (); +#else + /* Bail out if no window privates or window handle is invalid */ + if (!pWinPriv || !pWinPriv->hWnd) + return; + + /* Get a pointer to our previous sibling window */ + pPrevWin = pWin->prevSib; + + /* + * Look for a sibling window with + * valid privates and window handle + */ + while (pPrevWin + && !winGetWindowPriv(pPrevWin) + && !winGetWindowPriv(pPrevWin)->hWnd) + pPrevWin = pPrevWin->prevSib; + + /* Check if we found a valid sibling */ + if (pPrevWin) + { + /* Valid sibling - get handle to insert window after */ + hInsertAfter = winGetWindowPriv(pPrevWin)->hWnd; + uFlags = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE; + + hWnd = GetNextWindow (pWinPriv->hWnd, GW_HWNDPREV); + + do + { + if (GetProp (hWnd, WIN_WINDOW_PROP)) + { + if (hWnd == winGetWindowPriv(pPrevWin)->hWnd) + { + uFlags |= SWP_NOZORDER; + } + break; + } + hWnd = GetNextWindow (hWnd, GW_HWNDPREV); + } + while (hWnd); + } + else + { + /* No valid sibling - make this window the top window */ + hInsertAfter = HWND_TOP; + uFlags = SWP_NOMOVE | SWP_NOSIZE; + } + + /* Perform the restacking operation in Windows */ + SetWindowPos (pWinPriv->hWnd, + hInsertAfter, + 0, 0, + 0, 0, + uFlags); +#endif +} + + +/* + * winCreateWindowsWindow - Create a Windows window associated with an X window + */ + +void +winCreateWindowsWindow (WindowPtr pWin) +{ + int iX, iY; + int iWidth; + int iHeight; + HWND hWnd; + HWND hFore = NULL; + winWindowPriv(pWin); + HICON hIcon; + HICON hIconSmall; + winPrivScreenPtr pScreenPriv = pWinPriv->pScreenPriv; + WinXSizeHints hints; + WindowPtr pDaddy; + + winInitMultiWindowClass(); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winCreateWindowsWindow - pWin: %08x\n", pWin); +#endif + + iX = pWin->drawable.x + GetSystemMetrics (SM_XVIRTUALSCREEN); + iY = pWin->drawable.y + GetSystemMetrics (SM_YVIRTUALSCREEN); + + iWidth = pWin->drawable.width; + iHeight = pWin->drawable.height; + + /* If it's an InputOutput window, and so is going to end up being made visible, + make sure the window actually ends up somewhere where it will be visible */ + if (pWin->drawable.class != InputOnly) + { + if ((iX < GetSystemMetrics (SM_XVIRTUALSCREEN)) || (iX > GetSystemMetrics (SM_CXVIRTUALSCREEN))) + iX = CW_USEDEFAULT; + + if ((iY < GetSystemMetrics (SM_YVIRTUALSCREEN)) || (iY > GetSystemMetrics (SM_CYVIRTUALSCREEN))) + iY = CW_USEDEFAULT; + } + + if (winMultiWindowGetTransientFor (pWin, &pDaddy)) + { + if (pDaddy) + { + hFore = GetForegroundWindow(); + if (hFore && (pDaddy != (WindowPtr)GetProp(hFore, WIN_WID_PROP))) hFore = NULL; + } + } + else + { + /* Default positions if none specified */ + if (!winMultiWindowGetWMNormalHints(pWin, &hints)) + hints.flags = 0; + if (!(hints.flags & (USPosition|PPosition)) && + !pWin->overrideRedirect) + { + iX = CW_USEDEFAULT; + iY = CW_USEDEFAULT; + } + } + + /* Create the window */ + /* Make it OVERLAPPED in create call since WS_POPUP doesn't support */ + /* CW_USEDEFAULT, change back to popup after creation */ + hWnd = CreateWindowExA (WS_EX_TOOLWINDOW, /* Extended styles */ + WINDOW_CLASS_X, /* Class name */ + WINDOW_TITLE_X, /* Window name */ + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + iX, /* Horizontal position */ + iY, /* Vertical position */ + iWidth, /* Right edge */ + iHeight, /* Bottom edge */ + hFore, /* Null or Parent window if transient*/ + (HMENU) NULL, /* No menu */ + GetModuleHandle (NULL), /* Instance handle */ + pWin); /* ScreenPrivates */ + if (hWnd == NULL) + { + ErrorF ("winCreateWindowsWindow - CreateWindowExA () failed: %d\n", + (int) GetLastError ()); + } + pWinPriv->hWnd = hWnd; + + /* Set application or .XWinrc defined Icons */ + winSelectIcons(pWin, &hIcon, &hIconSmall); + if (hIcon) SendMessage (hWnd, WM_SETICON, ICON_BIG, (LPARAM) hIcon); + if (hIconSmall) SendMessage (hWnd, WM_SETICON, ICON_SMALL, (LPARAM) hIconSmall); + + /* Change style back to popup, already placed... */ + SetWindowLongPtr(hWnd, GWL_STYLE, WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + SetWindowPos (hWnd, 0, 0, 0, 0, 0, + SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + /* Make sure it gets the proper system menu for a WS_POPUP, too */ + GetSystemMenu (hWnd, TRUE); + + /* Cause any .XWinrc menus to be added in main WNDPROC */ + PostMessage (hWnd, WM_INIT_SYS_MENU, 0, 0); + + SetProp (hWnd, WIN_WID_PROP, (HANDLE) winGetWindowID(pWin)); + + /* Flag that this Windows window handles its own activation */ + SetProp (hWnd, WIN_NEEDMANAGE_PROP, (HANDLE) 0); + + /* Call engine-specific create window procedure */ + (*pScreenPriv->pwinFinishCreateWindowsWindow) (pWin); +} + + +Bool winInDestroyWindowsWindow = FALSE; +/* + * winDestroyWindowsWindow - Destroy a Windows window associated + * with an X window + */ +static void +winDestroyWindowsWindow (WindowPtr pWin) +{ + MSG msg; + winWindowPriv(pWin); + BOOL oldstate = winInDestroyWindowsWindow; + HICON hIcon; + HICON hIconSm; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winDestroyWindowsWindow\n"); +#endif + + /* Bail out if the Windows window handle is invalid */ + if (pWinPriv->hWnd == NULL) + return; + + winInDestroyWindowsWindow = TRUE; + + /* Store the info we need to destroy after this window is gone */ + hIcon = (HICON)SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_BIG, 0); + hIconSm = (HICON)SendMessage(pWinPriv->hWnd, WM_GETICON, ICON_SMALL, 0); + + SetProp (pWinPriv->hWnd, WIN_WINDOW_PROP, NULL); + + /* Destroy the Windows window */ + DestroyWindow (pWinPriv->hWnd); + + /* Null our handle to the Window so referencing it will cause an error */ + pWinPriv->hWnd = NULL; + + /* Destroy any icons we created for this window */ + winDestroyIcon(hIcon); + winDestroyIcon(hIconSm); + + /* Process all messages on our queue */ + while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + { + if (g_hDlgDepthChange == 0 || !IsDialogMessage (g_hDlgDepthChange, &msg)) + { + DispatchMessage (&msg); + } + } + + winInDestroyWindowsWindow = oldstate; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("-winDestroyWindowsWindow\n"); +#endif +} + + +/* + * winUpdateWindowsWindow - Redisplay/redraw a Windows window + * associated with an X window + */ + +static void +winUpdateWindowsWindow (WindowPtr pWin) +{ + winWindowPriv(pWin); + HWND hWnd = pWinPriv->hWnd; + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winUpdateWindowsWindow\n"); +#endif + + /* Check if the Windows window's parents have been destroyed */ + if (pWin->parent != NULL + && pWin->parent->parent == NULL + && pWin->mapped) + { + /* Create the Windows window if it has been destroyed */ + if (hWnd == NULL) + { + winCreateWindowsWindow (pWin); + assert (pWinPriv->hWnd != NULL); + } + + /* Display the window without activating it */ + if (pWin->drawable.class != InputOnly) + ShowWindow (pWinPriv->hWnd, SW_SHOWNOACTIVATE); + + /* Send first paint message */ + UpdateWindow (pWinPriv->hWnd); + } + else if (hWnd != NULL) + { + /* Destroy the Windows window if its parents are destroyed */ + winDestroyWindowsWindow (pWin); + assert (pWinPriv->hWnd == NULL); + } + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("-winUpdateWindowsWindow\n"); +#endif +} + + +/* + * winGetWindowID - + */ + +XID +winGetWindowID (WindowPtr pWin) +{ + WindowIDPairRec wi = {pWin, 0}; + ClientPtr c = wClient(pWin); + + /* */ + FindClientResourcesByType (c, RT_WINDOW, winFindWindow, &wi); + +#if CYGMULTIWINDOW_DEBUG + ErrorF ("winGetWindowID - Window ID: %d\n", wi.id); +#endif + + return wi.id; +} + + +/* + * winFindWindow - + */ + +static void +winFindWindow (pointer value, XID id, pointer cdata) +{ + WindowIDPairPtr wi = (WindowIDPairPtr)cdata; + + if (value == wi->value) + { + wi->id = id; + } +} + + +/* + * winReorderWindowsMultiWindow - + */ + +void +winReorderWindowsMultiWindow (void) +{ + HWND hwnd = NULL; + WindowPtr pWin = NULL; + WindowPtr pWinSib = NULL; + XID vlist[2]; + static Bool fRestacking = FALSE; /* Avoid recusive calls to this function */ + DWORD dwCurrentProcessID = GetCurrentProcessId (); + DWORD dwWindowProcessID = 0; + +#if CYGMULTIWINDOW_DEBUG || CYGWINDOWING_DEBUG + winTrace ("winReorderWindowsMultiWindow\n"); +#endif + + if (fRestacking) + { + /* It is a recusive call so immediately exit */ +#if CYGWINDOWING_DEBUG + ErrorF ("winReorderWindowsMultiWindow - " + "exit because fRestacking == TRUE\n"); +#endif + return; + } + fRestacking = TRUE; + + /* Loop through top level Window windows, descending in Z order */ + for ( hwnd = GetTopWindow (NULL); + hwnd; + hwnd = GetNextWindow (hwnd, GW_HWNDNEXT) ) + { + /* Don't take care of other Cygwin/X process's windows */ + GetWindowThreadProcessId (hwnd, &dwWindowProcessID); + + if ( GetProp (hwnd, WIN_WINDOW_PROP) + && (dwWindowProcessID == dwCurrentProcessID) + && !IsIconic (hwnd) ) /* ignore minimized windows */ + { + pWinSib = pWin; + pWin = GetProp (hwnd, WIN_WINDOW_PROP); + + if (!pWinSib) + { /* 1st window - raise to the top */ + vlist[0] = Above; + + ConfigureWindow (pWin, CWStackMode, vlist, wClient(pWin)); + } + else + { /* 2nd or deeper windows - just below the previous one */ + vlist[0] = winGetWindowID (pWinSib); + vlist[1] = Below; + + ConfigureWindow (pWin, CWSibling | CWStackMode, + vlist, wClient(pWin)); + } + } + } + + fRestacking = FALSE; +} + + +/* + * winMinimizeWindow - Minimize in response to WM_CHANGE_STATE + */ + +void +winMinimizeWindow (Window id) +{ + WindowPtr pWin; + winPrivWinPtr pWinPriv; +#ifdef XWIN_MULTIWINDOWEXTWM + win32RootlessWindowPtr pRLWinPriv; +#endif + HWND hWnd; + ScreenPtr pScreen = NULL; + winPrivScreenPtr pScreenPriv = NULL; + winScreenInfo *pScreenInfo = NULL; + +#if CYGWINDOWING_DEBUG + ErrorF ("winMinimizeWindow\n"); +#endif + + dixLookupResourceByType((pointer) &pWin, id, RT_WINDOW, NullClient, DixUnknownAccess); + if (!pWin) + { + ErrorF("%s: NULL pWin. Leaving\n", __FUNCTION__); + return; + } + + pScreen = pWin->drawable.pScreen; + if (pScreen) pScreenPriv = winGetScreenPriv(pScreen); + if (pScreenPriv) pScreenInfo = pScreenPriv->pScreenInfo; + +#ifdef XWIN_MULTIWINDOWEXTWM + if (pScreenPriv && pScreenInfo->fInternalWM) + { + pRLWinPriv = (win32RootlessWindowPtr) RootlessFrameForWindow (pWin, FALSE); + hWnd = pRLWinPriv->hWnd; + } + else +#else + if (pScreenPriv) +#endif + { + pWinPriv = winGetWindowPriv (pWin); + hWnd = pWinPriv->hWnd; + } + + ShowWindow (hWnd, SW_MINIMIZE); +} + + +/* + * CopyWindow - See Porting Layer Definition - p. 39 + */ +void +winCopyWindowMultiWindow (WindowPtr pWin, DDXPointRec oldpt, + RegionPtr oldRegion) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + +#if CYGWINDOWING_DEBUG + ErrorF ("CopyWindowMultiWindow\n"); +#endif + WIN_UNWRAP(CopyWindow); + (*pScreen->CopyWindow)(pWin, oldpt, oldRegion); + WIN_WRAP(CopyWindow, winCopyWindowMultiWindow); +} + + +/* + * MoveWindow - See Porting Layer Definition - p. 42 + */ +void +winMoveWindowMultiWindow (WindowPtr pWin, int x, int y, + WindowPtr pSib, VTKind kind) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + +#if CYGWINDOWING_DEBUG + ErrorF ("MoveWindowMultiWindow to (%d, %d)\n", x, y); +#endif + + WIN_UNWRAP(MoveWindow); + (*pScreen->MoveWindow)(pWin, x, y, pSib, kind); + WIN_WRAP(MoveWindow, winMoveWindowMultiWindow); +} + + +/* + * ResizeWindow - See Porting Layer Definition - p. 42 + */ +void +winResizeWindowMultiWindow (WindowPtr pWin, int x, int y, unsigned int w, + unsigned int h, WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + winScreenPriv(pScreen); + +#if CYGWINDOWING_DEBUG + ErrorF ("ResizeWindowMultiWindow to (%d, %d) - %dx%d\n", x, y, w, h); +#endif + WIN_UNWRAP(ResizeWindow); + (*pScreen->ResizeWindow)(pWin, x, y, w, h, pSib); + WIN_WRAP(ResizeWindow, winResizeWindowMultiWindow); +} + + +/* + * winAdjustXWindow + * + * Move and resize X window with respect to corresponding Windows window. + * This is called from WM_MOVE/WM_SIZE handlers when the user performs + * any windowing operation (move, resize, minimize, maximize, restore). + * + * The functionality is the inverse of winPositionWindowMultiWindow, which + * adjusts Windows window with respect to X window. + */ +int +winAdjustXWindow (WindowPtr pWin, HWND hwnd) +{ + RECT rcDraw; /* Rect made from pWin->drawable to be adjusted */ + RECT rcWin; /* The source: WindowRect from hwnd */ + DrawablePtr pDraw; + XID vlist[4]; + LONG dX, dY, dW, dH, x, y; + DWORD dwStyle, dwExStyle; + +#define WIDTH(rc) (rc.right - rc.left) +#define HEIGHT(rc) (rc.bottom - rc.top) + +#if CYGWINDOWING_DEBUG + ErrorF ("winAdjustXWindow\n"); +#endif + + if (IsIconic (hwnd)) + { +#if CYGWINDOWING_DEBUG + ErrorF ("\timmediately return because the window is iconized\n"); +#endif + /* + * If the Windows window is minimized, its WindowRect has + * meaningless values so we don't adjust X window to it. + */ + vlist[0] = 0; + vlist[1] = 0; + return ConfigureWindow (pWin, CWX | CWY, vlist, wClient(pWin)); + } + + pDraw = &pWin->drawable; + + /* Calculate the window rect from the drawable */ + x = pDraw->x + GetSystemMetrics (SM_XVIRTUALSCREEN); + y = pDraw->y + GetSystemMetrics (SM_YVIRTUALSCREEN); + SetRect (&rcDraw, x, y, x + pDraw->width, y + pDraw->height); +#ifdef CYGMULTIWINDOW_DEBUG + winDebug("\tDrawable extend {%d, %d, %d, %d}, {%d, %d}\n", + rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom, + rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top); +#endif + dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE); + dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE); +#ifdef CYGMULTIWINDOW_DEBUG + winDebug("\tWindowStyle: %08x %08x\n", dwStyle, dwExStyle); +#endif + AdjustWindowRectEx (&rcDraw, dwStyle, FALSE, dwExStyle); + + /* The source of adjust */ + GetWindowRect (hwnd, &rcWin); +#ifdef CYGMULTIWINDOW_DEBUG + winDebug("\tWindow extend {%d, %d, %d, %d}, {%d, %d}\n", + rcWin.left, rcWin.top, rcWin.right, rcWin.bottom, + rcWin.right - rcWin.left, rcWin.bottom - rcWin.top); + winDebug("\tDraw extend {%d, %d, %d, %d}, {%d, %d}\n", + rcDraw.left, rcDraw.top, rcDraw.right, rcDraw.bottom, + rcDraw.right - rcDraw.left, rcDraw.bottom - rcDraw.top); +#endif + + if (EqualRect (&rcDraw, &rcWin)) { + /* Bail if no adjust is needed */ +#if CYGWINDOWING_DEBUG + ErrorF ("\treturn because already adjusted\n"); +#endif + return 0; + } + + /* Calculate delta values */ + dX = rcWin.left - rcDraw.left; + dY = rcWin.top - rcDraw.top; + dW = WIDTH(rcWin) - WIDTH(rcDraw); + dH = HEIGHT(rcWin) - HEIGHT(rcDraw); + + /* + * Adjust. + * We may only need to move (vlist[0] and [1]), or only resize + * ([2] and [3]) but currently we set all the parameters and leave + * the decision to ConfigureWindow. The reason is code simplicity. + */ + vlist[0] = pDraw->x + dX - wBorderWidth(pWin); + vlist[1] = pDraw->y + dY - wBorderWidth(pWin); + vlist[2] = pDraw->width + dW; + vlist[3] = pDraw->height + dH; +#if CYGWINDOWING_DEBUG + ErrorF ("\tConfigureWindow to (%ld, %ld) - %ldx%ld\n", vlist[0], vlist[1], + vlist[2], vlist[3]); +#endif + return ConfigureWindow (pWin, CWX | CWY | CWWidth | CWHeight, + vlist, wClient(pWin)); + +#undef WIDTH +#undef HEIGHT +} + |