Make wxGTK wxScrolled::GetViewStart() behave as the generic version

Update the scroll position before scrolling in wxGTK to make it
consistent with the other ports.

Add a unit test checking that all ports behave consistently.
This commit is contained in:
Vadim Zeitlin
2026-09-20 02:32:07 +02:00
parent a9390a6035
commit 4a80ac3caa
2 changed files with 46 additions and 3 deletions
+7 -3
View File
@@ -147,11 +147,17 @@ void wxScrollHelper::DoScrollOneDir(int orient,
m_win->SetScrollPos(orient, pos);
pos = m_win->GetScrollPos(orient);
const int diff = (*posOld - pos)*pixelsPerLine;
// Update the position before calling ScrollWindow(), as it may use
// GetViewStart(), which must already return the new position, as it
// does in the other ports.
*posOld = pos;
const bool scrollingEnabled =
orient == wxHORIZONTAL ? m_xScrollingEnabled : m_yScrollingEnabled;
if ( scrollingEnabled )
{
int diff = (*posOld - pos)*pixelsPerLine;
m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0,
orient == wxHORIZONTAL ? 0 : diff);
}
@@ -161,8 +167,6 @@ void wxScrollHelper::DoScrollOneDir(int orient,
// physical move of the pixels is disabled.
m_targetWindow->Refresh(true, GetScrollRect());
}
*posOld = pos;
}
}
+39
View File
@@ -156,21 +156,30 @@ public:
m_scrollWindowCallCount++;
m_lastScrollWindowDelta = wxPoint(dx, dy);
m_lastScrollWindowViewStart = GetViewStart();
}
void ResetScrollWindowCalls()
{
m_scrollWindowCallCount = 0;
m_lastScrollWindowDelta = wxPoint();
m_lastScrollWindowViewStart = wxDefaultPosition;
}
int GetScrollWindowCallCount() const { return m_scrollWindowCallCount; }
wxPoint GetLastScrollWindowDelta() const { return m_lastScrollWindowDelta; }
// Return the view start as it was during the last ScrollWindow() call.
wxPoint GetLastScrollWindowViewStart() const
{
return m_lastScrollWindowViewStart;
}
private:
int m_scrollWindowCallCount = 0;
wxPoint m_lastScrollWindowDelta;
wxPoint m_lastScrollWindowViewStart;
};
#endif // wxUSE_SCROLLBAR
@@ -216,6 +225,36 @@ TEST_CASE_METHOD(WindowTestCase, "Window::ScrolledWindowPhysicalScrolling",
CHECK( win->GetLastScrollWindowDelta() == wxPoint(-10, 0) );
}
TEST_CASE_METHOD(WindowTestCase, "Window::ScrolledWindowViewStart",
"[window][scroll]")
{
auto win = make_unique<ScrollCountingWindow>(wxTheApp->GetTopWindow());
// ScrollWindow() must be called after updating the scroll position, so
// that it can be used, e.g. to convert between logical and device
// coordinates, in the overridden version of this function.
win->Scroll(0, 3);
REQUIRE( win->GetScrollWindowCallCount() == 1 );
CHECK( win->GetLastScrollWindowDelta() == wxPoint(0, -30) );
CHECK( win->GetLastScrollWindowViewStart() == wxPoint(0, 3) );
win->ResetScrollWindowCalls();
win->Scroll(2, -1);
REQUIRE( win->GetScrollWindowCallCount() == 1 );
CHECK( win->GetLastScrollWindowDelta() == wxPoint(-20, 0) );
CHECK( win->GetLastScrollWindowViewStart() == wxPoint(2, 3) );
// When scrolling in both directions, ScrollWindow() is called twice and
// the view start must be fully updated by the time of the last call.
win->ResetScrollWindowCalls();
win->Scroll(1, 1);
REQUIRE( win->GetScrollWindowCallCount() == 2 );
CHECK( win->GetLastScrollWindowViewStart() == wxPoint(1, 1) );
}
#endif // wxUSE_SCROLLBAR
TEST_CASE_METHOD(WindowTestCase, "Window::ShowHideEvent", "[window]")