From 8fcf46f65c6a6bd9c4da303a464ddcea95323d3a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Mon, 10 Feb 2020 14:08:53 +0100 Subject: [PATCH] Forbid creation of wxPaintEvent objects from user code This doesn't work anyhow, so it's better to prevent the code doing this from compiling instead of getting run-time asserts or worse. Also simplify construction of these events inside wxWidgets by passing the window itself to the ctor instead of passing just its ID and calling SetEventObject() separately later. For consistency, do the same thing for wxNcPaintEvent too. --- docs/changes.txt | 4 ++++ include/wx/event.h | 19 ++++++++++++------- interface/wx/event.h | 2 +- src/common/event.cpp | 16 ++++++++++++++++ src/dfb/window.cpp | 6 ++---- src/gtk/window.cpp | 6 ++---- src/gtk1/glcanvas.cpp | 6 ++---- src/gtk1/window.cpp | 6 ++---- src/motif/window.cpp | 3 +-- src/msw/window.cpp | 6 ++---- src/osx/window_osx.cpp | 6 ++---- src/qt/glcanvas.cpp | 2 +- src/qt/window.cpp | 3 +-- src/univ/topluniv.cpp | 3 +-- src/x11/window.cpp | 6 ++---- tests/events/evthandler.cpp | 11 +++++++++++ tests/test.bkl | 6 +++--- 17 files changed, 65 insertions(+), 46 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 63a155fcbc..8925b02258 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -103,6 +103,10 @@ Changes in behaviour which may result in build errors then you will need to add these libraries to your make or project files yourself. +- wxPaintEvent objects can no longer be created by the application code. This + was never supposed to work and is now forbidden at compile-time instead of + resulting in errors during run-time. + - WXWIN_OS_DESCRIPTION doesn't exist any longer, use wxGetOsDescription(). - Never documented and not always available private wxGetClipboardData() diff --git a/include/wx/event.h b/include/wx/event.h index 293211aae3..39ca40725d 100644 --- a/include/wx/event.h +++ b/include/wx/event.h @@ -2337,12 +2337,14 @@ private: class WXDLLIMPEXP_CORE wxPaintEvent : public wxEvent { + // This ctor is only intended to be used by wxWidgets itself, so it's + // intentionally declared as private when not building the library itself. +#ifdef WXBUILDING public: - wxPaintEvent(int Id = 0) - : wxEvent(Id, wxEVT_PAINT) - { - } +#endif // WXBUILDING + explicit wxPaintEvent(wxWindowBase* window = NULL); +public: // default copy ctor and dtor are fine virtual wxEvent *Clone() const wxOVERRIDE { return new wxPaintEvent(*this); } @@ -2353,11 +2355,14 @@ private: class WXDLLIMPEXP_CORE wxNcPaintEvent : public wxEvent { + // This ctor is only intended to be used by wxWidgets itself, so it's + // intentionally declared as private when not building the library itself. +#ifdef WXBUILDING public: - wxNcPaintEvent(int winid = 0) - : wxEvent(winid, wxEVT_NC_PAINT) - { } +#endif // WXBUILDING + explicit wxNcPaintEvent(wxWindowBase* window = NULL); +public: virtual wxEvent *Clone() const wxOVERRIDE { return new wxNcPaintEvent(*this); } private: diff --git a/interface/wx/event.h b/interface/wx/event.h index 35b97325df..7f9c0e9d66 100644 --- a/interface/wx/event.h +++ b/interface/wx/event.h @@ -2222,7 +2222,7 @@ public: need a window to be repainted, use wxWindow::Refresh() instead of trying to manually create an event of this class. */ - wxPaintEvent(int id = 0); + explicit wxPaintEvent(wxWindow* window); }; diff --git a/src/common/event.cpp b/src/common/event.cpp index e453b9694e..2d7b822c38 100644 --- a/src/common/event.cpp +++ b/src/common/event.cpp @@ -458,6 +458,22 @@ wxString wxCommandEvent::GetString() const return m_cmdString; } +// ---------------------------------------------------------------------------- +// wxPaintEvent and wxNcPaintEvent +// ---------------------------------------------------------------------------- + +wxPaintEvent::wxPaintEvent(wxWindowBase* window) + : wxEvent(window ? window->GetId() : 0, wxEVT_PAINT) +{ + SetEventObject(window); +} + +wxNcPaintEvent::wxNcPaintEvent(wxWindowBase* window) + : wxEvent(window ? window->GetId() : 0, wxEVT_NC_PAINT) +{ + SetEventObject(window); +} + // ---------------------------------------------------------------------------- // wxUpdateUIEvent // ---------------------------------------------------------------------------- diff --git a/src/dfb/window.cpp b/src/dfb/window.cpp index 888cf7491f..dd6a310f09 100644 --- a/src/dfb/window.cpp +++ b/src/dfb/window.cpp @@ -684,8 +684,7 @@ void wxWindowDFB::PaintWindow(const wxRect& rect) // only send wxNcPaintEvent if drawing at least part of nonclient area: if ( !clientRect.Contains(rect) ) { - wxNcPaintEvent eventNc(GetId()); - eventNc.SetEventObject(this); + wxNcPaintEvent eventNc(this); HandleWindowEvent(eventNc); } else @@ -697,8 +696,7 @@ void wxWindowDFB::PaintWindow(const wxRect& rect) // only send wxPaintEvent if drawing at least part of client area: if ( rect.Intersects(clientRect) ) { - wxPaintEvent eventPt(GetId()); - eventPt.SetEventObject(this); + wxPaintEvent eventPt(this); HandleWindowEvent(eventPt); } else diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index c85fe9fbb1..c00031bbb5 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -5205,12 +5205,10 @@ void wxWindowGTK::GTKSendPaintEvents(const GdkRegion* region) wxFAIL_MSG( "unsupported background style" ); } - wxNcPaintEvent nc_paint_event( GetId() ); - nc_paint_event.SetEventObject( this ); + wxNcPaintEvent nc_paint_event( this ); HandleWindowEvent( nc_paint_event ); - wxPaintEvent paint_event( GetId() ); - paint_event.SetEventObject( this ); + wxPaintEvent paint_event( this ); HandleWindowEvent( paint_event ); #if wxGTK_HAS_COMPOSITING_SUPPORT diff --git a/src/gtk1/glcanvas.cpp b/src/gtk1/glcanvas.cpp index b75b3766d8..17ab11450f 100644 --- a/src/gtk1/glcanvas.cpp +++ b/src/gtk1/glcanvas.cpp @@ -65,8 +65,7 @@ extern "C" { static gint gtk_glwindow_map_callback( GtkWidget * WXUNUSED(widget), wxGLCanvas *win ) { - wxPaintEvent event( win->GetId() ); - event.SetEventObject( win ); + wxPaintEvent event( win ); win->HandleWindowEvent( event ); win->GetUpdateRegion().Clear(); @@ -302,8 +301,7 @@ void wxGLCanvas::OnInternalIdle() { if (!m_updateRegion.IsEmpty()) { - wxPaintEvent event( GetId() ); - event.SetEventObject( this ); + wxPaintEvent event( this ); HandleWindowEvent( event ); GetUpdateRegion().Clear(); diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index 98224b25fb..55a266b9f5 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -3599,12 +3599,10 @@ void wxWindowGTK::GtkSendPaintEvents() m_clearRegion.Clear(); } - wxNcPaintEvent nc_paint_event( GetId() ); - nc_paint_event.SetEventObject( this ); + wxNcPaintEvent nc_paint_event( this ); HandleWindowEvent( nc_paint_event ); - wxPaintEvent paint_event( GetId() ); - paint_event.SetEventObject( this ); + wxPaintEvent paint_event( this ); HandleWindowEvent( paint_event ); m_clipPaintRegion = false; diff --git a/src/motif/window.cpp b/src/motif/window.cpp index a3bb7b274f..023770f093 100644 --- a/src/motif/window.cpp +++ b/src/motif/window.cpp @@ -1621,8 +1621,7 @@ void wxWindow::DoPaint() eraseEvent.SetEventObject(this); HandleWindowEvent(eraseEvent); - wxPaintEvent event(GetId()); - event.SetEventObject(this); + wxPaintEvent event(this); HandleWindowEvent(event); m_needsRefresh = false; diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 0d06fcf9a5..2572ec0efc 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -5260,8 +5260,7 @@ bool wxWindowMSW::HandlePaint() paintStack.push(PaintData(this)); - wxPaintEvent event(m_windowId); - event.SetEventObject(this); + wxPaintEvent event(this); bool processed = HandleWindowEvent(event); @@ -5280,8 +5279,7 @@ bool wxWindowMSW::HandlePaint() // note that we must generate NC event after the normal one as otherwise // BeginPaint() will happily overwrite our decorations with the background // colour - wxNcPaintEvent eventNc(m_windowId); - eventNc.SetEventObject(this); + wxNcPaintEvent eventNc(this); HandleWindowEvent(eventNc); // don't keep an HRGN we don't need any longer (GetUpdateRegion() can only diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index 4eaa5a907c..1e58f4c1ab 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -1989,9 +1989,8 @@ bool wxWindowMac::MacDoRedraw( long time ) { // paint the window itself - wxPaintEvent event(GetId()); + wxPaintEvent event(this); event.SetTimestamp(time); - event.SetEventObject(this); handled = HandleWindowEvent(event); } @@ -2040,8 +2039,7 @@ void wxWindowMac::MacPaintChildrenBorders() if ( m_updateRegion.Contains(clientOrigin.x+x-10, clientOrigin.y+y-10, w+20, h+20) ) { // paint custom borders - wxNcPaintEvent eventNc( child->GetId() ); - eventNc.SetEventObject( child ); + wxNcPaintEvent eventNc( child ); if ( !child->HandleWindowEvent( eventNc ) ) { child->MacPaintBorders(0, 0) ; diff --git a/src/qt/glcanvas.cpp b/src/qt/glcanvas.cpp index 60be7159f9..f89645c014 100644 --- a/src/qt/glcanvas.cpp +++ b/src/qt/glcanvas.cpp @@ -62,7 +62,7 @@ void wxQtGLWidget::resizeGL(int w, int h) void wxQtGLWidget::paintGL() { - wxPaintEvent event( GetHandler()->GetId() ); + wxPaintEvent event( GetHandler() ); EmitEvent(event); } diff --git a/src/qt/window.cpp b/src/qt/window.cpp index 5e1ac194ef..e2ac004a2b 100644 --- a/src/qt/window.cpp +++ b/src/qt/window.cpp @@ -1281,8 +1281,7 @@ bool wxWindowQt::QtHandlePaintEvent ( QWidget *handler, QPaintEvent *event ) } // send the paint event (wxWindowDC will draw directly): - wxPaintEvent paint( GetId() ); - paint.SetEventObject(this); + wxPaintEvent paint( this ); handled = ProcessWindowEvent(paint); m_updateRegion.Clear(); } diff --git a/src/univ/topluniv.cpp b/src/univ/topluniv.cpp index 312ce6a912..460f465892 100644 --- a/src/univ/topluniv.cpp +++ b/src/univ/topluniv.cpp @@ -216,8 +216,7 @@ long wxTopLevelWindow::GetDecorationsStyle() const void wxTopLevelWindow::RefreshTitleBar() { - wxNcPaintEvent event(GetId()); - event.SetEventObject(this); + wxNcPaintEvent event(this); GetEventHandler()->ProcessEvent(event); } diff --git a/src/x11/window.cpp b/src/x11/window.cpp index 373151892a..ddcd303511 100644 --- a/src/x11/window.cpp +++ b/src/x11/window.cpp @@ -1282,8 +1282,7 @@ void wxWindowX11::SendPaintEvents() m_clipPaintRegion = true; - wxPaintEvent paint_event( GetId() ); - paint_event.SetEventObject( this ); + wxPaintEvent paint_event( this ); HandleWindowEvent( paint_event ); m_updateRegion.Clear(); @@ -1324,8 +1323,7 @@ void wxWindowX11::SendNcPaintEvents() } } - wxNcPaintEvent nc_paint_event( GetId() ); - nc_paint_event.SetEventObject( this ); + wxNcPaintEvent nc_paint_event( this ); HandleWindowEvent( nc_paint_event ); m_updateNcArea = false; diff --git a/tests/events/evthandler.cpp b/tests/events/evthandler.cpp index a2ef903dbb..6be6c2d1ec 100644 --- a/tests/events/evthandler.cpp +++ b/tests/events/evthandler.cpp @@ -534,3 +534,14 @@ public: void OnIdle(wxIdleEvent&) { } }; #endif // C++11 + +// Another compilation-time-only test, but this one checking that these event +// objects can't be created from outside of the library. +#ifdef TEST_INVALID_EVENT_CREATION + +void TestEventCreation() +{ + wxPaintEvent eventPaint; +} + +#endif // TEST_INVALID_EVENT_CREATION diff --git a/tests/test.bkl b/tests/test.bkl index 70326b8dce..00f0c0b013 100644 --- a/tests/test.bkl +++ b/tests/test.bkl @@ -365,9 +365,9 @@ failtest_combobox: failtest_evthandler: @$(RM) test_evthandler.o - @for d in GLOBAL STATIC METHOD FUNCTOR NO_HANDLER DERIVED WRONG_CLASS; do \ - if $(MAKE) CXXWARNINGS=-DTEST_INVALID_BIND_$$d test_evthandler.o 2>/dev/null; then \ - echo "*** Compilation with TEST_INVALID_BIND_$$d unexpectedly succeeded.">&2; \ + @for d in BIND_GLOBAL BIND_STATIC BIND_METHOD BIND_FUNCTOR BIND_NO_HANDLER BIND_DERIVED BIND_WRONG_CLASS EVENT_CREATION; do \ + if $(MAKE) CXXWARNINGS=-DTEST_INVALID_$$d test_evthandler.o 2>/dev/null; then \ + echo "*** Compilation with TEST_INVALID_$$d unexpectedly succeeded.">&2; \ exit 1; \ fi; \ done; \