From 6cfce50a6040b265cd1790249c5550e2a2c7d494 Mon Sep 17 00:00:00 2001 From: Leland Lucius Date: Thu, 3 Sep 2015 02:33:41 -0500 Subject: [PATCH] Fix for bug #1173 Basically, just restored a bit of code to the ProgressDialog that I'd removed during the conversion now that it's understood what is actually happening. --- src/widgets/ProgressDialog.cpp | 63 +++++++++++++++++++++++++++++++++- src/widgets/ProgressDialog.h | 3 ++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/widgets/ProgressDialog.cpp b/src/widgets/ProgressDialog.cpp index 7941a63fc..c2c7515d8 100644 --- a/src/widgets/ProgressDialog.cpp +++ b/src/widgets/ProgressDialog.cpp @@ -1017,7 +1017,30 @@ ProgressDialog::~ProgressDialog() mDisable = NULL; } - Beep(); + if (IsShown()) + { + Show(false); + + Beep(); + } + +#if defined(__WXGTK__) + // Under GTK, when applying any effect that prompts the user, it's more than + // like that FindFocus() will return NULL. So, make sure something has focus. + if (GetParent()) { + GetParent()->SetFocus(); + } +#endif + + // Restore saved focus, but only if the window still exists. + // + // It is possible that it was a deferred deletion and it was deleted since + // we captured the focused window. So, we need to verify that the window + // still exists by searching all of the wxWidgets windows. It's the only + // sure way. + if (mHadFocus && SearchForWindow(wxTopLevelWindows, mHadFocus)) { + mHadFocus->SetFocus(); + } } void ProgressDialog::Init() @@ -1025,6 +1048,25 @@ void ProgressDialog::Init() mLastValue = 0; mDisable = NULL; mIsTransparent = true; + + // There's a problem where the focus is not returned to the window that had + // it before creating this object. The reason is because the focus events + // that are sent to the parent window after the wxWindowDisabler are created + // are tossed and focus will not get restored to the parent once the disabler + // is deleted. + // + // So, we capture and restore the focus ourselves. + + mHadFocus = wxWindow::FindFocus(); + +#if defined(__WXGTK__) + // Under GTK, when applying any effect that prompts the user, it's more than + // likely that FindFocus() will return NULL. So, make sure something has focus. + if (GetParent()) + { + GetParent()->SetFocus(); + } +#endif } bool ProgressDialog::Create(const wxString & title, @@ -1404,6 +1446,25 @@ void ProgressDialog::SetMessage(const wxString & message) } } +// +// Recursivaly search the window list for the given window. +// +bool ProgressDialog::SearchForWindow(const wxWindowList & list, const wxWindow *searchfor) const +{ + wxWindowList::compatibility_iterator node = list.GetFirst(); + while (node) + { + wxWindow *win = node->GetData(); + if (win == searchfor || SearchForWindow(win->GetChildren(), searchfor)) + { + return true; + } + node = node->GetNext(); + } + + return false; +} + void ProgressDialog::OnCancel(wxCommandEvent & WXUNUSED(event)) { FindWindowById(wxID_CANCEL, this)->Disable(); diff --git a/src/widgets/ProgressDialog.h b/src/widgets/ProgressDialog.h index f51d307ff..1e719e5dd 100644 --- a/src/widgets/ProgressDialog.h +++ b/src/widgets/ProgressDialog.h @@ -67,6 +67,8 @@ public: void SetMessage(const wxString & message); protected: + wxWindow *mHadFocus; + wxStaticText *mElapsed; wxStaticText *mRemaining; wxGauge *mGauge; @@ -82,6 +84,7 @@ protected: private: void Init(); + bool SearchForWindow(const wxWindowList & list, const wxWindow *searchfor) const; void OnCancel(wxCommandEvent & e); void OnStop(wxCommandEvent & e); void OnCloseWindow(wxCloseEvent & e);