From 487018f42e9c61069ed55217c5f935b427d7770b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 17:55:42 +0000 Subject: [PATCH 01/10] Handle mouse capture loss gracefully in the drawing sample Reset the selection and avoid the assert which happened when the capture was lost unexpectedly (e.g. due to switching to another window using some key combination without releasing the mouse). --- samples/drawing/drawing.cpp | 40 ++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index 37a7b4585b..2bb122ffd2 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -107,6 +107,7 @@ public: void OnMouseMove(wxMouseEvent &event); void OnMouseDown(wxMouseEvent &event); void OnMouseUp(wxMouseEvent &event); + void OnMouseCaptureLost(wxMouseCaptureLostEvent &event); void ToShow(int show) { m_show = show; Refresh(); } int GetPage() { return m_show; } @@ -160,6 +161,10 @@ protected: void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime); + // Remove the rubber band if it's currently shown and return true or just + // return false if we're not showing it. + bool StopRubberBanding(); + private: MyFrame *m_owner; @@ -503,6 +508,7 @@ wxBEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow) EVT_MOTION (MyCanvas::OnMouseMove) EVT_LEFT_DOWN (MyCanvas::OnMouseDown) EVT_LEFT_UP (MyCanvas::OnMouseUp) + EVT_MOUSE_CAPTURE_LOST (MyCanvas::OnMouseCaptureLost) wxEND_EVENT_TABLE() #include "smile.xpm" @@ -2097,19 +2103,28 @@ void MyCanvas::OnMouseDown(wxMouseEvent &event) CaptureMouse() ; } +bool MyCanvas::StopRubberBanding() +{ + if ( !m_rubberBand ) + return false; + + { + wxClientDC dc( this ); + PrepareDC( dc ); + wxDCOverlay overlaydc( m_overlay, &dc ); + overlaydc.Clear(); + } + m_overlay.Reset(); + m_rubberBand = false; + + return true; +} + void MyCanvas::OnMouseUp(wxMouseEvent &event) { - if ( m_rubberBand ) + if ( StopRubberBanding() ) { ReleaseMouse(); - { - wxClientDC dc( this ); - PrepareDC( dc ); - wxDCOverlay overlaydc( m_overlay, &dc ); - overlaydc.Clear(); - } - m_overlay.Reset(); - m_rubberBand = false; wxPoint endpoint = CalcUnscrolledPosition(event.GetPosition()); @@ -2123,6 +2138,13 @@ void MyCanvas::OnMouseUp(wxMouseEvent &event) } } +void MyCanvas::OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) +{ + StopRubberBanding(); + + wxLogStatus(m_owner, "Mouse capture lost"); +} + #if wxUSE_GRAPHICS_CONTEXT void MyCanvas::UseGraphicRenderer(wxGraphicsRenderer* renderer) { From 91031bcfeec01391de000bcf3375e4a8af45c172 Mon Sep 17 00:00:00 2001 From: AliKet Date: Tue, 20 Dec 2022 12:44:20 +0100 Subject: [PATCH 02/10] Add native wxOverlay implementation for wxMSW Using generic implementation doesn't work any longer since the switch to using composited windows (i.e. turning on WS_EX_COMPOSITED) by default as drawing using wxClientDC has no effect. So implement wxOverlay in a different way by using a layered window covering the original window and drawing on it instead. This is similar to Cocoa implementation of wxOverlay. Closes #23047. --- Makefile.in | 36 +++-- build/bakefiles/files.bkl | 1 + build/cmake/files.cmake | 1 + build/files | 1 + build/msw/makefile.gcc | 28 ++++ build/msw/makefile.vc | 28 ++++ build/msw/wx_core.vcxproj | 1 + build/msw/wx_core.vcxproj.filters | 3 + include/wx/private/overlay.h | 2 + src/msw/overlay.cpp | 228 ++++++++++++++++++++++++++++++ 10 files changed, 321 insertions(+), 8 deletions(-) create mode 100644 src/msw/overlay.cpp diff --git a/Makefile.in b/Makefile.in index 2359e53008..fa24e8b1cd 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4976,7 +4976,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS = \ monodll_uuid.o \ monodll_msw_evtloop.o \ monodll_access.o \ - monodll_msw_bmpbndl.o + monodll_msw_bmpbndl.o \ + monodll_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS) @@ -5704,7 +5705,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_1 = \ monodll_uuid.o \ monodll_msw_evtloop.o \ monodll_access.o \ - monodll_msw_bmpbndl.o + monodll_msw_bmpbndl.o \ + monodll_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_1 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_1) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_1 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS) @@ -6732,7 +6734,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_2 = \ monolib_uuid.o \ monolib_msw_evtloop.o \ monolib_access.o \ - monolib_msw_bmpbndl.o + monolib_msw_bmpbndl.o \ + monolib_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_2 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_2) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_2 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS_17) @@ -7460,7 +7463,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_3 = \ monolib_uuid.o \ monolib_msw_evtloop.o \ monolib_access.o \ - monolib_msw_bmpbndl.o + monolib_msw_bmpbndl.o \ + monolib_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_3 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_3) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_3 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS_17) @@ -8642,7 +8646,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_4 = \ coredll_uuid.o \ coredll_msw_evtloop.o \ coredll_access.o \ - coredll_msw_bmpbndl.o + coredll_msw_bmpbndl.o \ + coredll_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_4 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_4) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_4 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS_1_1) @@ -9370,7 +9375,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_5 = \ coredll_uuid.o \ coredll_msw_evtloop.o \ coredll_access.o \ - coredll_msw_bmpbndl.o + coredll_msw_bmpbndl.o \ + coredll_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_5 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_5) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_5 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS_1_1) @@ -10128,7 +10134,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_6 = \ corelib_uuid.o \ corelib_msw_evtloop.o \ corelib_access.o \ - corelib_msw_bmpbndl.o + corelib_msw_bmpbndl.o \ + corelib_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_6 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_6) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_6 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS_1_4) @@ -10856,7 +10863,8 @@ COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_7 = \ corelib_uuid.o \ corelib_msw_evtloop.o \ corelib_access.o \ - corelib_msw_bmpbndl.o + corelib_msw_bmpbndl.o \ + corelib_msw_overlay.o @COND_TOOLKIT_MSW@__LOWLEVEL_SRC_OBJECTS_7 = $(COND_TOOLKIT_MSW___LOWLEVEL_SRC_OBJECTS_7) @COND_TOOLKIT_OSX_COCOA@__LOWLEVEL_SRC_OBJECTS_7 = \ @COND_TOOLKIT_OSX_COCOA@ $(__OSX_LOWLEVEL_SRC_OBJECTS_1_4) @@ -17407,6 +17415,9 @@ monodll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONODLL_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@monodll_msw_bmpbndl.o: $(srcdir)/src/msw/bmpbndl.cpp $(MONODLL_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/bmpbndl.cpp +@COND_TOOLKIT_MSW_USE_GUI_1@monodll_msw_overlay.o: $(srcdir)/src/msw/overlay.cpp $(MONODLL_ODEP) +@COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/msw/overlay.cpp + @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@monodll_artmac.o: $(srcdir)/src/osx/artmac.cpp $(MONODLL_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONODLL_CXXFLAGS) $(srcdir)/src/osx/artmac.cpp @@ -22171,6 +22182,9 @@ monolib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@monolib_msw_bmpbndl.o: $(srcdir)/src/msw/bmpbndl.cpp $(MONOLIB_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/bmpbndl.cpp +@COND_TOOLKIT_MSW_USE_GUI_1@monolib_msw_overlay.o: $(srcdir)/src/msw/overlay.cpp $(MONOLIB_ODEP) +@COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/msw/overlay.cpp + @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@monolib_artmac.o: $(srcdir)/src/osx/artmac.cpp $(MONOLIB_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(MONOLIB_CXXFLAGS) $(srcdir)/src/osx/artmac.cpp @@ -27034,6 +27048,9 @@ coredll_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(COREDLL_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@coredll_msw_bmpbndl.o: $(srcdir)/src/msw/bmpbndl.cpp $(COREDLL_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/msw/bmpbndl.cpp +@COND_TOOLKIT_MSW_USE_GUI_1@coredll_msw_overlay.o: $(srcdir)/src/msw/overlay.cpp $(COREDLL_ODEP) +@COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/msw/overlay.cpp + @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@coredll_artmac.o: $(srcdir)/src/osx/artmac.cpp $(COREDLL_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(COREDLL_CXXFLAGS) $(srcdir)/src/osx/artmac.cpp @@ -30769,6 +30786,9 @@ corelib_sound_sdl.o: $(srcdir)/src/unix/sound_sdl.cpp $(CORELIB_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@corelib_msw_bmpbndl.o: $(srcdir)/src/msw/bmpbndl.cpp $(CORELIB_ODEP) @COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/msw/bmpbndl.cpp +@COND_TOOLKIT_MSW_USE_GUI_1@corelib_msw_overlay.o: $(srcdir)/src/msw/overlay.cpp $(CORELIB_ODEP) +@COND_TOOLKIT_MSW_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/msw/overlay.cpp + @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@corelib_artmac.o: $(srcdir)/src/osx/artmac.cpp $(CORELIB_ODEP) @COND_PLATFORM_MACOSX_1_TOOLKIT_OSX_COCOA_USE_GUI_1@ $(CXXC) -c -o $@ $(CORELIB_CXXFLAGS) $(srcdir)/src/osx/artmac.cpp diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index 18a596c268..073d5366bb 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -1764,6 +1764,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! src/msw/evtloop.cpp src/msw/ole/access.cpp src/msw/bmpbndl.cpp + src/msw/overlay.cpp wx/msw/nonownedwnd.h diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index 514016d530..ce67bff793 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -1640,6 +1640,7 @@ set(MSW_LOWLEVEL_SRC src/msw/evtloop.cpp src/msw/ole/access.cpp src/msw/bmpbndl.cpp + src/msw/overlay.cpp ) set(MSW_LOWLEVEL_HDR diff --git a/build/files b/build/files index 6ad7a8fc82..09b965eaa0 100644 --- a/build/files +++ b/build/files @@ -1626,6 +1626,7 @@ MSW_LOWLEVEL_SRC = src/msw/ole/oleutils.cpp src/msw/ole/safearray.cpp src/msw/ole/uuid.cpp + src/msw/overlay.cpp src/msw/palette.cpp src/msw/pen.cpp src/msw/popupwin.cpp diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index 56344ad17d..1b950ef3b5 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -1926,6 +1926,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_evtloop.o \ $(OBJS)\monodll_access.o \ $(OBJS)\monodll_msw_bmpbndl.o \ + $(OBJS)\monodll_overlay.o \ $(OBJS)\monodll_clrpickerg.o \ $(OBJS)\monodll_collpaneg.o \ $(OBJS)\monodll_filepickerg.o \ @@ -2274,6 +2275,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_evtloop.o \ $(OBJS)\monodll_access.o \ $(OBJS)\monodll_msw_bmpbndl.o \ + $(OBJS)\monodll_overlay.o \ $(OBJS)\monodll_generic_accel.o \ $(OBJS)\monodll_clrpickerg.o \ $(OBJS)\monodll_collpaneg.o \ @@ -2775,6 +2777,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_evtloop.o \ $(OBJS)\monolib_access.o \ $(OBJS)\monolib_msw_bmpbndl.o \ + $(OBJS)\monolib_overlay.o \ $(OBJS)\monolib_clrpickerg.o \ $(OBJS)\monolib_collpaneg.o \ $(OBJS)\monolib_filepickerg.o \ @@ -3123,6 +3126,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_evtloop.o \ $(OBJS)\monolib_access.o \ $(OBJS)\monolib_msw_bmpbndl.o \ + $(OBJS)\monolib_overlay.o \ $(OBJS)\monolib_generic_accel.o \ $(OBJS)\monolib_clrpickerg.o \ $(OBJS)\monolib_collpaneg.o \ @@ -3506,6 +3510,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_evtloop.o \ $(OBJS)\coredll_access.o \ $(OBJS)\coredll_msw_bmpbndl.o \ + $(OBJS)\coredll_overlay.o \ $(OBJS)\coredll_clrpickerg.o \ $(OBJS)\coredll_collpaneg.o \ $(OBJS)\coredll_filepickerg.o \ @@ -3854,6 +3859,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_evtloop.o \ $(OBJS)\coredll_access.o \ $(OBJS)\coredll_msw_bmpbndl.o \ + $(OBJS)\coredll_overlay.o \ $(OBJS)\coredll_generic_accel.o \ $(OBJS)\coredll_clrpickerg.o \ $(OBJS)\coredll_collpaneg.o \ @@ -4194,6 +4200,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_evtloop.o \ $(OBJS)\corelib_access.o \ $(OBJS)\corelib_msw_bmpbndl.o \ + $(OBJS)\corelib_overlay.o \ $(OBJS)\corelib_clrpickerg.o \ $(OBJS)\corelib_collpaneg.o \ $(OBJS)\corelib_filepickerg.o \ @@ -4542,6 +4549,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_evtloop.o \ $(OBJS)\corelib_access.o \ $(OBJS)\corelib_msw_bmpbndl.o \ + $(OBJS)\corelib_overlay.o \ $(OBJS)\corelib_generic_accel.o \ $(OBJS)\corelib_clrpickerg.o \ $(OBJS)\corelib_collpaneg.o \ @@ -8465,6 +8473,11 @@ $(OBJS)\monodll_msw_bmpbndl.o: ../../src/msw/bmpbndl.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monodll_overlay.o: ../../src/msw/overlay.cpp + $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\monodll_clrpickerg.o: ../../src/generic/clrpickerg.cpp $(CXX) -c -o $@ $(MONODLL_CXXFLAGS) $(CPPDEPS) $< @@ -11052,6 +11065,11 @@ $(OBJS)\monolib_msw_bmpbndl.o: ../../src/msw/bmpbndl.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\monolib_overlay.o: ../../src/msw/overlay.cpp + $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\monolib_clrpickerg.o: ../../src/generic/clrpickerg.cpp $(CXX) -c -o $@ $(MONOLIB_CXXFLAGS) $(CPPDEPS) $< @@ -13600,6 +13618,11 @@ $(OBJS)\coredll_msw_bmpbndl.o: ../../src/msw/bmpbndl.cpp $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\coredll_overlay.o: ../../src/msw/overlay.cpp + $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\coredll_clrpickerg.o: ../../src/generic/clrpickerg.cpp $(CXX) -c -o $@ $(COREDLL_CXXFLAGS) $(CPPDEPS) $< @@ -15353,6 +15376,11 @@ $(OBJS)\corelib_msw_bmpbndl.o: ../../src/msw/bmpbndl.cpp $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< endif +ifeq ($(USE_GUI),1) +$(OBJS)\corelib_overlay.o: ../../src/msw/overlay.cpp + $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< +endif + ifeq ($(USE_GUI),1) $(OBJS)\corelib_clrpickerg.o: ../../src/generic/clrpickerg.cpp $(CXX) -c -o $@ $(CORELIB_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index 8c5e0463df..a73ecc9829 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -2243,6 +2243,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_evtloop.obj \ $(OBJS)\monodll_access.obj \ $(OBJS)\monodll_msw_bmpbndl.obj \ + $(OBJS)\monodll_overlay.obj \ $(OBJS)\monodll_clrpickerg.obj \ $(OBJS)\monodll_collpaneg.obj \ $(OBJS)\monodll_filepickerg.obj \ @@ -2589,6 +2590,7 @@ ____CORE_SRC_FILENAMES_OBJECTS = \ $(OBJS)\monodll_evtloop.obj \ $(OBJS)\monodll_access.obj \ $(OBJS)\monodll_msw_bmpbndl.obj \ + $(OBJS)\monodll_overlay.obj \ $(OBJS)\monodll_generic_accel.obj \ $(OBJS)\monodll_clrpickerg.obj \ $(OBJS)\monodll_collpaneg.obj \ @@ -3092,6 +3094,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_evtloop.obj \ $(OBJS)\monolib_access.obj \ $(OBJS)\monolib_msw_bmpbndl.obj \ + $(OBJS)\monolib_overlay.obj \ $(OBJS)\monolib_clrpickerg.obj \ $(OBJS)\monolib_collpaneg.obj \ $(OBJS)\monolib_filepickerg.obj \ @@ -3438,6 +3441,7 @@ ____CORE_SRC_FILENAMES_1_OBJECTS = \ $(OBJS)\monolib_evtloop.obj \ $(OBJS)\monolib_access.obj \ $(OBJS)\monolib_msw_bmpbndl.obj \ + $(OBJS)\monolib_overlay.obj \ $(OBJS)\monolib_generic_accel.obj \ $(OBJS)\monolib_clrpickerg.obj \ $(OBJS)\monolib_collpaneg.obj \ @@ -3873,6 +3877,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_evtloop.obj \ $(OBJS)\coredll_access.obj \ $(OBJS)\coredll_msw_bmpbndl.obj \ + $(OBJS)\coredll_overlay.obj \ $(OBJS)\coredll_clrpickerg.obj \ $(OBJS)\coredll_collpaneg.obj \ $(OBJS)\coredll_filepickerg.obj \ @@ -4219,6 +4224,7 @@ ____CORE_SRC_FILENAMES_2_OBJECTS = \ $(OBJS)\coredll_evtloop.obj \ $(OBJS)\coredll_access.obj \ $(OBJS)\coredll_msw_bmpbndl.obj \ + $(OBJS)\coredll_overlay.obj \ $(OBJS)\coredll_generic_accel.obj \ $(OBJS)\coredll_clrpickerg.obj \ $(OBJS)\coredll_collpaneg.obj \ @@ -4559,6 +4565,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_evtloop.obj \ $(OBJS)\corelib_access.obj \ $(OBJS)\corelib_msw_bmpbndl.obj \ + $(OBJS)\corelib_overlay.obj \ $(OBJS)\corelib_clrpickerg.obj \ $(OBJS)\corelib_collpaneg.obj \ $(OBJS)\corelib_filepickerg.obj \ @@ -4905,6 +4912,7 @@ ____CORE_SRC_FILENAMES_3_OBJECTS = \ $(OBJS)\corelib_evtloop.obj \ $(OBJS)\corelib_access.obj \ $(OBJS)\corelib_msw_bmpbndl.obj \ + $(OBJS)\corelib_overlay.obj \ $(OBJS)\corelib_generic_accel.obj \ $(OBJS)\corelib_clrpickerg.obj \ $(OBJS)\corelib_collpaneg.obj \ @@ -8910,6 +8918,11 @@ $(OBJS)\monodll_msw_bmpbndl.obj: ..\..\src\msw\bmpbndl.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\bmpbndl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monodll_overlay.obj: ..\..\src\msw\overlay.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\msw\overlay.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monodll_clrpickerg.obj: ..\..\src\generic\clrpickerg.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONODLL_CXXFLAGS) ..\..\src\generic\clrpickerg.cpp @@ -11497,6 +11510,11 @@ $(OBJS)\monolib_msw_bmpbndl.obj: ..\..\src\msw\bmpbndl.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\bmpbndl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\monolib_overlay.obj: ..\..\src\msw\overlay.cpp + $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\msw\overlay.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\monolib_clrpickerg.obj: ..\..\src\generic\clrpickerg.cpp $(CXX) /c /nologo /TP /Fo$@ $(MONOLIB_CXXFLAGS) ..\..\src\generic\clrpickerg.cpp @@ -14045,6 +14063,11 @@ $(OBJS)\coredll_msw_bmpbndl.obj: ..\..\src\msw\bmpbndl.cpp $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\bmpbndl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\coredll_overlay.obj: ..\..\src\msw\overlay.cpp + $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\msw\overlay.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\coredll_clrpickerg.obj: ..\..\src\generic\clrpickerg.cpp $(CXX) /c /nologo /TP /Fo$@ $(COREDLL_CXXFLAGS) ..\..\src\generic\clrpickerg.cpp @@ -15798,6 +15821,11 @@ $(OBJS)\corelib_msw_bmpbndl.obj: ..\..\src\msw\bmpbndl.cpp $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\bmpbndl.cpp !endif +!if "$(USE_GUI)" == "1" +$(OBJS)\corelib_overlay.obj: ..\..\src\msw\overlay.cpp + $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\msw\overlay.cpp +!endif + !if "$(USE_GUI)" == "1" $(OBJS)\corelib_clrpickerg.obj: ..\..\src\generic\clrpickerg.cpp $(CXX) /c /nologo /TP /Fo$@ $(CORELIB_CXXFLAGS) ..\..\src\generic\clrpickerg.cpp diff --git a/build/msw/wx_core.vcxproj b/build/msw/wx_core.vcxproj index 98ded50540..f09fe70a84 100644 --- a/build/msw/wx_core.vcxproj +++ b/build/msw/wx_core.vcxproj @@ -1079,6 +1079,7 @@ + diff --git a/build/msw/wx_core.vcxproj.filters b/build/msw/wx_core.vcxproj.filters index dfe24b3836..361a4c9469 100644 --- a/build/msw/wx_core.vcxproj.filters +++ b/build/msw/wx_core.vcxproj.filters @@ -942,6 +942,9 @@ MSW Sources + + MSW Sources + MSW Sources diff --git a/include/wx/private/overlay.h b/include/wx/private/overlay.h index 60f272ff43..559d191802 100644 --- a/include/wx/private/overlay.h +++ b/include/wx/private/overlay.h @@ -17,6 +17,8 @@ #define wxHAS_NATIVE_OVERLAY 1 #elif defined(__WXOSX__) && wxOSX_USE_COCOA #define wxHAS_NATIVE_OVERLAY 1 +#elif defined(__WXMSW__) + #define wxHAS_NATIVE_OVERLAY 1 #elif defined(__WXGTK3__) #define wxHAS_NATIVE_OVERLAY 1 #define wxHAS_GENERIC_OVERLAY 1 diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp new file mode 100644 index 0000000000..b86b0c4a1a --- /dev/null +++ b/src/msw/overlay.cpp @@ -0,0 +1,228 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: src/msw/overlay.cpp +// Author: Ali Kettab +// Copyright: (c) 2022 Ali Kettab +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#include "wx/wxprec.h" + +#include "wx/private/overlay.h" +#include "wx/nativewin.h" +#include "wx/dcclient.h" +#include "wx/dcmemory.h" +#include "wx/msw/dc.h" +#include "wx/msw/private.h" + +namespace // anonymous +{ +class wxOverlayWindow : public wxNativeContainerWindow +{ +public: + static wxWindow* New(const wxRect& rect) + { + WNDCLASS wndclass; + wxZeroMemory(wndclass); + + wndclass.lpfnWndProc = ::DefWindowProc; + wndclass.hInstance = wxGetInstance(); + wndclass.lpszClassName = GetOverlayWindowClass(); + + if ( !::RegisterClass(&wndclass) ) + { + wxLogLastError(wxS("RegisterClass() in wxOverlayWindow::Create()")); + return nullptr; + } + + const wxPoint pos = rect.GetPosition(); + const wxSize size = rect.GetSize(); + WXDWORD exStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE; + + HWND hwnd = ::CreateWindowEx + ( + exStyle, + GetOverlayWindowClass(), + nullptr, + WS_POPUP | WS_VISIBLE, + pos.x, pos.y, + size.x, size.y, + (HWND)nullptr, + (HMENU)nullptr, + wxGetInstance(), + (LPVOID)nullptr + ); + + if ( !hwnd ) + { + wxLogLastError(wxS("CreateWindowEx() in wxOverlayWindow::Create()")); + return nullptr; + } + + if ( !::SetLayeredWindowAttributes(hwnd, 0, 128, LWA_COLORKEY|LWA_ALPHA) ) + { + wxLogLastError(wxS("SetLayeredWindowAttributes() in wxOverlayWindow::Create()")); + } + + return new wxOverlayWindow(hwnd); + } + + static const wxChar* GetOverlayWindowClass() + { + return wxS("wxOverlayWindow"); + } + + virtual bool Show(bool show) override + { + if ( !GetHandle() || !wxWindowBase::Show(show) ) + return false; + + if ( show ) + { + ::SetWindowPos(GetHandle(), nullptr, 0, 0, 0, 0, + SWP_NOSIZE | + SWP_NOMOVE | + SWP_NOREDRAW | + SWP_NOOWNERZORDER | + SWP_NOACTIVATE | + SWP_SHOWWINDOW); + } + else + { + ::ShowWindow(GetHandle(), SW_HIDE); + } + + return true; + } + + virtual bool Destroy() override + { + HWND hwnd = GetHandle(); + + if ( hwnd && !::DestroyWindow(hwnd) ) + { + wxLogLastError(wxS("DestroyWindow() in wxOverlayWindow::Destroy()")); + return false; + } + + if ( !::UnregisterClass(GetOverlayWindowClass(), wxGetInstance()) ) + { + wxLogLastError(wxS("UnregisterClass() in wxOverlayWindow::Destroy()")); + } + + return true; + } + +private: + wxOverlayWindow(HWND hwnd) : wxNativeContainerWindow(hwnd) {} + ~wxOverlayWindow() {} +}; +} // anonymous namespace + +class wxOverlayImpl : public wxOverlay::Impl +{ +public: + wxOverlayImpl() { } + ~wxOverlayImpl() { } + + virtual bool IsNative() const override { return true; } + virtual void Reset() override; + virtual bool IsOk() override; + virtual void Init(wxDC* dc, int x , int y , int width , int height) override; + virtual void BeginDrawing(wxDC* dc) override; + virtual void EndDrawing(wxDC* dc) override; + virtual void Clear(wxDC* dc) override; + +public: + // window the overlay is associated with + wxWindow* m_window = nullptr; + // the overlay window itself. doesn't have to be child of any window + // and is totally managed by this class + wxWindow* m_overlayWindow = nullptr; + + wxRect m_rect; + + // Drawing on the overlay window is achieved by hijacking the existing wxDC. + // i.e. any drawing done through wxDC should go to the offscreen bitmap m_bitmap + // which will eventually be drawn on the overlay window. + wxBitmap m_bitmap; + wxMemoryDC m_memDC; // for memory dc construction only. + WXHDC m_hdc; // the original HDC + + wxDECLARE_NO_COPY_CLASS(wxOverlayImpl); +}; + +bool wxOverlayImpl::IsOk() +{ + return m_overlayWindow != nullptr; +} + +void wxOverlayImpl::Init(wxDC* dc, int , int , int , int ) +{ + if ( IsOk() ) + return; + + m_window = dc->GetWindow(); + + m_rect.SetSize(m_window->GetClientSize()); + m_rect.SetPosition(m_window->GetScreenPosition()); + + m_bitmap.CreateWithDIPSize(m_rect.GetSize(), m_window->GetDPIScaleFactor()); + + m_overlayWindow = wxOverlayWindow::New(m_rect); +} + +void wxOverlayImpl::BeginDrawing(wxDC* dc) +{ + wxCHECK_RET( IsOk(), wxS("overlay not initialized") ); + + m_memDC.SelectObject(m_bitmap); + + auto impl = dc->GetImpl(); + auto msw_impl = static_cast(impl); + + m_hdc = GetHdcOf(*msw_impl); // save the original hdc + + msw_impl->SetHDC(GetHdcOf(m_memDC)); + msw_impl->UpdateClipBox(); +} + +void wxOverlayImpl::EndDrawing(wxDC* dc) +{ + wxCHECK_RET( IsOk(), wxS("overlay not initialized") ); + + m_memDC.SelectObject(wxNullBitmap); + + auto impl = dc->GetImpl(); + auto msw_impl = static_cast(impl); + + msw_impl->SetHDC(m_hdc); // restore the original hdc + msw_impl->UpdateClipBox(); + + wxWindowDC winDC(m_overlayWindow); + winDC.DrawBitmap(m_bitmap, wxPoint(0, 0)); +} + +void wxOverlayImpl::Clear(wxDC* WXUNUSED(dc)) +{ + wxCHECK_RET( IsOk(), wxS("overlay not initialized") ); + + // doesn't work with non double buffered m_window + // m_memDC.SetBackground(*wxTRANSPARENT_BRUSH); + + m_memDC.SetBackground(wxBrush(wxTransparentColour)); + m_memDC.Clear(); +} + +void wxOverlayImpl::Reset() +{ + if ( IsOk() ) + { + m_overlayWindow->Destroy(); + m_overlayWindow = nullptr; + } +} + +wxOverlay::Impl* wxOverlay::Create() +{ + return new wxOverlayImpl; +} From cd652cbf1c53aa0e2bf752258186173da8352cf8 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:05:09 +0000 Subject: [PATCH 03/10] Fix activation loss when creating wxOverlayWindow Don't use WS_VISIBLE when creating the window, but show it later using SWP_NOACTIVATE to prevent it from stealing the activation from the main window which would be inappropriate. --- src/msw/overlay.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index b86b0c4a1a..2f086dcc15 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -43,7 +43,7 @@ public: exStyle, GetOverlayWindowClass(), nullptr, - WS_POPUP | WS_VISIBLE, + WS_POPUP, pos.x, pos.y, size.x, size.y, (HWND)nullptr, @@ -63,7 +63,9 @@ public: wxLogLastError(wxS("SetLayeredWindowAttributes() in wxOverlayWindow::Create()")); } - return new wxOverlayWindow(hwnd); + auto overlayWin = new wxOverlayWindow(hwnd); + overlayWin->Show(true); + return overlayWin; } static const wxChar* GetOverlayWindowClass() From abcf5c94857c519058c3c26a9ae2f0f07185bc50 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:07:30 +0000 Subject: [PATCH 04/10] Minor C++11-ification of wxOverlayWindow code Use "= default" for the special member functions that can be defaulted and initialize the member variables in their declaration. No real changes. --- src/msw/overlay.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index 2f086dcc15..cc31f02f21 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -116,15 +116,15 @@ public: private: wxOverlayWindow(HWND hwnd) : wxNativeContainerWindow(hwnd) {} - ~wxOverlayWindow() {} + ~wxOverlayWindow() = default; }; } // anonymous namespace class wxOverlayImpl : public wxOverlay::Impl { public: - wxOverlayImpl() { } - ~wxOverlayImpl() { } + wxOverlayImpl() = default; + ~wxOverlayImpl() = default; virtual bool IsNative() const override { return true; } virtual void Reset() override; @@ -148,7 +148,7 @@ public: // which will eventually be drawn on the overlay window. wxBitmap m_bitmap; wxMemoryDC m_memDC; // for memory dc construction only. - WXHDC m_hdc; // the original HDC + WXHDC m_hdc = 0; // the original HDC wxDECLARE_NO_COPY_CLASS(wxOverlayImpl); }; From 2e44bc1cb3f8198908d2ad6d8753a122d7653217 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:21:29 +0000 Subject: [PATCH 05/10] Don't use wxNativeContainerWindow as wxOverlayWindow base class This seems unnecessary, we can just use wxWindow directly. --- src/msw/overlay.cpp | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index cc31f02f21..c59432348b 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -8,7 +8,6 @@ #include "wx/wxprec.h" #include "wx/private/overlay.h" -#include "wx/nativewin.h" #include "wx/dcclient.h" #include "wx/dcmemory.h" #include "wx/msw/dc.h" @@ -16,7 +15,7 @@ namespace // anonymous { -class wxOverlayWindow : public wxNativeContainerWindow +class wxOverlayWindow : public wxWindow { public: static wxWindow* New(const wxRect& rect) @@ -64,7 +63,15 @@ public: } auto overlayWin = new wxOverlayWindow(hwnd); + + // Let the object know that it's currently hidden (because we + // intentionally don't use WS_VISIBLE when creating it to avoid + // stealing activation from the parent window). + overlayWin->wxWindowBase::Show(false); + + // And show it using SWP_NOACTIVATE flag now. overlayWin->Show(true); + return overlayWin; } @@ -98,8 +105,23 @@ public: virtual bool Destroy() override { - HWND hwnd = GetHandle(); + // Save the HWND and reset it in the object itself as we delete it + // manually below. + const HWND hwnd = GetHandle(); + m_hWnd = nullptr; + // This window must be deleted manually because it's not owned by any + // other one, so do it here and handle the rest of the destruction in a + // static function which won't (even accidentally) access the already + // destroyed object. + delete this; + + return DoDestroy(hwnd); + } + +private: + static bool DoDestroy(HWND hwnd) + { if ( hwnd && !::DestroyWindow(hwnd) ) { wxLogLastError(wxS("DestroyWindow() in wxOverlayWindow::Destroy()")); @@ -114,8 +136,11 @@ public: return true; } -private: - wxOverlayWindow(HWND hwnd) : wxNativeContainerWindow(hwnd) {} + explicit wxOverlayWindow(HWND hwnd) + { + m_hWnd = hwnd; + } + ~wxOverlayWindow() = default; }; } // anonymous namespace From 3c4d3270b5034b2443cb56a680321b3eeee22e9b Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:25:53 +0000 Subject: [PATCH 06/10] Stop registering special window class for wxOverlayWindow This seems unnecessary, we can simply use the same class as for all the other windows for this one. --- src/msw/overlay.cpp | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index c59432348b..34bdc840bc 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -20,19 +20,6 @@ class wxOverlayWindow : public wxWindow public: static wxWindow* New(const wxRect& rect) { - WNDCLASS wndclass; - wxZeroMemory(wndclass); - - wndclass.lpfnWndProc = ::DefWindowProc; - wndclass.hInstance = wxGetInstance(); - wndclass.lpszClassName = GetOverlayWindowClass(); - - if ( !::RegisterClass(&wndclass) ) - { - wxLogLastError(wxS("RegisterClass() in wxOverlayWindow::Create()")); - return nullptr; - } - const wxPoint pos = rect.GetPosition(); const wxSize size = rect.GetSize(); WXDWORD exStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE; @@ -40,7 +27,7 @@ public: HWND hwnd = ::CreateWindowEx ( exStyle, - GetOverlayWindowClass(), + GetMSWClassName(0), nullptr, WS_POPUP, pos.x, pos.y, @@ -75,11 +62,6 @@ public: return overlayWin; } - static const wxChar* GetOverlayWindowClass() - { - return wxS("wxOverlayWindow"); - } - virtual bool Show(bool show) override { if ( !GetHandle() || !wxWindowBase::Show(show) ) @@ -128,11 +110,6 @@ private: return false; } - if ( !::UnregisterClass(GetOverlayWindowClass(), wxGetInstance()) ) - { - wxLogLastError(wxS("UnregisterClass() in wxOverlayWindow::Destroy()")); - } - return true; } From 969d9b11089d86e3e46700d2d5498451b4934c4d Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:27:43 +0000 Subject: [PATCH 07/10] Remove special logic for destroying wxOverlayWindow It can be destroyed as any other window. --- src/msw/overlay.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index 34bdc840bc..0be410791b 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -85,34 +85,7 @@ public: return true; } - virtual bool Destroy() override - { - // Save the HWND and reset it in the object itself as we delete it - // manually below. - const HWND hwnd = GetHandle(); - m_hWnd = nullptr; - - // This window must be deleted manually because it's not owned by any - // other one, so do it here and handle the rest of the destruction in a - // static function which won't (even accidentally) access the already - // destroyed object. - delete this; - - return DoDestroy(hwnd); - } - private: - static bool DoDestroy(HWND hwnd) - { - if ( hwnd && !::DestroyWindow(hwnd) ) - { - wxLogLastError(wxS("DestroyWindow() in wxOverlayWindow::Destroy()")); - return false; - } - - return true; - } - explicit wxOverlayWindow(HWND hwnd) { m_hWnd = hwnd; From 2a56ed336f89d25a347e96c409ce1904528e9030 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:40:38 +0000 Subject: [PATCH 08/10] Simplify the code even further and remove wxOverlayWindow This class doesn't seem to be necessary at all, finally, we can just use wxWindow directly, so do it to simplify the code and avoid using Win32 API directly. --- src/msw/overlay.cpp | 104 +++++++++++++------------------------------- 1 file changed, 31 insertions(+), 73 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index 0be410791b..03b7dc7a80 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -15,84 +15,42 @@ namespace // anonymous { -class wxOverlayWindow : public wxWindow + +wxWindow* wxCreateOverlayWindow(const wxRect& rect) { -public: - static wxWindow* New(const wxRect& rect) + auto overlayWin = new wxWindow(); + + overlayWin->MSWCreate + ( + overlayWin->GetMSWClassName(0), + nullptr, // No title + rect.GetPosition(), + rect.GetSize(), + WS_POPUP, + WS_EX_LAYERED | + WS_EX_TRANSPARENT | + WS_EX_NOACTIVATE + ); + + if ( !::SetLayeredWindowAttributes(GetHwndOf(overlayWin), 0, 128, + LWA_COLORKEY | LWA_ALPHA) ) { - const wxPoint pos = rect.GetPosition(); - const wxSize size = rect.GetSize(); - WXDWORD exStyle = WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_NOACTIVATE; - - HWND hwnd = ::CreateWindowEx - ( - exStyle, - GetMSWClassName(0), - nullptr, - WS_POPUP, - pos.x, pos.y, - size.x, size.y, - (HWND)nullptr, - (HMENU)nullptr, - wxGetInstance(), - (LPVOID)nullptr - ); - - if ( !hwnd ) - { - wxLogLastError(wxS("CreateWindowEx() in wxOverlayWindow::Create()")); - return nullptr; - } - - if ( !::SetLayeredWindowAttributes(hwnd, 0, 128, LWA_COLORKEY|LWA_ALPHA) ) - { - wxLogLastError(wxS("SetLayeredWindowAttributes() in wxOverlayWindow::Create()")); - } - - auto overlayWin = new wxOverlayWindow(hwnd); - - // Let the object know that it's currently hidden (because we - // intentionally don't use WS_VISIBLE when creating it to avoid - // stealing activation from the parent window). - overlayWin->wxWindowBase::Show(false); - - // And show it using SWP_NOACTIVATE flag now. - overlayWin->Show(true); - - return overlayWin; + wxLogLastError(wxS("SetLayeredWindowAttributes()")); } - virtual bool Show(bool show) override - { - if ( !GetHandle() || !wxWindowBase::Show(show) ) - return false; + // We intentionally don't use WS_VISIBLE when creating this window to avoid + // stealing activation from the parent, so show it using SWP_NOACTIVATE now. + ::SetWindowPos(GetHwndOf(overlayWin), nullptr, 0, 0, 0, 0, + SWP_NOSIZE | + SWP_NOMOVE | + SWP_NOREDRAW | + SWP_NOOWNERZORDER | + SWP_NOACTIVATE | + SWP_SHOWWINDOW); - if ( show ) - { - ::SetWindowPos(GetHandle(), nullptr, 0, 0, 0, 0, - SWP_NOSIZE | - SWP_NOMOVE | - SWP_NOREDRAW | - SWP_NOOWNERZORDER | - SWP_NOACTIVATE | - SWP_SHOWWINDOW); - } - else - { - ::ShowWindow(GetHandle(), SW_HIDE); - } + return overlayWin; +} - return true; - } - -private: - explicit wxOverlayWindow(HWND hwnd) - { - m_hWnd = hwnd; - } - - ~wxOverlayWindow() = default; -}; } // anonymous namespace class wxOverlayImpl : public wxOverlay::Impl @@ -145,7 +103,7 @@ void wxOverlayImpl::Init(wxDC* dc, int , int , int , int ) m_bitmap.CreateWithDIPSize(m_rect.GetSize(), m_window->GetDPIScaleFactor()); - m_overlayWindow = wxOverlayWindow::New(m_rect); + m_overlayWindow = wxCreateOverlayWindow(m_rect); } void wxOverlayImpl::BeginDrawing(wxDC* dc) From d573815c1ce3ce805820eb12ed4da4efb820a44a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 14 Feb 2023 18:46:22 +0000 Subject: [PATCH 09/10] Use transparent colour for clearing the layered window This seems more clear than using a transparent brush. --- src/msw/overlay.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index 03b7dc7a80..78b13e38a9 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -141,10 +141,10 @@ void wxOverlayImpl::Clear(wxDC* WXUNUSED(dc)) { wxCHECK_RET( IsOk(), wxS("overlay not initialized") ); - // doesn't work with non double buffered m_window - // m_memDC.SetBackground(*wxTRANSPARENT_BRUSH); - - m_memDC.SetBackground(wxBrush(wxTransparentColour)); + // Note that the colour used here is the same one that we specify as + // LWA_COLORKEY when creating the layered window, so it is actually + // transparent. + m_memDC.SetBackground(*wxBLACK); m_memDC.Clear(); } From c871d749bdfc7b375a31277391ca47a63e30da4e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Fri, 17 Feb 2023 15:13:58 +0000 Subject: [PATCH 10/10] Disable erasing the overlay window background This resulted in flicker when not using compositing (and should be an optimization even when using it). --- src/msw/overlay.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/msw/overlay.cpp b/src/msw/overlay.cpp index 78b13e38a9..030df35636 100644 --- a/src/msw/overlay.cpp +++ b/src/msw/overlay.cpp @@ -32,6 +32,8 @@ wxWindow* wxCreateOverlayWindow(const wxRect& rect) WS_EX_NOACTIVATE ); + overlayWin->SetBackgroundStyle(wxBG_STYLE_PAINT); + if ( !::SetLayeredWindowAttributes(GetHwndOf(overlayWin), 0, 128, LWA_COLORKEY | LWA_ALPHA) ) {