diff --git a/windows/putty.mft b/windows/putty.mft index fdd000d2..94b7be0c 100644 --- a/windows/putty.mft +++ b/windows/putty.mft @@ -26,6 +26,10 @@ true + + PerMonitorV2 + diff --git a/windows/puttytel.mft b/windows/puttytel.mft index 81b4ddaa..0cc5891d 100644 --- a/windows/puttytel.mft +++ b/windows/puttytel.mft @@ -26,6 +26,10 @@ true + + PerMonitorV2 + diff --git a/windows/window.c b/windows/window.c index cc4bba8b..aa0be484 100644 --- a/windows/window.c +++ b/windows/window.c @@ -82,6 +82,14 @@ #define WHEEL_DELTA 120 #endif +/* DPI awareness support */ +#ifndef WM_DPICHANGED +#define WM_DPICHANGED 0x02E0 +#define WM_DPICHANGED_BEFOREPARENT 0x02E2 +#define WM_DPICHANGED_AFTERPARENT 0x02E3 +#define WM_GETDPISCALEDSIZE 0x02E4 +#endif + /* VK_PACKET, used to send Unicode characters in WM_KEYDOWNs */ #ifndef VK_PACKET #define VK_PACKET 0xE7 @@ -94,6 +102,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned char *output); static void init_palette(void); static void init_fonts(int, int); +static void init_dpi_info(void); static void another_font(int); static void deinit_fonts(void); static void set_input_locale(HKL); @@ -193,6 +202,16 @@ static LPLOGPALETTE logpal; bool tried_pal = false; COLORREF colorref_modifier = 0; +enum MONITOR_DPI_TYPE { MDT_EFFECTIVE_DPI, MDT_ANGULAR_DPI, MDT_RAW_DPI, MDT_DEFAULT }; +DECL_WINDOWS_FUNCTION(static, HRESULT, GetDpiForMonitor, (HMONITOR hmonitor, enum MONITOR_DPI_TYPE dpiType, UINT *dpiX, UINT *dpiY)); +DECL_WINDOWS_FUNCTION(static, HRESULT, GetSystemMetricsForDpi, (int nIndex, UINT dpi)); +DECL_WINDOWS_FUNCTION(static, HRESULT, AdjustWindowRectExForDpi, (LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi)); + +static struct _dpi_info { + POINT cur_dpi; + RECT new_wnd_rect; +} dpi_info; + static HBITMAP caretbm; static int dbltime, lasttime, lastact; @@ -713,6 +732,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) wgs.term_hwnd = CreateWindowExW( exwinmode, uappname, uappname, winmode, CW_USEDEFAULT, CW_USEDEFAULT, guess_width, guess_height, NULL, NULL, inst, NULL); + memset(&dpi_info, 0, sizeof(struct _dpi_info)); + init_dpi_info(); sfree(uappname); } @@ -1341,6 +1362,30 @@ static int get_font_width(HDC hdc, const TEXTMETRIC *tm) return ret; } +static void init_dpi_info(void) +{ + if (dpi_info.cur_dpi.x == 0 || dpi_info.cur_dpi.y == 0) { + if (p_GetDpiForMonitor) { + UINT dpiX, dpiY; + HMONITOR currentMonitor = MonitorFromWindow( + wgs.term_hwnd, MONITOR_DEFAULTTOPRIMARY); + if (p_GetDpiForMonitor(currentMonitor, MDT_EFFECTIVE_DPI, + &dpiX, &dpiY) == S_OK) { + dpi_info.cur_dpi.x = (int)dpiX; + dpi_info.cur_dpi.y = (int)dpiY; + } + } + + /* Fall back to system DPI */ + if (dpi_info.cur_dpi.x == 0 || dpi_info.cur_dpi.y == 0) { + HDC hdc = GetDC(wgs.term_hwnd); + dpi_info.cur_dpi.x = GetDeviceCaps(hdc, LOGPIXELSX); + dpi_info.cur_dpi.y = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(wgs.term_hwnd, hdc); + } + } +} + /* * Initialise all the fonts we will need initially. There may be as many as * three or as few as one. The other (potentially) twenty-one fonts are done @@ -1397,7 +1442,7 @@ static void init_fonts(int pick_width, int pick_height) font_height = font->height; if (font_height > 0) { font_height = - -MulDiv(font_height, GetDeviceCaps(hdc, LOGPIXELSY), 72); + -MulDiv(font_height, dpi_info.cur_dpi.y, 72); } } font_width = pick_width; @@ -1794,6 +1839,35 @@ static void reset_window(int reinit) { return; } + /* Resize window after DPI change */ + if (reinit == 3 && p_GetSystemMetricsForDpi && p_AdjustWindowRectExForDpi) { + RECT rect; + rect.left = rect.top = 0; + rect.right = (font_width * term->cols); + if (conf_get_bool(conf, CONF_scrollbar)) + rect.right += p_GetSystemMetricsForDpi(SM_CXVSCROLL, + dpi_info.cur_dpi.x); + rect.bottom = (font_height * term->rows); + p_AdjustWindowRectExForDpi( + &rect, GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE), + FALSE, GetWindowLongPtr(wgs.term_hwnd, GWL_EXSTYLE), + dpi_info.cur_dpi.x); + rect.right += (window_border * 2); + rect.bottom += (window_border * 2); + OffsetRect(&dpi_info.new_wnd_rect, + ((dpi_info.new_wnd_rect.right - dpi_info.new_wnd_rect.left) - + (rect.right - rect.left)) / 2, + ((dpi_info.new_wnd_rect.bottom - dpi_info.new_wnd_rect.top) - + (rect.bottom - rect.top)) / 2); + SetWindowPos(wgs.term_hwnd, NULL, + dpi_info.new_wnd_rect.left, dpi_info.new_wnd_rect.top, + rect.right - rect.left, rect.bottom - rect.top, + SWP_NOZORDER); + + InvalidateRect(wgs.term_hwnd, NULL, true); + return; + } + /* Hmm, a force re-init means we should ignore the current window * so we resize to the default font size. */ @@ -3031,6 +3105,12 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } sys_cursor_update(); return 0; + case WM_DPICHANGED: + dpi_info.cur_dpi.x = LOWORD(wParam); + dpi_info.cur_dpi.y = HIWORD(wParam); + dpi_info.new_wnd_rect = *(RECT*)(lParam); + reset_window(3); + return 0; case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_BOTTOM: @@ -3974,9 +4054,13 @@ static void init_winfuncs(void) { HMODULE user32_module = load_system32_dll("user32.dll"); HMODULE winmm_module = load_system32_dll("winmm.dll"); + HMODULE shcore_module = load_system32_dll("shcore.dll"); GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx); GET_WINDOWS_FUNCTION(user32_module, ToUnicodeEx); GET_WINDOWS_FUNCTION_PP(winmm_module, PlaySound); + GET_WINDOWS_FUNCTION_NO_TYPECHECK(shcore_module, GetDpiForMonitor); + GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, GetSystemMetricsForDpi); + GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, AdjustWindowRectExForDpi); } /*