Skip to content

Commit

Permalink
Work around wxListCtrl repainting problems with WS_EX_COMPOSITED
Browse files Browse the repository at this point in the history
It seems that simply creating wxPaintDC, i.e. calling BeginPaint(),
ourselves and then letting the native control draw into it, disables
whichever optimizations are used by the control that break its drawing
with WS_EX_COMPOSITED, so always do this in our OnPaint(), even if we
don't need to draw anything ourselves.

This allows to avoid disabling WS_EX_COMPOSITED when wxListCtrl is used,
which resulted in horrible flicker before.

See wxWidgets#23585.
  • Loading branch information
vadz committed Jun 4, 2023
1 parent 9710592 commit 15e4f5b
Showing 1 changed file with 8 additions and 21 deletions.
29 changes: 8 additions & 21 deletions src/msw/listctrl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,6 @@ bool wxListCtrl::Create(wxWindow *parent,
if ( !MSWCreateControl(WC_LISTVIEW, wxEmptyString, pos, size) )
return false;

// LISTVIEW doesn't redraw correctly when WS_EX_COMPOSITED is used by
// either the control itself (which never happens now, see our overridden
// SetDoubleBuffered()) or even by any of its parents, so we must reset
// this style for them.
MSWDisableComposited();

const wxVisualAttributes& defAttrs = GetDefaultAttributes();

if ( wxMSWDarkMode::IsActive() )
Expand Down Expand Up @@ -373,14 +367,7 @@ void wxListCtrl::MSWInitHeader()

void wxListCtrl::MSWAfterReparent()
{
// We did it for the original parent in our Create(), but we need to do it
// here for the new one.
MSWDisableComposited();

// Ideally we'd re-enable WS_EX_COMPOSITED for the old parent, but this is
// difficult to do correctly, as we'd need to track the number of list
// controls under it instead of just turning it on/off, so for now we don't
// do it.
// This is not used any more, to be removed.
}

WXDWORD wxListCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
Expand Down Expand Up @@ -3355,7 +3342,10 @@ WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam)
return CDRF_DODEFAULT;
}

// Necessary for drawing hrules and vrules, if specified
// We need to draw the control ourselves to make it work with WS_EX_COMPOSITED:
// by default, it's not redrawn correctly, apparently due to some optimizations
// used internally, but creating wxPaintDC ourselves seems to be sufficient to
// avoid them, so we do it even if we don't draw anything on it ourselves.
void wxListCtrl::OnPaint(wxPaintEvent& event)
{
const int itemCount = GetItemCount();
Expand All @@ -3376,16 +3366,13 @@ void wxListCtrl::OnPaint(wxPaintEvent& event)
needToErase = true;
}

if ( !(needToDraw || needToErase) )
{
event.Skip();
return;
}

wxPaintDC dc(this);

wxListCtrlBase::OnPaint(event);

if ( !needToDraw && !needToErase )
return;

// Reset the device origin since it may have been set
dc.SetDeviceOrigin(0, 0);

Expand Down

0 comments on commit 15e4f5b

Please sign in to comment.