diff options
| author | Mattias EngdegÄrd | 2019-11-25 18:54:20 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2019-11-27 11:14:55 +0100 |
| commit | 215f678c7262db2ed353f2bf1e0a97c59a452605 (patch) | |
| tree | 0efa6ea5136c9125fab217463f3deb8ed9c1db63 /src | |
| parent | aa89c84e00d8dc85100e6fedab7631c415e6364d (diff) | |
| download | emacs-215f678c7262db2ed353f2bf1e0a97c59a452605.tar.gz emacs-215f678c7262db2ed353f2bf1e0a97c59a452605.zip | |
Fine-grained NS modifier key settings (bug#38296)
For the ns-KEY-modifier and ns-right-KEY-modifier variables, KEY
being 'control', 'command', 'alternate' and 'function', allow
values on the form (:ordinary SYMBOL :function :SYMBOL :mouse SYMBOL),
so that the key can be used for different modifiers (or none) in
different contexts. This is particularly useful for using the macOS
Option key for extended character entry while still using it as an
Emacs modifier for function keys and mouse clicks.
* src/nsterm.m (mod_of_kind, right_mod, nil_or_none): Helper functions.
(EV_MODIFIERS2): Add KIND argument.
(EV_MODIFIERS): Adapt call to EV_MODIFIERS2.
(ns_get_shifted_character): Use correct event kind for modifiers.
(ns-alternate-modifier, ns-right-alternate-modifier)
(ns-command-modifier, ns-right-command-modifier)
(ns-control-modifier, ns-right-control-modifier)
(ns-function-modifier): Rewrite doc strings for new data format.
(QCordinary, QCfunction, QCmouse): Define symbols.
* lisp/cus-start.el: Conform to new data types.
* doc/emacs/macos.texi (Mac / GNUstep Basics)
(Mac / GNUstep Customization): Improved documentation.
* etc/NEWS: Mention the change.
Diffstat (limited to 'src')
| -rw-r--r-- | src/nsterm.m | 150 |
1 files changed, 102 insertions, 48 deletions
diff --git a/src/nsterm.m b/src/nsterm.m index e1d745e332d..52a9830be82 100644 --- a/src/nsterm.m +++ b/src/nsterm.m | |||
| @@ -354,6 +354,19 @@ static CGPoint menu_mouse_point; | |||
| 354 | #define NSLeftAlternateKeyMask (0x000020 | NSEventModifierFlagOption) | 354 | #define NSLeftAlternateKeyMask (0x000020 | NSEventModifierFlagOption) |
| 355 | #define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption) | 355 | #define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption) |
| 356 | 356 | ||
| 357 | /* MODIFIER if a symbol; otherwise its property KIND, if a symbol. */ | ||
| 358 | static Lisp_Object | ||
| 359 | mod_of_kind (Lisp_Object modifier, Lisp_Object kind) | ||
| 360 | { | ||
| 361 | if (SYMBOLP (modifier)) | ||
| 362 | return modifier; | ||
| 363 | else | ||
| 364 | { | ||
| 365 | Lisp_Object val = Fplist_get (modifier, kind); | ||
| 366 | return SYMBOLP (val) ? val : Qnil; | ||
| 367 | } | ||
| 368 | } | ||
| 369 | |||
| 357 | static unsigned int | 370 | static unsigned int |
| 358 | ev_modifiers_helper (unsigned int flags, unsigned int left_mask, | 371 | ev_modifiers_helper (unsigned int flags, unsigned int left_mask, |
| 359 | unsigned int right_mask, unsigned int either_mask, | 372 | unsigned int right_mask, unsigned int either_mask, |
| @@ -380,30 +393,35 @@ ev_modifiers_helper (unsigned int flags, unsigned int left_mask, | |||
| 380 | return modifiers; | 393 | return modifiers; |
| 381 | } | 394 | } |
| 382 | 395 | ||
| 383 | #define EV_MODIFIERS2(flags) \ | 396 | #define EV_MODIFIERS2(flags, kind) \ |
| 384 | (((flags & NSEventModifierFlagHelp) ? \ | 397 | (((flags & NSEventModifierFlagHelp) ? \ |
| 385 | hyper_modifier : 0) \ | 398 | hyper_modifier : 0) \ |
| 386 | | ((flags & NSEventModifierFlagShift) ? \ | 399 | | ((flags & NSEventModifierFlagShift) ? \ |
| 387 | shift_modifier : 0) \ | 400 | shift_modifier : 0) \ |
| 388 | | ((flags & NS_FUNCTION_KEY_MASK) ? \ | 401 | | ((flags & NS_FUNCTION_KEY_MASK) \ |
| 389 | parse_solitary_modifier (ns_function_modifier) : 0) \ | 402 | ? parse_solitary_modifier (mod_of_kind (ns_function_modifier, \ |
| 403 | kind)) \ | ||
| 404 | : 0) \ | ||
| 390 | | ev_modifiers_helper (flags, NSLeftControlKeyMask, \ | 405 | | ev_modifiers_helper (flags, NSLeftControlKeyMask, \ |
| 391 | NSRightControlKeyMask, \ | 406 | NSRightControlKeyMask, \ |
| 392 | NSEventModifierFlagControl, \ | 407 | NSEventModifierFlagControl, \ |
| 393 | ns_control_modifier, \ | 408 | mod_of_kind (ns_control_modifier, kind), \ |
| 394 | ns_right_control_modifier) \ | 409 | mod_of_kind (ns_right_control_modifier, \ |
| 410 | kind)) \ | ||
| 395 | | ev_modifiers_helper (flags, NSLeftCommandKeyMask, \ | 411 | | ev_modifiers_helper (flags, NSLeftCommandKeyMask, \ |
| 396 | NSRightCommandKeyMask, \ | 412 | NSRightCommandKeyMask, \ |
| 397 | NSEventModifierFlagCommand, \ | 413 | NSEventModifierFlagCommand, \ |
| 398 | ns_command_modifier, \ | 414 | mod_of_kind (ns_command_modifier, kind), \ |
| 399 | ns_right_command_modifier) \ | 415 | mod_of_kind (ns_right_command_modifier, \ |
| 416 | kind)) \ | ||
| 400 | | ev_modifiers_helper (flags, NSLeftAlternateKeyMask, \ | 417 | | ev_modifiers_helper (flags, NSLeftAlternateKeyMask, \ |
| 401 | NSRightAlternateKeyMask, \ | 418 | NSRightAlternateKeyMask, \ |
| 402 | NSEventModifierFlagOption, \ | 419 | NSEventModifierFlagOption, \ |
| 403 | ns_alternate_modifier, \ | 420 | mod_of_kind (ns_alternate_modifier, kind), \ |
| 404 | ns_right_alternate_modifier)) | 421 | mod_of_kind (ns_right_alternate_modifier, \ |
| 422 | kind))) | ||
| 405 | 423 | ||
| 406 | #define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags]) | 424 | #define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags], QCmouse) |
| 407 | 425 | ||
| 408 | #define EV_UDMODIFIERS(e) \ | 426 | #define EV_UDMODIFIERS(e) \ |
| 409 | ((([e type] == NSEventTypeLeftMouseDown) ? down_modifier : 0) \ | 427 | ((([e type] == NSEventTypeLeftMouseDown) ? down_modifier : 0) \ |
| @@ -2599,6 +2617,18 @@ get_keysym_name (int keysym) | |||
| 2599 | } | 2617 | } |
| 2600 | 2618 | ||
| 2601 | #ifdef NS_IMPL_COCOA | 2619 | #ifdef NS_IMPL_COCOA |
| 2620 | static Lisp_Object | ||
| 2621 | right_mod (Lisp_Object left, Lisp_Object right) | ||
| 2622 | { | ||
| 2623 | return EQ (right, Qleft) ? left : right; | ||
| 2624 | } | ||
| 2625 | |||
| 2626 | static bool | ||
| 2627 | nil_or_none (Lisp_Object val) | ||
| 2628 | { | ||
| 2629 | return NILP (val) || EQ (val, Qnone); | ||
| 2630 | } | ||
| 2631 | |||
| 2602 | static UniChar | 2632 | static UniChar |
| 2603 | ns_get_shifted_character (NSEvent *event) | 2633 | ns_get_shifted_character (NSEvent *event) |
| 2604 | /* Look up the character corresponding to the key pressed on the | 2634 | /* Look up the character corresponding to the key pressed on the |
| @@ -2630,25 +2660,25 @@ ns_get_shifted_character (NSEvent *event) | |||
| 2630 | NSTRACE ("ns_get_shifted_character"); | 2660 | NSTRACE ("ns_get_shifted_character"); |
| 2631 | 2661 | ||
| 2632 | if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask | 2662 | if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask |
| 2633 | && (EQ (ns_right_alternate_modifier, Qnone) | 2663 | && nil_or_none (mod_of_kind (right_mod (ns_alternate_modifier, |
| 2634 | || (EQ (ns_right_alternate_modifier, Qleft) | 2664 | ns_right_alternate_modifier), |
| 2635 | && EQ (ns_alternate_modifier, Qnone)))) | 2665 | QCordinary))) |
| 2636 | modifiers |= rightOptionKey; | 2666 | modifiers |= rightOptionKey; |
| 2637 | 2667 | ||
| 2638 | if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask | 2668 | if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask |
| 2639 | && EQ (ns_alternate_modifier, Qnone)) | 2669 | && nil_or_none (mod_of_kind (ns_alternate_modifier, QCordinary))) |
| 2640 | modifiers |= optionKey; | 2670 | modifiers |= optionKey; |
| 2641 | 2671 | ||
| 2642 | if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask | 2672 | if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask |
| 2643 | && (EQ (ns_right_command_modifier, Qnone) | 2673 | && nil_or_none (mod_of_kind (right_mod (ns_command_modifier, |
| 2644 | || (EQ (ns_right_command_modifier, Qleft) | 2674 | ns_right_command_modifier), |
| 2645 | && EQ (ns_command_modifier, Qnone)))) | 2675 | QCordinary))) |
| 2646 | /* Carbon doesn't differentiate between left and right command | 2676 | /* Carbon doesn't differentiate between left and right command |
| 2647 | keys. */ | 2677 | keys. */ |
| 2648 | modifiers |= cmdKey; | 2678 | modifiers |= cmdKey; |
| 2649 | 2679 | ||
| 2650 | if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask | 2680 | if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask |
| 2651 | && EQ (ns_command_modifier, Qnone)) | 2681 | && nil_or_none (mod_of_kind (ns_command_modifier, QCordinary))) |
| 2652 | modifiers |= cmdKey; | 2682 | modifiers |= cmdKey; |
| 2653 | 2683 | ||
| 2654 | result = UCKeyTranslate (layout, [event keyCode], kUCKeyActionDown, | 2684 | result = UCKeyTranslate (layout, [event keyCode], kUCKeyActionDown, |
| @@ -6287,7 +6317,8 @@ not_in_argv (NSString *arg) | |||
| 6287 | modifier keys, which returns 0 for shift-like modifiers. | 6317 | modifier keys, which returns 0 for shift-like modifiers. |
| 6288 | Therefore its return value is the set of control-like | 6318 | Therefore its return value is the set of control-like |
| 6289 | modifiers. */ | 6319 | modifiers. */ |
| 6290 | emacs_event->modifiers = EV_MODIFIERS2 (flags); | 6320 | Lisp_Object kind = fnKeysym ? QCfunction : QCordinary; |
| 6321 | emacs_event->modifiers = EV_MODIFIERS2 (flags, kind); | ||
| 6291 | 6322 | ||
| 6292 | /* Function keys (such as the F-keys, arrow keys, etc.) set | 6323 | /* Function keys (such as the F-keys, arrow keys, etc.) set |
| 6293 | modifiers as though the fn key has been pressed when it | 6324 | modifiers as though the fn key has been pressed when it |
| @@ -6296,7 +6327,9 @@ not_in_argv (NSString *arg) | |||
| 6296 | <home>). We need to unset the fn modifier in these cases. | 6327 | <home>). We need to unset the fn modifier in these cases. |
| 6297 | FIXME: Can we avoid setting it in the first place? */ | 6328 | FIXME: Can we avoid setting it in the first place? */ |
| 6298 | if (fnKeysym && (flags & NS_FUNCTION_KEY_MASK)) | 6329 | if (fnKeysym && (flags & NS_FUNCTION_KEY_MASK)) |
| 6299 | emacs_event->modifiers ^= parse_solitary_modifier (ns_function_modifier); | 6330 | emacs_event->modifiers |
| 6331 | ^= parse_solitary_modifier (mod_of_kind (ns_function_modifier, | ||
| 6332 | QCfunction)); | ||
| 6300 | 6333 | ||
| 6301 | if (NS_KEYLOG) | 6334 | if (NS_KEYLOG) |
| 6302 | fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n", | 6335 | fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n", |
| @@ -9399,57 +9432,75 @@ syms_of_nsterm (void) | |||
| 9399 | 9432 | ||
| 9400 | DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier, | 9433 | DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier, |
| 9401 | "This variable describes the behavior of the alternate or option key.\n\ | 9434 | "This variable describes the behavior of the alternate or option key.\n\ |
| 9402 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9435 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9403 | that key.\n\ | 9436 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9404 | Set to none means that the alternate / option key is not interpreted by Emacs\n\ | 9437 | separately for ordinary keys, function keys, and mouse events.\n\ |
| 9405 | at all, allowing it to be used at a lower level for accented character entry."); | 9438 | \n\ |
| 9439 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9440 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9406 | ns_alternate_modifier = Qmeta; | 9441 | ns_alternate_modifier = Qmeta; |
| 9407 | 9442 | ||
| 9408 | DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier, | 9443 | DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier, |
| 9409 | "This variable describes the behavior of the right alternate or option key.\n\ | 9444 | "This variable describes the behavior of the right alternate or option key.\n\ |
| 9410 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9445 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9411 | that key.\n\ | 9446 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9412 | Set to left means be the same key as `ns-alternate-modifier'.\n\ | 9447 | separately for ordinary keys, function keys, and mouse events.\n\ |
| 9413 | Set to none means that the alternate / option key is not interpreted by Emacs\n\ | 9448 | It can also be `left' to use the value of `ns-alternate-modifier' instead.\n\ |
| 9414 | at all, allowing it to be used at a lower level for accented character entry."); | 9449 | \n\ |
| 9450 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9451 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9415 | ns_right_alternate_modifier = Qleft; | 9452 | ns_right_alternate_modifier = Qleft; |
| 9416 | 9453 | ||
| 9417 | DEFVAR_LISP ("ns-command-modifier", ns_command_modifier, | 9454 | DEFVAR_LISP ("ns-command-modifier", ns_command_modifier, |
| 9418 | "This variable describes the behavior of the command key.\n\ | 9455 | "This variable describes the behavior of the command key.\n\ |
| 9419 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9456 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9420 | that key."); | 9457 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9458 | separately for ordinary keys, function keys, and mouse events.\n\ | ||
| 9459 | \n\ | ||
| 9460 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9461 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9421 | ns_command_modifier = Qsuper; | 9462 | ns_command_modifier = Qsuper; |
| 9422 | 9463 | ||
| 9423 | DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier, | 9464 | DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier, |
| 9424 | "This variable describes the behavior of the right command key.\n\ | 9465 | "This variable describes the behavior of the right command key.\n\ |
| 9425 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9466 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9426 | that key.\n\ | 9467 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9427 | Set to left means be the same key as `ns-command-modifier'.\n\ | 9468 | separately for ordinary keys, function keys, and mouse events.\n\ |
| 9428 | Set to none means that the command / option key is not interpreted by Emacs\n\ | 9469 | It can also be `left' to use the value of `ns-command-modifier' instead.\n\ |
| 9429 | at all, allowing it to be used at a lower level for accented character entry."); | 9470 | \n\ |
| 9471 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9472 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9430 | ns_right_command_modifier = Qleft; | 9473 | ns_right_command_modifier = Qleft; |
| 9431 | 9474 | ||
| 9432 | DEFVAR_LISP ("ns-control-modifier", ns_control_modifier, | 9475 | DEFVAR_LISP ("ns-control-modifier", ns_control_modifier, |
| 9433 | "This variable describes the behavior of the control key.\n\ | 9476 | "This variable describes the behavior of the control key.\n\ |
| 9434 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9477 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9435 | that key."); | 9478 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9479 | separately for ordinary keys, function keys, and mouse events.\n\ | ||
| 9480 | \n\ | ||
| 9481 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9482 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9436 | ns_control_modifier = Qcontrol; | 9483 | ns_control_modifier = Qcontrol; |
| 9437 | 9484 | ||
| 9438 | DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier, | 9485 | DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier, |
| 9439 | "This variable describes the behavior of the right control key.\n\ | 9486 | "This variable describes the behavior of the right control key.\n\ |
| 9440 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9487 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9441 | that key.\n\ | 9488 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9442 | Set to left means be the same key as `ns-control-modifier'.\n\ | 9489 | separately for ordinary keys, function keys, and mouse events.\n\ |
| 9443 | Set to none means that the control / option key is not interpreted by Emacs\n\ | 9490 | It can also be `left' to use the value of `ns-control-modifier' instead.\n\ |
| 9444 | at all, allowing it to be used at a lower level for accented character entry."); | 9491 | \n\ |
| 9492 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9493 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9445 | ns_right_control_modifier = Qleft; | 9494 | ns_right_control_modifier = Qleft; |
| 9446 | 9495 | ||
| 9447 | DEFVAR_LISP ("ns-function-modifier", ns_function_modifier, | 9496 | DEFVAR_LISP ("ns-function-modifier", ns_function_modifier, |
| 9448 | "This variable describes the behavior of the function key (on laptops).\n\ | 9497 | "This variable describes the behavior of the function (fn) key.\n\ |
| 9449 | Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\ | 9498 | Either SYMBOL, describing the behaviour for any event,\n\ |
| 9450 | that key.\n\ | 9499 | or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\ |
| 9451 | Set to none means that the function key is not interpreted by Emacs at all,\n\ | 9500 | separately for ordinary keys, function keys, and mouse events.\n\ |
| 9452 | allowing it to be used at a lower level for accented character entry."); | 9501 | \n\ |
| 9502 | Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\ | ||
| 9503 | If `none', the key is ignored by Emacs and retains its standard meaning."); | ||
| 9453 | ns_function_modifier = Qnone; | 9504 | ns_function_modifier = Qnone; |
| 9454 | 9505 | ||
| 9455 | DEFVAR_LISP ("ns-antialias-text", ns_antialias_text, | 9506 | DEFVAR_LISP ("ns-antialias-text", ns_antialias_text, |
| @@ -9529,6 +9580,9 @@ This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); | |||
| 9529 | 9580 | ||
| 9530 | DEFSYM (Qcocoa, "cocoa"); | 9581 | DEFSYM (Qcocoa, "cocoa"); |
| 9531 | DEFSYM (Qgnustep, "gnustep"); | 9582 | DEFSYM (Qgnustep, "gnustep"); |
| 9583 | DEFSYM (QCordinary, ":ordinary"); | ||
| 9584 | DEFSYM (QCfunction, ":function"); | ||
| 9585 | DEFSYM (QCmouse, ":mouse"); | ||
| 9532 | 9586 | ||
| 9533 | #ifdef NS_IMPL_COCOA | 9587 | #ifdef NS_IMPL_COCOA |
| 9534 | Fprovide (Qcocoa, Qnil); | 9588 | Fprovide (Qcocoa, Qnil); |