mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-17 19:11:00 -05:00
Merge legacy-Windows fixes (mostly) from 'pre-0.77'.
This commit is contained in:
197
windows/window.c
197
windows/window.c
@ -191,6 +191,9 @@ 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, BOOL, GetMonitorInfoA, (HMONITOR, LPMONITORINFO));
|
||||
DECL_WINDOWS_FUNCTION(static, HMONITOR, MonitorFromPoint, (POINT, DWORD));
|
||||
DECL_WINDOWS_FUNCTION(static, HMONITOR, MonitorFromWindow, (HWND, DWORD));
|
||||
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));
|
||||
@ -441,6 +444,72 @@ static void close_session(void *ignored_context)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Some machinery to deal with switching the window type between ANSI
|
||||
* and Unicode. We prefer Unicode, but some PuTTY builds still try to
|
||||
* run on machines so old that they don't support that mode. So we're
|
||||
* prepared to fall back to an ANSI window if we have to. For this
|
||||
* purpose, we swap out a few Windows API functions, and wrap
|
||||
* SetWindowText so that if we're not in Unicode mode we first convert
|
||||
* the wide string we're given.
|
||||
*/
|
||||
static bool unicode_window;
|
||||
static BOOL (WINAPI *sw_PeekMessage)(LPMSG, HWND, UINT, UINT, UINT);
|
||||
static LRESULT (WINAPI *sw_DispatchMessage)(const MSG *);
|
||||
static LRESULT (WINAPI *sw_DefWindowProc)(HWND, UINT, WPARAM, LPARAM);
|
||||
static void sw_SetWindowText(HWND hwnd, wchar_t *text)
|
||||
{
|
||||
if (unicode_window) {
|
||||
SetWindowTextW(hwnd, text);
|
||||
} else {
|
||||
char *mb = dup_wc_to_mb(DEFAULT_CODEPAGE, 0, text, "?", &ucsdata);
|
||||
SetWindowTextA(hwnd, mb);
|
||||
sfree(mb);
|
||||
}
|
||||
}
|
||||
|
||||
static HINSTANCE hprev;
|
||||
|
||||
/*
|
||||
* Also, registering window classes has to be done in a fiddly way.
|
||||
*/
|
||||
#define SETUP_WNDCLASS(wndclass, classname) do { \
|
||||
wndclass.style = 0; \
|
||||
wndclass.lpfnWndProc = WndProc; \
|
||||
wndclass.cbClsExtra = 0; \
|
||||
wndclass.cbWndExtra = 0; \
|
||||
wndclass.hInstance = hinst; \
|
||||
wndclass.hIcon = LoadIcon(hinst, MAKEINTRESOURCE(IDI_MAINICON)); \
|
||||
wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM); \
|
||||
wndclass.hbrBackground = NULL; \
|
||||
wndclass.lpszMenuName = NULL; \
|
||||
wndclass.lpszClassName = classname; \
|
||||
} while (0)
|
||||
wchar_t *terminal_window_class_w(void)
|
||||
{
|
||||
static wchar_t *classname = NULL;
|
||||
if (!classname)
|
||||
classname = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
||||
if (!hprev) {
|
||||
WNDCLASSW wndclassw;
|
||||
SETUP_WNDCLASS(wndclassw, classname);
|
||||
RegisterClassW(&wndclassw);
|
||||
}
|
||||
return classname;
|
||||
}
|
||||
char *terminal_window_class_a(void)
|
||||
{
|
||||
static char *classname = NULL;
|
||||
if (!classname)
|
||||
classname = dupcat(appname, ".ansi");
|
||||
if (!hprev) {
|
||||
WNDCLASSA wndclassa;
|
||||
SETUP_WNDCLASS(wndclassa, classname);
|
||||
RegisterClassA(&wndclassa);
|
||||
}
|
||||
return classname;
|
||||
}
|
||||
|
||||
const unsigned cmdline_tooltype =
|
||||
TOOLTYPE_HOST_ARG |
|
||||
TOOLTYPE_PORT_ARG |
|
||||
@ -457,6 +526,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
dll_hijacking_protection();
|
||||
|
||||
hinst = inst;
|
||||
hprev = prev;
|
||||
|
||||
sk_init();
|
||||
|
||||
@ -505,23 +575,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
*/
|
||||
gui_term_process_cmdline(conf, cmdline);
|
||||
|
||||
if (!prev) {
|
||||
WNDCLASSW wndclass;
|
||||
|
||||
wndclass.style = 0;
|
||||
wndclass.lpfnWndProc = WndProc;
|
||||
wndclass.cbClsExtra = 0;
|
||||
wndclass.cbWndExtra = 0;
|
||||
wndclass.hInstance = inst;
|
||||
wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON));
|
||||
wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM);
|
||||
wndclass.hbrBackground = NULL;
|
||||
wndclass.lpszMenuName = NULL;
|
||||
wndclass.lpszClassName = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
||||
|
||||
RegisterClassW(&wndclass);
|
||||
}
|
||||
|
||||
memset(&ucsdata, 0, sizeof(ucsdata));
|
||||
|
||||
conf_cache_data();
|
||||
@ -557,6 +610,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN)
|
||||
resize_forbidden = true;
|
||||
wchar_t *uappname = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
||||
window_name = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
||||
icon_name = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
||||
if (!conf_get_bool(conf, CONF_scrollbar))
|
||||
winmode &= ~(WS_VSCROLL);
|
||||
if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED ||
|
||||
@ -566,9 +621,42 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
exwinmode |= WS_EX_TOPMOST;
|
||||
if (conf_get_bool(conf, CONF_sunken_edge))
|
||||
exwinmode |= WS_EX_CLIENTEDGE;
|
||||
|
||||
#ifdef TEST_ANSI_WINDOW
|
||||
/* For developer testing of ANSI window support, pretend
|
||||
* CreateWindowExW failed */
|
||||
wgs.term_hwnd = NULL;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
#else
|
||||
unicode_window = true;
|
||||
sw_PeekMessage = PeekMessageW;
|
||||
sw_DispatchMessage = DispatchMessageW;
|
||||
sw_DefWindowProc = DefWindowProcW;
|
||||
wgs.term_hwnd = CreateWindowExW(
|
||||
exwinmode, uappname, uappname, winmode, CW_USEDEFAULT,
|
||||
CW_USEDEFAULT, guess_width, guess_height, NULL, NULL, inst, NULL);
|
||||
exwinmode, terminal_window_class_w(), uappname,
|
||||
winmode, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
guess_width, guess_height, NULL, NULL, inst, NULL);
|
||||
#endif
|
||||
|
||||
#if defined LEGACY_WINDOWS || defined TEST_ANSI_WINDOW
|
||||
if (!wgs.term_hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) {
|
||||
/* Fall back to an ANSI window, swapping in all the ANSI
|
||||
* window message handling functions */
|
||||
unicode_window = false;
|
||||
sw_PeekMessage = PeekMessageA;
|
||||
sw_DispatchMessage = DispatchMessageA;
|
||||
sw_DefWindowProc = DefWindowProcA;
|
||||
wgs.term_hwnd = CreateWindowExA(
|
||||
exwinmode, terminal_window_class_a(), appname,
|
||||
winmode, CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
guess_width, guess_height, NULL, NULL, inst, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!wgs.term_hwnd) {
|
||||
modalfatalbox("Unable to create terminal window: %s",
|
||||
win_strerror(GetLastError()));
|
||||
}
|
||||
memset(&dpi_info, 0, sizeof(struct _dpi_info));
|
||||
init_dpi_info();
|
||||
sfree(uappname);
|
||||
@ -761,13 +849,13 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
handle_wait_activate(hwl, n - WAIT_OBJECT_0);
|
||||
handle_wait_list_free(hwl);
|
||||
|
||||
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
while (sw_PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
|
||||
if (msg.message == WM_QUIT)
|
||||
goto finished; /* two-level break */
|
||||
|
||||
HWND logbox = event_log_window();
|
||||
if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg)))
|
||||
DispatchMessageW(&msg);
|
||||
sw_DispatchMessage(&msg);
|
||||
|
||||
/*
|
||||
* WM_NETEVENT messages seem to jump ahead of others in
|
||||
@ -1271,9 +1359,9 @@ static int get_font_width(HDC hdc, const TEXTMETRIC *tm)
|
||||
static void init_dpi_info(void)
|
||||
{
|
||||
if (dpi_info.cur_dpi.x == 0 || dpi_info.cur_dpi.y == 0) {
|
||||
if (p_GetDpiForMonitor) {
|
||||
if (p_GetDpiForMonitor && p_MonitorFromWindow) {
|
||||
UINT dpiX, dpiY;
|
||||
HMONITOR currentMonitor = MonitorFromWindow(
|
||||
HMONITOR currentMonitor = p_MonitorFromWindow(
|
||||
wgs.term_hwnd, MONITOR_DEFAULTTOPRIMARY);
|
||||
if (p_GetDpiForMonitor(currentMonitor, MDT_EFFECTIVE_DPI,
|
||||
&dpiX, &dpiY) == S_OK) {
|
||||
@ -2177,7 +2265,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
* within an interactive scrollbar-drag can be handled
|
||||
* differently. */
|
||||
in_scrollbar_loop = true;
|
||||
LRESULT result = DefWindowProcW(hwnd, message, wParam, lParam);
|
||||
LRESULT result = sw_DefWindowProc(
|
||||
hwnd, message, wParam, lParam);
|
||||
in_scrollbar_loop = false;
|
||||
return result;
|
||||
}
|
||||
@ -2596,27 +2685,26 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
|
||||
GetCursorPos(&pt);
|
||||
#ifndef NO_MULTIMON
|
||||
{
|
||||
if (p_GetMonitorInfoA && p_MonitorFromPoint) {
|
||||
HMONITOR mon;
|
||||
MONITORINFO mi;
|
||||
|
||||
mon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
|
||||
mon = p_MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
|
||||
|
||||
if (mon != NULL) {
|
||||
mi.cbSize = sizeof(MONITORINFO);
|
||||
GetMonitorInfo(mon, &mi);
|
||||
p_GetMonitorInfoA(mon, &mi);
|
||||
|
||||
if (mi.rcMonitor.left == pt.x &&
|
||||
mi.rcMonitor.top == pt.y) {
|
||||
mouse_on_hotspot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
} else
|
||||
#endif
|
||||
if (pt.x == 0 && pt.y == 0) {
|
||||
mouse_on_hotspot = true;
|
||||
}
|
||||
#endif
|
||||
if (is_full_screen() && press &&
|
||||
button == MBT_LEFT && mouse_on_hotspot) {
|
||||
SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU,
|
||||
@ -2960,11 +3048,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
term, r.right - r.left, r.bottom - r.top);
|
||||
}
|
||||
if (wParam == SIZE_MINIMIZED)
|
||||
SetWindowTextW(hwnd,
|
||||
conf_get_bool(conf, CONF_win_name_always) ?
|
||||
window_name : icon_name);
|
||||
sw_SetWindowText(hwnd,
|
||||
conf_get_bool(conf, CONF_win_name_always) ?
|
||||
window_name : icon_name);
|
||||
if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
|
||||
SetWindowTextW(hwnd, window_name);
|
||||
sw_SetWindowText(hwnd, window_name);
|
||||
if (wParam == SIZE_RESTORED) {
|
||||
processed_resize = false;
|
||||
clear_full_screen();
|
||||
@ -3186,7 +3274,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
} else {
|
||||
len = TranslateKey(message, wParam, lParam, buf);
|
||||
if (len == -1)
|
||||
return DefWindowProcW(hwnd, message, wParam, lParam);
|
||||
return sw_DefWindowProc(hwnd, message, wParam, lParam);
|
||||
|
||||
if (len != 0) {
|
||||
/*
|
||||
@ -3284,7 +3372,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
* post the things to us as part of a macro manoeuvre,
|
||||
* we're ready to cope.
|
||||
*/
|
||||
{
|
||||
if (unicode_window) {
|
||||
static wchar_t pending_surrogate = 0;
|
||||
wchar_t c = wParam;
|
||||
|
||||
@ -3298,6 +3386,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
} else if (!IS_SURROGATE(c)) {
|
||||
term_keyinputw(term, &c, 1);
|
||||
}
|
||||
} else {
|
||||
char c = (unsigned char)wParam;
|
||||
term_seen_key_event(term);
|
||||
if (ldisc)
|
||||
term_keyinput(term, CP_ACP, &c, 1);
|
||||
}
|
||||
return 0;
|
||||
case WM_SYSCOLORCHANGE:
|
||||
@ -3373,7 +3466,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
* Any messages we don't process completely above are passed through to
|
||||
* DefWindowProc() for default processing.
|
||||
*/
|
||||
return DefWindowProcW(hwnd, message, wParam, lParam);
|
||||
return sw_DefWindowProc(hwnd, message, wParam, lParam);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4041,6 +4134,9 @@ static void init_winfuncs(void)
|
||||
GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx);
|
||||
GET_WINDOWS_FUNCTION(user32_module, ToUnicodeEx);
|
||||
GET_WINDOWS_FUNCTION_PP(winmm_module, PlaySound);
|
||||
GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, GetMonitorInfoA);
|
||||
GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, MonitorFromPoint);
|
||||
GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, MonitorFromWindow);
|
||||
GET_WINDOWS_FUNCTION_NO_TYPECHECK(shcore_module, GetDpiForMonitor);
|
||||
GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, GetSystemMetricsForDpi);
|
||||
GET_WINDOWS_FUNCTION_NO_TYPECHECK(user32_module, AdjustWindowRectExForDpi);
|
||||
@ -4724,18 +4820,28 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
|
||||
|
||||
static void wintw_set_title(TermWin *tw, const char *title, int codepage)
|
||||
{
|
||||
wchar_t *new_window_name = dup_mb_to_wc(codepage, 0, title);
|
||||
if (!wcscmp(new_window_name, window_name)) {
|
||||
sfree(new_window_name);
|
||||
return;
|
||||
}
|
||||
sfree(window_name);
|
||||
window_name = dup_mb_to_wc(codepage, 0, title);
|
||||
window_name = new_window_name;
|
||||
if (conf_get_bool(conf, CONF_win_name_always) || !IsIconic(wgs.term_hwnd))
|
||||
SetWindowTextW(wgs.term_hwnd, window_name);
|
||||
sw_SetWindowText(wgs.term_hwnd, window_name);
|
||||
}
|
||||
|
||||
static void wintw_set_icon_title(TermWin *tw, const char *title, int codepage)
|
||||
{
|
||||
wchar_t *new_icon_name = dup_mb_to_wc(codepage, 0, title);
|
||||
if (!wcscmp(new_icon_name, icon_name)) {
|
||||
sfree(new_icon_name);
|
||||
return;
|
||||
}
|
||||
sfree(icon_name);
|
||||
icon_name = dup_mb_to_wc(codepage, 0, title);
|
||||
icon_name = new_icon_name;
|
||||
if (!conf_get_bool(conf, CONF_win_name_always) && IsIconic(wgs.term_hwnd))
|
||||
SetWindowTextW(wgs.term_hwnd, icon_name);
|
||||
sw_SetWindowText(wgs.term_hwnd, icon_name);
|
||||
}
|
||||
|
||||
static void wintw_set_scrollbar(TermWin *tw, int total, int start, int page)
|
||||
@ -5641,23 +5747,24 @@ static bool is_full_screen()
|
||||
static bool get_fullscreen_rect(RECT * ss)
|
||||
{
|
||||
#if defined(MONITOR_DEFAULTTONEAREST) && !defined(NO_MULTIMON)
|
||||
if (p_GetMonitorInfoA && p_MonitorFromWindow) {
|
||||
HMONITOR mon;
|
||||
MONITORINFO mi;
|
||||
mon = MonitorFromWindow(wgs.term_hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
mon = p_MonitorFromWindow(wgs.term_hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
mi.cbSize = sizeof(mi);
|
||||
GetMonitorInfo(mon, &mi);
|
||||
p_GetMonitorInfoA(mon, &mi);
|
||||
|
||||
/* structure copy */
|
||||
*ss = mi.rcMonitor;
|
||||
return true;
|
||||
#else
|
||||
}
|
||||
#endif
|
||||
/* could also use code like this:
|
||||
ss->left = ss->top = 0;
|
||||
ss->right = GetSystemMetrics(SM_CXSCREEN);
|
||||
ss->bottom = GetSystemMetrics(SM_CYSCREEN);
|
||||
*/
|
||||
return GetClientRect(GetDesktopWindow(), ss);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user