Avoid using very large wxDC origin offsets with wxGenericListCtrl
Unix builds / Ubuntu 18.04 wxGTK 3 compatible 3.0 (push) Has been cancelled
Unix builds / Ubuntu 24.04 wxGTK ASAN not compatible (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK UTF-8 (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxQt (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxX11 (push) Has been cancelled
Unix builds / Ubuntu 20.04 wxGTK 3 with clang (push) Has been cancelled
Unix builds / Ubuntu 22.04 wxGTK with wx containers (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxDFB (push) Has been cancelled
Unix builds / Ubuntu 24.04 wxGTK UBSAN (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 3 static with gcc 4.8 (push) Has been cancelled
Unix builds / Ubuntu 18.04 wxGTK 2 (push) Has been cancelled
CMake builds / Ubuntu 22.04 wxGTK 3 (push) Has been cancelled
CMake builds / macOS latest wxGTK 3 Unix Makefiles (push) Has been cancelled
CMake builds / MSW/MSVC wxMSW (push) Has been cancelled
CMake builds / MSW/Clang wxMSW (push) Has been cancelled
CMake builds / macOS latest wxOSX Ninja (push) Has been cancelled
CMake builds / macOS 14 wxOSX Xcode (push) Has been cancelled
CMake builds / macOS 14 wxIOS (push) Has been cancelled
CMake builds / MSW/MSVC wxQt 5.15 (push) Has been cancelled
CMake builds / MSW/MSVC wxQt 6.10 (push) Has been cancelled
Mac builds / wxMac ARM ASAN not compatible (push) Has been cancelled
Mac builds / wxMac Universal C++14 (push) Has been cancelled
Mac builds / wxiOS Simulator on Silicon Mac (push) Has been cancelled
Mac builds / wxiOS (push) Has been cancelled
Mac builds / wxMac Intel C++17 (push) Has been cancelled
Mac Xcode builds / iOS Simulator static (push) Has been cancelled
Mac Xcode builds / macOS dynamic Release (push) Has been cancelled
Mac Xcode builds / iOS static Debug (push) Has been cancelled
MSW builds / wxMSW vs2022 DLL Debug x64 (push) Has been cancelled
MSW builds / wxMSW vs2022 DLL Release x64 (push) Has been cancelled
MSW builds / wxMSW vs2022 Debug Win32 (push) Has been cancelled
MSW builds / wxMSW vs2022 Release arm64 (push) Has been cancelled
MSW builds / wxMSW vs2026 DLL Release x64 (push) Has been cancelled
MSW cross-builds / wxMSW 64 bits not compatible (push) Has been cancelled
MSW cross-builds / wxMSW/Univ (push) Has been cancelled
MSW cross-builds / wxMSW 32 bits (push) Has been cancelled
Code Checks / Check Spelling (push) Has been cancelled
Code Checks / Check Whitespace (push) Has been cancelled
Code Checks / Check Mixed EOL (push) Has been cancelled
Code Checks / Check C++ Style (push) Has been cancelled
Code Checks / Check All Headers In allheaders.h (push) Has been cancelled

Using the wxDC origin to implement scrolled drawing can require very large
origin offsets, which can exceed Cairo coordinate limits (2^23), and therefore
currently wxGTK3 limits as well. Managing the scroll offsets turns out to be
pretty simple in this case, avoiding any coordinate limitations.
See #25365
This commit is contained in:
paulcor
2026-06-20 10:48:01 -07:00
committed by GitHub
parent 4dd107ae7d
commit 0ec0518993
2 changed files with 33 additions and 37 deletions
+1 -2
View File
@@ -275,13 +275,12 @@ public:
}
// draw the line on the given DC in icon/list mode
void Draw( wxDC *dc, bool current );
void Draw( wxDC *dc, const wxPoint& origin, bool current );
// the same in report mode: it needs more parameters as we don't store
// everything in the item in report mode
void DrawInReportMode( wxDC *dc,
const wxRect& rect,
const wxRect& rectHL,
bool highlighted,
bool current,
bool checked );
+32 -35
View File
@@ -708,11 +708,14 @@ void wxListLineData::ApplyAttributes(wxDC *dc,
#endif
}
void wxListLineData::Draw(wxDC *dc, bool current)
void wxListLineData::Draw(wxDC *dc, const wxPoint& origin, bool current)
{
wxCHECK_RET( !m_items.empty(), wxT("no subitems at all??") );
ApplyAttributes(dc, m_gi->m_rectHighlight, IsHighlighted(), current);
wxRect rect(m_gi->m_rectHighlight);
rect.Offset(origin);
ApplyAttributes(dc, rect, IsHighlighted(), current);
wxListItemData* const item = &m_items[0];
if (item->HasImage())
@@ -720,13 +723,14 @@ void wxListLineData::Draw(wxDC *dc, bool current)
// centre the image inside our rectangle, this looks nicer when items
// ae aligned in a row
const wxRect& rectIcon = m_gi->m_rectIcon;
m_owner->DrawImage(item->GetImage(), dc, rectIcon.x, rectIcon.y);
m_owner->DrawImage(
item->GetImage(), dc, rectIcon.x + origin.x, rectIcon.y + origin.y);
}
if (item->HasText())
{
const wxRect& rectLabel = m_gi->m_rectLabel;
wxRect rectLabel = m_gi->m_rectLabel;
rectLabel.Offset(origin);
wxDCClipper clipper(*dc, rectLabel);
dc->DrawText(item->GetText(), rectLabel.x, rectLabel.y);
@@ -735,7 +739,6 @@ void wxListLineData::Draw(wxDC *dc, bool current)
void wxListLineData::DrawInReportMode( wxDC *dc,
const wxRect& rect,
const wxRect& rectHL,
bool highlighted,
bool current,
bool checked )
@@ -746,7 +749,7 @@ void wxListLineData::DrawInReportMode( wxDC *dc,
// Note: GetSubItemRect() needs to be modified if the layout here changes.
ApplyAttributes(dc, rectHL, highlighted, current);
ApplyAttributes(dc, rect, highlighted, current);
wxCoord x = rect.x;
wxCoord yMid = rect.y + rect.height/2;
@@ -2048,10 +2051,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
return;
}
GetListCtrl()->PrepareDC( dc );
int dev_x, dev_y;
GetListCtrl()->CalcScrolledPosition( 0, 0, &dev_x, &dev_y );
const wxPoint origin(GetListCtrl()->CalcScrolledPosition(wxPoint(0, 0)));
if ( InReportView() )
{
@@ -2075,10 +2075,6 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
visibleEnd = visibleTo;
}
wxRect rectLine;
int xOrig = dc.LogicalToDeviceX( 0 );
int yOrig = dc.LogicalToDeviceY( 0 );
// tell the caller cache to cache the data
if ( IsVirtual() )
{
@@ -2091,13 +2087,14 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
GetParent()->GetEventHandler()->ProcessEvent( evCache );
}
for ( size_t line = visibleFrom; line <= visibleEnd; line++ )
wxRect rectLine(GetLineRect(visibleFrom));
rectLine.Offset(origin);
for (size_t line = visibleFrom;
line <= visibleEnd;
line++, rectLine.y += rectLine.height)
{
rectLine = GetLineRect(line);
if ( !IsExposed(rectLine.x + xOrig, rectLine.y + yOrig,
rectLine.width, rectLine.height) )
if ( !IsExposed(rectLine) )
{
// don't redraw unaffected lines to avoid flicker
continue;
@@ -2120,7 +2117,6 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
GetLine(line)->DrawInReportMode( &dc,
rectLine,
GetLineHighlightRect(line),
IsHighlighted(line),
line == m_current,
IsItemChecked(line) );
@@ -2133,12 +2129,13 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
size_t i = visibleFrom;
if (i == 0) i = 1; // Don't draw the first one
for ( ; i <= visibleEnd; i++ )
int y = (i - visibleFrom) * lineHeight;
for ( ; i <= visibleEnd; i++, y += lineHeight )
{
dc.SetPen(pen);
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawLine(0 - dev_x, i * lineHeight,
clientSize.x - dev_x, i * lineHeight);
dc.DrawLine(0, y, clientSize.x, y);
}
// Draw last horizontal rule
@@ -2146,8 +2143,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
{
dc.SetPen( pen );
dc.SetBrush( *wxTRANSPARENT_BRUSH );
dc.DrawLine(0 - dev_x, (m_lineTo + 1) * lineHeight,
clientSize.x - dev_x , (m_lineTo + 1) * lineHeight );
dc.DrawLine(0, y, clientSize.x, y);
}
}
@@ -2160,7 +2156,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
GetItemRect(visibleFrom, firstItemRect);
GetItemRect(visibleTo, lastItemRect);
int x = firstItemRect.GetX();
int x = rectLine.x;
dc.SetPen(pen);
dc.SetBrush(* wxTRANSPARENT_BRUSH);
@@ -2171,15 +2167,14 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
{
int colWidth = GetColumnWidth(col);
x += colWidth;
int x_pos = x - dev_x;
int x_pos = x;
if (col < GetColumnCount()-1) x_pos -= 2;
int ruleHeight = m_extendRulesAndAlternateColour && visibleEnd > visibleTo
? clientHeight
: lastItemRect.GetBottom() + 1 - dev_y;
: lastItemRect.GetBottom() + 1;
dc.DrawLine(x_pos, firstItemRect.GetY() - 1 - dev_y,
x_pos, ruleHeight);
dc.DrawLine(x_pos, firstItemRect.GetY() - 1, x_pos, ruleHeight);
}
}
}
@@ -2188,7 +2183,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
size_t count = GetItemCount();
for ( size_t i = 0; i < count; i++ )
{
GetLine(i)->Draw( &dc, i == m_current );
GetLine(i)->Draw( &dc, origin, i == m_current );
}
}
@@ -2202,8 +2197,10 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
if ( IsHighlighted(m_current) )
flags |= wxCONTROL_SELECTED;
wxRendererNative::Get().
DrawFocusRect(this, dc, GetLineHighlightRect(m_current), flags);
wxRect rect(GetLineHighlightRect(m_current));
rect.Offset(origin);
wxRendererNative::Get().DrawFocusRect(this, dc, rect, flags);
}
#endif // !__WXMAC__
}