From ef1b1557c9316969e70b6f68b13ac1b44aaa9c38 Mon Sep 17 00:00:00 2001 From: driver1998 Date: Wed, 2 Sep 2020 10:56:49 +0800 Subject: [PATCH 1/6] Add config for DPI scaling of the emulated screen --- src/config.c | 8 +++++++- src/include/86box/86box.h | 1 + src/pc.c | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/config.c b/src/config.c index 8e23cb3a8..208673c0d 100644 --- a/src/config.c +++ b/src/config.c @@ -459,7 +459,8 @@ load_general(void) force_43 = !!config_get_int(cat, "force_43", 0); scale = config_get_int(cat, "scale", 1); if (scale > 3) - scale = 3; + scale = 3; + dpi_scale = config_get_int(cat, "dpi_scale", 1); enable_overscan = !!config_get_int(cat, "enable_overscan", 0); vid_cga_contrast = !!config_get_int(cat, "vid_cga_contrast", 0); @@ -1605,6 +1606,11 @@ save_general(void) else config_set_int(cat, "scale", scale); + if (dpi_scale == 1) + config_delete_var(cat, "dpi_scale"); + else + config_set_int(cat, "dpi_scale", dpi_scale); + if (enable_overscan == 0) config_delete_var(cat, "enable_overscan"); else diff --git a/src/include/86box/86box.h b/src/include/86box/86box.h index d4ca61b88..595bfa0e5 100644 --- a/src/include/86box/86box.h +++ b/src/include/86box/86box.h @@ -82,6 +82,7 @@ extern int window_w, window_h, /* (C) window size and */ invert_display, /* (C) invert the display */ suppress_overscan; /* (C) suppress overscans */ extern int scale; /* (C) screen scale factor */ +extern int dpi_scale; /* (C) DPI scaling of the emulated screen */ extern int vid_api; /* (C) video renderer */ extern int vid_cga_contrast, /* (C) video */ video_fullscreen, /* (C) video */ diff --git a/src/pc.c b/src/pc.c index 488085301..db15ee617 100644 --- a/src/pc.c +++ b/src/pc.c @@ -116,6 +116,7 @@ int window_w, window_h, /* (C) window size and */ invert_display = 0, /* (C) invert the display */ suppress_overscan = 0; /* (C) suppress overscans */ int scale = 0; /* (C) screen scale factor */ +int dpi_scale = 0; /* (C) DPI scaling of the emulated screen */ int vid_api = 0; /* (C) video renderer */ int vid_cga_contrast = 0, /* (C) video */ video_fullscreen = 0, /* (C) video */ From a3a139e3efe294c40371a70d46bedfe0836f0cbf Mon Sep 17 00:00:00 2001 From: driver1998 Date: Wed, 2 Sep 2020 11:03:14 +0800 Subject: [PATCH 2/6] Add PMv2 related APIs --- src/include/86box/win.h | 15 ++++++++++++++ src/win/win_ui.c | 44 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/include/86box/win.h b/src/include/86box/win.h index 5537f4f30..9d3e8724b 100644 --- a/src/include/86box/win.h +++ b/src/include/86box/win.h @@ -33,6 +33,19 @@ # include "resource.h" # undef BITMAP +/* DPI Awareness Context, copied from MinGW-w64 windef.h */ +#ifndef _DPI_AWARENESS_CONTEXTS_ +DECLARE_HANDLE(DPI_AWARENESS_CONTEXT); +#define DPI_AWARENESS_CONTEXT_UNAWARE ((DPI_AWARENESS_CONTEXT)-1) +#define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((DPI_AWARENESS_CONTEXT)-2) +#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((DPI_AWARENESS_CONTEXT)-3) +#define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((DPI_AWARENESS_CONTEXT)-4) +#define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((DPI_AWARENESS_CONTEXT)-5) +#endif + +#ifndef WM_DPICHANGED_AFTERPARENT +#define WM_DPICHANGED_AFTERPARENT 0x02E3 +#endif /* Class names and such. */ #define CLASS_NAME L"86BoxMainWnd" @@ -119,6 +132,8 @@ extern void win_joystick_handle(PRAWINPUT raw); extern void win_notify_dlg_open(void); extern void win_notify_dlg_closed(void); +extern int win_get_dpi(HWND hwnd); +extern int win_get_system_metrics(int i, int dpi); extern LPARAM win_get_string(int id); diff --git a/src/win/win_ui.c b/src/win/win_ui.c index edcf91385..ef7d6cd89 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -37,6 +37,7 @@ #include <86box/vid_ega.h> // for update_overscan #include <86box/plat.h> #include <86box/plat_midi.h> +#include <86box/plat_dynld.h> #include <86box/ui.h> #include <86box/win.h> #include <86box/version.h> @@ -73,6 +74,43 @@ static int save_window_pos = 0, pause_state = 0; static int vis = -1; +/* Per Monitor DPI Aware v2 APIs, Windows 10 v1703+ */ +void* user32_handle = NULL; +static UINT (WINAPI *pGetDpiForWindow)(HWND); +static UINT (WINAPI *pGetSystemMetricsForDpi)(int i, UINT dpi); +static DPI_AWARENESS_CONTEXT (WINAPI *pGetWindowDpiAwarenessContext)(HWND); +static BOOL (WINAPI *pAreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT A, DPI_AWARENESS_CONTEXT B); +static dllimp_t user32_imports[] = { +{ "GetDpiForWindow", &pGetDpiForWindow }, +{ "GetSystemMetricsForDpi", &pGetSystemMetricsForDpi }, +{ "GetWindowDpiAwarenessContext", &pGetWindowDpiAwarenessContext }, +{ "AreDpiAwarenessContextsEqual", &pAreDpiAwarenessContextsEqual }, +{ NULL, NULL } +}; + +int +win_get_dpi(HWND hwnd) { + if (user32_handle != NULL) { + return pGetDpiForWindow(hwnd); + } else { + HDC dc = GetDC(hwnd); + UINT dpi = GetDeviceCaps(dc, LOGPIXELSX); + ReleaseDC(hwnd, dc); + return dpi; + } +} + +int win_get_system_metrics(int index, int dpi) { + if (user32_handle != NULL) { + /* Only call GetSystemMetricsForDpi when we are using PMv2 */ + DPI_AWARENESS_CONTEXT c = pGetWindowDpiAwarenessContext(hwndMain); + if (pAreDpiAwarenessContextsEqual(c, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)) + return pGetSystemMetricsForDpi(index, dpi); + } + + return GetSystemMetrics(index); +} + /* Set host cursor visible or not. */ void show_cursor(int val) @@ -894,6 +932,9 @@ ui_init(int nCmdShow) TASKDIALOGCONFIG tdconfig = {0}; TASKDIALOG_BUTTON tdbuttons[] = {{IDCANCEL, MAKEINTRESOURCE(IDS_2119)}}; + /* Load DPI related Windows 10 APIs */ + user32_handle = dynld_module("user32.dll", user32_imports); + /* Set up TaskDialog configuration. */ tdconfig.cbSize = sizeof(tdconfig); tdconfig.dwFlags = TDF_ENABLE_HYPERLINKS; @@ -1137,6 +1178,9 @@ ui_init(int nCmdShow) discord_close(); #endif + if (user32_handle != NULL) + dynld_close(user32_handle); + return(messages.wParam); } From 95f9485ff859e348add33d008aada45d35778725 Mon Sep 17 00:00:00 2001 From: driver1998 Date: Wed, 2 Sep 2020 11:19:09 +0800 Subject: [PATCH 3/6] Main UI: HiDPI support --- src/win/86Box.manifest | 38 +++++++----- src/win/win_ui.c | 138 +++++++++++++++++++---------------------- 2 files changed, 86 insertions(+), 90 deletions(-) diff --git a/src/win/86Box.manifest b/src/win/86Box.manifest index ebccd7674..cf0e13b91 100644 --- a/src/win/86Box.manifest +++ b/src/win/86Box.manifest @@ -1,21 +1,27 @@  - - + + - + - + + + + true + permonitorv2 + + diff --git a/src/win/win_ui.c b/src/win/win_ui.c index ef7d6cd89..c72c83b0c 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -70,6 +70,8 @@ static wchar_t wTitle[512]; static HHOOK hKeyboardHook; static int hook_enabled = 0, manager_wm = 0; static int save_window_pos = 0, pause_state = 0; +static int dpi = 96; +static int padded_frame = 0; static int vis = -1; @@ -111,6 +113,24 @@ int win_get_system_metrics(int index, int dpi) { return GetSystemMetrics(index); } +void +ResizeWindowByClientArea(HWND hwnd, int width, int height) +{ + if (vid_resize || padded_frame) { + int padding = win_get_system_metrics(SM_CXPADDEDBORDER, dpi); + width += (win_get_system_metrics(SM_CXFRAME, dpi) + padding) * 2; + height += (win_get_system_metrics(SM_CYFRAME, dpi) + padding) * 2; + } else { + width += win_get_system_metrics(SM_CXFIXEDFRAME, dpi) * 2; + height += win_get_system_metrics(SM_CYFIXEDFRAME, dpi) * 2; + } + + height += win_get_system_metrics(SM_CYCAPTION, dpi); + height += win_get_system_metrics(SM_CYBORDER, dpi) + win_get_system_metrics(SM_CYMENUSIZE, dpi); + + SetWindowPos(hwnd, NULL, 0, 0, width, height, SWP_NOMOVE); +} + /* Set host cursor visible or not. */ void show_cursor(int val) @@ -328,8 +348,8 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HMENU hmenu; - int i, sb_borders[3]; - RECT rect; + int i; + RECT rect, *rect_p; int temp_x, temp_y; @@ -430,42 +450,20 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (vid_resize) SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW) | WS_VISIBLE); - else - SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX) | WS_VISIBLE); + else + SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE); - SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders); - - GetWindowRect(hwnd, &rect); - - /* Main Window. */ - if (GetSystemMetrics(SM_CXPADDEDBORDER) == 0) { - /* For platforms that subsystem version < 6.0 (default on mingw/msys2) */ - /* In this case, border sizes are different between resizable and non-resizable window */ - MoveWindow(hwnd, rect.left, rect.top, - unscaled_size_x + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2), - unscaled_size_y + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + (GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYMENUSIZE)) + GetSystemMetrics(SM_CYCAPTION) + sbar_height, - TRUE); - } else { - /* For platforms that subsystem version >= 6.0 (default on llvm-mingw, mainly for Windows/ARM) */ - /* In this case, border sizes are the same between resizable and non-resizable window */ - MoveWindow(hwnd, rect.left, rect.top, - unscaled_size_x + ((GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2), - unscaled_size_y + ((GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2) + (GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYMENUSIZE)) + GetSystemMetrics(SM_CYCAPTION) + sbar_height, - TRUE); - } + /* Main Window. */ + ResizeWindowByClientArea(hwnd, unscaled_size_x, unscaled_size_y + sbar_height); /* Render window. */ MoveWindow(hwndRender, 0, 0, unscaled_size_x, unscaled_size_y, TRUE); GetWindowRect(hwndRender, &rect); /* Status bar. */ - MoveWindow(hwndSBAR, - 0, rect.bottom + GetSystemMetrics(SM_CYEDGE), - unscaled_size_x, 17, TRUE); + MoveWindow(hwndSBAR, 0, rect.bottom, unscaled_size_x, 17, TRUE); if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); } @@ -478,6 +476,9 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) EnableMenuItem(hmenu, IDM_VID_SCALE_2X, vid_resize ? MF_GRAYED : MF_ENABLED); EnableMenuItem(hmenu, IDM_VID_SCALE_3X, vid_resize ? MF_GRAYED : MF_ENABLED); EnableMenuItem(hmenu, IDM_VID_SCALE_4X, vid_resize ? MF_GRAYED : MF_ENABLED); + + scrnsz_x = unscaled_size_x; + scrnsz_y = unscaled_size_y; doresize = 1; config_save(); break; @@ -662,12 +663,22 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_ENTERMENULOOP: break; + case WM_DPICHANGED: + dpi = HIWORD(wParam); + GetWindowRect(hwndSBAR, &rect); + sbar_height = rect.bottom - rect.top; + rect_p = (RECT*)lParam; + if (vid_resize) { + MoveWindow(hwnd, rect_p->left, rect_p->top, rect_p->right - rect_p->left, rect_p->bottom - rect_p->top, TRUE); + } else if (!user_resize) { + doresize = 1; + } + break; + case WM_SIZE: if (user_resize && !vid_resize) break; - SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders); - temp_x = (lParam & 0xFFFF); temp_y = (lParam >> 16); @@ -684,26 +695,22 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) if (temp_y < 1) temp_y = 1; - if ((temp_x != scrnsz_x) || (temp_y != scrnsz_y)) + if (vid_resize && ((temp_x != scrnsz_x) || (temp_y != scrnsz_y))) { + scrnsz_x = temp_x; + scrnsz_y = temp_y; doresize = 1; + } - scrnsz_x = temp_x; - scrnsz_y = temp_y; - - MoveWindow(hwndRender, 0, 0, scrnsz_x, scrnsz_y, TRUE); + MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE); GetWindowRect(hwndRender, &rect); /* Status bar. */ - MoveWindow(hwndSBAR, - 0, rect.bottom + GetSystemMetrics(SM_CYEDGE), - scrnsz_x, 17, TRUE); + MoveWindow(hwndSBAR, 0, rect.bottom, temp_x, 17, TRUE); - plat_vidsize(scrnsz_x, scrnsz_y); + plat_vidsize(temp_x, temp_y); if (mouse_capture) { - GetWindowRect(hwndRender, &rect); - ClipCursor(&rect); } @@ -1014,6 +1021,19 @@ ui_init(int nCmdShow) ui_window_title(title); + /* Get the current DPI */ + dpi = win_get_dpi(hwndMain); + + /* Check if we have a padded window frame */ + padded_frame = (GetSystemMetrics(SM_CXPADDEDBORDER) != 0); + + /* Create the status bar window. */ + StatusBarCreate(hwndMain, IDC_STATUS, hinstance); + + /* Get the actual height of the status bar */ + GetWindowRect(hwndSBAR, &sbar_rect); + sbar_height = sbar_rect.bottom - sbar_rect.top; + /* Set up main window for resizing if configured. */ if (vid_resize) SetWindowLongPtr(hwnd, GWL_STYLE, @@ -1060,15 +1080,6 @@ ui_init(int nCmdShow) /* Initialize the mouse module. */ win_mouse_init(); - /* Create the status bar window. */ - StatusBarCreate(hwndMain, IDC_STATUS, hinstance); - - /* Get the actual height of the statusbar, - * since that is not something we can change. - */ - GetWindowRect(hwndSBAR, &sbar_rect); - sbar_height = sbar_rect.bottom - sbar_rect.top; - /* * Before we can create the Render window, we first have * to prepare some other things that it depends on. @@ -1262,42 +1273,21 @@ plat_pause(int p) void plat_resize(int x, int y) { - int sb_borders[3]; RECT r; /* First, see if we should resize the UI window. */ if (!vid_resize) { video_wait_for_blit(); - SendMessage(hwndSBAR, SB_GETBORDERS, 0, (LPARAM) sb_borders); - GetWindowRect(hwndMain, &r); - - if (GetSystemMetrics(SM_CXPADDEDBORDER) == 0) { - /* For platforms that subsystem version < 6.0 (gcc on mingw/msys2) */ - /* In this case, border sizes are different between resizable and non-resizable window */ - MoveWindow(hwndMain, r.left, r.top, - x + (GetSystemMetrics(vid_resize ? SM_CXSIZEFRAME : SM_CXFIXEDFRAME) * 2), - y + (GetSystemMetrics(vid_resize ? SM_CYSIZEFRAME : SM_CYFIXEDFRAME) * 2) + (GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYMENUSIZE)) + GetSystemMetrics(SM_CYCAPTION) + sbar_height, - TRUE); - } else { - /* For platforms that subsystem version >= 6.0 (clang/llvm on llvm-mingw, mainly for Windows/ARM) */ - /* In this case, border sizes are the same between resizable and non-resizable window */ - MoveWindow(hwndMain, r.left, r.top, - x + ((GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2), - y + ((GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2) + (GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYMENUSIZE)) + GetSystemMetrics(SM_CYCAPTION) + sbar_height, - TRUE); - } + ResizeWindowByClientArea(hwndMain, x, y + sbar_height); MoveWindow(hwndRender, 0, 0, x, y, TRUE); GetWindowRect(hwndRender, &r); - MoveWindow(hwndSBAR, - 0, r.bottom + GetSystemMetrics(SM_CYEDGE), - x, 17, TRUE); + MoveWindow(hwndSBAR, 0, y, x, 17, TRUE); if (mouse_capture) { - GetWindowRect(hwndRender, &r); ClipCursor(&r); } } From 429a83d3eb36654a0293994a2201038765cb43e4 Mon Sep 17 00:00:00 2001 From: driver1998 Date: Wed, 2 Sep 2020 11:26:26 +0800 Subject: [PATCH 4/6] Enable DPI scaling of emulated screen --- src/include/86box/resource.h | 1 + src/win/86Box.rc | 1 + src/win/win_ui.c | 28 +++++++++++++++++++++++++--- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/include/86box/resource.h b/src/include/86box/resource.h index b2c4810f6..b0422d18b 100644 --- a/src/include/86box/resource.h +++ b/src/include/86box/resource.h @@ -296,6 +296,7 @@ #define IDM_VID_SCALE_2X 40056 #define IDM_VID_SCALE_3X 40057 #define IDM_VID_SCALE_4X 40058 +#define IDM_VID_HIDPI 40059 #define IDM_VID_FULLSCREEN 40060 #define IDM_VID_FS_FULL 40061 #define IDM_VID_FS_43 40062 diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 845b65844..2d408cc9d 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -80,6 +80,7 @@ BEGIN MENUITEM "1.&5x", IDM_VID_SCALE_3X MENUITEM "&2x", IDM_VID_SCALE_4X END + MENUITEM "Hi&DPI scaling", IDM_VID_HIDPI MENUITEM SEPARATOR MENUITEM "&Fullscreen\tCtrl+Alt+PageUP", IDM_VID_FULLSCREEN POPUP "Fullscreen &stretch mode" diff --git a/src/win/win_ui.c b/src/win/win_ui.c index c72c83b0c..51f9ab77a 100644 --- a/src/win/win_ui.c +++ b/src/win/win_ui.c @@ -226,6 +226,7 @@ ResetAllMenus(void) CheckMenuItem(menuMain, IDM_VID_SCALE_1X+1, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SCALE_1X+2, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SCALE_1X+3, MF_UNCHECKED); + CheckMenuItem(menuMain, IDM_VID_HIDPI, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_CGACON, MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+0, MF_UNCHECKED); @@ -275,6 +276,7 @@ ResetAllMenus(void) CheckMenuItem(menuMain, IDM_VID_FS_FULL+video_fullscreen_scale, MF_CHECKED); CheckMenuItem(menuMain, IDM_VID_REMEMBER, window_remember?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_SCALE_1X+scale, MF_CHECKED); + CheckMenuItem(menuMain, IDM_VID_HIDPI, dpi_scale?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_CGACON, vid_cga_contrast?MF_CHECKED:MF_UNCHECKED); CheckMenuItem(menuMain, IDM_VID_GRAYCT_601+video_graytype, MF_CHECKED); @@ -453,15 +455,23 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) else SetWindowLongPtr(hwnd, GWL_STYLE, (WS_OVERLAPPEDWINDOW & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX) | WS_VISIBLE); + /* scale the screen base on DPI */ + if (dpi_scale) { + temp_x = MulDiv(unscaled_size_x, dpi, 96); + temp_y = MulDiv(unscaled_size_y, dpi, 96); + } else { + temp_x = unscaled_size_x; + temp_y = unscaled_size_y; + } /* Main Window. */ - ResizeWindowByClientArea(hwnd, unscaled_size_x, unscaled_size_y + sbar_height); + ResizeWindowByClientArea(hwnd, temp_x, temp_y + sbar_height); /* Render window. */ - MoveWindow(hwndRender, 0, 0, unscaled_size_x, unscaled_size_y, TRUE); + MoveWindow(hwndRender, 0, 0, temp_x, temp_y, TRUE); GetWindowRect(hwndRender, &rect); /* Status bar. */ - MoveWindow(hwndSBAR, 0, rect.bottom, unscaled_size_x, 17, TRUE); + MoveWindow(hwndSBAR, 0, rect.bottom, temp_x, 17, TRUE); if (mouse_capture) { ClipCursor(&rect); @@ -535,6 +545,13 @@ MainWindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) config_save(); break; + case IDM_VID_HIDPI: + dpi_scale = !dpi_scale; + CheckMenuItem(hmenu, IDM_VID_HIDPI, dpi_scale ? MF_CHECKED : MF_UNCHECKED); + doresize = 1; + config_save(); + break; + case IDM_VID_FORCE43: video_toggle_option(hmenu, &force_43, IDM_VID_FORCE43); video_force_resize_set(1); @@ -1280,6 +1297,11 @@ plat_resize(int x, int y) video_wait_for_blit(); + /* scale the screen base on DPI */ + if (dpi_scale) { + x = MulDiv(x, dpi, 96); + y = MulDiv(y, dpi, 96); + } ResizeWindowByClientArea(hwndMain, x, y + sbar_height); MoveWindow(hwndRender, 0, 0, x, y, TRUE); From 1f03e3b057e6108da6016c80c6b7d7e7c5eeb0d5 Mon Sep 17 00:00:00 2001 From: driver1998 Date: Wed, 2 Sep 2020 11:29:16 +0800 Subject: [PATCH 5/6] Status bar: HiDPI support --- src/win/win_stbar.c | 129 ++++++++++++++++++++++++++++---------------- 1 file changed, 83 insertions(+), 46 deletions(-) diff --git a/src/win/win_stbar.c b/src/win/win_stbar.c index 67add30f1..f29ff2523 100644 --- a/src/win/win_stbar.c +++ b/src/win/win_stbar.c @@ -70,6 +70,8 @@ static uint8_t *sb_part_icons; static int sb_parts = 0; static int sb_ready = 0; static uint8_t sb_map[256]; +static int dpi = 96; +static int icon_width = 24; /* Also used by win_settings.c */ intptr_t @@ -537,7 +539,7 @@ ui_sb_update_panes(void) sb_parts = 0; for (i=0; i= (sb_parts - 1)) return; - pt.x = id * SB_ICON_WIDTH; /* Justify to the left. */ + pt.x = id * icon_width; /* Justify to the left. */ pt.y = 0; /* Justify to the top. */ ClientToScreen(hwnd, (LPPOINT) &pt); @@ -744,6 +745,48 @@ StatusBarPopupMenu(HWND hwnd, POINT pt, int id) pt.x, pt.y, 0, hwndSBAR, NULL); } +/* API: Load status bar icons */ +void +StatusBarLoadIcon(HINSTANCE hInst) { + int i; + int x = win_get_system_metrics(SM_CXSMICON, dpi); + + for (i=0; i<256; i++) { + if (hIcon[i] != 0) + DestroyIcon(hIcon[i]); + } + + for (i = 16; i < 18; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 24; i < 26; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 32; i < 34; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 48; i < 50; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 56; i < 58; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 64; i < 66; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 80; i < 82; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 96; i < 98; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 144; i < 146; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 152; i < 154; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 160; i < 162; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 176; i < 178; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 184; i < 186; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 192; i < 194; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); + for (i = 243; i < 244; i++) + hIcon[i] = LoadImage(hInst, MAKEINTRESOURCE(i), IMAGE_ICON, x, x, LR_DEFAULTCOLOR); +} /* Handle messages for the Status Bar window. */ #if defined(__amd64__) || defined(__aarch64__) @@ -756,6 +799,8 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) RECT rc; POINT pt; int item_id = 0; + int i; + HINSTANCE hInst; switch (message) { case WM_COMMAND: @@ -768,20 +813,38 @@ StatusBarProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (PtInRect((LPRECT) &rc, pt)) - StatusBarPopupMenu(hwnd, pt, (pt.x / SB_ICON_WIDTH)); + StatusBarPopupMenu(hwnd, pt, (pt.x / icon_width)); break; case WM_LBUTTONDBLCLK: GetClientRect(hwnd, (LPRECT)& rc); pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); - item_id = (pt.x / SB_ICON_WIDTH); + item_id = (pt.x / icon_width); if (PtInRect((LPRECT) &rc, pt) && (item_id < sb_parts)) { if (sb_part_meanings[item_id] == SB_SOUND) SoundGainDialogCreate(hwndMain); } break; + case WM_DPICHANGED_AFTERPARENT: + /* DPI changed, reload icons */ + hInst = (HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE); + dpi = win_get_dpi(hwnd); + icon_width = MulDiv(SB_ICON_WIDTH, dpi, 96); + StatusBarLoadIcon(hInst); + + for (i=0; i Date: Thu, 3 Sep 2020 12:14:22 +0800 Subject: [PATCH 6/6] Settings: HiDPI support --- src/win/86Box.rc | 26 ++++++------ src/win/win_settings.c | 91 +++++++++++++++++++++++++++++++++++++----- 2 files changed, 95 insertions(+), 22 deletions(-) diff --git a/src/win/86Box.rc b/src/win/86Box.rc index 2d408cc9d..61cb789d3 100644 --- a/src/win/86Box.rc +++ b/src/win/86Box.rc @@ -317,7 +317,7 @@ BEGIN WS_BORDER,53,45,166,14 END -DLG_CONFIG DIALOG DISCARDABLE 0, 0, 366, 256 +DLG_CONFIG DIALOG DISCARDABLE 0, 0, 376, 256 STYLE DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "86Box Settings" FONT 9, "Segoe UI" @@ -325,8 +325,8 @@ BEGIN DEFPUSHBUTTON "OK",IDOK,246,235,50,14 PUSHBUTTON "Cancel",IDCANCEL,307,235,50,14 CONTROL "List2",IDC_SETTINGSCATLIST,"SysListView32",LVS_LIST | - LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,7,90,212 - CONTROL "",-1,"Static",SS_BLACKFRAME | SS_SUNKEN,1,226,363,1 + LVS_SHOWSELALWAYS | LVS_SINGLESEL | WS_BORDER | WS_TABSTOP,7,7,100,212 + CONTROL "",-1,"Static",SS_BLACKFRAME | SS_SUNKEN,1,226,373,1 /* Leave this commented out until we get into localization. */ #if 0 LTEXT "Language:",IDT_1700,7,237,41,10 @@ -335,7 +335,7 @@ BEGIN #endif END -DLG_CFG_MACHINE DIALOG DISCARDABLE 97, 0, 305, 199 +DLG_CFG_MACHINE DIALOG DISCARDABLE 107, 0, 305, 199 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -377,7 +377,7 @@ BEGIN #endif END -DLG_CFG_VIDEO DIALOG DISCARDABLE 97, 0, 267, 45 +DLG_CFG_VIDEO DIALOG DISCARDABLE 107, 0, 267, 45 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -390,7 +390,7 @@ BEGIN PUSHBUTTON "Configure",IDC_BUTTON_VOODOO,222,26,38,12 END -DLG_CFG_INPUT DIALOG DISCARDABLE 97, 0, 267, 65 +DLG_CFG_INPUT DIALOG DISCARDABLE 107, 0, 267, 65 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -407,7 +407,7 @@ BEGIN PUSHBUTTON "Joystick 4...",IDC_JOY4,209,44,50,14 END -DLG_CFG_SOUND DIALOG DISCARDABLE 97, 0, 267, 199 +DLG_CFG_SOUND DIALOG DISCARDABLE 107, 0, 267, 199 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -443,7 +443,7 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,115,94,10 END -DLG_CFG_NETWORK DIALOG DISCARDABLE 97, 0, 267, 63 +DLG_CFG_NETWORK DIALOG DISCARDABLE 107, 0, 267, 63 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -461,7 +461,7 @@ BEGIN PUSHBUTTON "Configure",IDC_CONFIGURE_NET,214,43,46,12 END -DLG_CFG_PORTS DIALOG DISCARDABLE 97, 0, 267, 135 +DLG_CFG_PORTS DIALOG DISCARDABLE 107, 0, 267, 135 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -494,7 +494,7 @@ BEGIN BS_AUTOCHECKBOX | WS_TABSTOP,7,118,94,10 END -DLG_CFG_PERIPHERALS DIALOG DISCARDABLE 97, 0, 267, 220 +DLG_CFG_PERIPHERALS DIALOG DISCARDABLE 107, 0, 267, 220 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -551,7 +551,7 @@ BEGIN PUSHBUTTON "Configure",IDC_CONFIGURE_ISAMEM_4,217,190,38,12 END -DLG_CFG_HARD_DISKS DIALOG DISCARDABLE 97, 0, 267, 154 +DLG_CFG_HARD_DISKS DIALOG DISCARDABLE 107, 0, 267, 154 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -612,7 +612,7 @@ BEGIN WS_BORDER,7,16,204,12 END -DLG_CFG_FLOPPY_AND_CDROM_DRIVES DIALOG DISCARDABLE 97, 0, 267, 222 +DLG_CFG_FLOPPY_AND_CDROM_DRIVES DIALOG DISCARDABLE 107, 0, 267, 222 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN @@ -646,7 +646,7 @@ BEGIN LTEXT "Speed:",IDT_1758,7,207,24,8 END -DLG_CFG_OTHER_REMOVABLE_DEVICES DIALOG DISCARDABLE 97, 0, 267, 222 +DLG_CFG_OTHER_REMOVABLE_DEVICES DIALOG DISCARDABLE 107, 0, 267, 222 STYLE DS_CONTROL | WS_CHILD FONT 9, "Segoe UI" BEGIN diff --git a/src/win/win_settings.c b/src/win/win_settings.c index 961f2b255..846e069ba 100644 --- a/src/win/win_settings.c +++ b/src/win/win_settings.c @@ -71,6 +71,7 @@ static int first_cat = 0; +static int dpi = 96; /* Machine category */ static int temp_machine_type, temp_machine, temp_cpu_m, temp_cpu, temp_wait_states, temp_fpu, temp_sync; @@ -153,8 +154,11 @@ image_list_init(HWND hwndList, const uint8_t *icon_ids) int i = 0; - hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), - GetSystemMetrics(SM_CYSMICON), + hSmall = ListView_GetImageList(hwndList, LVSIL_SMALL); + if (hSmall != 0) ImageList_Destroy(hSmall); + + hSmall = ImageList_Create(win_get_system_metrics(SM_CXSMICON, dpi), + win_get_system_metrics(SM_CYSMICON, dpi), ILC_MASK | ILC_COLOR32, 1, 1); while(1) { @@ -2680,6 +2684,16 @@ win_settings_hard_disks_recalc_list(HWND hwndList) return TRUE; } +static void +win_settings_hard_disks_resize_columns(HWND hwndList) +{ + int iCol; + /* Bus, File, Cylinders, Heads, Sectors, Size */ + int width[C_COLUMNS_HARD_DISKS] = {130, 130, 41, 25, 25, 41}; + for (iCol = 0; iCol < C_COLUMNS_HARD_DISKS; iCol++) { + ListView_SetColumnWidth(hwndList, iCol, MulDiv(width[iCol], dpi, 96)); + } +} static BOOL win_settings_hard_disks_init_columns(HWND hwndList) @@ -2695,7 +2709,7 @@ win_settings_hard_disks_init_columns(HWND hwndList) switch(iCol) { case 0: /* Bus */ - lvc.cx = 135; + lvc.cx = 130; lvc.fmt = LVCFMT_LEFT; break; case 2: /* Cylinders */ @@ -2708,7 +2722,7 @@ win_settings_hard_disks_init_columns(HWND hwndList) lvc.fmt = LVCFMT_RIGHT; break; case 1: /* File */ - lvc.cx = 150; + lvc.cx = 130; lvc.fmt = LVCFMT_LEFT; break; case 5: /* Size (MB) 8 */ @@ -2721,6 +2735,7 @@ win_settings_hard_disks_init_columns(HWND hwndList) return FALSE; } + win_settings_hard_disks_resize_columns(hwndList); return TRUE; } @@ -3682,6 +3697,11 @@ hd_bus_skip: return FALSE; } + case WM_DPICHANGED_AFTERPARENT: + h = GetDlgItem(hdlg, IDC_LIST_HARD_DISKS); + win_settings_hard_disks_resize_columns(h); + image_list_init(h, (const uint8_t *) hd_icons); + break; default: return FALSE; } @@ -3920,6 +3940,14 @@ win_settings_zip_drives_recalc_list(HWND hwndList) } +static void +win_settings_floppy_drives_resize_columns(HWND hwndList) +{ + ListView_SetColumnWidth(hwndList, 0, MulDiv(250, dpi, 96)); + ListView_SetColumnWidth(hwndList, 1, MulDiv(50, dpi, 96)); + ListView_SetColumnWidth(hwndList, 2, MulDiv(75, dpi, 96)); +} + static BOOL win_settings_floppy_drives_init_columns(HWND hwndList) { @@ -3930,7 +3958,7 @@ win_settings_floppy_drives_init_columns(HWND hwndList) lvc.iSubItem = 0; lvc.pszText = plat_get_string(IDS_2092); - lvc.cx = 292; + lvc.cx = 250; lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 0, &lvc) == -1) @@ -3952,12 +3980,20 @@ win_settings_floppy_drives_init_columns(HWND hwndList) lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 2, &lvc) == -1) - return FALSE; + return FALSE; + win_settings_floppy_drives_resize_columns(hwndList); return TRUE; } +static void +win_settings_cdrom_drives_resize_columns(HWND hwndList) +{ + ListView_SetColumnWidth(hwndList, 0, MulDiv(342, dpi, 96)); + ListView_SetColumnWidth(hwndList, 1, MulDiv(50, dpi, 96)); +} + static BOOL win_settings_cdrom_drives_init_columns(HWND hwndList) { @@ -3981,11 +4017,18 @@ win_settings_cdrom_drives_init_columns(HWND hwndList) lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; + win_settings_cdrom_drives_resize_columns(hwndList); return TRUE; } +static void +win_settings_mo_drives_resize_columns(HWND hwndList) +{ + ListView_SetColumnWidth(hwndList, 0, MulDiv(120, dpi, 96)); + ListView_SetColumnWidth(hwndList, 1, MulDiv(260, dpi, 96)); +} static BOOL win_settings_mo_drives_init_columns(HWND hwndList) @@ -4010,11 +4053,18 @@ win_settings_mo_drives_init_columns(HWND hwndList) lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; + win_settings_mo_drives_resize_columns(hwndList); return TRUE; } +static void +win_settings_zip_drives_resize_columns(HWND hwndList) +{ + ListView_SetColumnWidth(hwndList, 0, MulDiv(342, dpi, 96)); + ListView_SetColumnWidth(hwndList, 1, MulDiv(50, dpi, 96)); +} static BOOL win_settings_zip_drives_init_columns(HWND hwndList) @@ -4039,8 +4089,9 @@ win_settings_zip_drives_init_columns(HWND hwndList) lvc.fmt = LVCFMT_LEFT; if (ListView_InsertColumn(hwndList, 1, &lvc) == -1) - return FALSE; + return FALSE; + win_settings_zip_drives_resize_columns(hwndList); return TRUE; } @@ -4856,6 +4907,14 @@ win_settings_floppy_and_cdrom_drives_proc(HWND hdlg, UINT message, WPARAM wParam } ignore_change = 0; + case WM_DPICHANGED_AFTERPARENT: + h = GetDlgItem(hdlg, IDC_LIST_FLOPPY_DRIVES); + win_settings_floppy_drives_resize_columns(h); + image_list_init(h, (const uint8_t *) fd_icons); + h = GetDlgItem(hdlg, IDC_LIST_CDROM_DRIVES); + win_settings_cdrom_drives_resize_columns(h); + image_list_init(h, (const uint8_t *) cd_icons); + break; default: return FALSE; } @@ -5122,6 +5181,14 @@ win_settings_other_removable_devices_proc(HWND hdlg, UINT message, WPARAM wParam } ignore_change = 0; + case WM_DPICHANGED_AFTERPARENT: + h = GetDlgItem(hdlg, IDC_LIST_MO_DRIVES); + win_settings_mo_drives_resize_columns(h); + image_list_init(h, (const uint8_t *) mo_icons); + h = GetDlgItem(hdlg, IDC_LIST_ZIP_DRIVES); + win_settings_zip_drives_resize_columns(h); + image_list_init(h, (const uint8_t *) zip_icons); + break; default: return FALSE; } @@ -5244,6 +5311,7 @@ win_settings_main_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_INITDIALOG: + dpi = win_get_dpi(hdlg); win_settings_init(); displayed_category = -1; h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); @@ -5277,6 +5345,11 @@ win_settings_main_proc(HWND hdlg, UINT message, WPARAM wParam, LPARAM lParam) return TRUE; } break; + case WM_DPICHANGED: + dpi = HIWORD(wParam); + h = GetDlgItem(hdlg, IDC_SETTINGSCATLIST); + image_list_init(h, (const uint8_t *) cat_icons); + break; default: return FALSE; }