From a15004fc5f2a05e59a60b66b9e36cbe5adad2291 Mon Sep 17 00:00:00 2001 From: dasimx Date: Thu, 28 Mar 2019 21:47:41 +0100 Subject: [PATCH] Fix handling display disconnection under wxMSW Information about display cached in wxDisplayFactory::m_impls and in wxDisplayFactoryMSW::m_displays could get out of sync after removing a display from the system, resulting in failures when calling various wxDisplay functions later. To fix this, reuse InvalidateCache() to invalidate the cache in wxDisplayFactoryMSW too, making it virtual in order to allow overriding it there. Also call InvalidateCache() from wxDisplayFactoryMSW itself instead of doing it from wxWindow, as this works even when the application isn't showing any windows (and also keeps all display-related code together). Closes https://github.com/wxWidgets/wxWidgets/pull/1246 --- include/wx/private/display.h | 2 +- src/msw/display.cpp | 12 +++++++++--- src/msw/window.cpp | 2 -- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/wx/private/display.h b/include/wx/private/display.h index 15668eaaf8..81712747c3 100644 --- a/include/wx/private/display.h +++ b/include/wx/private/display.h @@ -49,7 +49,7 @@ public: virtual int GetFromWindow(const wxWindow *window); // Trigger recreation of wxDisplayImpl when they're needed the next time. - void InvalidateCache() { ClearImpls(); } + virtual void InvalidateCache() { ClearImpls(); } protected: // create a new display object diff --git a/src/msw/display.cpp b/src/msw/display.cpp index 6fd48acd44..993b3cdaa9 100644 --- a/src/msw/display.cpp +++ b/src/msw/display.cpp @@ -192,9 +192,15 @@ public: virtual int GetFromPoint(const wxPoint& pt) wxOVERRIDE; virtual int GetFromWindow(const wxWindow *window) wxOVERRIDE; + void InvalidateCache() wxOVERRIDE + { + wxDisplayFactory::InvalidateCache(); + DoRefreshMonitors(); + } + // Called when we receive WM_SETTINGCHANGE to refresh the list of monitor // handles. - static void RefreshMonitors() { ms_factory->DoRefreshMonitors(); } + static void RefreshMonitors() { ms_factory->InvalidateCache(); } // Declare the second argument as int to avoid problems with older SDKs not // declaring MONITOR_DPI_TYPE enum. @@ -529,9 +535,9 @@ bool wxDisplayMSW::ChangeMode(const wxVideoMode& mode) LRESULT APIENTRY wxDisplayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { - if ( msg == WM_SETTINGCHANGE ) + if ( msg == WM_SETTINGCHANGE || msg == WM_DISPLAYCHANGE ) { - wxDisplayFactoryMSW::RefreshMonitors(); + wxDisplay::InvalidateCache(); return 0; } diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 9b717bb3d9..56eef3d15c 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -4723,8 +4723,6 @@ bool wxWindowMSW::HandleSysColorChange() bool wxWindowMSW::HandleDisplayChange() { - wxDisplay::InvalidateCache(); - wxDisplayChangedEvent event; event.SetEventObject(this);