aboutsummaryrefslogtreecommitdiffstats
path: root/src/w32term.c
diff options
context:
space:
mode:
authorEli Zaretskii2021-12-01 15:36:55 +0200
committerEli Zaretskii2021-12-01 15:36:55 +0200
commitbab29694047d060bb58ff88e1a4d2cc7ef05df2a (patch)
tree25dffd70f392ccace1007b53b491707ad44dda1a /src/w32term.c
parentc13b49a110ffd23975e98c053746054492a3908a (diff)
downloademacs-bab29694047d060bb58ff88e1a4d2cc7ef05df2a.tar.gz
emacs-bab29694047d060bb58ff88e1a4d2cc7ef05df2a.zip
Support precision mouse scrolling on MS-Windows
* src/w32fns.c (w32_wnd_proc): Pass the WM_SETTINGCHANGE message to the Lisp thread. * src/w32term.c (w32_construct_mouse_wheel): Support mice with precision scrolling wheel. (w32_get_mouse_wheel_vertical_delta): New function. (w32_read_socket): When the WM_SETTINGCHANGE is received, call 'w32_get_mouse_wheel_vertical_delta'. (w32_initialize): Call 'w32_get_mouse_wheel_vertical_delta' at startup. * src/nsterm.m (syms_of_nsterm): * src/haikuterm.c (syms_of_haikuterm): * src/xterm.c (syms_of_xterm): Remove window-system specific variables for coalescing mwheel events. * src/keyboard.c (syms_of_keyboard) <mwheel-coalesce-scroll-events>: New variable, to replace the above platform-specific ones. * doc/lispref/commands.texi (Misc Events): Improve wording of the description of mouse-wheel events.
Diffstat (limited to 'src/w32term.c')
-rw-r--r--src/w32term.c99
1 files changed, 94 insertions, 5 deletions
diff --git a/src/w32term.c b/src/w32term.c
index 07a5cd35649..6b7cbbea6ca 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -164,6 +164,10 @@ int last_scroll_bar_drag_pos;
164/* Keyboard code page - may be changed by language-change events. */ 164/* Keyboard code page - may be changed by language-change events. */
165int w32_keyboard_codepage; 165int w32_keyboard_codepage;
166 166
167/* The number of screen lines to scroll for the default mouse-wheel
168 scroll amount, given by WHEEL_DELTA. */
169static UINT w32_wheel_scroll_lines;
170
167#ifdef CYGWIN 171#ifdef CYGWIN
168int w32_message_fd = -1; 172int w32_message_fd = -1;
169#endif /* CYGWIN */ 173#endif /* CYGWIN */
@@ -272,6 +276,19 @@ XGetGCValues (void *ignore, XGCValues *gc,
272#endif 276#endif
273 277
274static void 278static void
279w32_get_mouse_wheel_vertical_delta (void)
280{
281 if (os_subtype != OS_SUBTYPE_NT)
282 return;
283
284 UINT scroll_lines;
285 BOOL ret = SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0,
286 &scroll_lines, 0);
287 if (ret)
288 w32_wheel_scroll_lines = scroll_lines;
289}
290
291static void
275w32_set_clip_rectangle (HDC hdc, RECT *rect) 292w32_set_clip_rectangle (HDC hdc, RECT *rect)
276{ 293{
277 if (rect) 294 if (rect)
@@ -3203,32 +3220,94 @@ w32_construct_mouse_wheel (struct input_event *result, W32Msg *msg,
3203{ 3220{
3204 POINT p; 3221 POINT p;
3205 int delta; 3222 int delta;
3223 static int sum_delta_y = 0;
3206 3224
3207 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT 3225 result->kind = msg->msg.message == WM_MOUSEHWHEEL ? HORIZ_WHEEL_EVENT
3208 : WHEEL_EVENT; 3226 : WHEEL_EVENT;
3209 result->code = 0; 3227 result->code = 0;
3210 result->timestamp = msg->msg.time; 3228 result->timestamp = msg->msg.time;
3229 result->arg = Qnil;
3211 3230
3212 /* A WHEEL_DELTA positive value indicates that the wheel was rotated 3231 /* A WHEEL_DELTA positive value indicates that the wheel was rotated
3213 forward, away from the user (up); a negative value indicates that 3232 forward, away from the user (up); a negative value indicates that
3214 the wheel was rotated backward, toward the user (down). */ 3233 the wheel was rotated backward, toward the user (down). */
3215 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam); 3234 delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
3235 if (delta == 0)
3236 {
3237 result->kind = NO_EVENT;
3238 return Qnil;
3239 }
3240
3241 /* With multiple monitors, we can legitimately get negative
3242 coordinates, so cast to short to interpret them correctly. */
3243 p.x = (short) LOWORD (msg->msg.lParam);
3244 p.y = (short) HIWORD (msg->msg.lParam);
3245
3246 if (eabs (delta) < WHEEL_DELTA)
3247 {
3248 /* This is high-precision mouse wheel, which sends
3249 fine-resolution wheel events. Produce a wheel event only if
3250 the conditions for sending such an event are fulfilled. */
3251 int scroll_unit = max (w32_wheel_scroll_lines, 1), nlines;
3252 double value_to_report;
3253
3254 /* w32_wheel_scroll_lines == INT_MAX means the user asked for
3255 "entire page" to be the scroll unit. We interpret that as
3256 the height of the window under the mouse pointer. */
3257 if (w32_wheel_scroll_lines == INT_MAX)
3258 {
3259 Lisp_Object window = window_from_coordinates (f, p.x, p.y, NULL,
3260 false, false);
3261 if (!WINDOWP (window))
3262 {
3263 result->kind = NO_EVENT;
3264 return Qnil;
3265 }
3266 scroll_unit = XWINDOW (window)->pixel_height;
3267 if (scroll_unit < 1) /* paranoia */
3268 scroll_unit = 1;
3269 }
3270
3271 /* If mwheel-coalesce-scroll-events is non-nil, report a wheel event
3272 only when we have accumulated enough delta's for WHEEL_DELTA. */
3273 if (mwheel_coalesce_scroll_events)
3274 {
3275 /* If the user changed the direction, reset the accumulated
3276 deltas. */
3277 if ((delta > 0) != (sum_delta_y > 0))
3278 sum_delta_y = 0;
3279 sum_delta_y += delta;
3280 /* https://docs.microsoft.com/en-us/previous-versions/ms997498(v=msdn.10) */
3281 if (eabs (sum_delta_y) < WHEEL_DELTA)
3282 {
3283 result->kind = NO_EVENT;
3284 return Qnil;
3285 }
3286 value_to_report =
3287 ((double)FRAME_LINE_HEIGHT (f) * scroll_unit)
3288 / ((double)WHEEL_DELTA / sum_delta_y);
3289 sum_delta_y = 0;
3290 }
3291 else
3292 value_to_report =
3293 ((double)FRAME_LINE_HEIGHT (f) * scroll_unit)
3294 / ((double)WHEEL_DELTA / delta);
3295 nlines = value_to_report / FRAME_LINE_HEIGHT (f) + 0.5;
3296 result->arg = list3 (make_fixnum (nlines),
3297 make_float (0.0),
3298 make_float (value_to_report));
3299 }
3216 3300
3217 /* The up and down modifiers indicate if the wheel was rotated up or 3301 /* The up and down modifiers indicate if the wheel was rotated up or
3218 down based on WHEEL_DELTA value. */ 3302 down based on WHEEL_DELTA value. */
3219 result->modifiers = (msg->dwModifiers 3303 result->modifiers = (msg->dwModifiers
3220 | ((delta < 0 ) ? down_modifier : up_modifier)); 3304 | ((delta < 0 ) ? down_modifier : up_modifier));
3221 3305
3222 /* With multiple monitors, we can legitimately get negative
3223 coordinates, so cast to short to interpret them correctly. */
3224 p.x = (short) LOWORD (msg->msg.lParam);
3225 p.y = (short) HIWORD (msg->msg.lParam);
3226 /* For the case that F's w32 window is not msg->msg.hwnd. */ 3306 /* For the case that F's w32 window is not msg->msg.hwnd. */
3227 ScreenToClient (FRAME_W32_WINDOW (f), &p); 3307 ScreenToClient (FRAME_W32_WINDOW (f), &p);
3228 XSETINT (result->x, p.x); 3308 XSETINT (result->x, p.x);
3229 XSETINT (result->y, p.y); 3309 XSETINT (result->y, p.y);
3230 XSETFRAME (result->frame_or_window, f); 3310 XSETFRAME (result->frame_or_window, f);
3231 result->arg = Qnil;
3232 return Qnil; 3311 return Qnil;
3233} 3312}
3234 3313
@@ -4905,6 +4984,14 @@ w32_read_socket (struct terminal *terminal,
4905 } 4984 }
4906 break; 4985 break;
4907 4986
4987 case WM_SETTINGCHANGE:
4988 /* We are only interested in changes of the number of lines
4989 to scroll when the vertical mouse wheel is moved. This
4990 is only supported on NT. */
4991 if (msg.msg.wParam == SPI_SETWHEELSCROLLLINES)
4992 w32_get_mouse_wheel_vertical_delta ();
4993 break;
4994
4908 case WM_KEYDOWN: 4995 case WM_KEYDOWN:
4909 case WM_SYSKEYDOWN: 4996 case WM_SYSKEYDOWN:
4910 f = w32_window_to_frame (dpyinfo, msg.msg.hwnd); 4997 f = w32_window_to_frame (dpyinfo, msg.msg.hwnd);
@@ -7522,6 +7609,8 @@ w32_initialize (void)
7522 horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border 7609 horizontal_scroll_bar_left_border = horizontal_scroll_bar_right_border
7523 = GetSystemMetrics (SM_CYHSCROLL); 7610 = GetSystemMetrics (SM_CYHSCROLL);
7524 } 7611 }
7612
7613 w32_get_mouse_wheel_vertical_delta ();
7525} 7614}
7526 7615
7527void 7616void