X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/3a9531212a6d0077e566912d4790020315d15eb1..d8d6c7e50e1fcf5171ec15f8a3e9bdcd141f0b64:/window.c diff --git a/window.c b/window.c index 1b61b6c6..59901010 100644 --- a/window.c +++ b/window.c @@ -67,9 +67,12 @@ #define VK_PROCESSKEY 0xE5 #endif -/* Needed for mouse wheel support and not defined in earlier SDKs. */ +/* Mouse wheel support. */ #ifndef WM_MOUSEWHEEL -#define WM_MOUSEWHEEL 0x020A +#define WM_MOUSEWHEEL 0x020A /* not defined in earlier SDKs */ +#endif +#ifndef WHEEL_DELTA +#define WHEEL_DELTA 120 #endif static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); @@ -81,6 +84,7 @@ static void init_fonts(int, int); static void another_font(int); static void deinit_fonts(void); static void set_input_locale(HKL); +static int do_mouse_wheel_msg(UINT message, WPARAM wParam, LPARAM lParam); static int is_full_screen(void); static void make_full_screen(void); @@ -100,9 +104,12 @@ static WPARAM pend_netevent_wParam = 0; static LPARAM pend_netevent_lParam = 0; static void enact_pending_netevent(void); static void flash_window(int mode); +static void sys_cursor_update(void); static time_t last_movement = 0; +static int caret_x = -1, caret_y = -1; + #define FONT_NORMAL 0 #define FONT_BOLD 1 #define FONT_UNDERLINE 2 @@ -152,6 +159,8 @@ static int compose_state = 0; static OSVERSIONINFO osVersion; +static UINT wm_mousewheel = WM_MOUSEWHEEL; + /* Dummy routine, only required in plink. */ void ldisc_update(int echo, int edit) { @@ -201,6 +210,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } /* + * If we're running a version of Windows that doesn't support + * WM_MOUSEWHEEL, find out what message number we should be + * using instead. + */ + if (osVersion.dwMajorVersion < 4 || + (osVersion.dwMajorVersion == 4 && + osVersion.dwPlatformId != VER_PLATFORM_WIN32_NT)) + wm_mousewheel = RegisterWindowMessage("MSWHEEL_ROLLMSG"); + + /* * See if we can find our Help file. */ { @@ -704,7 +723,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) timer_id = 0; } HideCaret(hwnd); - term_out(); + if (GetCapture() != hwnd) + term_out(); term_update(); ShowCaret(hwnd); @@ -1498,7 +1518,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, case WM_TIMER: if (pending_netevent) enact_pending_netevent(); - term_out(); + if (GetCapture() != hwnd) + term_out(); noise_regular(); HideCaret(hwnd); term_update(); @@ -1846,45 +1867,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, #define TO_CHR_X(x) ((((x)<0 ? (x)-font_width+1 : (x))-offset_width) / font_width) #define TO_CHR_Y(y) ((((y)<0 ? (y)-font_height+1: (y))-offset_height) / font_height) -#define WHEEL_DELTA 120 - case WM_MOUSEWHEEL: - { - wheel_accumulator += (short) HIWORD(wParam); - wParam = LOWORD(wParam); - - /* process events when the threshold is reached */ - while (abs(wheel_accumulator) >= WHEEL_DELTA) { - int b; - - /* reduce amount for next time */ - if (wheel_accumulator > 0) { - b = MBT_WHEEL_UP; - wheel_accumulator -= WHEEL_DELTA; - } else if (wheel_accumulator < 0) { - b = MBT_WHEEL_DOWN; - wheel_accumulator += WHEEL_DELTA; - } else - break; - - if (send_raw_mouse) { - /* send a mouse-down followed by a mouse up */ - - term_mouse(b, - MA_CLICK, - TO_CHR_X(X_POS(lParam)), - TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, - wParam & MK_CONTROL, is_alt_pressed()); - term_mouse(b, MA_RELEASE, TO_CHR_X(X_POS(lParam)), - TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, - wParam & MK_CONTROL, is_alt_pressed()); - } else { - /* trigger a scroll */ - term_scroll(0, - b == MBT_WHEEL_UP ? -rows / 2 : rows / 2); - } - } - return 0; - } case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: @@ -1957,7 +1939,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, */ noise_ultralight(lParam); - if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) { + if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) && + GetCapture() == hwnd) { Mouse_Button b; if (wParam & MK_LBUTTON) b = MBT_LEFT; @@ -2062,6 +2045,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, show_mouseptr(1); has_focus = FALSE; DestroyCaret(); + caret_x = caret_y = -1; /* ensure caret is replaced next time */ term_out(); term_update(); break; @@ -2178,6 +2162,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, case WM_FULLSCR_ON_MAX: fullscr_on_max = TRUE; break; + case WM_MOVE: + sys_cursor_update(); + break; case WM_SIZE: #ifdef RDB_DEBUG_PATCH debug((27, "WM_SIZE %s (%d,%d)", @@ -2261,6 +2248,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, reset_window(0); } } + sys_cursor_update(); return 0; case WM_VSCROLL: switch (LOWORD(wParam)) { @@ -2370,6 +2358,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, /* wParam == Font number */ /* lParam == Locale */ set_input_locale((HKL)lParam); + sys_cursor_update(); break; case WM_IME_NOTIFY: if(wParam == IMN_SETOPENSTATUS) { @@ -2442,6 +2431,56 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, SetCursor(LoadCursor(NULL, IDC_ARROW)); return TRUE; } + default: + if (message == wm_mousewheel) { + int shift_pressed=0, control_pressed=0, alt_pressed=0; + + if (message == WM_MOUSEWHEEL) { + wheel_accumulator += (short)HIWORD(wParam); + shift_pressed=LOWORD(wParam) & MK_SHIFT; + control_pressed=LOWORD(wParam) & MK_CONTROL; + } else { + BYTE keys[256]; + wheel_accumulator += (int)wParam; + if (GetKeyboardState(keys)!=0) { + shift_pressed=keys[VK_SHIFT]&0x80; + control_pressed=keys[VK_CONTROL]&0x80; + } + } + + /* process events when the threshold is reached */ + while (abs(wheel_accumulator) >= WHEEL_DELTA) { + int b; + + /* reduce amount for next time */ + if (wheel_accumulator > 0) { + b = MBT_WHEEL_UP; + wheel_accumulator -= WHEEL_DELTA; + } else if (wheel_accumulator < 0) { + b = MBT_WHEEL_DOWN; + wheel_accumulator += WHEEL_DELTA; + } else + break; + + if (send_raw_mouse && + !(cfg.mouse_override && shift_pressed)) { + /* send a mouse-down followed by a mouse up */ + term_mouse(b, + MA_CLICK, + TO_CHR_X(X_POS(lParam)), + TO_CHR_Y(Y_POS(lParam)), shift_pressed, + control_pressed, is_alt_pressed()); + term_mouse(b, MA_RELEASE, TO_CHR_X(X_POS(lParam)), + TO_CHR_Y(Y_POS(lParam)), shift_pressed, + control_pressed, is_alt_pressed()); + } else { + /* trigger a scroll */ + term_scroll(0, + b == MBT_WHEEL_UP ? -rows / 2 : rows / 2); + } + } + return 0; + } } return DefWindowProc(hwnd, message, wParam, lParam); @@ -2455,13 +2494,35 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, */ void sys_cursor(int x, int y) { + int cx, cy; + + if (!has_focus) return; + + /* + * Avoid gratuitously re-updating the cursor position and IMM + * window if there's no actual change required. + */ + cx = x * font_width + offset_width; + cy = y * font_height + offset_height; + if (cx == caret_x && cy == caret_y) + return; + caret_x = cx; + caret_y = cy; + + sys_cursor_update(); +} + +static void sys_cursor_update(void) +{ COMPOSITIONFORM cf; HIMC hIMC; if (!has_focus) return; - - SetCaretPos(x * font_width + offset_width, - y * font_height + offset_height); + + if (caret_x < 0 || caret_y < 0) + return; + + SetCaretPos(caret_x, caret_y); /* IMM calls on Win98 and beyond only */ if(osVersion.dwPlatformId == VER_PLATFORM_WIN32s) return; /* 3.11 */ @@ -2472,8 +2533,8 @@ void sys_cursor(int x, int y) /* we should have the IMM functions */ hIMC = ImmGetContext(hwnd); cf.dwStyle = CFS_POINT; - cf.ptCurrentPos.x = x * font_width + offset_width; - cf.ptCurrentPos.y = y * font_height + offset_height; + cf.ptCurrentPos.x = caret_x; + cf.ptCurrentPos.y = caret_y; ImmSetCompositionWindow(hIMC, &cf); ImmReleaseContext(hwnd, hIMC);