mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
From: (author)
Date: (date)
Subject: win32: apply DPI awareness before any window is created
Move the SetProcessDpiAwareness call from win32_resources_init()
(invoked deep inside frontend_win32_init) to the very top of
rarch_main(), above CoInitialize and any other code that may
create an HWND directly or transitively.
Background
----------
SetProcessDpiAwareness returns E_ACCESSDENIED if called after the
process has a top-level window. When it fails, the process silently
stays DPI-Unaware — meaning GetDeviceCaps reports a fixed 96 DPI
regardless of the actual monitor DPI or Windows scaling setting,
and the compositor bitmap-stretches the output instead of letting
RetroArch render natively.
The previous call site was too late on several Windows entry paths:
- frontend_driver_attach_console() can run before
frontend_driver_init_first() (confirmed by the existing
FIXME at frontend/frontend_driver.c:515). AllocConsole
creates a console window, locking DPI awareness to Unaware.
- CoInitialize() at the top of rarch_main() can instantiate
a hidden OLE message window in some STA configurations,
also locking DPI awareness.
- The Qt UI companion (HAVE_QT build) defers QApplication
construction until the user presses F5 on Qt 5 builds with
ui_companion_toggle=false, so Qt's own HighDpiScaling
attribute is set far too late to matter.
The new call site runs before all three of the above. It is
reached for every Windows entry path: the plain main() in
retroarch.c and the Qt main() in ui/drivers/ui_qt.cpp both
delegate straight to rarch_main(argc, argv, NULL).
No behavioural change on non-Windows builds; the call is
guarded by `#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)`
matching the existing CoInitialize guard.
Verification
------------
Confirmed via Task Manager's "DPI Awareness" column (which reads
the OS-side GetProcessDpiAwareness value, not a self-report):
retroarch.exe shows "System" after the patch, both on a normal
startup and with verbose logging enabled (which forces the
attach_console / AllocConsole path that previously raced this call).
Visual demonstration of the downstream effect requires a display
in the <32" range at non-100% Windows scaling, which was not
available during development. The API-level confirmation is
considered sufficient; a reviewer on a DPI-scaled PC monitor can
verify Ozone/MaterialUI menu scaling directly.
Future work (not part of this commit)
-------------------------------------
This applies PROCESS_SYSTEM_DPI_AWARE (level 1) to match the
behaviour the old media/rarch.manifest declared. Upgrading to
PerMonitorV2 (SetProcessDpiAwarenessContext with
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) would allow the DPI
reported to RetroArch to follow the current monitor when the
window is moved across displays with different scaling, instead
of staying frozen to the primary monitor's startup DPI. That
upgrade additionally requires handling WM_DPICHANGED in the
WndProc to re-query metrics and invalidate cached scale factors,
and should land as a separate commit with its own testing.
--- a/gfx/common/win32_common.c
+++ b/gfx/common/win32_common.c
@@ -1991,17 +1991,26 @@
* IDR_MENU → win32_resources_create_menu() [in ui_win32.c]
* IDR_ACCELERATOR1 → win32_resources_get_accelerator()
* IDD_PICKCORE → win32_resources_pick_core_dialog() [in ui_win32.c]
- * rarch.manifest → apply_dpi_awareness() (called from _init)
+ * rarch.manifest → win32_apply_dpi_awareness()
+ * (called from the top of rarch_main, before
+ * any window is created)
* ---------------------------------------------------------------- */
static HACCEL s_accel_table = NULL;
/* DPI AWARENESS (replaces media/rarch.manifest)
* The manifest contained <dpiAware>true</dpiAware>.
- * We call the equivalent API at runtime. */
+ * We call the equivalent API at runtime.
+ *
+ * Must be called before the process creates any HWND (direct or
+ * transitive, e.g. via CoInitialize or AllocConsole). Once any
+ * top-level window exists, SetProcessDpiAwareness returns
+ * E_ACCESSDENIED and the process stays Unaware — meaning GetDeviceCaps
+ * reports a fixed 96 DPI regardless of monitor or scaling settings.
+ * See call site in retroarch.c (top of rarch_main). */
typedef HRESULT (WINAPI *pfn_SetProcessDpiAwareness)(int);
-static void apply_dpi_awareness(void)
+void win32_apply_dpi_awareness(void)
{
HMODULE shcore = LoadLibraryW(L"shcore.dll");
if (shcore)
@@ -2055,7 +2064,10 @@
void win32_resources_init(void)
{
- apply_dpi_awareness();
+ /* NOTE: DPI awareness is applied separately, at the very top of
+ * rarch_main(), to guarantee it runs before any window is created
+ * (including the hidden OLE window CoInitialize may create).
+ * See win32_apply_dpi_awareness(). */
s_accel_table = create_accelerator_table();
}
--- a/gfx/common/win32_common.h
+++ b/gfx/common/win32_common.h
@@ -175,8 +175,18 @@
* so that the .exe has an embedded icon visible in Explorer.
* Everything else is created at runtime via Win32 API calls. */
+/* Mark the process as DPI-aware (replaces the <dpiAware>true</dpiAware>
+ * entry that used to live in media/rarch.manifest).
+ *
+ * MUST be called before any HWND is created — directly or transitively
+ * (e.g. via CoInitialize or AllocConsole). Call it at the very top of
+ * rarch_main(), before anything else. Safe to call on any Windows
+ * version: falls back from SetProcessDpiAwareness (Win8.1+) to
+ * SetProcessDPIAware (Vista/7), and is a no-op on older systems. */
+void win32_apply_dpi_awareness(void);
+
/* Call once before creating any windows.
- * Applies DPI awareness and creates the accelerator table. */
+ * Creates the accelerator table and other programmatic resources. */
void win32_resources_init(void);
/* Release resources created by win32_resources_init(). */
--- a/retroarch.c
+++ b/retroarch.c
@@ -6141,6 +6141,14 @@
);
#endif
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
+ /* Mark the process DPI-aware BEFORE anything creates a window.
+ * CoInitialize below can create a hidden OLE message window on
+ * some STA configurations; once any HWND exists, the DPI setting
+ * is locked and GetDeviceCaps will report a fixed 96 DPI. */
+ {
+ extern void win32_apply_dpi_awareness(void);
+ win32_apply_dpi_awareness();
+ }
if (FAILED(CoInitialize(NULL)))
{
RARCH_ERR("FATAL: Failed to initialize the COM interface.\n");
This commit is contained in:
1 parent
ddbc77d3a1
commit
cc16a0dbdb
3 files changed
+35
-5
No files matched your search
@@ -1991,17 +1991,26 @@ bool win32_window_init(WNDCLASSEX *wndclass,
|
||||
* IDR_MENU → win32_resources_create_menu() [in ui_win32.c]
|
||||
* IDR_ACCELERATOR1 → win32_resources_get_accelerator()
|
||||
* IDD_PICKCORE → win32_resources_pick_core_dialog() [in ui_win32.c]
|
||||
* rarch.manifest → apply_dpi_awareness() (called from _init)
|
||||
* rarch.manifest → win32_apply_dpi_awareness()
|
||||
* (called from the top of rarch_main, before
|
||||
* any window is created)
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
static HACCEL s_accel_table = NULL;
|
||||
|
||||
/* DPI AWARENESS (replaces media/rarch.manifest)
|
||||
* The manifest contained <dpiAware>true</dpiAware>.
|
||||
* We call the equivalent API at runtime. */
|
||||
* We call the equivalent API at runtime.
|
||||
*
|
||||
* Must be called before the process creates any HWND (direct or
|
||||
* transitive, e.g. via CoInitialize or AllocConsole). Once any
|
||||
* top-level window exists, SetProcessDpiAwareness returns
|
||||
* E_ACCESSDENIED and the process stays Unaware — meaning GetDeviceCaps
|
||||
* reports a fixed 96 DPI regardless of monitor or scaling settings.
|
||||
* See call site in retroarch.c (top of rarch_main). */
|
||||
typedef HRESULT (WINAPI *pfn_SetProcessDpiAwareness)(int);
|
||||
|
||||
static void apply_dpi_awareness(void)
|
||||
void win32_apply_dpi_awareness(void)
|
||||
{
|
||||
HMODULE shcore = LoadLibraryW(L"shcore.dll");
|
||||
if (shcore)
|
||||
@@ -2055,7 +2064,10 @@ static HACCEL create_accelerator_table(void)
|
||||
|
||||
void win32_resources_init(void)
|
||||
{
|
||||
apply_dpi_awareness();
|
||||
/* NOTE: DPI awareness is applied separately, at the very top of
|
||||
* rarch_main(), to guarantee it runs before any window is created
|
||||
* (including the hidden OLE window CoInitialize may create).
|
||||
* See win32_apply_dpi_awareness(). */
|
||||
s_accel_table = create_accelerator_table();
|
||||
}
|
||||
|
||||
|
||||
@@ -175,8 +175,18 @@ void win32_setup_pixel_format(HDC hdc, bool supports_gl);
|
||||
* so that the .exe has an embedded icon visible in Explorer.
|
||||
* Everything else is created at runtime via Win32 API calls. */
|
||||
|
||||
/* Mark the process as DPI-aware (replaces the <dpiAware>true</dpiAware>
|
||||
* entry that used to live in media/rarch.manifest).
|
||||
*
|
||||
* MUST be called before any HWND is created — directly or transitively
|
||||
* (e.g. via CoInitialize or AllocConsole). Call it at the very top of
|
||||
* rarch_main(), before anything else. Safe to call on any Windows
|
||||
* version: falls back from SetProcessDpiAwareness (Win8.1+) to
|
||||
* SetProcessDPIAware (Vista/7), and is a no-op on older systems. */
|
||||
void win32_apply_dpi_awareness(void);
|
||||
|
||||
/* Call once before creating any windows.
|
||||
* Applies DPI awareness and creates the accelerator table. */
|
||||
* Creates the accelerator table and other programmatic resources. */
|
||||
void win32_resources_init(void);
|
||||
|
||||
/* Release resources created by win32_resources_init(). */
|
||||
|
||||
@@ -6141,6 +6141,14 @@ int rarch_main(int argc, char *argv[], void *data)
|
||||
);
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
|
||||
/* Mark the process DPI-aware BEFORE anything creates a window.
|
||||
* CoInitialize below can create a hidden OLE message window on
|
||||
* some STA configurations; once any HWND exists, the DPI setting
|
||||
* is locked and GetDeviceCaps will report a fixed 96 DPI. */
|
||||
{
|
||||
extern void win32_apply_dpi_awareness(void);
|
||||
win32_apply_dpi_awareness();
|
||||
}
|
||||
if (FAILED(CoInitialize(NULL)))
|
||||
{
|
||||
RARCH_ERR("FATAL: Failed to initialize the COM interface.\n");
|
||||
|
||||
Reference in new issue
Block a user