From 69110bd470da5e32051b6c2f118615ebba82a993 Mon Sep 17 00:00:00 2001 From: "Kevin B. McCarty" Date: Fri, 7 Apr 2017 18:55:00 +0200 Subject: [PATCH] Fix spurious scrolling with deeply nested control The original ticket #9563 about children inside a wxScrolledWindow being scrolled, instead of just handling the mouse click (e.g. by toggling the checkbox), was fixed some time ago when the child was a direct child of wxPanel. However the same problem still existed when the child was inside another window which was itself a child of wxPanel. Generalize the fix by ignoring the child focus event if any of the window ancestors passes our check instead of checking only the window itself. Closes #17154. --- src/generic/scrlwing.cpp | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp index 6315f5a97f..5e8202c913 100644 --- a/src/generic/scrlwing.cpp +++ b/src/generic/scrlwing.cpp @@ -1079,22 +1079,28 @@ void wxScrollHelperBase::HandleOnChildFocus(wxChildFocusEvent& event) // window again to make the child widget visible. This leads to ugly // flickering when using nested wxPanels/wxScrolledWindows. // - // Ignore this event if 'win' is derived from wxControlContainer AND its - // parent is the m_targetWindow AND 'win' is not actually reciving the - // focus (win != FindFocus). TODO: This affects all wxControlContainer - // objects, but wxControlContainer is not part of the wxWidgets RTTI and - // so wxDynamicCast(win, wxControlContainer) does not compile. Find a way - // to determine if 'win' derives from wxControlContainer. Until then, - // testing if 'win' derives from wxPanel will probably get >90% of all - // cases. + // Ignore this event if 'win', or any of its ancestors, is derived from + // wxControlContainer AND its parent is the m_targetWindow AND 'win' is not + // actually receiving the focus (win != FindFocus). + // + // TODO: This affects all wxControlContainer objects, but + // wxControlContainer is not part of the wxWidgets RTTI and so + // wxDynamicCast(win, wxControlContainer) does not compile. Find a way to + // determine if 'win' derives from wxControlContainer. Until then, testing + // if 'win' derives from wxPanel will probably get >90% of all cases. - wxWindow *actual_focus=wxWindow::FindFocus(); - if (win != actual_focus && - wxDynamicCast(win, wxPanel) != 0 && - win->GetParent() == m_targetWindow) - // if win is a wxPanel and receives the focus, it should not be - // scrolled into view - return; + wxWindow * const actual_focus = wxWindow::FindFocus(); + for ( wxWindow* w = win; w; w = w->GetParent() ) + { + if ( w != actual_focus && + wxDynamicCast(w, wxPanel) != NULL && + w->GetParent() == m_targetWindow ) + { + // if it is a wxPanel and receives the focus, it should not be + // scrolled into view + return; + } + } const wxRect viewRect(m_targetWindow->GetClientRect());