From: Colin Harrison <[email protected]> Improve internal WM to: Remove frames from 'dock' windows and make them topmost in -multiwindow mode. Remove frames from windows with MOTIF_WM_HINTS of no decorations in -multiwindow mode. Apply some _NET_WM_STATE hints in -multiwindow mode. Improve handling of overrideRedirect windows: minimal window decoration and force in front of topmost window only if it is also an X window
XXX: Is GetWindowLongPtr(GWLP_USERDATA) == XMING_SIGNATURE doing the same thing as GetProp(WIN_WID_PROP) != NULL Signed-off-by: Jon TURNEY <[email protected]> --- hw/xwin/winmultiwindowwm.c | 103 +++++++++++++++++++++++++++++++++++++++ hw/xwin/winmultiwindowwndproc.c | 74 +++++++++++++++++----------- hw/xwin/winwindow.h | 15 ++++++ 3 files changed, 164 insertions(+), 28 deletions(-) diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index ea9dfca..b996a04 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-2008 * *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 */ @@ -186,6 +188,8 @@ PreserveWin32Stack(WMInfoPtr pWMInfo, Window iWindow, UINT direction); static Bool CheckAnotherWindowManager (Display *pDisplay, DWORD dwScreen); +static void +ApplyHints (Display *pDisplay, Window iWindow, HWND hWnd); /* * Local globals @@ -689,6 +693,7 @@ winMultiWindowWMProc (void *pArg) #if CYGMULTIWINDOW_DEBUG ErrorF ("\tWM_WM_MAP\n"); #endif + ApplyHints (pWMInfo->pDisplay, pNode->msg.iWindow, pNode->msg.hwndWindow); /* Put a note as to the HWND associated with this Window */ XChangeProperty (pWMInfo->pDisplay, pNode->msg.iWindow, @@ -706,6 +711,17 @@ winMultiWindowWMProc (void *pArg) #endif break; + case WM_WM_MAP2: + XChangeProperty (pWMInfo->pDisplay, + pNode->msg.iWindow, + pWMInfo->atmPrivMap, + XA_INTEGER,//pWMInfo->atmPrivMap, + 32, + PropModeReplace, + (unsigned char *) &(pNode->msg.hwndWindow), + 1); + break; + case WM_WM_UNMAP: #if CYGMULTIWINDOW_DEBUG ErrorF ("\tWM_WM_UNMAP\n"); @@ -1433,3 +1449,90 @@ winDeinitMultiWindowWM (void) ErrorF ("winDeinitMultiWindowWM - Noting shutdown in progress\n"); g_shutdown = TRUE; } + +static void +ApplyHints (Display *pDisplay, Window iWindow, HWND hWnd) +{ + Atom type; + static Atom windowType, windowState, motif_wm_hints; + int format; + unsigned long nitems = 0, left = 0; + unsigned char *data = 0; + + if (!hWnd) return; + if (!IsWindow (hWnd)) return; + + if (windowType == None) windowType = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE", False); + if (windowState == None) windowState = XInternAtom(pDisplay, "_NET_WM_STATE", False); + if (motif_wm_hints == None) motif_wm_hints = XInternAtom(pDisplay, "_MOTIF_WM_HINTS", False); + + if (XGetWindowProperty(pDisplay, iWindow, windowType, 0L, + 1L, False, XA_ATOM, &type, &format, + &nitems, &left, &data) == Success) + { + if (data != None) + { + Atom a; + static Atom dockWindow, dialogWindow; + if (dockWindow == None) dockWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DOCK", False); + if (dialogWindow == None) dialogWindow = XInternAtom(pDisplay, "_NET_WM_WINDOW_TYPE_DIALOG", False); + memcpy (&a, data, sizeof (Atom)); + XFree(data); + if (a == dockWindow) + { + SetWindowLongPtr (hWnd, GWL_STYLE, (GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW) | WS_SIZEBOX); + SetWindowPos (hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE); + return; + } + else if (a == dialogWindow) + { + SetForegroundWindow (hWnd); + return; + } + } + } + + if (XGetWindowProperty(pDisplay, iWindow, windowState, 0L, + 1L, False, XA_ATOM, &type, &format, + &nitems, &left, &data) == Success) + { + if (data != None) + { + Atom a; + static Atom hiddenState, fullscreenState, aboveState; + if (hiddenState == None) hiddenState = XInternAtom(pDisplay, "_NET_WM_STATE_HIDDEN", False); + if (fullscreenState == None) fullscreenState = XInternAtom(pDisplay, "_NET_WM_STATE_FULLSCREEN", False); + if (aboveState == None) aboveState = XInternAtom(pDisplay, "_NET_WM_STATE_ABOVE", False); + memcpy (&a, data, sizeof (Atom)); + XFree(data); + if (a == hiddenState) + PostMessage(hWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + else if (a == fullscreenState) + PostMessage(hWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + else if (a == aboveState) + SetWindowPos (hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + } + } + + nitems = left = 0; + data = 0; + if (XGetWindowProperty(pDisplay, iWindow, motif_wm_hints, 0L, + 5L, False, motif_wm_hints, &type, &format, + &nitems, &left, &data) == Success) + { + if (data != None) + { + struct MwmHints hintsdata; + struct MwmHints *hints = &hintsdata; + memcpy (hints, data, sizeof (MwmHints)); + XFree(data); + if ((hints->flags & MWM_HINTS_DECORATIONS) && (hints->decorations == 0)) + { + SetWindowLongPtr (hWnd, GWL_STYLE, GetWindowLongPtr(hWnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW); + SetWindowPos (hWnd, NULL, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOZORDER); + return; + } + } + } + SetForegroundWindow (hWnd); +} diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index 5477bd7..b0ad6da 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -407,6 +407,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: @@ -844,27 +846,41 @@ 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)) { + RECT rcNew; + int iDx, iDy; + unsigned long rcStyle; + + /* 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_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + /* Set the window standard style flags */ + else SetWindowLongPtr (hwnd, GWL_STYLE, + WS_POPUP | WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS); + + rcStyle = winOverrideStyle((unsigned long)pWin); + if (rcStyle & STYLE_TOPMOST) + SetWindowPos (hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); + else if (rcStyle & STYLE_MAXIMIZE) + PostMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + else if (rcStyle & STYLE_MINIMIZE) + PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + + if (rcStyle & STYLE_NOTITLE) + SetWindowLongPtr (hwnd, GWL_STYLE, (GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW) | WS_SIZEBOX); + else if (rcStyle & STYLE_NOFRAME) + SetWindowLongPtr (hwnd, GWL_STYLE, GetWindowLongPtr(hwnd, GWL_STYLE) & ~WS_OVERLAPPEDWINDOW); + /* Setup a rectangle with the X window position and size */ SetRect (&rcNew, pDraw->x, @@ -880,7 +896,7 @@ winTopLevelWindowProc (HWND hwnd, UINT message, /* */ AdjustWindowRectEx (&rcNew, - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW, + GetWindowLongPtr (hwnd, GWL_STYLE), FALSE, WS_EX_APPWINDOW); @@ -900,35 +916,37 @@ winTopLevelWindowProc (HWND hwnd, UINT message, rcNew.right, rcNew.bottom); #endif - /* Set the window extended style flags */ - SetWindowLongPtr (hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW); - - /* Set the window standard style flags */ - SetWindowLongPtr (hwnd, GWL_STYLE, - WS_POPUP | WS_SIZEBOX | WS_OVERLAPPEDWINDOW); - /* Position the Windows window */ - SetWindowPos (hwnd, HWND_TOP, + SetWindowPos (hwnd, NULL, rcNew.left, rcNew.top, rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, - SWP_NOMOVE | SWP_FRAMECHANGED - | SWP_SHOWWINDOW | SWP_NOACTIVATE); + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOZORDER); /* Bring the Windows window to the foreground */ SetForegroundWindow (hwnd); } + wmMsg.msg = WM_WM_MAP; } 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; diff --git a/hw/xwin/winwindow.h b/hw/xwin/winwindow.h index 38db55f..9b33c49 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-2008 * *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,20 @@ 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_MANAGE (WM_USER + 100) #define WM_UNMANAGE (WM_USER + 102) +#define MWM_HINTS_DECORATIONS (1L << 1) + +typedef struct MwmHints { + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; +} MwmHints; + void winSendMessageToWM (void *pWMInfo, winWMMessagePtr msg); -- 1.6.1.2 _______________________________________________ xorg-devel mailing list [email protected] http://lists.x.org/mailman/listinfo/xorg-devel
