[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.
This commit is contained in:
Fabrice de Gans 2022-10-09 14:05:17 -07:00 committed by Rafael Kitover
parent 0d86432a31
commit 297d7c06c4
7 changed files with 92 additions and 138 deletions

View File

@ -27,7 +27,7 @@ jobs:
mingw-w64-clang-x86_64-FAudio mingw-w64-clang-x86_64-FAudio
mingw-w64-clang-x86_64-cmake mingw-w64-clang-x86_64-cmake
mingw-w64-clang-x86_64-ninja 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-sfml
mingw-w64-clang-x86_64-SDL2 mingw-w64-clang-x86_64-SDL2
zip zip

View File

@ -1115,7 +1115,7 @@ windows_installdeps() {
;; ;;
esac 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_OPENAL" ] && pkgs="$pkgs openal"
[ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg" [ -n "$ENABLE_FFMPEG" ] && pkgs="$pkgs ffmpeg"

View File

@ -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}/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-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) list(APPEND ALL_SRC_WX ${CMAKE_CURRENT_SOURCE_DIR}/widgets/dpi-support.cpp)
if(APPLE) if(APPLE)
list(APPEND SRC_WX macsupport.mm) list(APPEND SRC_WX macsupport.mm)
list(APPEND SRC_WX widgets/dpi-support-mac.mm) list(APPEND SRC_WX widgets/dpi-support-mac.mm)
elseif(WIN32)
list(APPEND SRC_WX widgets/dpi-support-win.cpp)
else() else()
list(APPEND SRC_WX widgets/dpi-support.cpp) list(APPEND SRC_WX widgets/dpi-support.cpp)
endif() endif()
@ -989,14 +986,13 @@ if(NOT TRANSLATIONS_ONLY)
endif() endif()
if(WIN32) if(WIN32)
# This is necessary for DPI support and is not included by default in # Force a re-link when the manifest file is modified.
# the msys2 build. set_target_properties(visualboyadvance-m
target_link_libraries(visualboyadvance-m shcore) PROPERTIES
LINK_DEPENDS
"${CMAKE_CURRENT_LIST_DIR}/visualboyadvance-m.manifest")
if(MSVC) 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. # Disable the auto-generated manifest from CMake.
target_link_options(visualboyadvance-m PRIVATE "/MANIFEST:NO") target_link_options(visualboyadvance-m PRIVATE "/MANIFEST:NO")
endif() endif()
@ -1004,24 +1000,22 @@ if(NOT TRANSLATIONS_ONLY)
# link libgcc/libstdc++ statically on mingw # link libgcc/libstdc++ statically on mingw
# and adjust link command when making a static binary # and adjust link command when making a static binary
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX AND VBAM_STATIC)
if(VBAM_STATIC) # some dists don't have a static libpthread
# 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 ")
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE} -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread ")
if(WIN32) if(WIN32)
add_custom_command( add_custom_command(
TARGET visualboyadvance-m PRE_LINK TARGET visualboyadvance-m PRE_LINK
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/msys-link-static.cmake COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/msys-link-static.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
else() else()
add_custom_command( add_custom_command(
TARGET visualboyadvance-m PRE_LINK TARGET visualboyadvance-m PRE_LINK
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/link-static.cmake COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_SOURCE_DIR}/link-static.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
endif()
endif() endif()
endif() endif()

View File

@ -54,7 +54,6 @@ GameArea::GameArea()
, basic_width(GBAWidth) , basic_width(GBAWidth)
, basic_height(GBAHeight) , basic_height(GBAHeight)
, fullscreen(false) , fullscreen(false)
, dpi_scale_factor_(widgets::DPIScaleFactorForWindow(this))
, paused(false) , paused(false)
, pointer_blanked(false) , pointer_blanked(false)
, mouse_active_time(0) , mouse_active_time(0)
@ -746,11 +745,12 @@ void GameArea::DelBorder()
void GameArea::AdjustMinSize() void GameArea::AdjustMinSize()
{ {
wxWindow* frame = wxGetApp().frame; 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 // 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 // but setting it to scaled size makes resizing to default easier
wxSize sz((std::ceil(basic_width * 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_)); (std::ceil(basic_height * gopts.video_scale) * dpi_scale_factor));
SetMinSize(sz); SetMinSize(sz);
#if wxCHECK_VERSION(2, 8, 8) #if wxCHECK_VERSION(2, 8, 8)
sz = frame->ClientToWindowSize(sz); sz = frame->ClientToWindowSize(sz);
@ -763,9 +763,10 @@ void GameArea::AdjustMinSize()
void GameArea::LowerMinSize() void GameArea::LowerMinSize()
{ {
wxWindow* frame = wxGetApp().frame; wxWindow* frame = wxGetApp().frame;
double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this);
wxSize sz(std::ceil(basic_width * dpi_scale_factor_), wxSize sz(std::ceil(basic_width * dpi_scale_factor),
std::ceil(basic_height * dpi_scale_factor_)); std::ceil(basic_height * dpi_scale_factor));
SetMinSize(sz); SetMinSize(sz);
// do not take decorations into account // do not take decorations into account
@ -779,8 +780,10 @@ void GameArea::AdjustSize(bool force)
if (fullscreen) if (fullscreen)
return; return;
const wxSize newsz((std::ceil(basic_width * gopts.video_scale) * dpi_scale_factor_), double dpi_scale_factor = widgets::DPIScaleFactorForWindow(this);
(std::ceil(basic_height * gopts.video_scale) * dpi_scale_factor_)); 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) { if (!force) {
wxSize sz = GetClientSize(); wxSize sz = GetClientSize();
@ -959,16 +962,6 @@ void GameArea::OnKillFocus(wxFocusEvent& ev)
ev.Skip(); 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() void GameArea::Pause()
{ {
if (paused) if (paused)
@ -1340,9 +1333,6 @@ void GameArea::OnSDLJoy(wxJoyEvent& ev)
BEGIN_EVENT_TABLE(GameArea, wxPanel) BEGIN_EVENT_TABLE(GameArea, wxPanel)
EVT_IDLE(GameArea::OnIdle) EVT_IDLE(GameArea::OnIdle)
EVT_SDLJOY(GameArea::OnSDLJoy) 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 // FIXME: wxGTK does not generate motion events in MainFrame (not sure
// what to do about it) // what to do about it)
EVT_MOUSE_EVENTS(GameArea::MouseEvent) EVT_MOUSE_EVENTS(GameArea::MouseEvent)

View File

@ -1,55 +0,0 @@
#include "widgets/dpi-support.h"
#include <Windows.h>
#include <VersionHelpers.h>
#include <shellscalingapi.h>
#include <wx/window.h>
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<int>(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<int>(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

View File

@ -36,7 +36,65 @@
#include "wayland.h" #include "wayland.h"
#include "wx/gamecontrol.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<wxvbamApp*>(wxApp::GetInstance());
}
IMPLEMENT_DYNAMIC_CLASS(MainFrame, wxFrame) IMPLEMENT_DYNAMIC_CLASS(MainFrame, wxFrame)
#ifndef NO_ONLINEUPDATES #ifndef NO_ONLINEUPDATES
@ -194,36 +252,7 @@ wxString wxvbamApp::GetAbsolutePath(wxString path)
return path; return path;
} }
bool wxvbamApp::OnInit() 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__
using_wayland = IsItWayland(); using_wayland = IsItWayland();
// use consistent names for config // use consistent names for config

View File

@ -642,7 +642,6 @@ protected:
int basic_width, basic_height; int basic_width, basic_height;
bool fullscreen; bool fullscreen;
double dpi_scale_factor_ = 0;
bool paused; bool paused;
void OnIdle(wxIdleEvent&); void OnIdle(wxIdleEvent&);
@ -653,9 +652,6 @@ protected:
void EraseBackground(wxEraseEvent& ev); void EraseBackground(wxEraseEvent& ev);
void OnSize(wxSizeEvent& ev); void OnSize(wxSizeEvent& ev);
void OnKillFocus(wxFocusEvent& 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 #ifndef NO_FFMPEG
recording::MediaRecorder snd_rec, vid_rec; recording::MediaRecorder snd_rec, vid_rec;