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.
This commit is contained in:
Kevin B. McCarty 2017-04-07 18:55:00 +02:00 committed by Vadim Zeitlin
parent 60bd6842e4
commit 69110bd470

View File

@ -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());