From 8bce6d0b8905fae81792ec547a10c40f4bc84de5 Mon Sep 17 00:00:00 2001 From: RealDolos Date: Sat, 17 Nov 2018 21:56:56 +0100 Subject: w32_common: Support HiDPI on Windows --- DOCS/man/options.rst | 4 ++-- osdep/mpv.exe.manifest | 5 +++-- video/out/w32_common.c | 32 ++++++++++++++++++++++++-------- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index bd00d16fb4..0a96d18baf 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -3117,10 +3117,10 @@ Window - ``--monitoraspect=16:9`` or ``--monitoraspect=1.7777`` ``--hidpi-window-scale``, ``--no-hidpi-window-scale`` - (OS X, X11, and Wayland only) + (OS X, Windows, X11, and Wayland only) Scale the window size according to the backing scale factor (default: yes). On regular HiDPI resolutions the window opens with double the size but appears - as having the same size as on none-HiDPI resolutions. This is the default OS X + as having the same size as on non-HiDPI resolutions. This is the default OS X behavior. ``--native-fs``, ``--no-native-fs`` diff --git a/osdep/mpv.exe.manifest b/osdep/mpv.exe.manifest index 31386e8ab1..accc2eddc8 100644 --- a/osdep/mpv.exe.manifest +++ b/osdep/mpv.exe.manifest @@ -8,8 +8,9 @@ /> mpv - The Movie Player - - True/PM + + True/PM + PerMonitorV2,PerMonitor diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 4965324d38..6f927d7f28 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -69,6 +69,7 @@ typedef enum MONITOR_DPI_TYPE { struct w32_api { HRESULT (WINAPI *pGetDpiForMonitor)(HMONITOR, MONITOR_DPI_TYPE, UINT*, UINT*); BOOL (WINAPI *pImmDisableIME)(DWORD); + BOOL (WINAPI *pAdjustWindowRectExForDpi)(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi); }; struct vo_w32_state { @@ -110,6 +111,7 @@ struct vo_w32_state { uint32_t o_dheight; int dpi; + double dpi_scale; bool disable_screensaver; bool cursor_visible; @@ -148,16 +150,22 @@ struct vo_w32_state { HANDLE avrt_handle; }; -static void add_window_borders(HWND hwnd, RECT *rc) +static void add_window_borders(struct vo_w32_state *w32, HWND hwnd, RECT *rc) { - AdjustWindowRect(rc, GetWindowLongPtrW(hwnd, GWL_STYLE), 0); + if (w32->api.pAdjustWindowRectExForDpi) { + w32->api.pAdjustWindowRectExForDpi(rc, + GetWindowLongPtrW(hwnd, GWL_STYLE), 0, + GetWindowLongPtrW(hwnd, GWL_EXSTYLE), w32->dpi); + } else { + AdjustWindowRect(rc, GetWindowLongPtrW(hwnd, GWL_STYLE), 0); + } } // basically a reverse AdjustWindowRect (win32 doesn't appear to have this) -static void subtract_window_borders(HWND hwnd, RECT *rc) +static void subtract_window_borders(struct vo_w32_state *w32, HWND hwnd, RECT *rc) { RECT b = { 0, 0, 0, 0 }; - add_window_borders(hwnd, &b); + add_window_borders(w32, hwnd, &b); rc->left -= b.left; rc->top -= b.top; rc->right -= b.right; @@ -523,16 +531,19 @@ static void update_dpi(struct vo_w32_state *w32) if (w32->api.pGetDpiForMonitor && w32->api.pGetDpiForMonitor(w32->monitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK) { w32->dpi = (int)dpiX; + w32->dpi_scale = w32->opts->hidpi_window_scale ? w32->dpi / 96.0 : 1.0; MP_VERBOSE(w32, "DPI detected from the new API: %d\n", w32->dpi); return; } HDC hdc = GetDC(NULL); if (hdc) { w32->dpi = GetDeviceCaps(hdc, LOGPIXELSX); + w32->dpi_scale = w32->opts->hidpi_window_scale ? w32->dpi / 96.0 : 1.0; ReleaseDC(NULL, hdc); MP_VERBOSE(w32, "DPI detected from the old API: %d\n", w32->dpi); } else { w32->dpi = 96; + w32->dpi_scale = 1.0; MP_VERBOSE(w32, "Couldn't determine DPI, falling back to %d\n", w32->dpi); } } @@ -818,7 +829,7 @@ static void fit_window_on_screen(struct vo_w32_state *w32) RECT screen = get_working_area(w32); if (w32->opts->border && w32->opts->fit_border) - subtract_window_borders(w32->window, &screen); + subtract_window_borders(w32, w32->window, &screen); if (fit_rect(&w32->windowrc, &screen)) { MP_VERBOSE(w32, "adjusted window bounds: %d:%d:%d:%d\n", @@ -924,7 +935,7 @@ static void update_window_state(struct vo_w32_state *w32) return; RECT wr = w32->windowrc; - add_window_borders(w32->window, &wr); + add_window_borders(w32, w32->window, &wr); SetWindowPos(w32->window, w32->opts->ontop ? HWND_TOPMOST : HWND_NOTOPMOST, wr.left, wr.top, rect_w(wr), rect_h(wr), @@ -1088,7 +1099,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, // get client area of the windows if it had the rect rc // (subtracting the window borders) RECT r = *rc; - subtract_window_borders(w32->window, &r); + subtract_window_borders(w32, w32->window, &r); int c_w = rect_w(r), c_h = rect_h(r); float aspect = w32->o_dwidth / (float) MPMAX(w32->o_dheight, 1); int d_w = c_h * aspect - c_w; @@ -1384,7 +1395,7 @@ static void gui_thread_reconfig(void *ptr) struct mp_rect screen = { r.left, r.top, r.right, r.bottom }; struct vo_win_geometry geo; - vo_calc_window_geometry(vo, &screen, &geo); + vo_calc_window_geometry2(vo, &screen, w32->dpi_scale, &geo); vo_apply_window_geometry(vo, &geo); bool reset_size = w32->o_dwidth != vo->dwidth || @@ -1440,6 +1451,11 @@ static void w32_api_load(struct vo_w32_state *w32) w32->api.pGetDpiForMonitor = !shcore_dll ? NULL : (void *)GetProcAddress(shcore_dll, "GetDpiForMonitor"); + HMODULE user32_dll = LoadLibraryW(L"user32.dll"); + // Available since Win10 + w32->api.pAdjustWindowRectExForDpi = !user32_dll ? NULL : + (void *)GetProcAddress(user32_dll, "AdjustWindowRectExForDpi"); + // imm32.dll must be loaded dynamically // to account for machines without East Asian language support HMODULE imm32_dll = LoadLibraryW(L"imm32.dll"); -- cgit v1.2.3