Commit: patch 9.0.1970: win32: high-dpi support can be improved

5 views
Skip to first unread message

Christian Brabandt

unread,
Oct 2, 2023, 3:30:12 PM10/2/23
to vim...@googlegroups.com
patch 9.0.1970: win32: high-dpi support can be improved

Commit: https://github.com/vim/vim/commit/7086b3e76a81cf87592077d54e0ef46a60006c2c
Author: Ken Takata <ken...@csc.jp>
Date: Mon Oct 2 21:26:03 2023 +0200

patch 9.0.1970: win32: high-dpi support can be improved

Problem: win32: high-dpi support can be improved
Solution: implement WM_GETDPISCALEDSIZE

win32: Better support of Per-Monitor V2 High DPI

Implement WM_GETDPISCALEDSIZE.
It is not so easy to calculate the new size without actually changing
the size. So, this returns an approximate size.

This doesn't work well when a bitmap font (e.g. FixedSys) is selected,
but I think this is acceptable.

closes: #11812
closes: #13252

Signed-off-by: Christian Brabandt <c...@256bit.org>
Co-authored-by: Ken Takata <ken...@csc.jp>

diff --git a/src/gui_w32.c b/src/gui_w32.c
index 162fe30a1..85adec67e 100644
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -226,6 +226,10 @@ gui_mch_set_rendering_options(char_u *s)
# define WM_DPICHANGED 0x02E0
#endif

+#ifndef WM_GETDPISCALEDSIZE
+# define WM_GETDPISCALEDSIZE 0x02E4
+#endif
+
#ifndef WM_MOUSEHWHEEL
# define WM_MOUSEHWHEEL 0x020E
#endif
@@ -379,6 +383,7 @@ typedef enum DPI_AWARENESS {
static int s_dpi = DEFAULT_DPI;
static BOOL s_in_dpichanged = FALSE;
static DPI_AWARENESS s_process_dpi_aware = DPI_AWARENESS_INVALID;
+static RECT s_suggested_rect;

static UINT (WINAPI *pGetDpiForSystem)(void) = NULL;
static UINT (WINAPI *pGetDpiForWindow)(HWND hwnd) = NULL;
@@ -4734,13 +4739,32 @@ _OnMenuSelect(HWND hwnd, WPARAM wParam, LPARAM lParam)
}
#endif

+ static BOOL
+_OnGetDpiScaledSize(HWND hwnd, UINT dpi, SIZE *size)
+{
+ //TRACE("DPI: %d, SIZE=(%d,%d), s_dpi: %d", dpi, size->cx, size->cy, s_dpi);
+
+ // Calculate new approximate size.
+ // FIXME: If a bitmap font (e.g. FixedSys) is used, the font size may not
+ // be changed. In that case, the calculated size can be wrong.
+ size->cx = size->cx * dpi / s_dpi;
+ size->cy = size->cy * dpi / s_dpi;
+ //TRACE("New approx. SIZE=(%d,%d)", size->cx, size->cy);
+
+ return FALSE;
+}
+
static LRESULT
-_OnDpiChanged(HWND hwnd, UINT xdpi UNUSED, UINT ydpi, RECT *rc UNUSED)
+_OnDpiChanged(HWND hwnd, UINT xdpi UNUSED, UINT ydpi, RECT *rc)
{
s_dpi = ydpi;
s_in_dpichanged = TRUE;
//TRACE("DPI: %d", ydpi);

+ s_suggested_rect = *rc;
+ //TRACE("Suggested pos&size: %d,%d %d,%d", rc->left, rc->top,
+ // rc->right - rc->left, rc->bottom - rc->top);
+
update_scrollbar_size();
update_toolbar_size();
set_tabline_font();
@@ -4893,6 +4917,8 @@ _WndProc(
return DefWindowProcW(hwnd, uMsg, wParam, lParam);
return 1L;
#endif
+ case WM_GETDPISCALEDSIZE:
+ return _OnGetDpiScaledSize(hwnd, (UINT)wParam, (SIZE *)lParam);
case WM_DPICHANGED:
return _OnDpiChanged(hwnd, (UINT)LOWORD(wParam), (UINT)HIWORD(wParam),
(RECT*)lParam);
@@ -5550,7 +5576,12 @@ gui_mch_set_shellsize(
if (IsZoomed(s_hwnd) && starting == 0)
ShowWindow(s_hwnd, SW_SHOWNORMAL);

- GetWindowRect(s_hwnd, &window_rect);
+ if (s_in_dpichanged)
+ // Use the suggested position when in WM_DPICHANGED.
+ window_rect = s_suggested_rect;
+ else
+ // Use current position.
+ GetWindowRect(s_hwnd, &window_rect);

// compute the size of the outside of the window
win_width = width + (pGetSystemMetricsForDpi(SM_CXFRAME, s_dpi) +
@@ -5567,21 +5598,36 @@ gui_mch_set_shellsize(
window_rect.bottom = window_rect.top + win_height;

// If the window is going off the screen, move it on to the screen.
- if ((direction & RESIZE_HOR) && window_rect.right > workarea_rect.right)
- OffsetRect(&window_rect, workarea_rect.right - window_rect.right, 0);
+ // Don't adjust the position when in WM_DPICHANGED.
+ if (!s_in_dpichanged)
+ {
+ if ((direction & RESIZE_HOR)
+ && window_rect.right > workarea_rect.right)
+ OffsetRect(&window_rect,
+ workarea_rect.right - window_rect.right, 0);

- if ((direction & RESIZE_HOR) && window_rect.left < workarea_rect.left)
- OffsetRect(&window_rect, workarea_rect.left - window_rect.left, 0);
+ if ((direction & RESIZE_HOR)
+ && window_rect.left < workarea_rect.left)
+ OffsetRect(&window_rect,
+ workarea_rect.left - window_rect.left, 0);

- if ((direction & RESIZE_VERT) && window_rect.bottom > workarea_rect.bottom)
- OffsetRect(&window_rect, 0, workarea_rect.bottom - window_rect.bottom);
+ if ((direction & RESIZE_VERT)
+ && window_rect.bottom > workarea_rect.bottom)
+ OffsetRect(&window_rect,
+ 0, workarea_rect.bottom - window_rect.bottom);

- if ((direction & RESIZE_VERT) && window_rect.top < workarea_rect.top)
- OffsetRect(&window_rect, 0, workarea_rect.top - window_rect.top);
+ if ((direction & RESIZE_VERT)
+ && window_rect.top < workarea_rect.top)
+ OffsetRect(&window_rect,
+ 0, workarea_rect.top - window_rect.top);
+ }

MoveWindow(s_hwnd, window_rect.left, window_rect.top,
win_width, win_height, TRUE);

+ //TRACE("New pos: %d,%d New size: %d,%d",
+ // window_rect.left, window_rect.top, win_width, win_height);
+
SetActiveWindow(s_hwnd);
SetFocus(s_hwnd);

diff --git a/src/version.c b/src/version.c
index 3056f35d7..de1fe3f3c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -704,6 +704,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 1970,
/**/
1969,
/**/
Reply all
Reply to author
Forward
0 new messages