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.
This commit is contained in:
Václav Slavík 2016-08-01 18:10:37 +02:00
parent ea8cb7a24a
commit a352e95a30

View File

@ -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<wxWindow> 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