summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Turney <jon.turney@dronecode.org.uk>2015-07-01 23:17:31 +0100
committerJon Turney <jon.turney@dronecode.org.uk>2016-11-17 13:15:44 +0000
commit32e1287c405dfebb4e42569f5927f287ef1e0a85 (patch)
tree9a078f7502c42ce534f8ad2283a8d00edf630481
parent4ee45d5e51f33f483705709d2c5e662099cc0807 (diff)
Map window in WM_WINDOWPOSCHANGED not WM_SHOWWINDOW
Instead of using WM_SHOWWINDOW, use WM_WINDOWPOSCHANGED SWP_(SHOW|HIDE)WINDOW events to map and unmap the window. WM_WINDOWPOSCHANGED doesn't have the quirks that WM_SHOWWINDOW has, which can lead to it being emitted multiple times while the window is in the shown state, so it's a reliable way of reacting to the window being shown and hidden. See also http://blogs.msdn.com/b/oldnewthing/archive/2008/01/15/7113860.aspx v2: Don't unmap windows on SWP_HIDEWINDOW Treating SWP_HIDEWINDOW symetrically with SWP_SHOWWINDOW and unmapping the X window on SWP_HIDEWINDOW makes the window inaccessible after a virtual desktop change with Dexpot.
-rw-r--r--hw/xwin/winmultiwindowwndproc.c132
1 files changed, 68 insertions, 64 deletions
diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index 150201134..5e5efb15e 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -905,65 +905,6 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
/* else: Wait for WM_EXITSIZEMOVE */
return 0;
- case WM_SHOWWINDOW:
- /* Bail out if the window is being hidden */
- if (!wParam)
- return 0;
-
- /* */
- if (!pWin->overrideRedirect) {
- HWND zstyle = HWND_NOTOPMOST;
-
- /* Flag that this window needs to be made active when clicked */
- SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
-
- winUpdateWindowPosition(hwnd, &zstyle);
-
- {
- WinXWMHints hints;
-
- if (winMultiWindowGetWMHints(pWin, &hints)) {
- /*
- Give the window focus, unless it has an InputHint
- which is FALSE (this is used by e.g. glean to
- avoid every test window grabbing the focus)
- */
- if (!((hints.flags & InputHint) && (!hints.input))) {
- SetForegroundWindow(hwnd);
- }
- }
- }
- wmMsg.msg = WM_WM_MAP_MANAGED;
- }
- else { /* It is an overridden window so make it top of Z stack */
-
- HWND forHwnd = GetForegroundWindow();
-
-#if CYGWINDOWING_DEBUG
- ErrorF("overridden window is shown\n");
-#endif
- 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_MAP_UNMANAGED;
- }
-
- /* Tell our Window Manager thread to map the window */
- if (fWMMsgInitialized)
- winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
-
- winStartMousePolling(s_pScreenPriv);
-
- return 0;
-
case WM_SIZING:
/* Need to legalize the size according to WM_NORMAL_HINTS */
/* for applications like xterm */
@@ -1016,12 +957,75 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
}
}
}
+
+ /* Window is being shown */
+ if (pWinPos->flags & SWP_SHOWWINDOW) {
+ if (!pWin->overrideRedirect) {
+ HWND zstyle = HWND_NOTOPMOST;
+
+ /* Flag that this window needs to be made active when clicked */
+ SetProp(hwnd, WIN_NEEDMANAGE_PROP, (HANDLE) 1);
+
+ winUpdateWindowPosition(hwnd, &zstyle);
+
+ {
+ WinXWMHints hints;
+
+ if (winMultiWindowGetWMHints(pWin, &hints)) {
+ /*
+ Give the window focus, unless it has an InputHint
+ which is FALSE (this is used by e.g. glean to
+ avoid every test window grabbing the focus)
+ */
+ if (!((hints.flags & InputHint) && (!hints.input))) {
+ SetForegroundWindow(hwnd);
+ }
+ }
+ }
+ wmMsg.msg = WM_WM_MAP_MANAGED;
+ }
+ else { /* It is an overridden window so make it top of Z stack */
+ 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_MAP_UNMANAGED;
+ }
+
+ /* Tell our Window Manager thread to map the window */
+ if (fWMMsgInitialized)
+ winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg);
+
+ winStartMousePolling(s_pScreenPriv);
+ }
+
+ /*
+ We don't react to SWP_HIDEWINDOW indicating window is being hidden in
+ a symmetrical way (i.e. by sending WM_WM_UNMAP)
+
+ If the cause of the window being hidden is the X windows being unmapped,
+ (WM_STATE has changed to WithdrawnState), then the window has already
+ been unmapped.
+
+ Virtual desktop software (like VirtuaWin or Dexpot) uses SWP_HIDEWINDOW
+ to hide windows on other desktops. We mustn't unmap the X window in
+ that situation, as it becomes inaccessible.
+ */
}
- /*
- * Pass the message to DefWindowProc to let the function
- * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
- */
- break;
+ /*
+ * Pass the message to DefWindowProc to let the function
+ * break down WM_WINDOWPOSCHANGED to WM_MOVE and WM_SIZE.
+ */
+ break;
case WM_ENTERSIZEMOVE:
hasEnteredSizeMove = TRUE;