summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Turney <jon.turney@dronecode.org.uk>2016-01-11 16:05:59 +0000
committerJon Turney <jon.turney@dronecode.org.uk>2018-05-13 18:21:59 +0100
commitfce615acfea85e7b85b2e0c6b5d7abb98205b5a2 (patch)
treea124b3ebc517c0d449c4970bb680595692e5e0b8
parent62f7e38f1e110999e4f4801f850ec495bba17492 (diff)
Fix a problem with initially maximized windows
Fix a problem which occurs when a window is initially maxmimized: It's shown unmaximized, then maximized. The initial unmaximized show causes a WM_WM_CHANGE_STATE to unmaximized to be sent, while a SW_MAXIMIZE is in flight. These overlapping in-flight messages can cause the window to get stuck flipping between maximized and unmaximized states. It seems that maximizing a Windows window is not a state, but an action which can only be applied to a visible window. So, this can't be fixed by maximizing the window before it is made visible. Instead, explicitly sequence things so the window is always initially shown unmaximized, then start tracking the state, and then maximize it.
-rw-r--r--hw/xwin/winmultiwindowwm.c72
-rw-r--r--hw/xwin/winmultiwindowwndproc.c4
2 files changed, 46 insertions, 30 deletions
diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c
index 68bfe8aac..03ec89e22 100644
--- a/hw/xwin/winmultiwindowwm.c
+++ b/hw/xwin/winmultiwindowwm.c
@@ -106,6 +106,9 @@ extern void winUpdateWindowPosition(HWND hWnd, HWND * zstyle);
#define WIN_MSG_QUEUE_FNAME "/dev/windows"
#endif
+#define HINT_MAX (1L<<0)
+#define HINT_MIN (1L<<1)
+
/*
* Local structures
*/
@@ -193,7 +196,7 @@ static Bool
CheckAnotherWindowManager(xcb_connection_t *conn, DWORD dwScreen);
static void
- winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, Bool onCreate);
+ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, unsigned long *maxmin);
static void
winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd);
@@ -708,7 +711,7 @@ UpdateIcon(WMInfoPtr pWMInfo, xcb_window_t iWindow)
*/
static void
-UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow, Bool onCreate)
+UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow, unsigned long *maxmin)
{
HWND hWnd;
HWND zstyle = HWND_NOTOPMOST;
@@ -723,7 +726,7 @@ UpdateStyle(WMInfoPtr pWMInfo, xcb_window_t iWindow, Bool onCreate)
return;
/* Determine the Window style, which determines borders and clipping region... */
- winApplyHints(pWMInfo, iWindow, hWnd, &zstyle, onCreate);
+ winApplyHints(pWMInfo, iWindow, hWnd, &zstyle, maxmin);
winUpdateWindowPosition(hWnd, &zstyle);
/* Apply the updated window style, without changing it's show or activation state */
@@ -976,9 +979,12 @@ winMultiWindowWMProc(void *pArg)
/* Branch on the message type */
switch (pNode->msg.msg) {
case WM_WM_CREATE:
+ {
+ unsigned long maxmin = 0;
#if CYGMULTIWINDOW_DEBUG
ErrorF("\tWM_WM_CREATE\n");
#endif
+
/* Put a note as to the HWND associated with this Window */
xcb_change_property(pWMInfo->conn, XCB_PROP_MODE_REPLACE,
pNode->msg.iWindow, pWMInfo->atmPrivMap,
@@ -987,7 +993,7 @@ winMultiWindowWMProc(void *pArg)
/* Determine the Window style, which determines borders and clipping region... */
- UpdateStyle(pWMInfo, pNode->msg.iWindow, TRUE);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin);
/* Display the window without activating it */
{
@@ -999,7 +1005,7 @@ winMultiWindowWMProc(void *pArg)
if (reply) {
if (reply->_class != InputOnly)
- ShowWindow(pNode->msg.hwndWindow, SW_SHOWNOACTIVATE);
+ ShowWindow(pNode->msg.hwndWindow, SW_SHOWNA);
free(reply);
}
}
@@ -1007,7 +1013,20 @@ winMultiWindowWMProc(void *pArg)
/* Send first paint message */
UpdateWindow(pNode->msg.hwndWindow);
- break;
+ /* Establish initial state */
+ UpdateState(pWMInfo, pNode->msg.iWindow, XCB_ICCCM_WM_STATE_NORMAL);
+
+ /*
+ It only makes sense to apply minimize/maximize override as the
+ initial state, otherwise that state can't be changed.
+ */
+ if (maxmin & HINT_MAX)
+ SendMessage(pNode->msg.hwndWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
+ else if (maxmin & HINT_MIN)
+ SendMessage(pNode->msg.hwndWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
+ }
+
+ break;
#if 0
case WM_WM_MOVE:
@@ -1043,8 +1062,11 @@ winMultiWindowWMProc(void *pArg)
break;
case WM_WM_MAP_MANAGED:
+ {
+ unsigned long maxmin = 0;
+
UpdateName(pWMInfo, pNode->msg.iWindow);
- UpdateStyle(pWMInfo, pNode->msg.iWindow, TRUE);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin);
UpdateIcon(pWMInfo, pNode->msg.iWindow);
/* Reshape */
@@ -1056,8 +1078,9 @@ winMultiWindowWMProc(void *pArg)
winUpdateRgnMultiWindow(pWin);
}
}
+ }
- break;
+ break;
case WM_WM_UNMAP:
@@ -1126,11 +1149,13 @@ winMultiWindowWMProc(void *pArg)
case WM_WM_HINTS_EVENT:
{
+ unsigned long maxmin = 0;
+
/* Don't do anything if this is an override-redirect window */
if (IsOverrideRedirect(pWMInfo->conn, pNode->msg.iWindow))
break;
- UpdateStyle(pWMInfo, pNode->msg.iWindow, FALSE);
+ UpdateStyle(pWMInfo, pNode->msg.iWindow, &maxmin);
}
break;
@@ -2002,12 +2027,9 @@ winApplyUrgency(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd)
#define HINT_NOMINIMIZE (1L<<5)
#define HINT_NOSYSMENU (1L<<6)
#define HINT_SKIPTASKBAR (1L<<7)
-/* These two are used on their own */
-#define HINT_MAX (1L<<0)
-#define HINT_MIN (1L<<1)
static void
-winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, Bool onCreate)
+winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle, unsigned long *maxmin)
{
xcb_connection_t *conn = pWMInfo->conn;
@@ -2018,9 +2040,10 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle,
static int generation;
unsigned long hint = HINT_BORDER | HINT_SIZEBOX | HINT_CAPTION;
- unsigned long maxmin = 0;
unsigned long style, exStyle;
+ *maxmin = 0;
+
if (!hWnd)
return;
if (!IsWindow(hWnd))
@@ -2052,9 +2075,9 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle,
if (pAtom[i] == skiptaskbarState)
hint |= HINT_SKIPTASKBAR;
if (pAtom[i] == hiddenState)
- maxmin |= HINT_MIN;
+ *maxmin |= HINT_MIN;
else if (pAtom[i] == fullscreenState)
- maxmin |= HINT_MAX;
+ *maxmin |= HINT_MAX;
if (pAtom[i] == belowState)
*zstyle = HWND_BOTTOM;
else if (pAtom[i] == aboveState)
@@ -2066,7 +2089,7 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle,
}
if (verMax && horMax)
- maxmin |= HINT_MAX;
+ *maxmin |= HINT_MAX;
free(reply);
}
@@ -2180,12 +2203,6 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle,
style = STYLE_NONE;
style = winOverrideStyle(res_name, res_class, window_name);
- /*
- It only makes sense to apply minimize/maximize override when the
- window is mapped, as otherwise the state can't be changed.
- */
- if (!onCreate)
- style &= ~(STYLE_MAXIMIZE | STYLE_MINIMIZE);
#define APPLICATION_ID_FORMAT "%s.xwin.%s"
#define APPLICATION_ID_UNKNOWN "unknown"
@@ -2208,17 +2225,12 @@ winApplyHints(WMInfoPtr pWMInfo, xcb_window_t iWindow, HWND hWnd, HWND * zstyle,
if (style & STYLE_TOPMOST)
*zstyle = HWND_TOPMOST;
else if (style & STYLE_MAXIMIZE)
- maxmin = (hint & ~HINT_MIN) | HINT_MAX;
+ *maxmin = (hint & ~HINT_MIN) | HINT_MAX;
else if (style & STYLE_MINIMIZE)
- maxmin = (hint & ~HINT_MAX) | HINT_MIN;
+ *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) |
diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c
index b54c0d47b..a6187e6d4 100644
--- a/hw/xwin/winmultiwindowwndproc.c
+++ b/hw/xwin/winmultiwindowwndproc.c
@@ -299,6 +299,10 @@ static
void
winAdjustXWindowState(winPrivScreenPtr s_pScreenPriv, winWMMessageRec *wmMsg)
{
+ /* Do nothing if window has not yet been given initial state */
+ if (!GetProp(wmMsg->hwndWindow, WIN_STATE_PROP))
+ return;
+
wmMsg->msg = WM_WM_CHANGE_STATE;
if (IsIconic(wmMsg->hwndWindow)) {
wmMsg->dwID = 3; // IconicState