Patch 8.2.4109
Problem: MS-Windows: high dpi support is outdated.
Solution: Improve High DPI support by using PerMonitorV2. (closes #9525,
closes #3102)
Files: src/gui.c, src/gui.h, src/gui_w32.c, src/vim.manifest
*** ../vim-8.2.4108/src/gui.c 2022-01-05 17:49:10.873225135 +0000
--- src/gui.c 2022-01-16 14:10:11.087353555 +0000
***************
*** 1433,1442 ****
if (gui.menu_is_active)
text_area_y += gui.menu_height;
#endif
- #if defined(FEAT_TOOLBAR) && defined(FEAT_GUI_MSWIN)
- if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
- text_area_y = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
- #endif
# if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_MOTIF))
--- 1433,1438 ----
***************
*** 1445,1451 ****
#endif
#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
! || defined(FEAT_GUI_HAIKU))
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
{
# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
--- 1441,1447 ----
#endif
#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_ATHENA) \
! || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_MSWIN))
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
{
# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
***************
*** 1529,1539 ****
# endif
# ifdef FEAT_TOOLBAR
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
- # if defined(FEAT_GUI_MSWIN) && defined(FEAT_TOOLBAR)
- base_height += (TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT);
- # else
base_height += gui.toolbar_height;
- # endif
# endif
# if defined(FEAT_GUI_TABLINE) && (defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU))
--- 1525,1531 ----
***************
*** 4342,4354 ****
#if defined(FEAT_TOOLBAR) && (defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_ATHENA) \
|| defined(FEAT_GUI_HAIKU))
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
- # if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_HAIKU)
y += gui.toolbar_height;
- # else
- # ifdef FEAT_GUI_MSWIN
- y += TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
- # endif
- # endif
#endif
#if defined(FEAT_GUI_TABLINE) && defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_HAIKU)
--- 4334,4340 ----
*** ../vim-8.2.4108/src/gui.h 2021-11-16 20:03:50.851550914 +0000
--- src/gui.h 2022-01-16 14:10:11.087353555 +0000
***************
*** 424,430 ****
#endif
#if defined(FEAT_TOOLBAR) \
! && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU))
int toolbar_height; // height of the toolbar
#endif
--- 424,430 ----
#endif
#if defined(FEAT_TOOLBAR) \
! && (defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_HAIKU) || defined(FEAT_GUI_MSWIN))
int toolbar_height; // height of the toolbar
#endif
*** ../vim-8.2.4108/src/gui_w32.c 2022-01-05 20:24:34.272005652 +0000
--- src/gui_w32.c 2022-01-16 14:10:11.087353555 +0000
***************
*** 40,45 ****
--- 40,47 ----
#ifdef FEAT_MENU
static int gui_mswin_get_menu_height(int fix_window);
+ #else
+ # define gui_mswin_get_menu_height(fix_window) 0
#endif
#if defined(FEAT_RENDER_OPTIONS) || defined(PROTO)
***************
*** 230,235 ****
--- 232,241 ----
# define MK_XBUTTON2 0x0040
#endif
+ #ifndef WM_DPICHANGED
+ # define WM_DPICHANGED 0x02E0
+ #endif
+
#ifdef PROTO
/*
* Define a few things for generating prototypes. This is just to avoid
***************
*** 314,320 ****
static int destroying = FALSE; // call DestroyWindow() ourselves
#ifdef MSWIN_FIND_REPLACE
! static UINT s_findrep_msg = 0; // set in gui_w[16/32].c
static FINDREPLACEW s_findrep_struct;
static HWND s_findrep_hwnd = NULL;
static int s_findrep_is_find; // TRUE for find dialog, FALSE
--- 320,326 ----
static int destroying = FALSE; // call DestroyWindow() ourselves
#ifdef MSWIN_FIND_REPLACE
! static UINT s_findrep_msg = 0;
static FINDREPLACEW s_findrep_struct;
static HWND s_findrep_hwnd = NULL;
static int s_findrep_is_find; // TRUE for find dialog, FALSE
***************
*** 358,363 ****
--- 364,426 ----
# define MyTranslateMessage(x) TranslateMessage(x)
#endif
+ #ifndef _DPI_AWARENESS_CONTEXTS_
+ typedef HANDLE DPI_AWARENESS_CONTEXT;
+
+ typedef enum DPI_AWARENESS {
+ DPI_AWARENESS_INVALID = -1,
+ DPI_AWARENESS_UNAWARE = 0,
+ DPI_AWARENESS_SYSTEM_AWARE = 1,
+ DPI_AWARENESS_PER_MONITOR_AWARE = 2
+ } DPI_AWARENESS;
+
+ # 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
+
+ #define DEFAULT_DPI 96
+ static int s_dpi = DEFAULT_DPI;
+ static BOOL s_in_dpichanged = FALSE;
+ static DPI_AWARENESS s_process_dpi_aware = DPI_AWARENESS_INVALID;
+
+ static UINT (WINAPI *pGetDpiForSystem)(void) = NULL;
+ static UINT (WINAPI *pGetDpiForWindow)(HWND hwnd) = NULL;
+ static int (WINAPI *pGetSystemMetricsForDpi)(int, UINT) = NULL;
+ //static INT (WINAPI *pGetWindowDpiAwarenessContext)(HWND hwnd) = NULL;
+ static DPI_AWARENESS_CONTEXT (WINAPI *pSetThreadDpiAwarenessContext)(DPI_AWARENESS_CONTEXT dpiContext) = NULL;
+ static DPI_AWARENESS (WINAPI *pGetAwarenessFromDpiAwarenessContext)(DPI_AWARENESS_CONTEXT) = NULL;
+
+ static UINT WINAPI
+ stubGetDpiForSystem(void)
+ {
+ HWND hwnd = GetDesktopWindow();
+ HDC hdc = GetWindowDC(hwnd);
+ UINT dpi = GetDeviceCaps(hdc, LOGPIXELSY);
+ ReleaseDC(hwnd, hdc);
+ return dpi;
+ }
+
+ static int WINAPI
+ stubGetSystemMetricsForDpi(int nIndex, UINT dpi)
+ {
+ return GetSystemMetrics(nIndex);
+ }
+
+ static int
+ adjust_fontsize_by_dpi(int size)
+ {
+ return size * s_dpi / (int)pGetDpiForSystem();
+ }
+
+ static int
+ adjust_by_system_dpi(int size)
+ {
+ return size * (int)pGetDpiForSystem() / DEFAULT_DPI;
+ }
+
#if defined(FEAT_DIRECTX)
static int
directx_enabled(void)
***************
*** 1348,1354 ****
#ifdef FEAT_TOOLBAR
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
SendMessage(s_toolbarhwnd, WM_SIZE,
! (WPARAM)0, (LPARAM)(w + ((long)(TOOLBAR_BUTTON_HEIGHT+8)<<16)));
#endif
#if defined(FEAT_GUI_TABLINE)
if (showing_tabline)
--- 1411,1417 ----
#ifdef FEAT_TOOLBAR
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
SendMessage(s_toolbarhwnd, WM_SIZE,
! (WPARAM)0, MAKELPARAM(w, gui.toolbar_height));
#endif
#if defined(FEAT_GUI_TABLINE)
if (showing_tabline)
***************
*** 1358,1364 ****
# ifdef FEAT_TOOLBAR
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
! top = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
# endif
GetClientRect(s_hwnd, &rect);
MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE);
--- 1421,1427 ----
# ifdef FEAT_TOOLBAR
if (vim_strchr(p_go, GO_TOOLBAR) != NULL)
! top = gui.toolbar_height;
# endif
GetClientRect(s_hwnd, &rect);
MoveWindow(s_tabhwnd, 0, top, rect.right, gui.tabline_height, TRUE);
***************
*** 1414,1421 ****
GetWindowRect(s_textArea, &rcTxt);
GetWindowRect(s_hwnd, &rcWnd);
xpad = rcWnd.right - rcTxt.right - gui.scrollbar_width
! - GetSystemMetrics(SM_CXFRAME)
! - GetSystemMetrics(SM_CXPADDEDBORDER);
return (xpad < 0) ? 0 : xpad;
}
--- 1477,1484 ----
GetWindowRect(s_textArea, &rcTxt);
GetWindowRect(s_hwnd, &rcWnd);
xpad = rcWnd.right - rcTxt.right - gui.scrollbar_width
! - pGetSystemMetricsForDpi(SM_CXFRAME, s_dpi)
! - pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi);
return (xpad < 0) ? 0 : xpad;
}
***************
*** 1428,1435 ****
GetWindowRect(s_textArea, &rcTxt);
GetWindowRect(s_hwnd, &rcWnd);
ypad = rcWnd.bottom - rcTxt.bottom - gui.scrollbar_height
! - GetSystemMetrics(SM_CYFRAME)
! - GetSystemMetrics(SM_CXPADDEDBORDER);
return (ypad < 0) ? 0 : ypad;
}
--- 1491,1498 ----
GetWindowRect(s_textArea, &rcTxt);
GetWindowRect(s_hwnd, &rcWnd);
ypad = rcWnd.bottom - rcTxt.bottom - gui.scrollbar_height
! - pGetSystemMetricsForDpi(SM_CYFRAME, s_dpi)
! - pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi);
return (ypad < 0) ? 0 : ypad;
}
***************
*** 1467,1472 ****
--- 1530,1542 ----
return NULL;
}
+ static void
+ update_scrollbar_size(void)
+ {
+ gui.scrollbar_width = pGetSystemMetricsForDpi(SM_CXVSCROLL, s_dpi);
+ gui.scrollbar_height = pGetSystemMetricsForDpi(SM_CYHSCROLL, s_dpi);
+ }
+
/*
* Get the character size of a font.
*/
***************
*** 1545,1551 ****
--- 1615,1624 ----
GuiFont font = NOFONT;
if (get_logfont(&lf, name, NULL, giveErrorIfMissing) == OK)
+ {
+ lf.lfHeight = adjust_fontsize_by_dpi(lf.lfHeight);
font = get_font_handle(&lf);
+ }
if (font == NOFONT && giveErrorIfMissing)
semsg(_(e_unknown_font_str), name);
return font;
***************
*** 2858,2871 ****
int cx,
int cy)
{
! if (!IsMinimized(hwnd))
{
gui_resize_shell(cx, cy);
- #ifdef FEAT_MENU
// Menu bar may wrap differently now
gui_mswin_get_menu_height(TRUE);
- #endif
}
}
--- 2931,2942 ----
int cx,
int cy)
{
! if (!IsMinimized(hwnd) && !s_in_dpichanged)
{
gui_resize_shell(cx, cy);
// Menu bar may wrap differently now
gui_mswin_get_menu_height(TRUE);
}
}
***************
*** 2949,2964 ****
int base_width, base_height;
base_width = gui_get_base_width()
! + (GetSystemMetrics(SM_CXFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
base_height = gui_get_base_height()
! + (GetSystemMetrics(SM_CYFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
! + GetSystemMetrics(SM_CYCAPTION)
! #ifdef FEAT_MENU
! + gui_mswin_get_menu_height(FALSE)
! #endif
! ;
*cols = (w - base_width) / gui.char_width;
*rows = (h - base_height) / gui.char_height;
*valid_w = base_width + *cols * gui.char_width;
--- 3020,3032 ----
int base_width, base_height;
base_width = gui_get_base_width()
! + (pGetSystemMetricsForDpi(SM_CXFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2;
base_height = gui_get_base_height()
! + (pGetSystemMetricsForDpi(SM_CYFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2
! + pGetSystemMetricsForDpi(SM_CYCAPTION, s_dpi)
! + gui_mswin_get_menu_height(FALSE);
*cols = (w - base_width) / gui.char_width;
*rows = (h - base_height) / gui.char_height;
*valid_w = base_width + *cols * gui.char_width;
***************
*** 3245,3256 ****
#ifdef FEAT_MBYTE_IME
/*
* Set correct LOGFONTW to IME. Use 'guifontwide' if available, otherwise use
! * 'guifont'
*/
static void
update_im_font(void)
{
! LOGFONTW lf_wide;
if (p_guifontwide != NULL && *p_guifontwide != NUL
&& gui.wide_font != NOFONT
--- 3313,3324 ----
#ifdef FEAT_MBYTE_IME
/*
* Set correct LOGFONTW to IME. Use 'guifontwide' if available, otherwise use
! * 'guifont'.
*/
static void
update_im_font(void)
{
! LOGFONTW lf_wide, lf;
if (p_guifontwide != NULL && *p_guifontwide != NUL
&& gui.wide_font != NOFONT
***************
*** 3258,3264 ****
norm_logfont = lf_wide;
else
norm_logfont = sub_logfont;
! im_set_font(&norm_logfont);
}
#endif
--- 3326,3337 ----
norm_logfont = lf_wide;
else
norm_logfont = sub_logfont;
!
! lf = norm_logfont;
! if (s_process_dpi_aware == DPI_AWARENESS_UNAWARE)
! // Work around when PerMonitorV2 is not enabled in the process level.
! lf.lfHeight = lf.lfHeight * DEFAULT_DPI / s_dpi;
! im_set_font(&lf);
}
#endif
***************
*** 3310,3322 ****
int
gui_mch_init_font(char_u *font_name, int fontset UNUSED)
{
! LOGFONTW lf;
GuiFont font = NOFONT;
char_u *p;
// Load the font
if (get_logfont(&lf, font_name, NULL, TRUE) == OK)
font = get_font_handle(&lf);
if (font == NOFONT)
return FAIL;
--- 3383,3399 ----
int
gui_mch_init_font(char_u *font_name, int fontset UNUSED)
{
! LOGFONTW lf, lfOrig;
GuiFont font = NOFONT;
char_u *p;
// Load the font
if (get_logfont(&lf, font_name, NULL, TRUE) == OK)
+ {
+ lfOrig = lf;
+ lf.lfHeight = adjust_fontsize_by_dpi(lf.lfHeight);
font = get_font_handle(&lf);
+ }
if (font == NOFONT)
return FAIL;
***************
*** 3329,3348 ****
sub_logfont = lf;
#endif
#ifdef FEAT_MBYTE_IME
! update_im_font();
#endif
gui_mch_free_font(gui.norm_font);
gui.norm_font = font;
! current_font_height = lf.lfHeight;
GetFontSize(font);
! p = logfont2name(lf);
if (p != NULL)
{
hl_set_font_name(p);
// When setting 'guifont' to "*" replace it with the actual font name.
- //
if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0)
{
vim_free(p_guifont);
--- 3406,3425 ----
sub_logfont = lf;
#endif
#ifdef FEAT_MBYTE_IME
! if (!s_in_dpichanged)
! update_im_font();
#endif
gui_mch_free_font(gui.norm_font);
gui.norm_font = font;
! current_font_height = lfOrig.lfHeight;
GetFontSize(font);
! p = logfont2name(lfOrig);
if (p != NULL)
{
hl_set_font_name(p);
// When setting 'guifont' to "*" replace it with the actual font name.
if (STRCMP(font_name, "*") == 0 && STRCMP(p_guifont, "*") == 0)
{
vim_free(p_guifont);
***************
*** 3428,3453 ****
if (win_socket_id == 0)
{
gui_resize_shell(rect.right - rect.left
! - (GetSystemMetrics(SM_CXFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2,
rect.bottom - rect.top
! - (GetSystemMetrics(SM_CYFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
! - GetSystemMetrics(SM_CYCAPTION)
! #ifdef FEAT_MENU
! - gui_mswin_get_menu_height(FALSE)
! #endif
! );
}
else
{
// Inside another window, don't use the frame and border.
gui_resize_shell(rect.right - rect.left,
! rect.bottom - rect.top
! #ifdef FEAT_MENU
! - gui_mswin_get_menu_height(FALSE)
! #endif
! );
}
}
--- 3505,3523 ----
if (win_socket_id == 0)
{
gui_resize_shell(rect.right - rect.left
! - (pGetSystemMetricsForDpi(SM_CXFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2,
rect.bottom - rect.top
! - (pGetSystemMetricsForDpi(SM_CYFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2
! - pGetSystemMetricsForDpi(SM_CYCAPTION, s_dpi)
! - gui_mswin_get_menu_height(FALSE));
}
else
{
// Inside another window, don't use the frame and border.
gui_resize_shell(rect.right - rect.left,
! rect.bottom - rect.top - gui_mswin_get_menu_height(FALSE));
}
}
***************
*** 4101,4107 ****
#if defined(FEAT_TOOLBAR) || defined(FEAT_GUI_TABLINE)
// Older MSVC compilers don't have LPNMTTDISPINFO[AW] thus we need to define
// it here if LPNMTTDISPINFO isn't defined.
! // MingW doesn't define LPNMTTDISPINFO but typedefs it. Thus we need to check
// _MSC_VER.
# if !defined(LPNMTTDISPINFO) && defined(_MSC_VER)
typedef struct tagNMTTDISPINFOA {
--- 4171,4177 ----
#if defined(FEAT_TOOLBAR) || defined(FEAT_GUI_TABLINE)
// Older MSVC compilers don't have LPNMTTDISPINFO[AW] thus we need to define
// it here if LPNMTTDISPINFO isn't defined.
! // MinGW doesn't define LPNMTTDISPINFO but typedefs it. Thus we need to check
// _MSC_VER.
# if !defined(LPNMTTDISPINFO) && defined(_MSC_VER)
typedef struct tagNMTTDISPINFOA {
***************
*** 4178,4185 ****
--- 4248,4258 ----
static int s_usenewlook; // emulate W95/NT4 non-bold dialogs
#ifdef FEAT_TOOLBAR
static void initialise_toolbar(void);
+ static void update_toolbar_size(void);
static LRESULT CALLBACK toolbar_wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
static int get_toolbar_bitmap(vimmenu_T *menu);
+ #else
+ # define update_toolbar_size()
#endif
#ifdef FEAT_GUI_TABLINE
***************
*** 4419,4424 ****
--- 4492,4498 ----
if (gui_w32_get_menu_font(&lfSysmenu) != OK)
return;
+ lfSysmenu.lfHeight = adjust_fontsize_by_dpi(lfSysmenu.lfHeight);
font = CreateFontIndirectW(&lfSysmenu);
SendMessage(s_tabhwnd, WM_SETFONT, (WPARAM)font, TRUE);
***************
*** 4441,4446 ****
--- 4515,4522 ----
*/
gui.tabline_height = tm.tmHeight + tm.tmInternalLeading + 7;
}
+ #else
+ # define set_tabline_font()
#endif
/*
***************
*** 4452,4461 ****
if (n == SPI_SETWHEELSCROLLLINES)
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0,
&mouse_scroll_lines, 0);
- #if defined(FEAT_GUI_TABLINE) && defined(USE_SYSMENU_FONT)
if (n == SPI_SETNONCLIENTMETRICS)
set_tabline_font();
- #endif
return 0;
}
--- 4528,4535 ----
***************
*** 4556,4561 ****
--- 4630,4657 ----
return TRUE;
}
+ static LRESULT
+ _OnDpiChanged(HWND hwnd, UINT xdpi, UINT ydpi, RECT *rc)
+ {
+ s_dpi = ydpi;
+ s_in_dpichanged = TRUE;
+ //TRACE("DPI: %d", ydpi);
+
+ update_scrollbar_size();
+ update_toolbar_size();
+ set_tabline_font();
+
+ gui_init_font(*p_guifont == NUL ? hl_get_font_name() : p_guifont, FALSE);
+ gui_get_wide_font();
+ gui_mswin_get_menu_height(FALSE);
+ #ifdef FEAT_MBYTE_IME
+ im_set_position(gui.row, gui.col);
+ #endif
+ InvalidateRect(hwnd, NULL, TRUE);
+
+ s_in_dpichanged = FALSE;
+ return 0L;
+ }
static LRESULT CALLBACK
***************
*** 4916,4921 ****
--- 5012,5020 ----
return MyWindowProc(hwnd, uMsg, wParam, lParam);
return 1L;
#endif
+ case WM_DPICHANGED:
+ return _OnDpiChanged(hwnd, (UINT)LOWORD(wParam), (UINT)HIWORD(wParam),
+ (RECT*)lParam);
default:
#ifdef MSWIN_FIND_REPLACE
***************
*** 5216,5221 ****
--- 5315,5363 ----
#endif
}
+ static void
+ load_dpi_func(void)
+ {
+ HMODULE hUser32;
+
+ hUser32 = GetModuleHandle("user32.dll");
+ if (hUser32 == NULL)
+ goto fail;
+
+ pGetDpiForSystem = (void*)GetProcAddress(hUser32, "GetDpiForSystem");
+ pGetDpiForWindow = (void*)GetProcAddress(hUser32, "GetDpiForWindow");
+ pGetSystemMetricsForDpi = (void*)GetProcAddress(hUser32, "GetSystemMetricsForDpi");
+ //pGetWindowDpiAwarenessContext = (void*)GetProcAddress(hUser32, "GetWindowDpiAwarenessContext");
+ pSetThreadDpiAwarenessContext = (void*)GetProcAddress(hUser32, "SetThreadDpiAwarenessContext");
+ pGetAwarenessFromDpiAwarenessContext = (void*)GetProcAddress(hUser32, "GetAwarenessFromDpiAwarenessContext");
+
+ if (pSetThreadDpiAwarenessContext != NULL)
+ {
+ DPI_AWARENESS_CONTEXT oldctx = pSetThreadDpiAwarenessContext(
+ DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
+ if (oldctx != NULL)
+ {
+ TRACE("DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 enabled");
+ s_process_dpi_aware = pGetAwarenessFromDpiAwarenessContext(oldctx);
+ #ifdef DEBUG
+ if (s_process_dpi_aware == DPI_AWARENESS_UNAWARE)
+ {
+ TRACE("WARNING: PerMonitorV2 is not enabled in the process level for some reasons. IME window may not shown correctly.");
+ }
+ #endif
+ return;
+ }
+ }
+
+ fail:
+ // Disable PerMonitorV2 APIs.
+ pGetDpiForSystem = stubGetDpiForSystem;
+ pGetDpiForWindow = NULL;
+ pGetSystemMetricsForDpi = stubGetSystemMetricsForDpi;
+ pSetThreadDpiAwarenessContext = NULL;
+ pGetAwarenessFromDpiAwarenessContext = NULL;
+ }
+
/*
* Initialise the GUI. Create all the windows, set up all the call-backs
* etc.
***************
*** 5242,5253 ****
s_htearbitmap = LoadBitmap(g_hinst, "IDB_TEAROFF");
#endif
! gui.scrollbar_width = GetSystemMetrics(SM_CXVSCROLL);
! gui.scrollbar_height = GetSystemMetrics(SM_CYHSCROLL);
#ifdef FEAT_MENU
gui.menu_height = 0; // Windows takes care of this
#endif
gui.border_width = 0;
s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
--- 5384,5401 ----
s_htearbitmap = LoadBitmap(g_hinst, "IDB_TEAROFF");
#endif
! load_dpi_func();
!
! s_dpi = pGetDpiForSystem();
! update_scrollbar_size();
!
#ifdef FEAT_MENU
gui.menu_height = 0; // Windows takes care of this
#endif
gui.border_width = 0;
+ #ifdef FEAT_TOOLBAR
+ gui.toolbar_height = TOOLBAR_BUTTON_HEIGHT + TOOLBAR_BORDER_HEIGHT;
+ #endif
s_brush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
***************
*** 5336,5341 ****
--- 5484,5496 ----
if (s_hwnd == NULL)
return FAIL;
+ if (pGetDpiForWindow != NULL)
+ {
+ s_dpi = pGetDpiForWindow(s_hwnd);
+ update_scrollbar_size();
+ //TRACE("System DPI: %d, DPI: %d", pGetDpiForSystem(), s_dpi);
+ }
+
#ifdef GLOBAL_IME
global_ime_init(atom, s_hwnd);
#endif
***************
*** 5391,5397 ****
DragAcceptFiles(s_hwnd, TRUE);
// Do we need to bother with this?
! // m_fMouseAvail = GetSystemMetrics(SM_MOUSEPRESENT);
// Get background/foreground colors from the system
gui_mch_def_colors();
--- 5546,5552 ----
DragAcceptFiles(s_hwnd, TRUE);
// Do we need to bother with this?
! // m_fMouseAvail = pGetSystemMetricsForDpi(SM_MOUSEPRESENT, s_dpi);
// Get background/foreground colors from the system
gui_mch_def_colors();
***************
*** 5533,5547 ****
GetWindowRect(s_hwnd, &window_rect);
// compute the size of the outside of the window
! win_width = width + (GetSystemMetrics(SM_CXFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
! win_height = height + (GetSystemMetrics(SM_CYFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
! + GetSystemMetrics(SM_CYCAPTION)
! #ifdef FEAT_MENU
! + gui_mswin_get_menu_height(FALSE)
! #endif
! ;
// The following should take care of keeping Vim on the same monitor, no
// matter if the secondary monitor is left or right of the primary
--- 5688,5699 ----
GetWindowRect(s_hwnd, &window_rect);
// compute the size of the outside of the window
! win_width = width + (pGetSystemMetricsForDpi(SM_CXFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2;
! win_height = height + (pGetSystemMetricsForDpi(SM_CYFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2
! + pGetSystemMetricsForDpi(SM_CYCAPTION, s_dpi)
! + gui_mswin_get_menu_height(FALSE);
// The following should take care of keeping Vim on the same monitor, no
// matter if the secondary monitor is left or right of the primary
***************
*** 5568,5577 ****
SetActiveWindow(s_hwnd);
SetFocus(s_hwnd);
- #ifdef FEAT_MENU
// Menu may wrap differently now
gui_mswin_get_menu_height(!gui.starting);
- #endif
}
--- 5720,5727 ----
***************
*** 5669,5675 ****
case IMN_SETOPENSTATUS:
if (pImmGetOpenStatus(hImc))
{
! pImmSetCompositionFontW(hImc, &norm_logfont);
im_set_position(gui.row, gui.col);
// Disable langmap
--- 5819,5829 ----
case IMN_SETOPENSTATUS:
if (pImmGetOpenStatus(hImc))
{
! LOGFONTW lf = norm_logfont;
! if (s_process_dpi_aware == DPI_AWARENESS_UNAWARE)
! // Work around when PerMonitorV2 is not enabled in the process level.
! lf.lfHeight = lf.lfHeight * DEFAULT_DPI / s_dpi;
! pImmSetCompositionFontW(hImc, &lf);
im_set_position(gui.row, gui.col);
// Disable langmap
***************
*** 5837,5842 ****
--- 5991,6002 ----
cfs.ptCurrentPos.x = FILL_X(col);
cfs.ptCurrentPos.y = FILL_Y(row);
MapWindowPoints(s_textArea, s_hwnd, &cfs.ptCurrentPos, 1);
+ if (s_process_dpi_aware == DPI_AWARENESS_UNAWARE)
+ {
+ // Work around when PerMonitorV2 is not enabled in the process level.
+ cfs.ptCurrentPos.x = cfs.ptCurrentPos.x * DEFAULT_DPI / s_dpi;
+ cfs.ptCurrentPos.y = cfs.ptCurrentPos.y * DEFAULT_DPI / s_dpi;
+ }
pImmSetCompositionWindow(hImc, &cfs);
pImmReleaseContext(s_hwnd, hImc);
***************
*** 6438,6457 ****
get_work_area(&workarea_rect);
*screen_w = workarea_rect.right - workarea_rect.left
! - (GetSystemMetrics(SM_CXFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
// FIXME: dirty trick: Because the gui_get_base_height() doesn't include
// the menubar for MSwin, we subtract it from the screen height, so that
// the window size can be made to fit on the screen.
*screen_h = workarea_rect.bottom - workarea_rect.top
! - (GetSystemMetrics(SM_CYFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2
! - GetSystemMetrics(SM_CYCAPTION)
! #ifdef FEAT_MENU
! - gui_mswin_get_menu_height(FALSE)
! #endif
! ;
}
--- 6598,6614 ----
get_work_area(&workarea_rect);
*screen_w = workarea_rect.right - workarea_rect.left
! - (pGetSystemMetricsForDpi(SM_CXFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2;
// FIXME: dirty trick: Because the gui_get_base_height() doesn't include
// the menubar for MSwin, we subtract it from the screen height, so that
// the window size can be made to fit on the screen.
*screen_h = workarea_rect.bottom - workarea_rect.top
! - (pGetSystemMetricsForDpi(SM_CYFRAME, s_dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, s_dpi)) * 2
! - pGetSystemMetricsForDpi(SM_CYCAPTION, s_dpi)
! - gui_mswin_get_menu_height(FALSE);
}
***************
*** 6905,6910 ****
--- 7062,7070 ----
# endif
garray_T ga;
int l;
+ int dlg_icon_width;
+ int dlg_icon_height;
+ int dpi;
# ifndef NO_CONSOLE
// Don't output anything in silent mode ("ex -s")
***************
*** 6916,6922 ****
--- 7076,7088 ----
# endif
if (s_hwnd == NULL)
+ {
+ load_dpi_func();
+ s_dpi = dpi = pGetDpiForSystem();
get_dialog_font_metrics();
+ }
+ else
+ dpi = pGetDpiForSystem();
if ((type < 0) || (type > VIM_LAST_TYPE))
type = 0;
***************
*** 6974,6980 ****
else
# endif
font = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! VARIABLE_PITCH , DLG_FONT_NAME);
if (s_usenewlook)
{
oldFont = SelectFont(hdc, font);
--- 7140,7146 ----
else
# endif
font = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! VARIABLE_PITCH, DLG_FONT_NAME);
if (s_usenewlook)
{
oldFont = SelectFont(hdc, font);
***************
*** 7001,7008 ****
// We don't have a window, use the desktop area.
get_work_area(&workarea_rect);
maxDialogWidth = workarea_rect.right - workarea_rect.left - 100;
! if (maxDialogWidth > 600)
! maxDialogWidth = 600;
// Leave some room for the taskbar.
maxDialogHeight = workarea_rect.bottom - workarea_rect.top - 150;
}
--- 7167,7174 ----
// We don't have a window, use the desktop area.
get_work_area(&workarea_rect);
maxDialogWidth = workarea_rect.right - workarea_rect.left - 100;
! if (maxDialogWidth > adjust_by_system_dpi(600))
! maxDialogWidth = adjust_by_system_dpi(600);
// Leave some room for the taskbar.
maxDialogHeight = workarea_rect.bottom - workarea_rect.top - 150;
}
***************
*** 7011,7027 ****
// Use our own window for the size, unless it's very small.
GetWindowRect(s_hwnd, &rect);
maxDialogWidth = rect.right - rect.left
! - (GetSystemMetrics(SM_CXFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
! if (maxDialogWidth < DLG_MIN_MAX_WIDTH)
! maxDialogWidth = DLG_MIN_MAX_WIDTH;
maxDialogHeight = rect.bottom - rect.top
! - (GetSystemMetrics(SM_CYFRAME) +
! GetSystemMetrics(SM_CXPADDEDBORDER)) * 4
! - GetSystemMetrics(SM_CYCAPTION);
! if (maxDialogHeight < DLG_MIN_MAX_HEIGHT)
! maxDialogHeight = DLG_MIN_MAX_HEIGHT;
}
// Set dlgwidth to width of message.
--- 7177,7193 ----
// Use our own window for the size, unless it's very small.
GetWindowRect(s_hwnd, &rect);
maxDialogWidth = rect.right - rect.left
! - (pGetSystemMetricsForDpi(SM_CXFRAME, dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) * 2;
! if (maxDialogWidth < adjust_by_system_dpi(DLG_MIN_MAX_WIDTH))
! maxDialogWidth = adjust_by_system_dpi(DLG_MIN_MAX_WIDTH);
maxDialogHeight = rect.bottom - rect.top
! - (pGetSystemMetricsForDpi(SM_CYFRAME, dpi) +
! pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) * 4
! - pGetSystemMetricsForDpi(SM_CYCAPTION, dpi);
! if (maxDialogHeight < adjust_by_system_dpi(DLG_MIN_MAX_HEIGHT))
! maxDialogHeight = adjust_by_system_dpi(DLG_MIN_MAX_HEIGHT);
}
// Set dlgwidth to width of message.
***************
*** 7057,7063 ****
if (last_white != NULL)
{
// break the line just after a space
! ga.ga_len -= (int)(pend - (last_white + 1));
pend = last_white + 1;
last_white = NULL;
}
--- 7223,7230 ----
if (last_white != NULL)
{
// break the line just after a space
! if (pend > last_white)
! ga.ga_len -= (int)(pend - (last_white + 1));
pend = last_white + 1;
last_white = NULL;
}
***************
*** 7082,7093 ****
messageWidth += 10; // roundoff space
// Add width of icon to dlgwidth, and some space
! dlgwidth = messageWidth + DLG_ICON_WIDTH + 3 * dlgPaddingX
! + GetSystemMetrics(SM_CXVSCROLL);
! if (msgheight < DLG_ICON_HEIGHT)
! msgheight = DLG_ICON_HEIGHT;
/*
* Check button names. A long one will make the dialog wider.
--- 7249,7263 ----
messageWidth += 10; // roundoff space
+ dlg_icon_width = adjust_by_system_dpi(DLG_ICON_WIDTH);
+ dlg_icon_height = adjust_by_system_dpi(DLG_ICON_HEIGHT);
+
// Add width of icon to dlgwidth, and some space
! dlgwidth = messageWidth + dlg_icon_width + 3 * dlgPaddingX
! + pGetSystemMetricsForDpi(SM_CXVSCROLL, dpi);
! if (msgheight < dlg_icon_height)
! msgheight = dlg_icon_height;
/*
* Check button names. A long one will make the dialog wider.
***************
*** 7175,7181 ****
dlgheight = maxDialogHeight;
scroll_flag = WS_VSCROLL;
// Make sure scrollbar doesn't appear in the middle of the dialog
! messageWidth = dlgwidth - DLG_ICON_WIDTH - 3 * dlgPaddingX;
}
add_word(PixelToDialogY(dlgheight));
--- 7345,7351 ----
dlgheight = maxDialogHeight;
scroll_flag = WS_VSCROLL;
// Make sure scrollbar doesn't appear in the middle of the dialog
! messageWidth = dlgwidth - dlg_icon_width - 3 * dlgPaddingX;
}
add_word(PixelToDialogY(dlgheight));
***************
*** 7272,7285 ****
p = add_dialog_element(p, SS_ICON,
PixelToDialogX(dlgPaddingX),
PixelToDialogY(dlgPaddingY),
! PixelToDialogX(DLG_ICON_WIDTH),
! PixelToDialogY(DLG_ICON_HEIGHT),
DLG_NONBUTTON_CONTROL + 0, (WORD)0x0082,
dlg_icons[type]);
// Dialog message
p = add_dialog_element(p, ES_LEFT|scroll_flag|ES_MULTILINE|ES_READONLY,
! PixelToDialogX(2 * dlgPaddingX + DLG_ICON_WIDTH),
PixelToDialogY(dlgPaddingY),
(WORD)(PixelToDialogX(messageWidth) + 1),
PixelToDialogY(msgheight),
--- 7442,7455 ----
p = add_dialog_element(p, SS_ICON,
PixelToDialogX(dlgPaddingX),
PixelToDialogY(dlgPaddingY),
! PixelToDialogX(dlg_icon_width),
! PixelToDialogY(dlg_icon_height),
DLG_NONBUTTON_CONTROL + 0, (WORD)0x0082,
dlg_icons[type]);
// Dialog message
p = add_dialog_element(p, ES_LEFT|scroll_flag|ES_MULTILINE|ES_READONLY,
! PixelToDialogX(2 * dlgPaddingX + dlg_icon_width),
PixelToDialogY(dlgPaddingY),
(WORD)(PixelToDialogX(messageWidth) + 1),
PixelToDialogY(msgheight),
***************
*** 7573,7579 ****
else
#endif
hfontTools = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0,
! 0, 0, 0, 0, VARIABLE_PITCH , DLG_FONT_NAME);
if (hfontTools)
{
--- 7743,7749 ----
else
#endif
hfontTools = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0,
! 0, 0, 0, 0, VARIABLE_PITCH, DLG_FONT_NAME);
if (hfontTools)
{
***************
*** 7679,7685 ****
else
# endif
font = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! VARIABLE_PITCH , DLG_FONT_NAME);
if (s_usenewlook)
oldFont = SelectFont(hdc, font);
else
--- 7849,7855 ----
else
# endif
font = CreateFont(-DLG_FONT_POINT_SIZE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
! VARIABLE_PITCH, DLG_FONT_NAME);
if (s_usenewlook)
oldFont = SelectFont(hdc, font);
else
***************
*** 7978,7983 ****
--- 8148,8180 ----
s_toolbar_wndproc = SubclassWindow(s_toolbarhwnd, toolbar_wndproc);
gui_mch_show_toolbar(vim_strchr(p_go, GO_TOOLBAR) != NULL);
+
+ update_toolbar_size();
+ }
+
+ static void
+ update_toolbar_size(void)
+ {
+ int w, h;
+ TBMETRICS tbm = {sizeof(TBMETRICS)};
+
+ tbm.dwMask = TBMF_PAD | TBMF_BUTTONSPACING;
+ SendMessage(s_toolbarhwnd, TB_GETMETRICS, 0, (LPARAM)&tbm);
+ //TRACE("Pad: %d, %d", tbm.cxPad, tbm.cyPad);
+ //TRACE("ButtonSpacing: %d, %d", tbm.cxButtonSpacing, tbm.cyButtonSpacing);
+
+ w = (TOOLBAR_BUTTON_WIDTH + tbm.cxPad) * s_dpi / DEFAULT_DPI;
+ h = (TOOLBAR_BUTTON_HEIGHT + tbm.cyPad) * s_dpi / DEFAULT_DPI;
+ //TRACE("button size: %d, %d", w, h);
+ SendMessage(s_toolbarhwnd, TB_SETBUTTONSIZE, 0, MAKELPARAM(w, h));
+ gui.toolbar_height = h + 6;
+
+ //DWORD s = SendMessage(s_toolbarhwnd, TB_GETBUTTONSIZE, 0, 0);
+ //TRACE("actual button size: %d, %d", LOWORD(s), HIWORD(s));
+
+ // TODO:
+ // Currently, this function only updates the size of toolbar buttons.
+ // It would be nice if the toolbar images are resized based on DPI.
}
static LRESULT CALLBACK
***************
*** 8071,8079 ****
gui.tabline_height = TABLINE_HEIGHT;
- # ifdef USE_SYSMENU_FONT
set_tabline_font();
- # endif
}
/*
--- 8268,8274 ----
***************
*** 8090,8096 ****
{
TCHITTESTINFO htinfo;
htinfo.pt = pt;
! // ignore if a window under cusor is not tabcontrol.
if (s_tabhwnd == hWnd)
{
int idx = TabCtrl_HitTest(s_tabhwnd, &htinfo);
--- 8285,8291 ----
{
TCHITTESTINFO htinfo;
htinfo.pt = pt;
! // ignore if a window under cursor is not tabcontrol.
if (s_tabhwnd == hWnd)
{
int idx = TabCtrl_HitTest(s_tabhwnd, &htinfo);
***************
*** 8136,8142 ****
{
pt.x = GET_X_LPARAM(lParam);
pt.y = s_pt.y;
! if (abs(pt.x - s_pt.x) > GetSystemMetrics(SM_CXDRAG))
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
--- 8331,8338 ----
{
pt.x = GET_X_LPARAM(lParam);
pt.y = s_pt.y;
! if (abs(pt.x - s_pt.x) >
! pGetSystemMetricsForDpi(SM_CXDRAG, s_dpi))
{
SetCursor(LoadCursor(NULL, IDC_SIZEWE));
*** ../vim-8.2.4108/src/vim.manifest 2021-05-24 17:48:00.756582853 +0100
--- src/vim.manifest 2022-01-16 14:10:11.087353555 +0000
***************
*** 5,11 ****
Do ":help uganda" in Vim to read copying and usage conditions.
Do ":help credits" in Vim to see a list of people who contributed.
-->
! <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
<assemblyIdentity
processorArchitecture="*"
version="8.2.0.0"
--- 5,11 ----
Do ":help uganda" in Vim to read copying and usage conditions.
Do ":help credits" in Vim to see a list of people who contributed.
-->
! <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<assemblyIdentity
processorArchitecture="*"
version="8.2.0.0"
***************
*** 37,44 ****
</trustInfo>
<!-- Vista High DPI aware -->
<asmv3:application>
! <asmv3:windowsSettings xmlns="
http://schemas.microsoft.com/SMI/2005/WindowsSettings">
! <dpiAware>true</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
--- 37,45 ----
</trustInfo>
<!-- Vista High DPI aware -->
<asmv3:application>
! <asmv3:windowsSettings>
! <dpiAware xmlns="
http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
! <dpiAwareness xmlns="
http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
***************
*** 51,57 ****
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
! <!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
--- 52,58 ----
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
! <!--The ID below indicates application support for Windows 10 and 11 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
*** ../vim-8.2.4108/src/version.c 2022-01-16 13:58:29.878203450 +0000
--- src/version.c 2022-01-16 14:12:03.712060703 +0000
***************
*** 752,753 ****
--- 752,755 ----
{ /* Add new patch number below this line */
+ /**/
+ 4109,
/**/
--
MORTICIAN: What?
CUSTOMER: Nothing -- here's your nine pence.
DEAD PERSON: I'm not dead!
MORTICIAN: Here -- he says he's not dead!
CUSTOMER: Yes, he is.
DEAD PERSON: I'm not!
The Quest for the Holy Grail (Monty Python)
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///