From 297d7c06c47015c7da3f98baef11f302cc1206f7 Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Sun, 9 Oct 2022 14:05:17 -0700 Subject: [PATCH] [hidpi] Use wxWidgets 3.2 on Windows * Remove the custom handling for pre-3.1.4 builds on Windows since both the mingw and msvc builds now use 3.2. * Remove wxDPIChangedEvent handling, since this triggers a resize, which has the same effect. * Implement main/WinMain ourselves, rather than relying on wxWidgets macros. This allows us to initialize the console earlier in the process. * Add an explicit dependency on the manifest file to trigger a link when it is modified. --- .github/workflows/msys2-build.yml | 2 +- installdeps | 2 +- src/wx/CMakeLists.txt | 46 +++++++-------- src/wx/panel.cpp | 30 ++++------ src/wx/widgets/dpi-support-win.cpp | 55 ------------------ src/wx/wxvbam.cpp | 91 ++++++++++++++++++++---------- src/wx/wxvbam.h | 4 -- 7 files changed, 92 insertions(+), 138 deletions(-) delete mode 100644 src/wx/widgets/dpi-support-win.cpp diff --git a/.github/workflows/msys2-build.yml b/.github/workflows/msys2-build.yml index a2d45ca3..6283d3cf 100644 --- a/.github/workflows/msys2-build.yml +++ b/.github/workflows/msys2-build.yml @@ -27,7 +27,7 @@ jobs: mingw-w64-clang-x86_64-FAudio mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-ninja - mingw-w64-clang-x86_64-wxWidgets + mingw-w64-clang-x86_64-wxWidgets3.2 mingw-w64-clang-x86_64-sfml mingw-w64-clang-x86_64-SDL2 zip diff --git a/installdeps b/installdeps index 4a2f8c3f..a0f28dfd 100755 --- a/installdeps +++ b/installdeps @@ -1115,7 +1115,7 @@ windows_installdeps() { ;; esac - pkgs="$pkgs SDL2 sfml wxWidgets zlib binutils cmake crt-git extra-cmake-modules headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache" + pkgs="$pkgs SDL2 sfml wxWidgets3.2 zlib binutils cmake crt-git extra-cmake-modules headers-git make pkgconf tools-git windows-default-manifest libmangle-git ninja gdb ccache" [ -n "$ENABLE_OPENAL" ] && pkgs="$pkgs openal" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg" diff --git a/src/wx/CMakeLists.txt b/src/wx/CMakeLists.txt index fefca080..805a991a 100644 --- a/src/wx/CMakeLists.txt +++ b/src/wx/CMakeLists.txt @@ -759,14 +759,11 @@ set(ALL_SRC_WX ${SRC_WX}) list(APPEND ALL_SRC_WX ${CMAKE_CURRENT_SOURCE_DIR}/macsupport.mm) list(APPEND ALL_SRC_WX ${CMAKE_CURRENT_SOURCE_DIR}/widgets/dpi-support-mac.mm) -list(APPEND ALL_SRC_WX ${CMAKE_CURRENT_SOURCE_DIR}/widgets/dpi-support-win.cpp) list(APPEND ALL_SRC_WX ${CMAKE_CURRENT_SOURCE_DIR}/widgets/dpi-support.cpp) if(APPLE) list(APPEND SRC_WX macsupport.mm) list(APPEND SRC_WX widgets/dpi-support-mac.mm) -elseif(WIN32) - list(APPEND SRC_WX widgets/dpi-support-win.cpp) else() list(APPEND SRC_WX widgets/dpi-support.cpp) endif() @@ -989,14 +986,13 @@ if(NOT TRANSLATIONS_ONLY) endif() if(WIN32) - # This is necessary for DPI support and is not included by default in - # the msys2 build. - target_link_libraries(visualboyadvance-m shcore) + # Force a re-link when the manifest file is modified. + set_target_properties(visualboyadvance-m + PROPERTIES + LINK_DEPENDS + "${CMAKE_CURRENT_LIST_DIR}/visualboyadvance-m.manifest") if(MSVC) - # the debug lib libcmtd is linked in debug mode, so don't link the normal version - set_target_properties(visualboyadvance-m PROPERTIES LINK_FLAGS_DEBUG "/nodefaultlib:libcmt") - # Disable the auto-generated manifest from CMake. target_link_options(visualboyadvance-m PRIVATE "/MANIFEST:NO") endif() @@ -1004,24 +1000,22 @@ if(NOT TRANSLATIONS_ONLY) # link libgcc/libstdc++ statically on mingw # and adjust link command when making a static binary - if(CMAKE_COMPILER_IS_GNUCXX) - if(VBAM_STATIC) - # some dists don't have a static libpthread - set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread ") + if(CMAKE_COMPILER_IS_GNUCXX AND VBAM_STATIC) + # some dists don't have a static libpthread + set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread ") - if(WIN32) - add_custom_command( - TARGET visualboyadvance-m PRE_LINK - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/msys-link-static.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) - else() - add_custom_command( - TARGET visualboyadvance-m PRE_LINK - COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/link-static.cmake - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - ) - endif() + if(WIN32) + add_custom_command( + TARGET visualboyadvance-m PRE_LINK + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/msys-link-static.cmake + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) + else() + add_custom_command( + TARGET visualboyadvance-m PRE_LINK + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/link-static.cmake + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + ) endif() endif() diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index 5c45bb30..31f998a0 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -54,7 +54,6 @@ GameArea::GameArea() , basic_width(GBAWidth) , basic_height(GBAHeight) , fullscreen(false) - , dpi_scale_factor_(widgets::DPIScaleFactorForWindow(this)) , paused(false) , pointer_blanked(false) , mouse_active_time(0) @@ -746,11 +745,12 @@ void GameArea::DelBorder() void GameArea::AdjustMinSize() { wxWindow* frame = wxGetApp().frame; + double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this); // note: could safely set min size to 1x or less regardless of video_scale // but setting it to scaled size makes resizing to default easier - wxSize sz((std::ceil(basic_width * gopts.video_scale) * dpi_scale_factor_), - (std::ceil(basic_height * gopts.video_scale) * dpi_scale_factor_)); + wxSize sz((std::ceil(basic_width * gopts.video_scale) * dpi_scale_factor), + (std::ceil(basic_height * gopts.video_scale) * dpi_scale_factor)); SetMinSize(sz); #if wxCHECK_VERSION(2, 8, 8) sz = frame->ClientToWindowSize(sz); @@ -763,9 +763,10 @@ void GameArea::AdjustMinSize() void GameArea::LowerMinSize() { wxWindow* frame = wxGetApp().frame; + double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this); - wxSize sz(std::ceil(basic_width * dpi_scale_factor_), - std::ceil(basic_height * dpi_scale_factor_)); + wxSize sz(std::ceil(basic_width * dpi_scale_factor), + std::ceil(basic_height * dpi_scale_factor)); SetMinSize(sz); // do not take decorations into account @@ -779,8 +780,10 @@ void GameArea::AdjustSize(bool force) if (fullscreen) return; - const wxSize newsz((std::ceil(basic_width * gopts.video_scale) * dpi_scale_factor_), - (std::ceil(basic_height * gopts.video_scale) * dpi_scale_factor_)); + double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this); + const wxSize newsz( + (std::ceil(basic_width * gopts.video_scale) * dpi_scale_factor), + (std::ceil(basic_height * gopts.video_scale) * dpi_scale_factor)); if (!force) { wxSize sz = GetClientSize(); @@ -959,16 +962,6 @@ void GameArea::OnKillFocus(wxFocusEvent& ev) ev.Skip(); } -#if WX_HAS_NATIVE_HI_DPI_SUPPORT -void GameArea::OnDpiChanged(wxDPIChangedEvent&) { - if (dpi_scale_factor_ == GetDPIScaleFactor()) { - return; - } - dpi_scale_factor_ = GetDPIScaleFactor(); - AdjustSize(true); -} -#endif // WX_HAS_NATIVE_HI_DPI_SUPPORT - void GameArea::Pause() { if (paused) @@ -1340,9 +1333,6 @@ void GameArea::OnSDLJoy(wxJoyEvent& ev) BEGIN_EVENT_TABLE(GameArea, wxPanel) EVT_IDLE(GameArea::OnIdle) EVT_SDLJOY(GameArea::OnSDLJoy) -#if WX_HAS_NATIVE_HI_DPI_SUPPORT -EVT_DPI_CHANGED(GameArea::OnDpiChanged) -#endif // WX_HAS_NATIVE_HI_DPI_SUPPORT // FIXME: wxGTK does not generate motion events in MainFrame (not sure // what to do about it) EVT_MOUSE_EVENTS(GameArea::MouseEvent) diff --git a/src/wx/widgets/dpi-support-win.cpp b/src/wx/widgets/dpi-support-win.cpp deleted file mode 100644 index 5c5d87f0..00000000 --- a/src/wx/widgets/dpi-support-win.cpp +++ /dev/null @@ -1,55 +0,0 @@ -#include "widgets/dpi-support.h" - -#include -#include -#include - -#include - -namespace widgets { - -double DPIScaleFactorForWindow(wxWindow* window) { -#if WX_HAS_NATIVE_HI_DPI_SUPPORT - return window->GetDPIScaleFactor(); -#else - static constexpr double kStandardDpi = 96.0; - HWND wnd = window->GetHWND(); - if (IsWindows10OrGreater()) { - // We can't properly resize on DPI/Monitor change, but neither can - // wxWidgets so we're consistent. - UINT dpi = GetDpiForWindow(wnd); - if (dpi != 0) { - return static_cast(dpi) / kStandardDpi; - } - } - - if (IsWindows8Point1OrGreater()) { - HMONITOR monitor = MonitorFromWindow(wnd, MONITOR_DEFAULTTONEAREST); - UINT xdpi; - UINT ydpi; - HRESULT success = - GetDpiForMonitor(monitor, MDT_EFFECTIVE_DPI, &xdpi, &ydpi); - if (success == S_OK) { - return static_cast(ydpi) / kStandardDpi; - } - } - - HDC dc = GetDC(wnd); - if (dc == nullptr) { - return 1.0; - } - - int ydpi = GetDeviceCaps(dc, LOGPIXELSY); - ReleaseDC(nullptr, dc); - - return ydpi / kStandardDpi; -#endif // WX_HAS_NATIVE_HI_DPI_SUPPORT -} - -void RequestHighResolutionOpenGlSurfaceForWindow(wxWindow*) {} - -void GetRealPixelClientSize(wxWindow* window, int* x, int* y) { - window->GetClientSize(x, y); -} - -} // namespace widgets diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 47cfaf48..226a66e7 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -36,7 +36,65 @@ #include "wayland.h" #include "wx/gamecontrol.h" -IMPLEMENT_APP(wxvbamApp) +#ifdef __WXMSW__ + +int WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) { + bool console_attached = AttachConsole(ATTACH_PARENT_PROCESS) != FALSE; +#ifdef DEBUG + // In debug builds, create a console if none is attached. + if (!console_attached) { + console_attached = AllocConsole() != FALSE; + } +#endif // DEBUG + + // Redirect stdout/stderr to the console if one is attached. + // This code was taken from Dolphin. + // https://github.com/dolphin-emu/dolphin/blob/6cf99195c645f54d54c72322ad0312a0e56bc985/Source/Core/DolphinQt/Main.cpp#L112 + HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (console_attached && stdout_handle) { + freopen("CONOUT$", "w", stdout); + freopen("CONOUT$", "w", stderr); + } + + // Set up logging. +#ifdef DEBUG + wxLog::SetLogLevel(wxLOG_Trace); +#else // DEBUG + wxLog::SetLogLevel(wxLOG_Info); +#endif // DEBUG + + // Redirect e.g. --help to stderr. + wxMessageOutput::Set(new wxMessageOutputStderr()); + + // This will be freed on wxEntry exit. + wxApp::SetInstance(new wxvbamApp()); + return wxEntry(hInstance, hPrevInstance, lpCmdLine, nCmdShow); +} + +#else // __WXMSW__ + +int main(int argc, char* argv) { + // Set up logging. +#ifdef DEBUG + wxLog::SetLogLevel(wxLOG_Trace); +#else // DEBUG + wxLog::SetLogLevel(wxLOG_Info); +#endif // DEBUG + + // This will be freed on wxEntry exit. + wxApp::SetInstance(new wxvbamApp()); + return wxEntry(argc, argv); +} + +#endif // __WXMSW__ + +wxvbamApp& wxGetApp() { + return *static_cast(wxApp::GetInstance()); +} + IMPLEMENT_DYNAMIC_CLASS(MainFrame, wxFrame) #ifndef NO_ONLINEUPDATES @@ -194,36 +252,7 @@ wxString wxvbamApp::GetAbsolutePath(wxString path) return path; } -bool wxvbamApp::OnInit() -{ - // set up logging -#ifndef NDEBUG - wxLog::SetLogLevel(wxLOG_Trace); -#endif // !NDEBUG - -#ifdef __WXMSW__ - // in windows console mode debug builds, redirect e.g. --help to stderr -#ifndef NDEBUG - wxMessageOutput::Set(new wxMessageOutputStderr()); -#endif // !NDEBUG - - bool console_attached = AttachConsole(ATTACH_PARENT_PROCESS) != FALSE; -#ifndef NDEBUG - // In debug builds, create a console if none is attached. - if (!console_attached) { - console_attached = AllocConsole() != FALSE; - } -#endif // !NDEBUG - - // Redirect stdout/stderr to the console if one is attached. - // This code was taken from Dolphin. - // https://github.com/dolphin-emu/dolphin/blob/6cf99195c645f54d54c72322ad0312a0e56bc985/Source/Core/DolphinQt/Main.cpp#L112 - HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); - if (console_attached && stdout_handle) { - freopen("CONOUT$", "w", stdout); - freopen("CONOUT$", "w", stderr); - } -#endif // __WXMSW__ +bool wxvbamApp::OnInit() { using_wayland = IsItWayland(); // use consistent names for config diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index 21cebe22..1c9c9c4d 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -642,7 +642,6 @@ protected: int basic_width, basic_height; bool fullscreen; - double dpi_scale_factor_ = 0; bool paused; void OnIdle(wxIdleEvent&); @@ -653,9 +652,6 @@ protected: void EraseBackground(wxEraseEvent& ev); void OnSize(wxSizeEvent& ev); void OnKillFocus(wxFocusEvent& ev); -#if WX_HAS_NATIVE_HI_DPI_SUPPORT - void OnDpiChanged(wxDPIChangedEvent& ev); -#endif // WX_HAS_NATIVE_HI_DPI_SUPPORT #ifndef NO_FFMPEG recording::MediaRecorder snd_rec, vid_rec;