From a352e95a30b5081e4d07ea342f7bd5535360eadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Va=CC=81clav=20Slavi=CC=81k?= Date: Mon, 1 Aug 2016 18:10:37 +0200 Subject: [PATCH] wxMSW: Restore window focus after wxExecute If wxExecute() is called without the wxEXEC_NODISABLE flag, it disables all toplevel windows and then creates a helper dummy window. This moves focus to the helper window and when it's destroyed, back to the first(?) of the re-enabled application windows, thus loosing original focus. Remember previously focused window instead and try to restore focus to it. This still results in some flicker, but is better than completely changing focus and e.g. even changing the currently active window without user's input. --- src/msw/app.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/msw/app.cpp b/src/msw/app.cpp index 26c4d634f3..c8f49b8306 100644 --- a/src/msw/app.cpp +++ b/src/msw/app.cpp @@ -51,6 +51,7 @@ #include "wx/thread.h" #include "wx/scopeguard.h" #include "wx/vector.h" +#include "wx/weakref.h" #include "wx/msw/private.h" #include "wx/msw/dc.h" @@ -137,13 +138,15 @@ LRESULT WXDLLEXPORT APIENTRY wxWndProc(HWND, UINT, WPARAM, LPARAM); // AfterChildWaitLoop() struct ChildWaitLoopData { - ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *winActive_) + ChildWaitLoopData(wxWindowDisabler *wd_, wxWindow *focused_, wxWindow *winActive_) { wd = wd_; + focused = focused_; winActive = winActive_; } wxWindowDisabler *wd; + wxWeakRef focused; wxWindow *winActive; }; @@ -167,6 +170,8 @@ void *wxGUIAppTraits::BeforeChildWaitLoop() */ wxBeginBusyCursor(); + wxWindow* const focus = wxWindow::FindFocus(); + // first disable all existing windows wxWindowDisabler *wd = new wxWindowDisabler; @@ -183,7 +188,7 @@ void *wxGUIAppTraits::BeforeChildWaitLoop() ); winActive->Show(); - return new ChildWaitLoopData(wd, winActive); + return new ChildWaitLoopData(wd, focus, winActive); } void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig) @@ -194,6 +199,9 @@ void wxGUIAppTraits::AfterChildWaitLoop(void *dataOrig) delete data->wd; + if ( data->focused ) + data->focused->SetFocus(); + // finally delete the dummy dialog and, as wd has been already destroyed // and the other windows reenabled, the activation is going to return to // the window which had had it before