From 16a0fd7f61f80773447723b2d3a4733bb128f03e Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Sun, 11 Apr 2021 15:06:41 +0100 Subject: [PATCH 1/4] hw/xwin: Use revert-to-parent X focus mode in multiwindow WM Use revert-to-parent X focus mode, as recommended in ICCCM 4.1.7 --- hw/xwin/winmultiwindowwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 37f1a7a02..515281934 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -922,7 +922,7 @@ winMultiWindowWMProc(void *pArg) } if (!neverFocus) - xcb_set_input_focus(pWMInfo->conn, XCB_INPUT_FOCUS_POINTER_ROOT, + xcb_set_input_focus(pWMInfo->conn, XCB_INPUT_FOCUS_PARENT, pNode->msg.iWindow, XCB_CURRENT_TIME); if (IsWmProtocolAvailable(pWMInfo, From 6c0f39549dbe8c7c2e1322cc35332c5faba3d81a Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Mon, 17 Apr 2017 20:00:17 +0100 Subject: [PATCH 2/4] hw/xwin: Always set the X input focus to none when an X window loses focus In the multiwindow WM, we need to cancel the X input focus if the Windows input focus has gone to the desktop, or another application's window. We could maybe avoid some unneeded work by not doing this if the WM_KILLFOCUS wParam is another window owned by us, which is immediately going to be given the X input focus. --- hw/xwin/winmultiwindowwm.c | 8 ++++++++ hw/xwin/winmultiwindowwndproc.c | 10 +++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/hw/xwin/winmultiwindowwm.c b/hw/xwin/winmultiwindowwm.c index 515281934..27e65cac7 100644 --- a/hw/xwin/winmultiwindowwm.c +++ b/hw/xwin/winmultiwindowwm.c @@ -909,6 +909,7 @@ winMultiWindowWMProc(void *pArg) -- independently, the WM_TAKE_FOCUS protocol determines whether the WM should send a WM_TAKE_FOCUS ClientMessage. */ + if (pNode->msg.iWindow) { Bool neverFocus = FALSE; xcb_get_property_cookie_t cookie; @@ -932,6 +933,13 @@ winMultiWindowWMProc(void *pArg) pNode->msg.iWindow, pWMInfo->atmWmProtos, pWMInfo->atmWmTakeFocus); + } + else + /* Set the input focus to none */ + { + xcb_set_input_focus(pWMInfo->conn, XCB_INPUT_FOCUS_NONE, + XCB_NONE, XCB_CURRENT_TIME); + } break; diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index 31b5d6307..4fda60af2 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -810,9 +810,13 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Remove our keyboard hook if it is installed */ winRemoveKeyboardHookLL(); - /* Revert the X focus as well, but only if the Windows focus is going to another window */ - if (!wParam && pWin) - DeleteWindowFromAnyEvents(pWin, FALSE); + /* Revert the X focus as well */ + if (fWMMsgInitialized) + { + wmMsg.msg = WM_WM_ACTIVATE; + wmMsg.iWindow = 0; + winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); + } return 0; From 898978f6ab9f521dfc504b3e76a040610a673428 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Sat, 22 Apr 2017 17:35:04 +0100 Subject: [PATCH 3/4] hw/xwin: More adjustments to multiwindow mode focus handling The previous change is not enough, as WM_KILLFOCUS can apparently be sent to the window losing focus after WM_ACTIVATE has been sent to the window gaining focus. Try using WM_SETFOCUS instead, as that has the correct ordering and seems more logical. The test "!pWin || !pWin->overrideRedirect" is confusingly written: It's true if: (a) pWin is NULL (= X window doesn't exist, shouldn't happen), or (b) pWin->overrideRedirect is FALSE i.e. the intended effect is "don't give focus to override redirect windows" There seem to be some cases where this still isn't quite correct: A reproduction isn't known, but it seems to be related to minimizing a maximized Windows window, and having window activation move to a maximized X window beneath it. --- hw/xwin/winmultiwindowwndproc.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index 4fda60af2..29ae6b732 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -801,6 +801,16 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Add the keyboard hook if possible */ if (g_fKeyboardHookLL) g_fKeyboardHookLL = winInstallKeyboardHookLL(); + + /* Tell our Window Manager thread to activate the window */ + if (fWMMsgInitialized) + { + wmMsg.msg = WM_WM_ACTIVATE; + /* don't focus override redirect windows (e.g. menus) */ + if (!pWin || !pWin->overrideRedirect) + winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); + } + return 0; case WM_KILLFOCUS: @@ -900,21 +910,6 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Pass the message to the root window */ SendMessage(hwndScreen, message, wParam, lParam); - if (LOWORD(wParam) != WA_INACTIVE) { - /* Raise the window to the top in Z order */ - /* ago: Activate does not mean putting it to front! */ - /* - wmMsg.msg = WM_WM_RAISE; - if (fWMMsgInitialized) - winSendMessageToWM (s_pScreenPriv->pWMInfo, &wmMsg); - */ - - /* Tell our Window Manager thread to activate the window */ - wmMsg.msg = WM_WM_ACTIVATE; - if (fWMMsgInitialized) - if (!pWin || !pWin->overrideRedirect) /* for OOo menus */ - winSendMessageToWM(s_pScreenPriv->pWMInfo, &wmMsg); - } /* Prevent the mouse wheel from stalling when another window is minimized */ if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE && (HWND) lParam != NULL && (HWND) lParam != GetParent(hwnd)) From 1433d742c712661ddac8d484f272699325913271 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Sat, 28 Aug 2021 17:08:48 +0100 Subject: [PATCH 4/4] hw/xwin: Allow DefWindowProc to SetFocus() as needed after WM_ACTIVE Don't indicate we've processed WM_ACTIVATE, so DefWindowProc can do not-clearly specified default things with the focus. --- hw/xwin/winmultiwindowwndproc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/xwin/winmultiwindowwndproc.c b/hw/xwin/winmultiwindowwndproc.c index 29ae6b732..db5b574a1 100644 --- a/hw/xwin/winmultiwindowwndproc.c +++ b/hw/xwin/winmultiwindowwndproc.c @@ -910,11 +910,8 @@ winTopLevelWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) /* Pass the message to the root window */ SendMessage(hwndScreen, message, wParam, lParam); - /* Prevent the mouse wheel from stalling when another window is minimized */ - if (HIWORD(wParam) == 0 && LOWORD(wParam) == WA_ACTIVE && - (HWND) lParam != NULL && (HWND) lParam != GetParent(hwnd)) - SetFocus(hwnd); - return 0; + /* Allow DefWindowProc to SetFocus() as needed */ + break; case WM_ACTIVATEAPP: /*