Environment
Description
When several wxPanel children containing a wxDataViewListCtrl are placed inside a wxScrolledWindow, and these panels are moved with the mouse (dragging), the content of the wxDataViewListCtrl starts to flicker and redraw badly.
The flicker appears:
The background drawing in the wxScrolledWindow (lines from (0,0) to each child position) is stable enough; the problem is the internal repaint of wxDataViewListCtrl when its parent is moved.
With wxWidgets 3.3.1, everything works correctly (no flicker).
With wxWidgets 3.3.3, flicker appears when moving children inside a wxScrolledWindow.
Steps to reproduce
Expected behaviour
Actual behaviour
Minimal sample code
`// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef BORLANDC
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/dataview.h"
#define ID_DATASOURCE 10000
#define ID_PANEL 10001
// Class datasource declaration
class datasource: public wxPanel
{
DECLARE_DYNAMIC_CLASS( datasource )
public:
/// Constructors
datasource();
datasource( wxWindow* parent, wxWindowID id = ID_DATASOURCE, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL );
/// Creation
bool Create( wxWindow* parent, wxWindowID id = ID_DATASOURCE, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL );
/// Destructor
~datasource() {}
void CreateControls();
void OnDragStart(wxMouseEvent& event);
void OnDragMove(wxMouseEvent& event);
void OnDragEnd(wxMouseEvent& event);
void OnMouseCaptureLost(wxMouseCaptureLostEvent& event);
protected:
bool m_Dragging;
wxPoint m_DragStart;
};
#define ID_MAINFRAME 10000
#define ID_PANEL 10001
#define ID_ADDCHILD 10003
#define FRAME_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX
// Class MainFrame declaration
class MainFrame: public wxFrame
{
DECLARE_CLASS( MainFrame )
DECLARE_EVENT_TABLE()
public:
/// Constructors
MainFrame( wxWindow* parent, wxWindowID id = ID_MAINFRAME, const wxString& caption = _("MainFrame"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = FRAME_STYLE );
bool Create( wxWindow* parent, wxWindowID id = ID_MAINFRAME, const wxString& caption = _("MainFrame"), const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = FRAME_STYLE );
/// Destructor
~MainFrame() {}
/// Creates the controls and sizers
void CreateControls();
/// wxEVT_COMMAND_MENU_SELECTED event handler for ID_ADDCHILD
void OnAddchildClick( wxCommandEvent& event );
/// wxEVT_COMMAND_MENU_SELECTED event handler for wxID_EXIT
void OnExitClick( wxCommandEvent& event );
/// wxEVT_SIZE event handler for ID_PANEL
void OnSize( wxSizeEvent& event );
/// wxEVT_PAINT event handler for ID_PANEL
void OnPaint( wxPaintEvent& event );
protected:
wxScrolledWindow* m_Canvas;
wxInt32 m_Child_X;
wxInt32 m_Child_Y;
};
// Class Project1App declaration
class Project1App: public wxApp
{
DECLARE_CLASS( Project1App )
public:
/// Constructor
Project1App() {}
/// Initialises the application
virtual bool OnInit();
/// Called on exit
virtual int OnExit();
};
// Class Project1App implementation
IMPLEMENT_APP( Project1App )
IMPLEMENT_CLASS( Project1App, wxApp )
bool Project1App::OnInit()
{
MainFrame* mainWindow = new MainFrame( NULL );
mainWindow->Show(true);
return true;
}
int Project1App::OnExit()
{
return wxApp::OnExit();
}
// Class datasource implementation
IMPLEMENT_DYNAMIC_CLASS( datasource, wxPanel )
datasource::datasource()
{
m_Dragging = false;
}
datasource::datasource( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
{
m_Dragging = false;
Create(parent, id, pos, size, style);
}
bool datasource::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
{
SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
wxPanel::Create( parent, id, pos, size, style );
SetBackgroundColour(*wxLIGHT_GREY);
CreateControls();
return true;
}
void datasource::CreateControls()
{
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
SetSizer(itemBoxSizer2);
wxPanel* itemPanel2 = new wxPanel( this, ID_PANEL, wxDefaultPosition, wxSize(-1, 20), wxNO_BORDER|wxTAB_TRAVERSAL );
itemPanel2->SetBackgroundColour(*wxRED);
itemPanel2->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
itemBoxSizer2->Add(itemPanel2, 0, wxGROW|wxALL, 5);
wxDataViewListCtrl* itemWindow3 = new wxDataViewListCtrl( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxSIMPLE_BORDER );
itemBoxSizer2->Add(itemWindow3, 1, wxGROW|wxLEFT|wxRIGHT|wxBOTTOM, 5);
itemWindow3->AppendToggleColumn(wxEmptyString, wxDATAVIEW_CELL_ACTIVATABLE, 24, wxALIGN_CENTER);
itemWindow3->AppendIconTextColumn("Link/Field", wxDATAVIEW_CELL_INERT, 83, wxALIGN_LEFT);
itemWindow3->AppendTextColumn("Type", wxDATAVIEW_CELL_INERT, 76, wxALIGN_RIGHT);
itemWindow3->AppendTextColumn("Linked", wxDATAVIEW_CELL_INERT, 0, wxALIGN_LEFT, wxDATAVIEW_COL_HIDDEN);
wxVector<wxVariant> l_itemData;
wxDataViewIconText l_iconText("Field1");
l_itemData.push_back(wxVariant(false));
l_itemData.push_back(wxVariant(l_iconText));
l_itemData.push_back(wxVariant("TEXT"));
l_itemData.push_back(wxVariant(0));
itemWindow3->AppendItem(l_itemData);
l_itemData.clear();
l_iconText.SetText("Field2");
l_itemData.push_back(wxVariant(false));
l_itemData.push_back(wxVariant(l_iconText));
l_itemData.push_back(wxVariant("INTEGER"));
l_itemData.push_back(wxVariant(0));
itemWindow3->AppendItem(l_itemData);
itemPanel2->Bind(wxEVT_LEFT_DOWN, &datasource::OnDragStart, this);
Bind(wxEVT_LEFT_UP, &datasource::OnDragEnd, this);
Bind(wxEVT_MOTION, &datasource::OnDragMove, this);
Bind(wxEVT_MOUSE_CAPTURE_LOST, &datasource::OnMouseCaptureLost, this);
}
void datasource::OnDragStart(wxMouseEvent& event)
{
m_Dragging = true;
m_DragStart = event.GetPosition();
CaptureMouse();
}
void datasource::OnDragMove(wxMouseEvent& event)
{
if (!m_Dragging)
return;
wxPoint pos = GetPosition();
wxPoint delta = event.GetPosition() - m_DragStart;
Move(pos + delta);
if (GetParent())
GetParent()->Refresh();
}
void datasource::OnDragEnd(wxMouseEvent& event)
{
if (m_Dragging)
{
m_Dragging = false;
if (HasCapture())
ReleaseMouse();
}
}
void datasource::OnMouseCaptureLost(wxMouseCaptureLostEvent& event)
{
if (m_Dragging)
{
m_Dragging = false;
ReleaseMouse();
}
}
// Class MainFrame implementation
IMPLEMENT_CLASS( MainFrame, wxFrame )
BEGIN_EVENT_TABLE( MainFrame, wxFrame )
EVT_MENU( ID_ADDCHILD, MainFrame::OnAddchildClick )
EVT_MENU( wxID_EXIT, MainFrame::OnExitClick )
END_EVENT_TABLE()
MainFrame::MainFrame( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
m_Child_X = m_Child_Y = 0;
Create( parent, id, caption, pos, size, style );
}
bool MainFrame::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
wxFrame::Create( parent, id, caption, pos, size, style );
CreateControls();
return true;
}
void MainFrame::CreateControls()
{
wxMenuBar* menuBar = new wxMenuBar;
wxMenu* itemMenu3 = new wxMenu;
itemMenu3->Append(ID_ADDCHILD, _("Add Child"), wxEmptyString, wxITEM_NORMAL);
itemMenu3->Append(wxID_EXIT, _("E&xit\tAlt+F4"), wxEmptyString, wxITEM_NORMAL);
menuBar->Append(itemMenu3, _("Test"));
SetMenuBar(menuBar);
wxBoxSizer* itemBoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
SetSizer(itemBoxSizer1);
m_Canvas = new wxScrolledWindow( this, ID_PANEL, wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxHSCROLL|wxVSCROLL );
itemBoxSizer1->Add(m_Canvas, 1, wxGROW, 0);
m_Canvas->SetScrollbars(1, 1, 0, 0);
m_Canvas->SetBackgroundStyle(wxBG_STYLE_PAINT);
// Connect events and objects
m_Canvas->Connect(ID_PANEL, wxEVT_SIZE, wxSizeEventHandler(MainFrame::OnSize), NULL, this);
m_Canvas->Connect(ID_PANEL, wxEVT_PAINT, wxPaintEventHandler(MainFrame::OnPaint), NULL, this);
}
void MainFrame::OnAddchildClick( wxCommandEvent& event )
{
m_Child_X += 10;
m_Child_Y += 10;
datasource* l_Dts = new datasource( m_Canvas, wxID_ANY, wxPoint(m_Child_X, m_Child_Y));
l_Dts->Show();
l_Dts->SetSize(wxSize(200, 180));
}
void MainFrame::OnExitClick( wxCommandEvent& event )
{
Close();
}
void MainFrame::OnSize( wxSizeEvent& event )
{
Refresh();
event.Skip();
}
void MainFrame::OnPaint( wxPaintEvent& event )
{
wxPaintDC l_Dc(wxDynamicCast(event.GetEventObject(), wxWindow));
wxSize l_Size = m_Canvas->GetClientSize();
l_Dc.SetBackground(GetBackgroundColour());
l_Dc.Clear();
l_Dc.SetPen(wxPen(*wxRED, 3));
l_Dc.DrawLine(0, 0, l_Size.x, l_Size.y);
l_Dc.DrawLine(l_Size.x, 0, 0, l_Size.y);
for ( wxWindowList::const_iterator l_Idx = m_Canvas->GetChildren().begin(); l_Idx != m_Canvas->GetChildren().end(); ++l_Idx )
{
datasource* l_Dts = wxDynamicCast(*l_Idx, datasource);
if ( l_Dts )
{
wxPoint l_Pos = l_Dts->GetPosition();
l_Dc.DrawLine(0, 0, l_Pos.x, l_Pos.y);
}
}
}
`
Sorry for this long code but attach file failed each times I try.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
The code is mangled, I could fix this but there is really too much of it. Can you please try to reproduce the problem in the dataview sample with the smallest possible patch to it (please see our bug reporting guidelines)? It already has a wxDataViewListCtrl.
Also, I suspect this is related to turning off compositing in 3.3.3, in which case it's a reversal to 3.2 behaviour and not a "real" regression, but please let me know if it's worse than in 3.2 too.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
mainframe.zip
The complete code is in the zip archive.
I will try this weekend to build a smaller sample based on dataview sample.
I will also try with the version 3.2.11.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
I've recompile my test file with Visual Studio 2022 (vc++ 14) using 3.2.11 binaries files provided on Github.
Same problem.
To resume:
v3.2.11 => KO flickering
v3.3.1 => OK
v3.3.3 => KO flickering
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
This seems to confirm that the absence of flicker in 3.3.1 was due to the use of compositing there. This had to be reverted due to many other problems with, unfortunately.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
This seems to confirm that the absence of flicker in 3.3.1 was due to the use of compositing there. This had to be reverted due to many other problems with, unfortunately.
Does that mean no solution will be found, or is another solution needed, like the one in version 3.3.1, but without the disadvantages?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()
Another (and completely different) solution would need to be found, probably specific to wxDVC.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.![]()