aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Third2017-09-08 19:26:47 +0100
committerAlan Third2017-09-19 20:08:51 +0100
commita5fec62b519ae8c0a6528366ac8b71cd0c7ac52e (patch)
treef9b300285aacb4df9995ea5e4559663f2afee735 /src
parent7b3d1c6beb54ef6c423a93df88aebfd6fecbe2c2 (diff)
downloademacs-a5fec62b519ae8c0a6528366ac8b71cd0c7ac52e.tar.gz
emacs-a5fec62b519ae8c0a6528366ac8b71cd0c7ac52e.zip
Provide native touchpad scrolling on macOS
* etc/NEWS: Describe changes. * lisp/term/ns-win.el (mouse-wheel-scroll-amount, mouse-wheel-progressive-speed): Set to smarter values for macOS touchpads. * src/nsterm.m (emacsView::mouseDown): Use precise scrolling deltas to calculate scrolling for touchpads and mouse wheels. (syms_of_nsterm): Add variables 'ns-use-system-mwheel-acceleration', 'ns-touchpad-scroll-line-height' and 'ns-touchpad-use-momentum'. * src/keyboard.c (make_lispy_event): Pass on .arg when relevant. * src/termhooks.h (event_kind): Update comments re. WHEEL_EVENT. * lisp/mwheel.el (mwheel-scroll): Use line count. * lisp/subr.el (event-line-count): New function.
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c5
-rw-r--r--src/nsterm.m158
-rw-r--r--src/termhooks.h4
3 files changed, 153 insertions, 14 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index 4db50be855c..e8701b88708 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -5925,7 +5925,10 @@ make_lispy_event (struct input_event *event)
5925 ASIZE (wheel_syms)); 5925 ASIZE (wheel_syms));
5926 } 5926 }
5927 5927
5928 if (event->modifiers & (double_modifier | triple_modifier)) 5928 if (NUMBERP (event->arg))
5929 return list4 (head, position, make_number (double_click_count),
5930 event->arg);
5931 else if (event->modifiers & (double_modifier | triple_modifier))
5929 return list3 (head, position, make_number (double_click_count)); 5932 return list3 (head, position, make_number (double_click_count));
5930 else 5933 else
5931 return list2 (head, position); 5934 return list2 (head, position);
diff --git a/src/nsterm.m b/src/nsterm.m
index 27515335332..776635980e1 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -6498,24 +6498,139 @@ not_in_argv (NSString *arg)
6498 6498
6499 if ([theEvent type] == NSEventTypeScrollWheel) 6499 if ([theEvent type] == NSEventTypeScrollWheel)
6500 { 6500 {
6501 CGFloat delta = [theEvent deltaY]; 6501#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
6502 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */ 6502#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
6503 if (delta == 0) 6503 if ([theEvent respondsToSelector:@selector(hasPreciseScrollingDeltas)])
6504 { 6504 {
6505 delta = [theEvent deltaX]; 6505#endif
6506 if (delta == 0) 6506 /* If the input device is a touchpad or similar, use precise
6507 * scrolling deltas. These are measured in pixels, so we
6508 * have to add them up until they exceed one line height,
6509 * then we can send a scroll wheel event.
6510 *
6511 * If the device only has coarse scrolling deltas, like a
6512 * real mousewheel, the deltas represent a ratio of whole
6513 * lines, so round up the number of lines. This means we
6514 * always send one scroll event per click, but can still
6515 * scroll more than one line if the OS tells us to.
6516 */
6517 bool horizontal;
6518 int lines = 0;
6519 int scrollUp = NO;
6520
6521 /* FIXME: At the top or bottom of the buffer we should
6522 * ignore momentum-phase events. */
6523 if (! ns_touchpad_use_momentum
6524 && [theEvent momentumPhase] != NSEventPhaseNone)
6525 return;
6526
6527 if ([theEvent hasPreciseScrollingDeltas])
6507 { 6528 {
6508 NSTRACE_MSG ("deltaIsZero"); 6529 static int totalDeltaX, totalDeltaY;
6509 return; 6530 int lineHeight;
6531
6532 if (NUMBERP (ns_touchpad_scroll_line_height))
6533 lineHeight = XINT (ns_touchpad_scroll_line_height);
6534 else
6535 {
6536 /* FIXME: Use actual line height instead of the default. */
6537 lineHeight = default_line_pixel_height
6538 (XWINDOW (FRAME_SELECTED_WINDOW (emacsframe)));
6539 }
6540
6541 if ([theEvent phase] == NSEventPhaseBegan)
6542 {
6543 totalDeltaX = 0;
6544 totalDeltaY = 0;
6545 }
6546
6547 totalDeltaX += [theEvent scrollingDeltaX];
6548 totalDeltaY += [theEvent scrollingDeltaY];
6549
6550 /* Calculate the number of lines, if any, to scroll, and
6551 * reset the total delta for the direction we're NOT
6552 * scrolling so that small movements don't add up. */
6553 if (abs (totalDeltaX) > abs (totalDeltaY)
6554 && abs (totalDeltaX) > lineHeight)
6555 {
6556 horizontal = YES;
6557 scrollUp = totalDeltaX > 0;
6558
6559 lines = abs (totalDeltaX / lineHeight);
6560 totalDeltaX = totalDeltaX % lineHeight;
6561 totalDeltaY = 0;
6562 }
6563 else if (abs (totalDeltaY) >= abs (totalDeltaX)
6564 && abs (totalDeltaY) > lineHeight)
6565 {
6566 horizontal = NO;
6567 scrollUp = totalDeltaY > 0;
6568
6569 lines = abs (totalDeltaY / lineHeight);
6570 totalDeltaY = totalDeltaY % lineHeight;
6571 totalDeltaX = 0;
6572 }
6573
6574 if (lines > 1 && ! ns_use_system_mwheel_acceleration)
6575 lines = 1;
6510 } 6576 }
6511 emacs_event->kind = HORIZ_WHEEL_EVENT; 6577 else
6578 {
6579 CGFloat delta;
6580
6581 if ([theEvent scrollingDeltaY] == 0)
6582 {
6583 horizontal = YES;
6584 delta = [theEvent scrollingDeltaX];
6585 }
6586 else
6587 {
6588 horizontal = NO;
6589 delta = [theEvent scrollingDeltaY];
6590 }
6591
6592 lines = (ns_use_system_mwheel_acceleration)
6593 ? ceil (fabs (delta)) : 1;
6594
6595 scrollUp = delta > 0;
6596 }
6597
6598 if (lines == 0)
6599 return;
6600
6601 emacs_event->kind = horizontal ? HORIZ_WHEEL_EVENT : WHEEL_EVENT;
6602 emacs_event->arg = (make_number (lines));
6603
6604 emacs_event->code = 0;
6605 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
6606 (scrollUp ? up_modifier : down_modifier);
6607#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070
6512 } 6608 }
6513 else 6609 else
6514 emacs_event->kind = WHEEL_EVENT; 6610#endif
6611#endif /* defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 */
6612#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 1070
6613 {
6614 CGFloat delta = [theEvent deltaY];
6615 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
6616 if (delta == 0)
6617 {
6618 delta = [theEvent deltaX];
6619 if (delta == 0)
6620 {
6621 NSTRACE_MSG ("deltaIsZero");
6622 return;
6623 }
6624 emacs_event->kind = HORIZ_WHEEL_EVENT;
6625 }
6626 else
6627 emacs_event->kind = WHEEL_EVENT;
6515 6628
6516 emacs_event->code = 0; 6629 emacs_event->code = 0;
6517 emacs_event->modifiers = EV_MODIFIERS (theEvent) | 6630 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
6518 ((delta > 0) ? up_modifier : down_modifier); 6631 ((delta > 0) ? up_modifier : down_modifier);
6632 }
6633#endif
6519 } 6634 }
6520 else 6635 else
6521 { 6636 {
@@ -6524,9 +6639,11 @@ not_in_argv (NSString *arg)
6524 emacs_event->modifiers = EV_MODIFIERS (theEvent) 6639 emacs_event->modifiers = EV_MODIFIERS (theEvent)
6525 | EV_UDMODIFIERS (theEvent); 6640 | EV_UDMODIFIERS (theEvent);
6526 } 6641 }
6642
6527 XSETINT (emacs_event->x, lrint (p.x)); 6643 XSETINT (emacs_event->x, lrint (p.x));
6528 XSETINT (emacs_event->y, lrint (p.y)); 6644 XSETINT (emacs_event->y, lrint (p.y));
6529 EV_TRAILER (theEvent); 6645 EV_TRAILER (theEvent);
6646 return;
6530} 6647}
6531 6648
6532 6649
@@ -9166,6 +9283,23 @@ Note that this does not apply to images.
9166This variable is ignored on Mac OS X < 10.7 and GNUstep. */); 9283This variable is ignored on Mac OS X < 10.7 and GNUstep. */);
9167 ns_use_srgb_colorspace = YES; 9284 ns_use_srgb_colorspace = YES;
9168 9285
9286 DEFVAR_BOOL ("ns-use-system-mwheel-acceleration",
9287 ns_use_system_mwheel_acceleration,
9288 doc: /*Non-nil means use macOS's standard mouse wheel acceleration.
9289This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */);
9290 ns_use_system_mwheel_acceleration = YES;
9291
9292 DEFVAR_LISP ("ns-touchpad-scroll-line-height", ns_touchpad_scroll_line_height,
9293 doc: /*The number of pixels touchpad scrolling considers a line.
9294Nil or a non-number means use the default frame line height.
9295This variable is ignored on macOS < 10.7 and GNUstep. Default is nil. */);
9296 ns_touchpad_scroll_line_height = Qnil;
9297
9298 DEFVAR_BOOL ("ns-touchpad-use-momentum", ns_touchpad_use_momentum,
9299 doc: /*Non-nil means touchpad scrolling uses momentum.
9300This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */);
9301 ns_touchpad_use_momentum = YES;
9302
9169 /* TODO: move to common code */ 9303 /* TODO: move to common code */
9170 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, 9304 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
9171 doc: /* Which toolkit scroll bars Emacs uses, if any. 9305 doc: /* Which toolkit scroll bars Emacs uses, if any.
diff --git a/src/termhooks.h b/src/termhooks.h
index 97c128ba4e2..b5171bf1229 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -116,7 +116,9 @@ enum event_kind
116 .frame_or_window gives the frame 116 .frame_or_window gives the frame
117 the wheel event occurred in. 117 the wheel event occurred in.
118 .timestamp gives a timestamp (in 118 .timestamp gives a timestamp (in
119 milliseconds) for the event. */ 119 milliseconds) for the event.
120 .arg may contain the number of
121 lines to scroll. */
120 HORIZ_WHEEL_EVENT, /* A wheel event generated by a second 122 HORIZ_WHEEL_EVENT, /* A wheel event generated by a second
121 horizontal wheel that is present on some 123 horizontal wheel that is present on some
122 mice. See WHEEL_EVENT. */ 124 mice. See WHEEL_EVENT. */