To: vim_dev@googlegroups.com Subject: Patch 8.2.4109 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ 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. --> ! ! ! ! true --- 37,45 ---- ! ! true ! PerMonitorV2 *************** *** 51,57 **** ! --- 52,58 ---- ! *** ../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 -- Bram@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 ///