diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 74213791d..8560c6cc0 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -1,5 +1,6 @@ /* *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + *Copyright (C) Colin Harrison 2005-2009 * *Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -26,6 +27,7 @@ *from the XFree86 Project. * * Authors: Kensuke Matsuzaki + * Colin Harrison */ /* X headers */ @@ -56,6 +58,11 @@ #include "objbase.h" #include "ddraw.h" #include "winwindow.h" +#include "winprefs.h" +#include "window.h" +#include "pixmapstr.h" +#include "windowstr.h" + #ifdef XWIN_MULTIWINDOWEXTWM #include #else @@ -65,6 +72,8 @@ #endif extern void winDebug(const char *format, ...); +extern void winReshapeMultiWindow(WindowPtr pWin); +extern void winUpdateRgnMultiWindow(WindowPtr pWin); #ifndef CYGDEBUG #define CYGDEBUG NO @@ -186,6 +195,11 @@ PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction); static Bool CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen); +static void +winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle); + +void +winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle); /* * Local globals @@ -240,6 +254,12 @@ PushMessage (WMMsgQueuePtr pQueue, WMMsgNodePtr pNode) case WM_WM_MAP: ErrorF ("\tWM_WM_MAP\n"); break; + case WM_WM_MAP2: + ErrorF ("\tWM_WM_MAP2\n"); + break; + case WM_WM_MAP3: + ErrorF ("\tWM_WM_MAP3\n"); + break; case WM_WM_UNMAP: ErrorF ("\tWM_WM_UNMAP\n"); break; @@ -700,10 +720,42 @@ winMultiWindowWMProc (void *pArg) 1); UpdateName (pWMInfo, pNode->msg.iWindow); winUpdateIcon (pNode->msg.iWindow); -#if 0 - /* Handles the case where there are AOT windows above it in W32 */ - PreserveWin32Stack (pWMInfo, pNode->msg.iWindow, GW_HWNDPREV); + break; + + case WM_WM_MAP2: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_MAP2\n"); #endif + XChangeProperty (pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmPrivMap, + XA_INTEGER,//pWMInfo->atmPrivMap, + 32, + PropModeReplace, + (unsigned char *) &(pNode->msg.hwndWindow), + 1); + break; + + case WM_WM_MAP3: +#if CYGMULTIWINDOW_DEBUG + ErrorF ("\tWM_WM_MAP3\n"); +#endif + /* Put a note as to the HWND associated with this Window */ + XChangeProperty (pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmPrivMap, + XA_INTEGER,//pWMInfo->atmPrivMap, + 32, + PropModeReplace, + (unsigned char *) &(pNode->msg.hwndWindow), + 1); + UpdateName (pWMInfo, pNode->msg.iWindow); + winUpdateIcon (pNode->msg.iWindow); + { + HWND zstyle = HWND_NOTOPMOST; + winApplyHints (pWMInfo->pDisplay, pNode->msg.iWindow, pNode->msg.hwndWindow, &zstyle); + winUpdateWindowPosition (pNode->msg.hwndWindow, TRUE, &zstyle); + } break; case WM_WM_UNMAP: @@ -1435,3 +1487,168 @@ winDeinitMultiWindowWM (void) ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n"); g_shutdown = TRUE; } + +/* Windows window styles */ +#define HINT_NOFRAME (1l<<0) +#define HINT_BORDER (1L<<1) +#define HINT_SIZEBOX (1l<<2) +#define HINT_CAPTION (1l<<3) +/* These two are used on their own */ +#define HINT_MAX (1L<<0) +#define HINT_MIN (1L<<1) + +static void +winApplyHints (Display *pDisplay, Window iWindow, HWND hWnd, HWND *zstyle) +{ + static Atom windowState, motif_wm_hints, windowType; + static Atom hiddenState, fullscreenState, belowState, aboveState; + static Atom dockWindow; + static int generation; + Atom type, *pAtom = NULL; + int format; + unsigned long hint = 0, maxmin = 0, style, nitems = 0 , left = 0; + WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP); + + if (!hWnd) return; + if (!IsWindow (hWnd)) return; + + if (generation != serverGeneration) { + generation = serverGeneration; + windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False); + motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False); + windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False); + hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False); + fullscreenState = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False); + belowState = XInternAtom(pDisplay, "_NET_WM_STATE_BELOW", False); + aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False); + dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False); + } + + if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, + 1L, False, XA_ATOM, &type, &format, + &nitems, &left, (unsigned char **)&pAtom) == Success) + { + if (pAtom && nitems == 1) + { + if (*pAtom == hiddenState) maxmin |= HINT_MIN; + else if (*pAtom == fullscreenState) maxmin |= HINT_MAX; + if (*pAtom == belowState) *zstyle = HWND_BOTTOM; + else if (*pAtom == aboveState) *zstyle = HWND_TOPMOST; + } + if (pAtom) XFree(pAtom); + } + + nitems = left = 0; + MwmHints *mwm_hint = NULL; + if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L, + PropMwmHintsElements, False, motif_wm_hints, &type, &format, + &nitems, &left, (unsigned char **)&mwm_hint) == Success) + { + if (mwm_hint && nitems == PropMwmHintsElements && (mwm_hint->flags & MwmHintsDecorations)) + { + if (!mwm_hint->decorations) hint |= HINT_NOFRAME; + else if (!(mwm_hint->decorations & MwmDecorAll)) + { + if (mwm_hint->decorations & MwmDecorBorder) hint |= HINT_BORDER; + if (mwm_hint->decorations & MwmDecorHandle) hint |= HINT_SIZEBOX; + if (mwm_hint->decorations & MwmDecorTitle) hint |= HINT_CAPTION; + } + } + if (mwm_hint) XFree(mwm_hint); + } + + nitems = left = 0; + pAtom = NULL; + if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L, + 1L, False, XA_ATOM, &type, &format, + &nitems, &left, (unsigned char **)&pAtom) == Success) + { + if (pAtom && nitems == 1) + { + if (*pAtom == dockWindow) + { + hint = (hint & ~HINT_NOFRAME) | HINT_SIZEBOX; /* Xming puts a sizebox on dock windows */ + *zstyle = HWND_TOPMOST; + } + } + if (pAtom) XFree(pAtom); + } + + /* Apply Styles, overriding hint settings from above */ + style = winOverrideStyle((unsigned long)pWin); + if (style & STYLE_TOPMOST) *zstyle = HWND_TOPMOST; + else if (style & STYLE_MAXIMIZE) maxmin = (hint & ~HINT_MIN) | HINT_MAX; + else if (style & STYLE_MINIMIZE) maxmin = (hint & ~HINT_MAX) | HINT_MIN; + else if (style & STYLE_BOTTOM) *zstyle = HWND_BOTTOM; + + if (maxmin & HINT_MAX) SendMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + else if (maxmin & HINT_MIN) SendMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + + if (style & STYLE_NOTITLE) + hint = (hint & ~HINT_NOFRAME & ~HINT_BORDER & ~HINT_CAPTION) | HINT_SIZEBOX; + else if (style & STYLE_OUTLINE) + hint = (hint & ~HINT_NOFRAME & ~HINT_SIZEBOX & ~HINT_CAPTION) | HINT_BORDER; + else if (style & STYLE_NOFRAME) + hint = (hint & ~HINT_BORDER & ~HINT_CAPTION & ~HINT_SIZEBOX) | HINT_NOFRAME; + + style = GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_CAPTION & ~WS_SIZEBOX; /* Just in case */ + if (!style) return; + if (!hint) /* All on, but no resize of children is allowed */ + style = style | WS_CAPTION | (GetParent(hWnd) ? 0 : WS_SIZEBOX); + else if (hint & HINT_NOFRAME); /* All off, so do nothing */ + else style = style | ((hint & HINT_BORDER) ? WS_BORDER : 0) | + ((hint & HINT_SIZEBOX) ? (GetParent(hWnd) ? 0 : WS_SIZEBOX) : 0) | + ((hint & HINT_CAPTION) ? WS_CAPTION : 0); + SetWindowLongPtr (hWnd, GWL_STYLE, style); +} + +void +winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle) +{ + int iDx, iDy; + RECT rcNew; + WindowPtr pWin = GetProp (hWnd, WIN_WINDOW_PROP); + DrawablePtr pDraw = NULL; + + if (!pWin) return; + pDraw = &pWin->drawable; + if (!pDraw) return; + + /* Setup a rectangle with the X window position and size */ + SetRect (&rcNew, pDraw->x, pDraw->y, pDraw->x + pDraw->width, pDraw->y + pDraw->height); + +#if 0 + ErrorF ("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, + rcNew.right, rcNew.bottom); +#endif + + AdjustWindowRectEx (&rcNew, GetWindowLongPtr (hWnd, GWL_STYLE), FALSE, WS_EX_APPWINDOW); + + /* Calculate position deltas */ + iDx = pDraw->x - rcNew.left; + iDy = pDraw->y - rcNew.top; + + /* Calculate new rectangle */ + rcNew.left += iDx; + rcNew.right += iDx; + rcNew.top += iDy; + rcNew.bottom += iDy; + +#if 0 + ErrorF ("winUpdateWindowPosition - (%d, %d)-(%d, %d)\n", + rcNew.left, rcNew.top, + rcNew.right, rcNew.bottom); +#endif + + /* Position the Windows window */ + SetWindowPos (hWnd, *zstyle, rcNew.left, rcNew.top, + rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, + SWP_NOMOVE | ((reshape) ? 0 : SWP_NOREDRAW)); + + if (reshape) + { + winReshapeMultiWindow(pWin); + winUpdateRgnMultiWindow(pWin); + } +} diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index 313822972..543a1652f 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -51,6 +51,8 @@ extern Bool g_fKeyboardHookLL; extern Bool g_fSoftwareCursor; extern Bool g_fButton[3]; +extern void winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle); + /* * Local globals @@ -421,6 +423,8 @@ winTopLevelWindowProc (HWND hwnd, UINT message, SetWindowRgn (hwnd, hRgnWindow, TRUE); DeleteObject(hRgnWindow); + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)XMING_SIGNATURE); + return 0; case WM_INIT_SYS_MENU: @@ -865,94 +869,51 @@ winTopLevelWindowProc (HWND hwnd, UINT message, if (!wParam) return 0; - /* Tell X to map the window */ - MapWindow (pWin, wClient(pWin)); - /* */ if (!pWin->overrideRedirect) { - DWORD dwExStyle; - DWORD dwStyle; - RECT rcNew; - int iDx, iDy; - /* Flag that this window needs to be made active when clicked */ SetProp (hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1); - /* Get the standard and extended window style information */ - dwExStyle = GetWindowLongPtr (hwnd, GWL_EXSTYLE); - dwStyle = GetWindowLongPtr (hwnd, GWL_STYLE); - - /* */ - if (dwExStyle != WS_EX_APPWINDOW) + if (!(GetWindowLongPtr (hwnd, GWL_EXSTYLE) & WS_EX_APPWINDOW)) { - /* Setup a rectangle with the X window position and size */ - SetRect (&rcNew, - pDraw->x, - pDraw->y, - pDraw->x + pDraw->width, - pDraw->y + pDraw->height); - -#if 0 - ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n", - rcNew.left, rcNew.top, - rcNew.right, rcNew.bottom); -#endif - - /* */ - AdjustWindowRectEx (&rcNew, - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW, - FALSE, - WS_EX_APPWINDOW); - - /* Calculate position deltas */ - iDx = pDraw->x - rcNew.left; - iDy = pDraw->y - rcNew.top; - - /* Calculate new rectangle */ - rcNew.left += iDx; - rcNew.right += iDx; - rcNew.top += iDy; - rcNew.bottom += iDy; - -#if 0 - ErrorF ("winTopLevelWindowProc - (%d, %d)-(%d, %d)\n", - rcNew.left, rcNew.top, - rcNew.right, rcNew.bottom); -#endif + HWND zstyle = HWND_NOTOPMOST; /* Set the window extended style flags */ SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW); + /* Set the transient style flags */ + if (GetParent(hwnd)) SetWindowLongPtr (hwnd, GWL_STYLE, + WS_POPUP | WS_OVERLAPPED | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); /* Set the window standard style flags */ - SetWindowLongPtr (hwnd, GWL_STYLE, - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW); + else SetWindowLongPtr (hwnd, GWL_STYLE, + (WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS) + & ~WS_CAPTION & ~WS_SIZEBOX); - /* Position the Windows window */ - SetWindowPos (hwnd, HWND_TOP, - rcNew.left, rcNew.top, - rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, - SWP_NOMOVE | SWP_FRAMECHANGED - | SWP_SHOWWINDOW | SWP_NOACTIVATE); - - /* Bring the Windows window to the foreground */ + winUpdateWindowPosition (hwnd, FALSE, &zstyle); SetForegroundWindow (hwnd); } + wmMsg.msg = WM_WM_MAP3; } else /* It is an overridden window so make it top of Z stack */ { #if CYGWINDOWING_DEBUG ErrorF ("overridden window is shown\n"); #endif - SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, - SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + HWND forHwnd = GetForegroundWindow(); + if (forHwnd != NULL) + { + if (GetWindowLongPtr(forHwnd, GWLP_USERDATA) & (LONG_PTR)XMING_SIGNATURE) + { + if (GetWindowLongPtr(forHwnd, GWL_EXSTYLE) & WS_EX_TOPMOST) + SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + else + SetWindowPos (hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + } + wmMsg.msg = WM_WM_MAP2; } - /* Setup the Window Manager message */ - wmMsg.msg = WM_WM_MAP; - wmMsg.iWidth = pDraw->width; - wmMsg.iHeight = pDraw->height; - /* Tell our Window Manager thread to map the window */ if (fWMMsgInitialized) winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 38db55f5c..86c094334 100644 --- a/hw/xwin/winwindow.h +++ b/hw/xwin/winwindow.h @@ -2,6 +2,7 @@ #define _WINWINDOW_H_ /* *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved. + *Copyright (C) Colin Harrison 2005-2009 * *Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -28,6 +29,7 @@ *from the XFree86 Project. * * Authors: Kensuke Matsuzaki + * Colin Harrison */ #ifndef NO @@ -60,6 +62,8 @@ #define CYGWINDOWING_DEBUG NO #endif +#define XMING_SIGNATURE 0x12345678L + typedef struct _winPrivScreenRec *winPrivScreenPtr; @@ -111,9 +115,25 @@ typedef struct _winWMMessageRec{ #define WM_WM_NAME_EVENT (WM_USER + 9) #define WM_WM_HINTS_EVENT (WM_USER + 10) #define WM_WM_CHANGE_STATE (WM_USER + 11) +#define WM_WM_MAP2 (WM_USER + 12) +#define WM_WM_MAP3 (WM_USER + 13) #define WM_MANAGE (WM_USER + 100) #define WM_UNMANAGE (WM_USER + 102) +#define MwmHintsDecorations (1L << 1) + +#define MwmDecorAll (1l << 0) +#define MwmDecorBorder (1l << 1) +#define MwmDecorHandle (1l << 2) +#define MwmDecorTitle (1l << 3) + +/* This structure only contains 3 elements... the Motif 2.0 structure +contains 5... we only need the first 3... so that is all we will define */ +typedef struct MwmHints { + unsigned long flags, functions, decorations; +} MwmHints; +#define PropMwmHintsElements 3 + void winSendMessageToWM (void *pWMInfo, winWMMessagePtr msg);