From ff98ca5a32112525fb66af6fc875280a3a757d4f Mon Sep 17 00:00:00 2001 From: Paul Licameli Date: Thu, 2 Aug 2018 11:45:27 -0400 Subject: [PATCH] CellularPanel saves and restores focus for each click-drag-release... ... while the project makes note of which window has temporarily given up the focus; and TrackPanel can detect that, so that the yellow border of the focused track is still drawn while the panel "lends" the focus. Why do all this? So that, when the ruler is another CellularPanel, ESC key will work to abort drags in the ruler, but TrackPanel appearance won't change during the drags. --- src/CellularPanel.cpp | 20 +++++++++++++++----- src/Project.cpp | 5 +++++ src/Project.h | 6 ++++++ src/TrackPanel.cpp | 2 +- 4 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/CellularPanel.cpp b/src/CellularPanel.cpp index 01d033800..0d8fe78fd 100644 --- a/src/CellularPanel.cpp +++ b/src/CellularPanel.cpp @@ -106,6 +106,10 @@ void CellularPanel::Uncapture(wxMouseState *pState) if (HasCapture()) ReleaseMouse(); HandleMotion( *pState ); + + auto lender = GetProject()->mFocusLender.get(); + if (lender) + lender->SetFocus(); } bool CellularPanel::CancelDragging() @@ -654,10 +658,6 @@ try GetParent()->GetEventHandler()->ProcessEvent(e); } - if (event.ButtonDown()) { - SetFocus(); - } - if (event.Leaving()) { if ( !state.mUIHandle ) @@ -775,6 +775,9 @@ void CellularPanel::HandleClick( const TrackPanelMouseEvent &tpmEvent ) if (refreshResult & RefreshCode::Cancelled) state.mUIHandle.reset(), handle.reset(), ClearTargets(); else { + if( !HasFocus() ) + SetFocus(); + state.mpClickedCell = pCell; // Perhaps the clicked handle wants to update cursor and state message @@ -812,13 +815,20 @@ void CellularPanel::DoContextMenu( TrackPanelCell *pCell ) ProcessUIHandleResult(pCell, pCell, refreshResult); } -void CellularPanel::OnSetFocus(wxFocusEvent & WXUNUSED(event)) +void CellularPanel::OnSetFocus(wxFocusEvent &event) { + auto &ptr = GetProject()->mFocusLender; + if ( !ptr ) + ptr = event.GetWindow(); + SetFocusedCell(); } void CellularPanel::OnKillFocus(wxFocusEvent & WXUNUSED(event)) { + // Forget any borrowing of focus + GetProject()->mFocusLender = NULL; + if (AudacityProject::HasKeyboardCapture(this)) { AudacityProject::ReleaseKeyboard(this); diff --git a/src/Project.cpp b/src/Project.cpp index 8d7d5a6d4..f53bd893e 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -6258,3 +6258,8 @@ void AudacityProject::PlaybackScroller::OnTimer(wxCommandEvent &event) trackPanel->Refresh(false); } } + +bool AudacityProject::IsFocused( const wxWindow *window ) const +{ + return window == mFocusLender || window == wxWindow::FindFocus(); +} diff --git a/src/Project.h b/src/Project.h index 828883b0f..2a7e8c6f1 100644 --- a/src/Project.h +++ b/src/Project.h @@ -834,6 +834,12 @@ public: std::shared_ptr GetBackgroundCell() const { return mBackgroundCell; } + wxWindowRef mFocusLender; + + // Return true if the window is really focused, or if focus was borrowed + // from it + bool IsFocused( const wxWindow *window ) const; + DECLARE_EVENT_TABLE() }; diff --git a/src/TrackPanel.cpp b/src/TrackPanel.cpp index 7118d7f4e..44ecd112b 100644 --- a/src/TrackPanel.cpp +++ b/src/TrackPanel.cpp @@ -1270,7 +1270,7 @@ void TrackPanel::DrawEverythingElse(TrackPanelDrawingContext &context, // if (GetFocusedTrack() != NULL) { // the highlight was reportedly drawn even when something else // was the focus and no highlight should be drawn. -RBD - if (GetFocusedTrack() != NULL && wxWindow::FindFocus() == this) { + if (GetFocusedTrack() != NULL && GetProject()->IsFocused( this )) { HighlightFocusedTrack(dc, focusRect); }