summaryrefslogtreecommitdiff
path: root/wx+/focus.h
diff options
context:
space:
mode:
authorDaniel Wilhelm <shieldwed@outlook.com>2018-05-09 00:07:47 +0200
committerDaniel Wilhelm <shieldwed@outlook.com>2018-05-09 00:07:47 +0200
commit48c8efc58c9eb41da96b053806deb395d2e66443 (patch)
treea6da12e987ad778bafe6da7069c7fa8b1e761c68 /wx+/focus.h
parent9.6 (diff)
downloadFreeFileSync-48c8efc58c9eb41da96b053806deb395d2e66443.tar.gz
FreeFileSync-48c8efc58c9eb41da96b053806deb395d2e66443.tar.bz2
FreeFileSync-48c8efc58c9eb41da96b053806deb395d2e66443.zip
9.7
Diffstat (limited to 'wx+/focus.h')
-rwxr-xr-xwx+/focus.h66
1 files changed, 66 insertions, 0 deletions
diff --git a/wx+/focus.h b/wx+/focus.h
new file mode 100755
index 00000000..cd99d010
--- /dev/null
+++ b/wx+/focus.h
@@ -0,0 +1,66 @@
+// *****************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
+// * Copyright (C) Zenju (zenju AT freefilesync DOT org) - All Rights Reserved *
+// *****************************************************************************
+
+#ifndef FOCUS_1084731021985757843
+#define FOCUS_1084731021985757843
+
+#include <wx/toplevel.h>
+
+
+namespace zen
+{
+//pretty much the same like "bool wxWindowBase::IsDescendant(wxWindowBase* child) const" but without the obvious misnomer
+inline
+bool isComponentOf(const wxWindow* child, const wxWindow* top)
+{
+ for (const wxWindow* wnd = child; wnd != nullptr; wnd = wnd->GetParent())
+ if (wnd == top)
+ return true;
+ return false;
+}
+
+
+inline
+wxTopLevelWindow* getTopLevelWindow(wxWindow* child)
+{
+ for (wxWindow* wnd = child; wnd != nullptr; wnd = wnd->GetParent())
+ if (auto tlw = dynamic_cast<wxTopLevelWindow*>(wnd)) //why does wxWidgets use wxWindows::IsTopLevel() ??
+ return tlw;
+ return nullptr;
+}
+
+
+/*
+Preserving input focus has to be more clever than:
+ wxWindow* oldFocus = wxWindow::FindFocus();
+ ZEN_ON_SCOPE_EXIT(if (oldFocus) oldFocus->SetFocus());
+
+=> wxWindow::SetFocus() internally calls Win32 ::SetFocus, which calls ::SetActiveWindow, which - lord knows why - changes the foreground window to the focus window
+ even if the user is currently busy using a different app! More curiosity: this foreground focus stealing happens only during the *first* SetFocus() after app start!
+ It also can be avoided by changing focus back and forth with some other app after start => wxWidgets bug or Win32 feature???
+*/
+struct FocusPreserver
+{
+ ~FocusPreserver()
+ {
+ //wxTopLevelWindow::IsActive() does NOT call Win32 ::GetActiveWindow()!
+ //Instead it checks if ::GetFocus() is set somewhere inside the top level
+ //Note: Both Win32 active and focus windows are *thread-local* values, while foreground window is global! https://blogs.msdn.microsoft.com/oldnewthing/20131016-00/?p=2913
+ if (oldFocus_)
+ if (wxTopLevelWindow* topWin = getTopLevelWindow(oldFocus_))
+ if (topWin->IsActive()) //Linux/macOS: already behaves just like ::GetForegroundWindow() on Windows!
+ oldFocus_->SetFocus();
+ }
+
+ wxWindow* getFocus() const { return oldFocus_; }
+ void setFocus(wxWindow* win) { oldFocus_ = win; }
+
+private:
+ wxWindow* oldFocus_ = wxWindow::FindFocus();
+};
+}
+
+#endif //FOCUS_1084731021985757843
bgstack15