mirror of
https://github.com/wxWidgets/wxWidgets.git
synced 2026-09-23 06:33:59 +08:00
Respect disabled physical scrolling in Scroll
Make wxScrollHelper::DoScroll() use ScrollWindow() only for axes whose physical scrolling is enabled. Disabled axes still update their logical scroll position and invalidate the target window so it repaints. Add a regression test covering fully disabled physical scrolling and a mixed horizontal-enabled, vertical-disabled scroll. This commit is best viewed ignoring whitespace-only changes. Fixes #4433. Closes #26900.
This commit is contained in:
@@ -1587,29 +1587,55 @@ void wxScrollHelper::DoScroll( int x_pos, int y_pos )
|
||||
if ( new_x == m_xScrollPosition && new_y == m_yScrollPosition )
|
||||
return; // nothing to do, the position didn't change
|
||||
|
||||
const bool scrollX = m_xScrollPosition != new_x;
|
||||
const bool scrollY = m_yScrollPosition != new_y;
|
||||
const bool scrollWindow =
|
||||
(scrollX && m_xScrollingEnabled) ||
|
||||
(scrollY && m_yScrollingEnabled);
|
||||
|
||||
// flush all pending repaints before we change m_{x,y}ScrollPosition, as
|
||||
// otherwise invalidated area could be updated incorrectly later when
|
||||
// ScrollWindow() makes sure they're repainted before scrolling them
|
||||
m_targetWindow->Update();
|
||||
if ( scrollWindow )
|
||||
m_targetWindow->Update();
|
||||
|
||||
bool needsRefresh = false;
|
||||
|
||||
// update the position and scroll the window now:
|
||||
if (m_xScrollPosition != new_x)
|
||||
if ( scrollX )
|
||||
{
|
||||
int old_x = m_xScrollPosition;
|
||||
m_xScrollPosition = new_x;
|
||||
m_win->SetScrollPos( wxHORIZONTAL, new_x );
|
||||
m_targetWindow->ScrollWindow( (old_x-new_x)*m_xScrollPixelsPerLine, 0,
|
||||
GetScrollRect() );
|
||||
if ( m_xScrollingEnabled )
|
||||
{
|
||||
m_targetWindow->ScrollWindow( (old_x-new_x)*m_xScrollPixelsPerLine, 0,
|
||||
GetScrollRect() );
|
||||
}
|
||||
else
|
||||
{
|
||||
needsRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_yScrollPosition != new_y)
|
||||
if ( scrollY )
|
||||
{
|
||||
int old_y = m_yScrollPosition;
|
||||
m_yScrollPosition = new_y;
|
||||
m_win->SetScrollPos( wxVERTICAL, new_y );
|
||||
m_targetWindow->ScrollWindow( 0, (old_y-new_y)*m_yScrollPixelsPerLine,
|
||||
GetScrollRect() );
|
||||
if ( m_yScrollingEnabled )
|
||||
{
|
||||
m_targetWindow->ScrollWindow( 0, (old_y-new_y)*m_yScrollPixelsPerLine,
|
||||
GetScrollRect() );
|
||||
}
|
||||
else
|
||||
{
|
||||
needsRefresh = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( needsRefresh )
|
||||
m_targetWindow->Refresh(true, GetScrollRect());
|
||||
}
|
||||
|
||||
#endif // wxHAS_GENERIC_SCROLLWIN
|
||||
|
||||
+14
-3
@@ -147,9 +147,20 @@ void wxScrollHelper::DoScrollOneDir(int orient,
|
||||
m_win->SetScrollPos(orient, pos);
|
||||
pos = m_win->GetScrollPos(orient);
|
||||
|
||||
int diff = (*posOld - pos)*pixelsPerLine;
|
||||
m_targetWindow->ScrollWindow(orient == wxHORIZONTAL ? diff : 0,
|
||||
orient == wxHORIZONTAL ? 0 : diff);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Logical scrolling still changes the view position; only the
|
||||
// physical move of the pixels is disabled.
|
||||
m_targetWindow->Refresh(true, GetScrollRect());
|
||||
}
|
||||
|
||||
*posOld = pos;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
#include "wx/tooltip.h"
|
||||
#include "wx/wupdlock.h"
|
||||
|
||||
#if wxUSE_SCROLLBAR
|
||||
#include "wx/scrolwin.h"
|
||||
#endif // wxUSE_SCROLLBAR
|
||||
|
||||
#ifdef __WXGTK__
|
||||
#include "wx/gtk/private/backend.h"
|
||||
#endif // __WXGTK__
|
||||
@@ -132,6 +136,45 @@ private:
|
||||
};
|
||||
#endif // wxUSE_HELP
|
||||
|
||||
#if wxUSE_SCROLLBAR
|
||||
|
||||
class ScrollCountingWindow : public wxScrolledWindow
|
||||
{
|
||||
public:
|
||||
ScrollCountingWindow(wxWindow* parent)
|
||||
: wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxSize(100, 100))
|
||||
{
|
||||
SetScrollRate(10, 10);
|
||||
SetVirtualSize(1000, 1000);
|
||||
ResetScrollWindowCalls();
|
||||
}
|
||||
|
||||
virtual void ScrollWindow(int dx, int dy,
|
||||
const wxRect* rect = nullptr) override
|
||||
{
|
||||
wxUnusedVar(rect);
|
||||
|
||||
m_scrollWindowCallCount++;
|
||||
m_lastScrollWindowDelta = wxPoint(dx, dy);
|
||||
}
|
||||
|
||||
void ResetScrollWindowCalls()
|
||||
{
|
||||
m_scrollWindowCallCount = 0;
|
||||
m_lastScrollWindowDelta = wxPoint();
|
||||
}
|
||||
|
||||
int GetScrollWindowCallCount() const { return m_scrollWindowCallCount; }
|
||||
|
||||
wxPoint GetLastScrollWindowDelta() const { return m_lastScrollWindowDelta; }
|
||||
|
||||
private:
|
||||
int m_scrollWindowCallCount = 0;
|
||||
wxPoint m_lastScrollWindowDelta;
|
||||
};
|
||||
|
||||
#endif // wxUSE_SCROLLBAR
|
||||
|
||||
static void DoTestShowHideEvent(wxWindow* window)
|
||||
{
|
||||
EventCounter show(window, wxEVT_SHOW);
|
||||
@@ -149,6 +192,33 @@ static void DoTestShowHideEvent(wxWindow* window)
|
||||
CHECK( show.GetCount() == 2 );
|
||||
}
|
||||
|
||||
#if wxUSE_SCROLLBAR
|
||||
|
||||
TEST_CASE_METHOD(WindowTestCase, "Window::ScrolledWindowPhysicalScrolling",
|
||||
"[window][scroll]")
|
||||
{
|
||||
std::unique_ptr<ScrollCountingWindow>
|
||||
win(new ScrollCountingWindow(wxTheApp->GetTopWindow()));
|
||||
|
||||
win->EnableScrolling(false, false);
|
||||
win->Scroll(1, 2);
|
||||
|
||||
CHECK( win->GetViewStart() == wxPoint(1, 2) );
|
||||
CHECK( win->GetScrollWindowCallCount() == 0 );
|
||||
|
||||
win->Scroll(0, 0);
|
||||
win->EnableScrolling(true, false);
|
||||
win->ResetScrollWindowCalls();
|
||||
|
||||
win->Scroll(1, 2);
|
||||
|
||||
CHECK( win->GetViewStart() == wxPoint(1, 2) );
|
||||
REQUIRE( win->GetScrollWindowCallCount() == 1 );
|
||||
CHECK( win->GetLastScrollWindowDelta() == wxPoint(-10, 0) );
|
||||
}
|
||||
|
||||
#endif // wxUSE_SCROLLBAR
|
||||
|
||||
TEST_CASE_METHOD(WindowTestCase, "Window::ShowHideEvent", "[window]")
|
||||
{
|
||||
SECTION("Normal window")
|
||||
|
||||
Reference in New Issue
Block a user