diff options
| author | Alan Third | 2017-09-08 19:26:47 +0100 |
|---|---|---|
| committer | Alan Third | 2017-09-19 20:08:51 +0100 |
| commit | a5fec62b519ae8c0a6528366ac8b71cd0c7ac52e (patch) | |
| tree | f9b300285aacb4df9995ea5e4559663f2afee735 /src | |
| parent | 7b3d1c6beb54ef6c423a93df88aebfd6fecbe2c2 (diff) | |
| download | emacs-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.c | 5 | ||||
| -rw-r--r-- | src/nsterm.m | 158 | ||||
| -rw-r--r-- | src/termhooks.h | 4 |
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. | |||
| 9166 | This variable is ignored on Mac OS X < 10.7 and GNUstep. */); | 9283 | This 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. | ||
| 9289 | This 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. | ||
| 9294 | Nil or a non-number means use the default frame line height. | ||
| 9295 | This 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. | ||
| 9300 | This 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. */ |