unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#38296: Allow Option key to be modifier for non-char key and mouse events
@ 2019-11-20 10:55 Mattias Engdegård
  2019-11-21 18:39 ` Mattias Engdegård
  0 siblings, 1 reply; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-20 10:55 UTC (permalink / raw)
  To: 38296

[-- Attachment #1: Type: text/plain, Size: 812 bytes --]

Mac users, especially those of us with a non-US keyboard, need the Option keys for entering various characters, and thus set 'ns-alternate-modifier' to nil, or use 'ns-right-alternate-modifier' to employ only one of them for this purpose. However, this prevents use of that key as modifier for function keys (arrows, backspace etc) or mouse actions.

This patch adds the variable 'ns-alternate-modifier-char-entry' which, when non-nil, inhibits the Option key translation to Emacs modifiers for character keys but allows it for any other event. For example, setting

(setq ns-alternate-modifier 'super)
(setq ns-alternate-modifier-char-entry t)

makes Option act as Super with function keys and mouse clicks, but retains the standard macOS semantics for character entry (for example, Option + p = π).


[-- Attachment #2: 0001-Add-ns-alternate-modifier-char-entry.patch --]
[-- Type: application/octet-stream, Size: 7468 bytes --]

From 57e5811920211a41cfd97db9da30acebc32024e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Tue, 19 Nov 2019 20:54:49 +0100
Subject: [PATCH] Add ns-alternate-modifier-char-entry

Allow the Option keys to be used for normal character entry while
having them generate Emacs modifiers for other events
by setting 'ns-alternate-modifier-char-entry' to non-nil.

* doc/emacs/macos.texi (Mac / GNUstep Basics): Document the variable.
* lisp/cus-start.el (standard): Allow customisation.
* src/nsterm.m (EV_MODIFIERS2): Add argument.
(EV_MODIFIERS): Adapt EV_MODIFIERS2 invocation.
(ns_get_shifted_character, [EmacsView keyDown:]): Use the new variable.
(syms_of_nsterm): Define the new variable.
* etc/NEWS: Mention the new variable.
---
 doc/emacs/macos.texi |  6 ++++++
 etc/NEWS             |  6 ++++++
 lisp/cus-start.el    |  1 +
 src/nsterm.m         | 35 +++++++++++++++++++++++++----------
 4 files changed, 38 insertions(+), 10 deletions(-)

diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index d9920957ad..85ede7bd68 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -61,6 +61,12 @@ Mac / GNUstep Basics
 ignore them, in which case you get the default behavior of macOS
 accentuation system from the right @key{Option} key.
 
+@vindex ns-alternate-modifier-char-entry
+  To make the @key{Option} keys retain their macOS behaviour for
+entering characters but work as Emacs modifiers with function keys and
+mouse actions, set the @code{ns-alternate-modifier-char-entry}
+variable to a non-nil value.
+
   @kbd{S-mouse-1} adjusts the region to the click position,
 just like @kbd{mouse-3} (@code{mouse-save-then-kill}); it does not pop
 up a menu for changing the default face, as @kbd{S-mouse-1} normally
diff --git a/etc/NEWS b/etc/NEWS
index db00d40bb6..75f54304fe 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3218,6 +3218,12 @@ Previously it was supported only in the Cygwin-w32 build.
 ** Emacs now handles key combinations involving the macOS "command"
 and "option" modifier keys more correctly.
 
++++
+** New user option 'ns-alternate-modifier-char-entry'.
+Set to non-nil to allow the macOS "option" keys to be used for normal
+character entry while treating them as Emacs modifiers for function keys
+and mouse events.
+
 ** The special handling of 'frame-title-format' on NS where setting it
 to 't' would enable the macOS proxy icon has been replaced with a
 separate variable, 'ns-use-proxy-icon'.  'frame-title-format' will now
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index e4b6d8f2d6..9d50108204 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -470,6 +470,7 @@ minibuffer-prompt-properties--setter
 		      (const control) (const meta)
 		      (const alt) (const hyper)
 		      (const super)) "23.3")
+	     (ns-alternate-modifier-char-entry ns boolean "27.1")
 	     (ns-function-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as function)" none)
diff --git a/src/nsterm.m b/src/nsterm.m
index e1d745e332..38a404620d 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -380,7 +380,7 @@ - (NSColor *)colorUsingDefaultColorSpace
   return modifiers;
 }
 
-#define EV_MODIFIERS2(flags)                                            \
+#define EV_MODIFIERS2(flags, enable_alternate_mod)                      \
   (((flags & NSEventModifierFlagHelp) ?                                 \
     hyper_modifier : 0)                                                 \
    | ((flags & NSEventModifierFlagShift) ?                              \
@@ -397,13 +397,15 @@ - (NSColor *)colorUsingDefaultColorSpace
                           NSEventModifierFlagCommand,                   \
                           ns_command_modifier,                          \
                           ns_right_command_modifier)                    \
-   | ev_modifiers_helper (flags, NSLeftAlternateKeyMask,                \
-                          NSRightAlternateKeyMask,                      \
-                          NSEventModifierFlagOption,                    \
-                          ns_alternate_modifier,                        \
-                          ns_right_alternate_modifier))
+   | (enable_alternate_mod                                              \
+      ? ev_modifiers_helper (flags, NSLeftAlternateKeyMask,             \
+                             NSRightAlternateKeyMask,                   \
+                             NSEventModifierFlagOption,                 \
+                             ns_alternate_modifier,                     \
+                             ns_right_alternate_modifier)               \
+      : 0))
 
-#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags])
+#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags], true)
 
 #define EV_UDMODIFIERS(e)                                      \
     ((([e type] == NSEventTypeLeftMouseDown) ? down_modifier : 0)       \
@@ -2630,13 +2632,15 @@ so some key presses (TAB) are swallowed by the system.  */
   NSTRACE ("ns_get_shifted_character");
 
   if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask
-      && (EQ (ns_right_alternate_modifier, Qnone)
+      && (ns_alternate_modifier_char_entry
+          || EQ (ns_right_alternate_modifier, Qnone)
           || (EQ (ns_right_alternate_modifier, Qleft)
               && EQ (ns_alternate_modifier, Qnone))))
     modifiers |= rightOptionKey;
 
   if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
-      && EQ (ns_alternate_modifier, Qnone))
+      && (ns_alternate_modifier_char_entry
+          || EQ (ns_alternate_modifier, Qnone)))
     modifiers |= optionKey;
 
   if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask
@@ -6287,7 +6291,8 @@ In that case we use UCKeyTranslate (ns_get_shifted_character)
          modifier keys, which returns 0 for shift-like modifiers.
          Therefore its return value is the set of control-like
          modifiers.  */
-      emacs_event->modifiers = EV_MODIFIERS2 (flags);
+      bool enable_alt = fnKeysym || !ns_alternate_modifier_char_entry;
+      emacs_event->modifiers = EV_MODIFIERS2 (flags, enable_alt);
 
       /* Function keys (such as the F-keys, arrow keys, etc.) set
          modifiers as though the fn key has been pressed when it
@@ -9414,6 +9419,16 @@ Convert an X font name (XLFD) to an NS font name.
 at all, allowing it to be used at a lower level for accented character entry.");
   ns_right_alternate_modifier = Qleft;
 
+  DEFVAR_BOOL ("ns-alternate-modifier-char-entry",
+               ns_alternate_modifier_char_entry,
+               "Whether the option or alternate keys are used for character entry.\n\
+When non-nil, the alternate / option keys work as Emacs modifiers for\n\
+function keys and mouse actions but not with character-generating keys.\n\
+When nil, the keys are interpreted by Emacs for all events.\n\
+In either case, `ns-alternate-modifier' and `ns-right-alternate-modifier'\n\
+describe what Emacs modifiers are being generated.");
+  ns_alternate_modifier_char_entry = false;
+
   DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
                "This variable describes the behavior of the command key.\n\
 Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-- 
2.21.0 (Apple Git-122)


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-20 10:55 bug#38296: Allow Option key to be modifier for non-char key and mouse events Mattias Engdegård
@ 2019-11-21 18:39 ` Mattias Engdegård
  2019-11-21 21:12   ` Alan Third
  0 siblings, 1 reply; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-21 18:39 UTC (permalink / raw)
  To: 38296; +Cc: Alan Third

It was pointed out to me that it would be useful to set this behaviour individually for either Option key.
This can be accomplished in various ways. For example, ns-alternate-modifier-char-entry could be changed from a boolean into taking either of the values nil, left, right or both, indicating to which Option key it applies.
Or we could simply use two separate boolean variables. I'd appreciate advice from the NS maintainers about what practice is best.






^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-21 18:39 ` Mattias Engdegård
@ 2019-11-21 21:12   ` Alan Third
  2019-11-22 20:01     ` Mattias Engdegård
  2019-11-25 19:15     ` Mattias Engdegård
  0 siblings, 2 replies; 13+ messages in thread
From: Alan Third @ 2019-11-21 21:12 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: 38296

On Thu, Nov 21, 2019 at 07:39:49PM +0100, Mattias Engdegård wrote:
> It was pointed out to me that it would be useful to set this
> behaviour individually for either Option key. This can be
> accomplished in various ways. For example,
> ns-alternate-modifier-char-entry could be changed from a boolean
> into taking either of the values nil, left, right or both,
> indicating to which Option key it applies. Or we could simply use
> two separate boolean variables. I'd appreciate advice from the NS
> maintainers about what practice is best.

I was thinking about this and although the patch looks good to me, I
don’t find the variable name very descriptive. Perhaps it would be
better to go with something like ns-alternate-modifier-function-only?

Also probably best to add an ns-option-... alias too.

Do you think this functionality will only be required for the
alt/option key or will there be a demand to add it for command too? In
my experience the characters available via command are rather more
obscure, but I’ve little experience with non‐UK keyboards.

Anyway, as to your question, I think I prefer the two variable
approach. It mirrors the existing modifier variables.

Thanks for working on this.
-- 
Alan Third





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-21 21:12   ` Alan Third
@ 2019-11-22 20:01     ` Mattias Engdegård
  2019-11-25 19:15     ` Mattias Engdegård
  1 sibling, 0 replies; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-22 20:01 UTC (permalink / raw)
  To: Alan Third; +Cc: 38296

[-- Attachment #1: Type: text/plain, Size: 1343 bytes --]

21 nov. 2019 kl. 22.12 skrev Alan Third <alan@idiocy.org>:

> I was thinking about this and although the patch looks good to me, I
> don’t find the variable name very descriptive. Perhaps it would be
> better to go with something like ns-alternate-modifier-function-only?

Right. I wasn't satisfied with the name either, and ended up with ns-{left,right}-alternate-for-char-entry, which seemed more to the point.

> Also probably best to add an ns-option-... alias too.

Done. At first I thought it was just for compatibility and thus superfluous, but you are right --- the keys have always been Option on Macs; Alternate (or Alt) are from NeXT.

> Do you think this functionality will only be required for the
> alt/option key or will there be a demand to add it for command too? In
> my experience the characters available via command are rather more
> obscure, but I’ve little experience with non‐UK keyboards.

I've never seen Command be used to select characters at all. Some elaborate input methods?

> Anyway, as to your question, I think I prefer the two variable
> approach. It mirrors the existing modifier variables.

Agreed. As noted above, I used symmetric variables for the left and right option keys, both booleans, instead of a special 'left' value.

Thanks for the review; new patch attached.


[-- Attachment #2: 0001-Add-ns-left-right-alternate-for-char-entry.patch --]
[-- Type: application/octet-stream, Size: 10856 bytes --]

From 04a084cebc7ad77a6d11839b524f0441f66f7562 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Tue, 19 Nov 2019 20:54:49 +0100
Subject: [PATCH] Add ns-{left,right}-alternate-for-char-entry

Allow the left and right Option keys to be used for normal character
entry while having them generate Emacs modifiers for other events by
setting 'ns-left-alternate-for-char-entry' and
'ns-eight-alternate-for-char-entry', respectively, to non-nil.

The variables have the aliases
'ns-{left,right}-option-for-char-entry', following other variables.

* doc/emacs/macos.texi (Mac / GNUstep Basics): Document the variables.
* lisp/cus-start.el (standard): Allow customisation.
* src/nsterm.m (ev_modifiers_helper): Simplify.
(right_modifier): New helper function.
(EV_MODIFIERS2): Add arguments, use helper.
(EV_MODIFIERS): Adapt EV_MODIFIERS2 invocation.
(ns_get_shifted_character, [EmacsView keyDown:]): Use the new variables.
(syms_of_nsterm): Define the new variables.
* etc/NEWS: Mention the new variables.
* lisp/term/ns-win.el: Add variables aliases.
---
 doc/emacs/macos.texi |  9 +++++++
 etc/NEWS             |  6 +++++
 lisp/cus-start.el    |  2 ++
 lisp/term/ns-win.el  |  8 ++++++-
 src/nsterm.m         | 57 +++++++++++++++++++++++++++++++++++---------
 5 files changed, 70 insertions(+), 12 deletions(-)

diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index d9920957ad..ae2b6c0774 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -61,6 +61,15 @@ Mac / GNUstep Basics
 ignore them, in which case you get the default behavior of macOS
 accentuation system from the right @key{Option} key.
 
+@vindex ns-left-alternate-for-char-entry
+@vindex ns-right-alternate-for-char-entry
+  To make the left and right @key{Option} keys retain their macOS
+behaviour for entering characters but work as Emacs modifiers with
+function keys and mouse actions, set the
+@code{ns-left-alternate-for-char-entry} and
+@code{ns-right-alternate-for-char-entry} variables, respectively, to a
+non-nil value.
+
   @kbd{S-mouse-1} adjusts the region to the click position,
 just like @kbd{mouse-3} (@code{mouse-save-then-kill}); it does not pop
 up a menu for changing the default face, as @kbd{S-mouse-1} normally
diff --git a/etc/NEWS b/etc/NEWS
index 9dd573bd97..4998e7047e 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3229,6 +3229,12 @@ Previously it was supported only in the Cygwin-w32 build.
 ** Emacs now handles key combinations involving the macOS "command"
 and "option" modifier keys more correctly.
 
++++
+** New user options 'ns-{left,right}-option-for-char-entry'.
+Set to non-nil to allow the respective macOS "option" keys to be used
+for normal character entry while treating them as Emacs modifiers for
+function keys and mouse events.
+
 ** The special handling of 'frame-title-format' on NS where setting it
 to 't' would enable the macOS proxy icon has been replaced with a
 separate variable, 'ns-use-proxy-icon'.  'frame-title-format' will now
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index e4b6d8f2d6..81883bf1bd 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -470,6 +470,8 @@ minibuffer-prompt-properties--setter
 		      (const control) (const meta)
 		      (const alt) (const hyper)
 		      (const super)) "23.3")
+	     (ns-left-alternate-for-char-entry ns boolean "27.1")
+	     (ns-right-alternate-for-char-entry ns boolean "27.1")
 	     (ns-function-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as function)" none)
diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el
index 1841e679ac..432fa6040d 100644
--- a/lisp/term/ns-win.el
+++ b/lisp/term/ns-win.el
@@ -541,11 +541,17 @@ ns-alternate-modifier
 (defvar ns-right-alternate-modifier)
 (defvar ns-right-command-modifier)
 (defvar ns-right-control-modifier)
+(defvar ns-left-alternate-for-char-entry)
+(defvar ns-right-alternate-for-char-entry)
 
 ;; You say tomAYto, I say tomAHto..
 (with-no-warnings
   (defvaralias 'ns-option-modifier 'ns-alternate-modifier)
-  (defvaralias 'ns-right-option-modifier 'ns-right-alternate-modifier))
+  (defvaralias 'ns-right-option-modifier 'ns-right-alternate-modifier)
+  (defvaralias 'ns-left-option-for-char-entry
+               'ns-left-alternate-for-char-entry)
+  (defvaralias 'ns-right-option-for-char-entry
+               'ns-right-alternate-for-char-entry))
 
 (defun ns-do-hide-emacs ()
   (interactive)
diff --git a/src/nsterm.m b/src/nsterm.m
index e1d745e332..15cd79d97c 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -364,8 +364,7 @@ - (NSColor *)colorUsingDefaultColorSpace
   if (flags & either_mask)
     {
       BOOL left_key = (flags & left_mask) == left_mask;
-      BOOL right_key = (flags & right_mask) == right_mask
-        && ! EQ (right_modifier, Qleft);
+      BOOL right_key = (flags & right_mask) == right_mask;
 
       if (right_key)
         modifiers |= parse_solitary_modifier (right_modifier);
@@ -380,7 +379,14 @@ - (NSColor *)colorUsingDefaultColorSpace
   return modifiers;
 }
 
-#define EV_MODIFIERS2(flags)                                            \
+/* Effective right modifier, since RIGHT_MOD can be `left'.  */
+static Lisp_Object
+right_modifier (Lisp_Object left_mod, Lisp_Object right_mod)
+{
+  return EQ (right_mod, Qleft) ? left_mod : right_mod;
+}
+
+#define EV_MODIFIERS2(flags, left_alt, right_alt)                       \
   (((flags & NSEventModifierFlagHelp) ?                                 \
     hyper_modifier : 0)                                                 \
    | ((flags & NSEventModifierFlagShift) ?                              \
@@ -391,19 +397,24 @@ - (NSColor *)colorUsingDefaultColorSpace
                           NSRightControlKeyMask,                        \
                           NSEventModifierFlagControl,                   \
                           ns_control_modifier,                          \
-                          ns_right_control_modifier)                    \
+                          right_modifier (ns_control_modifier,          \
+                                          ns_right_control_modifier))   \
    | ev_modifiers_helper (flags, NSLeftCommandKeyMask,                  \
                           NSRightCommandKeyMask,                        \
                           NSEventModifierFlagCommand,                   \
                           ns_command_modifier,                          \
-                          ns_right_command_modifier)                    \
+                          right_modifier (ns_command_modifier,          \
+                                          ns_right_command_modifier))   \
    | ev_modifiers_helper (flags, NSLeftAlternateKeyMask,                \
                           NSRightAlternateKeyMask,                      \
                           NSEventModifierFlagOption,                    \
-                          ns_alternate_modifier,                        \
-                          ns_right_alternate_modifier))
+                          left_alt ? ns_alternate_modifier : Qnil,      \
+                          (right_alt                                    \
+                           ? right_modifier (ns_alternate_modifier,     \
+                                             ns_right_alternate_modifier) \
+                           : Qnil)))
 
-#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags])
+#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags], true, true)
 
 #define EV_UDMODIFIERS(e)                                      \
     ((([e type] == NSEventTypeLeftMouseDown) ? down_modifier : 0)       \
@@ -2630,13 +2641,15 @@ so some key presses (TAB) are swallowed by the system.  */
   NSTRACE ("ns_get_shifted_character");
 
   if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask
-      && (EQ (ns_right_alternate_modifier, Qnone)
+      && (ns_right_alternate_for_char_entry
+          || EQ (ns_right_alternate_modifier, Qnone)
           || (EQ (ns_right_alternate_modifier, Qleft)
               && EQ (ns_alternate_modifier, Qnone))))
     modifiers |= rightOptionKey;
 
   if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
-      && EQ (ns_alternate_modifier, Qnone))
+      && (ns_left_alternate_for_char_entry
+          || EQ (ns_alternate_modifier, Qnone)))
     modifiers |= optionKey;
 
   if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask
@@ -6287,7 +6300,9 @@ In that case we use UCKeyTranslate (ns_get_shifted_character)
          modifier keys, which returns 0 for shift-like modifiers.
          Therefore its return value is the set of control-like
          modifiers.  */
-      emacs_event->modifiers = EV_MODIFIERS2 (flags);
+      bool left_alt = fnKeysym || !ns_left_alternate_for_char_entry;
+      bool right_alt = fnKeysym || !ns_right_alternate_for_char_entry;
+      emacs_event->modifiers = EV_MODIFIERS2 (flags, left_alt, right_alt);
 
       /* Function keys (such as the F-keys, arrow keys, etc.) set
          modifiers as though the fn key has been pressed when it
@@ -9414,6 +9429,26 @@ Convert an X font name (XLFD) to an NS font name.
 at all, allowing it to be used at a lower level for accented character entry.");
   ns_right_alternate_modifier = Qleft;
 
+  DEFVAR_BOOL ("ns-left-alternate-for-char-entry",
+               ns_left_alternate_for_char_entry,
+               "Whether the left option or alternate key is used for character entry.\n\
+When non-nil, the left alternate / option key works as an Emacs modifier for\n\
+function keys and mouse actions but not with character-generating keys.\n\
+When nil, the key is interpreted by Emacs for all events.\n\
+In either case, `ns-alternate-modifier' describes what Emacs modifier\n\
+is being generated.");
+  ns_left_alternate_for_char_entry = false;
+
+  DEFVAR_BOOL ("ns-right-alternate-for-char-entry",
+               ns_right_alternate_for_char_entry,
+               "Whether the right option or alternate key is used for character entry.\n\
+When non-nil, the right alternate / option key works as an Emacs modifier for\n\
+function keys and mouse actions but not with character-generating keys.\n\
+When nil, the key is interpreted by Emacs for all events.\n\
+In either case, `ns-right-alternate-modifier' describes what Emacs modifier\n\
+is being generated.");
+  ns_right_alternate_for_char_entry = false;
+
   DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
                "This variable describes the behavior of the command key.\n\
 Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-- 
2.21.0 (Apple Git-122)


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-21 21:12   ` Alan Third
  2019-11-22 20:01     ` Mattias Engdegård
@ 2019-11-25 19:15     ` Mattias Engdegård
  2019-11-26 20:33       ` Alan Third
  2019-11-27  6:40       ` Richard Stallman
  1 sibling, 2 replies; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-25 19:15 UTC (permalink / raw)
  To: Alan Third; +Cc: 38296

[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]

21 nov. 2019 kl. 22.12 skrev Alan Third <alan@idiocy.org>:

> Do you think this functionality will only be required for the
> alt/option key or will there be a demand to add it for command too? In
> my experience the characters available via command are rather more
> obscure, but I’ve little experience with non‐UK keyboards.

Looking at Mitsuharu Yamamoto's Mac port made me change my mind: it solves the problem by allowing the variables to have values on the form (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), defining each modifier key separately for ordinary keys, function keys and mouse events.

This is more flexible, and turned out to be rather simple to implement, so I think this is better than adding variables. I did it for all ns-KEY-modifier and ns-right-KEY-modifier variables (KEY being control, command, alternate and function), since it seemed silly not to. The relevant macOS-specific documentation was improved as well.

Doing so also reduces gratuitous incompatibility with the Mac port.

Here is the new patch. Maybe we can get it done before Eli branches off Emacs 27.


[-- Attachment #2: 0001-Fine-grained-NS-modifier-key-settings-bug-38296.patch --]
[-- Type: application/octet-stream, Size: 26781 bytes --]

From a430631efdfdb1a668f1b0ffd6f6f857e0df3466 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mattias=20Engdeg=C3=A5rd?= <mattiase@acm.org>
Date: Mon, 25 Nov 2019 18:54:20 +0100
Subject: [PATCH] Fine-grained NS modifier key settings (bug#38296)

For the ns-MOD-modifier and ns-right-MOD-modifier variables, MOD
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.
---
 doc/emacs/macos.texi |  60 +++++++++++++----
 etc/NEWS             |   6 ++
 lisp/cus-start.el    |  97 ++++++++++++++++++++++++----
 src/nsterm.m         | 150 +++++++++++++++++++++++++++++--------------
 4 files changed, 241 insertions(+), 72 deletions(-)

diff --git a/doc/emacs/macos.texi b/doc/emacs/macos.texi
index d9920957ad..fe944e411d 100644
--- a/doc/emacs/macos.texi
+++ b/doc/emacs/macos.texi
@@ -48,18 +48,8 @@ Mac / GNUstep Basics
 Emacs provides a set of key bindings using this modifier key that mimic
 other Mac / GNUstep applications (@pxref{Mac / GNUstep Events}).  You
 can change these bindings in the usual way (@pxref{Key Bindings}).
-
-@vindex ns-alternate-modifier
-@vindex ns-right-alternate-modifier
-  The variable @code{ns-right-alternate-modifier} controls the
-behavior of the right @key{Alt} and @key{Option} keys.  These keys
-behave like the left-hand keys if the value is @code{left} (the
-default).  A value of @code{control}, @code{meta}, @code{alt},
-@code{super}, or @code{hyper} makes them behave like the corresponding
-modifier keys; a value of @code{left} means be the same key as
-@code{ns-alternate-modifier}; a value of @code{none} tells Emacs to
-ignore them, in which case you get the default behavior of macOS
-accentuation system from the right @key{Option} key.
+The modifiers themselves can be customised;
+@pxref{Mac / GNUstep Customization}.
 
   @kbd{S-mouse-1} adjusts the region to the click position,
 just like @kbd{mouse-3} (@code{mouse-save-then-kill}); it does not pop
@@ -107,6 +97,52 @@ Mac / GNUstep Customization
 keys and the fullscreen behavior.  To see all such options, use
 @kbd{M-x customize-group @key{RET} ns @key{RET}}.
 
+@subsection Modifier keys
+
+The following variables control the behaviour of the actual modifier
+keys:
+
+@table @code
+@vindex ns-alternate-modifier
+@vindex ns-right-alternate-modifier
+@item ns-alternate-modifier
+@itemx ns-right-alternate-modifier
+The left and right @key{Option} or @key{Alt} keys.
+
+@vindex ns-command-modifier
+@vindex ns-right-command-modifier
+@item ns-command-modifier
+@itemx ns-right-command-modifier
+The left and right @key{Command} keys.
+
+@vindex ns-control-modifier
+@vindex ns-right-control-modifier
+@item ns-control-modifier
+@itemx ns-right-control-modifier
+The left and right @key{Control} keys.
+
+@vindex ns-function-modifier
+@item ns-function-modifier
+The @key{Function} (fn) key.
+@end table
+
+The value of each variable is either a symbol, describing the key for
+any purpose, or a list on the form
+@code{(:ordinary @var{symbol} :function @var{symbol} :mouse @var{symbol})},
+which describes the modifier when used with ordinary keys, function keys
+(that do not produce a character, such as arrow keys), and mouse clicks.
+
+If the @var{symbol} is one of @code{control}, @code{meta}, @code{alt},
+@code{super} or @code{hyper}, this describes the Emacs modifier it
+represents.  If @var{symbol} is @code{none}, Emacs does not use the
+key, which retains its standard behaviour.  For instance, the
+@key{Option} key in macOS is normally used for composing additional
+characters.
+
+The variables for right-hand keys, like @code{ns-right-alternate-modifier},
+may also be set to @code{left}, which means to use the same behaviour as
+the corresponding left-hand key.
+
 @subsection Font Panel
 
 @findex ns-popup-font-panel
diff --git a/etc/NEWS b/etc/NEWS
index edd536f2f0..7056b99878 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -3241,6 +3241,12 @@ Previously it was supported only in the Cygwin-w32 build.
 ** Emacs now handles key combinations involving the macOS "command"
 and "option" modifier keys more correctly.
 
+** MacOS modifier key behaviour is now more adjustable.
+The behaviour of the macOS "Option", "Command", "Control" and
+"Function" keys can now be specified separately for use with
+ordinary keys, function keys and mouse clicks.  This allows using them
+in their standard macOS way for composing characters.
+
 ** The special handling of 'frame-title-format' on NS where setting it
 to 't' would enable the macOS proxy icon has been replaced with a
 separate variable, 'ns-use-proxy-icon'.  'frame-title-format' will now
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index e4b6d8f2d6..1c497ee5ae 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -424,16 +424,23 @@ minibuffer-prompt-properties--setter
 	     ;; msdos.c
 	     (dos-unsupported-char-glyph display integer)
 	     ;; nsterm.m
-             ;;
-             ;; FIXME: Why does ⌃ use nil instead of none?  Also the
-             ;; description is confusing; setting it to nil disables ⌃
-             ;; entirely.
 	     (ns-control-modifier
 	      ns
-	      (choice (const :tag "No modifier" nil)
+	      (choice (const :tag "No modifier" none)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "23.1")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "23.1")
 	     (ns-right-control-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as control)" none)
@@ -441,13 +448,35 @@ minibuffer-prompt-properties--setter
 			     left)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "24.1")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "24.1")
 	     (ns-command-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as layout switch)" none)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "23.1")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "23.1")
 	     (ns-right-command-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as layout switch)" none)
@@ -455,13 +484,35 @@ minibuffer-prompt-properties--setter
 			     left)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "24.1")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "24.1")
 	     (ns-alternate-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as alternate/option)" none)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "23.1")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "23.1")
 	     (ns-right-alternate-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as alternate/option)" none)
@@ -469,13 +520,35 @@ minibuffer-prompt-properties--setter
 			     left)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "23.3")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "23.3")
 	     (ns-function-modifier
 	      ns
 	      (choice (const :tag "No modifier (work as function)" none)
 		      (const control) (const meta)
 		      (const alt) (const hyper)
-		      (const super)) "23.1")
+		      (const super)
+                      (plist :key-type (choice (const :ordinary)
+                                               (const :function)
+                                               (const :mouse))
+                             :value-type (choice (const control)
+                                                 (const meta)
+                                                 (const alt)
+                                                 (const hyper)
+                                                 (const super)
+                                                 (const :tag "No modifier"
+                                                        none))))
+              "23.1")
 	     (ns-antialias-text ns boolean "23.1")
 	     (ns-auto-hide-menu-bar ns boolean "24.1")
              (ns-confirm-quit ns boolean "25.1")
diff --git a/src/nsterm.m b/src/nsterm.m
index e1d745e332..52a9830be8 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -354,6 +354,19 @@ - (NSColor *)colorUsingDefaultColorSpace
 #define NSLeftAlternateKeyMask  (0x000020 | NSEventModifierFlagOption)
 #define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption)
 
+/* MODIFIER if a symbol; otherwise its property KIND, if a symbol.  */
+static Lisp_Object
+mod_of_kind (Lisp_Object modifier, Lisp_Object kind)
+{
+  if (SYMBOLP (modifier))
+    return modifier;
+  else
+    {
+      Lisp_Object val = Fplist_get (modifier, kind);
+      return SYMBOLP (val) ? val : Qnil;
+    }
+}
+
 static unsigned int
 ev_modifiers_helper (unsigned int flags, unsigned int left_mask,
                      unsigned int right_mask, unsigned int either_mask,
@@ -380,30 +393,35 @@ - (NSColor *)colorUsingDefaultColorSpace
   return modifiers;
 }
 
-#define EV_MODIFIERS2(flags)                                            \
+#define EV_MODIFIERS2(flags, kind)                                      \
   (((flags & NSEventModifierFlagHelp) ?                                 \
     hyper_modifier : 0)                                                 \
    | ((flags & NSEventModifierFlagShift) ?                              \
       shift_modifier : 0)                                               \
-   | ((flags & NS_FUNCTION_KEY_MASK) ?                                  \
-      parse_solitary_modifier (ns_function_modifier) : 0)               \
+   | ((flags & NS_FUNCTION_KEY_MASK)                                    \
+      ? parse_solitary_modifier (mod_of_kind (ns_function_modifier,     \
+                                              kind))                    \
+      : 0)                                                              \
    | ev_modifiers_helper (flags, NSLeftControlKeyMask,                  \
                           NSRightControlKeyMask,                        \
                           NSEventModifierFlagControl,                   \
-                          ns_control_modifier,                          \
-                          ns_right_control_modifier)                    \
+                          mod_of_kind (ns_control_modifier, kind),      \
+                          mod_of_kind (ns_right_control_modifier,       \
+                                       kind))                           \
    | ev_modifiers_helper (flags, NSLeftCommandKeyMask,                  \
                           NSRightCommandKeyMask,                        \
                           NSEventModifierFlagCommand,                   \
-                          ns_command_modifier,                          \
-                          ns_right_command_modifier)                    \
+                          mod_of_kind (ns_command_modifier, kind),      \
+                          mod_of_kind (ns_right_command_modifier,       \
+                                       kind))                           \
    | ev_modifiers_helper (flags, NSLeftAlternateKeyMask,                \
                           NSRightAlternateKeyMask,                      \
                           NSEventModifierFlagOption,                    \
-                          ns_alternate_modifier,                        \
-                          ns_right_alternate_modifier))
+                          mod_of_kind (ns_alternate_modifier, kind),    \
+                          mod_of_kind (ns_right_alternate_modifier,     \
+                                       kind)))
 
-#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags])
+#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags], QCmouse)
 
 #define EV_UDMODIFIERS(e)                                      \
     ((([e type] == NSEventTypeLeftMouseDown) ? down_modifier : 0)       \
@@ -2599,6 +2617,18 @@ so some key presses (TAB) are swallowed by the system.  */
 }
 
 #ifdef NS_IMPL_COCOA
+static Lisp_Object
+right_mod (Lisp_Object left, Lisp_Object right)
+{
+  return EQ (right, Qleft) ? left : right;
+}
+
+static bool
+nil_or_none (Lisp_Object val)
+{
+  return NILP (val) || EQ (val, Qnone);
+}
+
 static UniChar
 ns_get_shifted_character (NSEvent *event)
 /* Look up the character corresponding to the key pressed on the
@@ -2630,25 +2660,25 @@ so some key presses (TAB) are swallowed by the system.  */
   NSTRACE ("ns_get_shifted_character");
 
   if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask
-      && (EQ (ns_right_alternate_modifier, Qnone)
-          || (EQ (ns_right_alternate_modifier, Qleft)
-              && EQ (ns_alternate_modifier, Qnone))))
+      && nil_or_none (mod_of_kind (right_mod (ns_alternate_modifier,
+                                              ns_right_alternate_modifier),
+                                   QCordinary)))
     modifiers |= rightOptionKey;
 
   if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask
-      && EQ (ns_alternate_modifier, Qnone))
+      && nil_or_none (mod_of_kind (ns_alternate_modifier, QCordinary)))
     modifiers |= optionKey;
 
   if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask
-      && (EQ (ns_right_command_modifier, Qnone)
-          || (EQ (ns_right_command_modifier, Qleft)
-              && EQ (ns_command_modifier, Qnone))))
+      && nil_or_none (mod_of_kind (right_mod (ns_command_modifier,
+                                              ns_right_command_modifier),
+                                   QCordinary)))
     /* Carbon doesn't differentiate between left and right command
        keys.  */
     modifiers |= cmdKey;
 
   if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask
-      && EQ (ns_command_modifier, Qnone))
+      && nil_or_none (mod_of_kind (ns_command_modifier, QCordinary)))
     modifiers |= cmdKey;
 
   result = UCKeyTranslate (layout, [event keyCode], kUCKeyActionDown,
@@ -6287,7 +6317,8 @@ In that case we use UCKeyTranslate (ns_get_shifted_character)
          modifier keys, which returns 0 for shift-like modifiers.
          Therefore its return value is the set of control-like
          modifiers.  */
-      emacs_event->modifiers = EV_MODIFIERS2 (flags);
+      Lisp_Object kind = fnKeysym ? QCfunction : QCordinary;
+      emacs_event->modifiers = EV_MODIFIERS2 (flags, kind);
 
       /* Function keys (such as the F-keys, arrow keys, etc.) set
          modifiers as though the fn key has been pressed when it
@@ -6296,7 +6327,9 @@ In that case we use UCKeyTranslate (ns_get_shifted_character)
          <home>).  We need to unset the fn modifier in these cases.
          FIXME: Can we avoid setting it in the first place?  */
       if (fnKeysym && (flags & NS_FUNCTION_KEY_MASK))
-        emacs_event->modifiers ^= parse_solitary_modifier (ns_function_modifier);
+        emacs_event->modifiers
+          ^= parse_solitary_modifier (mod_of_kind (ns_function_modifier,
+                                                   QCfunction));
 
       if (NS_KEYLOG)
         fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",
@@ -9399,57 +9432,75 @@ Convert an X font name (XLFD) to an NS font name.
 
   DEFVAR_LISP ("ns-alternate-modifier", ns_alternate_modifier,
                "This variable describes the behavior of the alternate or option key.\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.\n\
-Set to none means that the alternate / option key is not interpreted by Emacs\n\
-at all, allowing it to be used at a lower level for accented character entry.");
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_alternate_modifier = Qmeta;
 
   DEFVAR_LISP ("ns-right-alternate-modifier", ns_right_alternate_modifier,
                "This variable describes the behavior of the right alternate or option key.\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.\n\
-Set to left means be the same key as `ns-alternate-modifier'.\n\
-Set to none means that the alternate / option key is not interpreted by Emacs\n\
-at all, allowing it to be used at a lower level for accented character entry.");
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+It can also be `left' to use the value of `ns-alternate-modifier' instead.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_right_alternate_modifier = Qleft;
 
   DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
                "This variable describes the behavior of the command key.\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.");
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_command_modifier = Qsuper;
 
   DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
                "This variable describes the behavior of the right command key.\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.\n\
-Set to left means be the same key as `ns-command-modifier'.\n\
-Set to none means that the command / option key is not interpreted by Emacs\n\
-at all, allowing it to be used at a lower level for accented character entry.");
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+It can also be `left' to use the value of `ns-command-modifier' instead.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_right_command_modifier = Qleft;
 
   DEFVAR_LISP ("ns-control-modifier", ns_control_modifier,
                "This variable describes the behavior of the control key.\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.");
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_control_modifier = Qcontrol;
 
   DEFVAR_LISP ("ns-right-control-modifier", ns_right_control_modifier,
                "This variable describes the behavior of the right control key.\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.\n\
-Set to left means be the same key as `ns-control-modifier'.\n\
-Set to none means that the control / option key is not interpreted by Emacs\n\
-at all, allowing it to be used at a lower level for accented character entry.");
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+It can also be `left' to use the value of `ns-control-modifier' instead.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_right_control_modifier = Qleft;
 
   DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
-               "This variable describes the behavior of the function key (on laptops).\n\
-Set to the symbol control, meta, alt, super, or hyper means it is taken to be\n\
-that key.\n\
-Set to none means that the function key is not interpreted by Emacs at all,\n\
-allowing it to be used at a lower level for accented character entry.");
+               "This variable describes the behavior of the function (fn) key.\n\
+Either SYMBOL, describing the behaviour for any event,\n\
+or (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), describing behaviour\n\
+separately for ordinary keys, function keys, and mouse events.\n\
+\n\
+Each SYMBOL is `control', `meta', `alt', `super', `hyper' or `none'.\n\
+If `none', the key is ignored by Emacs and retains its standard meaning.");
   ns_function_modifier = Qnone;
 
   DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
@@ -9529,6 +9580,9 @@ Nil means use fullscreen the old (< 10.7) way.  The old way works better with
 
   DEFSYM (Qcocoa, "cocoa");
   DEFSYM (Qgnustep, "gnustep");
+  DEFSYM (QCordinary, ":ordinary");
+  DEFSYM (QCfunction, ":function");
+  DEFSYM (QCmouse, ":mouse");
 
 #ifdef NS_IMPL_COCOA
   Fprovide (Qcocoa, Qnil);
-- 
2.21.0 (Apple Git-122.2)


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-25 19:15     ` Mattias Engdegård
@ 2019-11-26 20:33       ` Alan Third
  2019-11-26 21:36         ` Mattias Engdegård
  2019-11-27  6:40       ` Richard Stallman
  1 sibling, 1 reply; 13+ messages in thread
From: Alan Third @ 2019-11-26 20:33 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: 38296

On Mon, Nov 25, 2019 at 08:15:31PM +0100, Mattias Engdegård wrote:
> 21 nov. 2019 kl. 22.12 skrev Alan Third <alan@idiocy.org>:
> 
> > Do you think this functionality will only be required for the
> > alt/option key or will there be a demand to add it for command too? In
> > my experience the characters available via command are rather more
> > obscure, but I’ve little experience with non‐UK keyboards.
> 
> Looking at Mitsuharu Yamamoto's Mac port made me change my mind: it
> solves the problem by allowing the variables to have values on the
> form (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), defining
> each modifier key separately for ordinary keys, function keys and
> mouse events.

I had wondered about doing something like this, but not as flexible.
Is this the exact interface used by the Mac port? I’m not keen on the
word ‘ordinary’, but there’s no use in us doing something different.

> This is more flexible, and turned out to be rather simple to
> implement, so I think this is better than adding variables. I did it
> for all ns-KEY-modifier and ns-right-KEY-modifier variables (KEY
> being control, command, alternate and function), since it seemed
> silly not to. The relevant macOS-specific documentation was improved
> as well.

Thanks, it looks good to me. I’ve got a few nitpicks re. the
documentation:

+The modifiers themselves can be customised;

I think that should be a colon at the end, not a semi‐colon, although
my grasp of semi‐colon use is tenuous at best.

+The value of each variable is either a symbol, describing the key for
+any purpose, or a list on the form
                         ^
                        of

+@key{Option} key in macOS is normally used for composing additional

I would remove the word ‘normally’. I think it’s redundant since we’re
already talking about ‘standard behaviour’.

Unless anyone else has objections I don’t see any reason not to push
this.
-- 
Alan Third





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-26 20:33       ` Alan Third
@ 2019-11-26 21:36         ` Mattias Engdegård
  2019-11-26 22:03           ` Alan Third
  2019-11-27  4:51           ` Eli Zaretskii
  0 siblings, 2 replies; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-26 21:36 UTC (permalink / raw)
  To: Alan Third; +Cc: 38296

26 nov. 2019 kl. 21.33 skrev Alan Third <alan@idiocy.org>:

> I had wondered about doing something like this, but not as flexible.
> Is this the exact interface used by the Mac port? I’m not keen on the
> word ‘ordinary’, but there’s no use in us doing something different.

Yes, it's the exact interface, except that the Mac port also allows an optional :button property for emulating multi-button mice. I didn't bother including that, but nothing prevents adding it later on.

> Thanks, it looks good to me. I’ve got a few nitpicks re. the
> documentation:

Those are always welcome!

> +The modifiers themselves can be customised;
> 
> I think that should be a colon at the end, not a semi‐colon, although
> my grasp of semi‐colon use is tenuous at best.

A @pxref command immediately follows, so the entire sentence would come out as

  The modifiers themselves can be customised; see Mac / GNUstep Customization.

Wouldn't the semicolon be more appropriate there? It does not really precede an elaboration, just another main clause.
I'm no native English speaker, though.

> +The value of each variable is either a symbol, describing the key for
> +any purpose, or a list on the form
>                         ^
>                        of

I'm torn here. What about 'having' instead?

> +@key{Option} key in macOS is normally used for composing additional
> 
> I would remove the word ‘normally’. I think it’s redundant since we’re
> already talking about ‘standard behaviour’.

Yes, but the phrase is then conditional on the symbol actually being 'none'.
Perhaps replacing 'normally' with 'then' would do?

> Unless anyone else has objections I don’t see any reason not to push
> this.

Thank you very much for the review!






^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-26 21:36         ` Mattias Engdegård
@ 2019-11-26 22:03           ` Alan Third
  2019-11-27 10:50             ` Mattias Engdegård
  2019-11-27  4:51           ` Eli Zaretskii
  1 sibling, 1 reply; 13+ messages in thread
From: Alan Third @ 2019-11-26 22:03 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: 38296

On Tue, Nov 26, 2019 at 10:36:32PM +0100, Mattias Engdegård wrote:
> 26 nov. 2019 kl. 21.33 skrev Alan Third <alan@idiocy.org>:
> 
> > I had wondered about doing something like this, but not as flexible.
> > Is this the exact interface used by the Mac port? I’m not keen on the
> > word ‘ordinary’, but there’s no use in us doing something different.
> 
> Yes, it's the exact interface, except that the Mac port also allows
> an optional :button property for emulating multi-button mice. I
> didn't bother including that, but nothing prevents adding it later
> on.

I’m happy with that then.

> > +The modifiers themselves can be customised;
> > 
> > I think that should be a colon at the end, not a semi‐colon, although
> > my grasp of semi‐colon use is tenuous at best.
> 
> A @pxref command immediately follows, so the entire sentence would come out as
> 
>   The modifiers themselves can be customised; see Mac / GNUstep Customization.
> 
> Wouldn't the semicolon be more appropriate there? It does not really precede an elaboration, just another main clause.
> I'm no native English speaker, though.

I’m always suspicious of semi-colons because there are two types of
English speakers: those who don’t know how they’re used and therefore
don’t use them, and those who don’t know how they’re used and
therefore use them everywhere. ;)

I’ve had a quick look through the Emacs documentation and I found at
least one other example of using the semi‐colon like this, so I’m
happy leaving it.

> > +The value of each variable is either a symbol, describing the key for
> > +any purpose, or a list on the form
> >                         ^
> >                        of
> 
> I'm torn here. What about 'having' instead?

Having works, but the phrase is ‘of the form’.

    https://en.wikipedia.org/wiki/Of_the_form

I actually just assumed it was a typo. :)

> > +@key{Option} key in macOS is normally used for composing additional
> > 
> > I would remove the word ‘normally’. I think it’s redundant since we’re
> > already talking about ‘standard behaviour’.
> 
> Yes, but the phrase is then conditional on the symbol actually being 'none'.
> Perhaps replacing 'normally' with 'then' would do?

Yes, sounds good.

Oh, and thank you for actually documenting this. It was on my todo
list for the Emacs 27 release.

-- 
Alan Third





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-26 21:36         ` Mattias Engdegård
  2019-11-26 22:03           ` Alan Third
@ 2019-11-27  4:51           ` Eli Zaretskii
  1 sibling, 0 replies; 13+ messages in thread
From: Eli Zaretskii @ 2019-11-27  4:51 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: alan, 38296

> From: Mattias Engdegård <mattiase@acm.org>
> Date: Tue, 26 Nov 2019 22:36:32 +0100
> Cc: 38296@debbugs.gnu.org
> 
>   The modifiers themselves can be customised; see Mac / GNUstep Customization.

Btw, "customised" is not the US English spelling; please fix before
pushing.





^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-25 19:15     ` Mattias Engdegård
  2019-11-26 20:33       ` Alan Third
@ 2019-11-27  6:40       ` Richard Stallman
  2019-11-27 10:45         ` Mattias Engdegård
  1 sibling, 1 reply; 13+ messages in thread
From: Richard Stallman @ 2019-11-27  6:40 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: alan, 38296

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

  > Looking at Mitsuharu Yamamoto's Mac port made me change my mind: it solves the problem by allowing the variables to have values on the form (:ordinary SYMBOL :function SYMBOL :mouse SYMBOL), defining each modifier key separately for ordinary keys, function keys and mouse events.

I'd like to understand what that feature does, but I can't tell from
that text.  Does it come with any documentation?  If so, coulod you
please show it?

Also, are you proposing we implement this for ALL platforms (that
would be clean and simple, in principle)?  Or just SOME platforms?

-- 
Dr Richard Stallman
Founder, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-27  6:40       ` Richard Stallman
@ 2019-11-27 10:45         ` Mattias Engdegård
  2019-11-28  4:17           ` Richard Stallman
  0 siblings, 1 reply; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-27 10:45 UTC (permalink / raw)
  To: Richard Stallman; +Cc: alan, 38296

27 nov. 2019 kl. 07.40 skrev Richard Stallman <rms@gnu.org>:

> I'd like to understand what that feature does, but I can't tell from
> that text.  Does it come with any documentation?  If so, coulod you
> please show it?

This text is part of the documentation of the mac-KEY-modifier variables in the Mac port:

---
The property list form can include the `:button' property for button
number mapping, which becomes active when the value of
`mac-emulate-three-button-mouse' is nil.  The `:button' property can
be either a positive integer specifying the destination of the primary
button only, or a list (VALUE-FOR-PRIMARY-BUTTON VALUE-FOR-MOUSE-2
VALUE-FOR-MOUSE-3 ...) of positive integers specifying the
destinations of multiple buttons in order.  Note that the secondary
button and the button 3 (usually the wheel button) correspond to
mouse-3 and mouse-2 respectively if the value of
`mac-wheel-button-is-mouse-2' is non-nil (default), and mouse-2 and
mouse-3 respectively otherwise.  If a button is mapped to the same
number as its source, then it behaves as if the button were not mapped
so the `:mouse' property becomes in effect instead.
---

> Also, are you proposing we implement this for ALL platforms (that
> would be clean and simple, in principle)?  Or just SOME platforms?

The variables generalised by the patch are specific to the NS port. Whether something like this would be useful for other platforms isn't anything I have contemplated, but it is not inconceivable --- it would make keys like AltGr free to use as modifiers for mouse gestures and non-character keys. (Like the Option key on Macs, the AltGr key is used for entering even plain ASCII characters such as $@[]{}|\ on many keyboards, making those keys essential for almost any task.)






^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-26 22:03           ` Alan Third
@ 2019-11-27 10:50             ` Mattias Engdegård
  0 siblings, 0 replies; 13+ messages in thread
From: Mattias Engdegård @ 2019-11-27 10:50 UTC (permalink / raw)
  To: Alan Third, Eli Zaretskii; +Cc: 38296-done

26 nov. 2019 kl. 23.03 skrev Alan Third <alan@idiocy.org>:

> Having works, but the phrase is ‘of the form’.

Right you are, 'of' it is then.


27 nov. 2019 kl. 05.51 skrev Eli Zaretskii <eliz@gnu.org>:

> Btw, "customised" is not the US English spelling; please fix before
> pushing.

Thank you, fixed. I'm not used to writing in that dialect.

Pushed to master.






^ permalink raw reply	[flat|nested] 13+ messages in thread

* bug#38296: Allow Option key to be modifier for non-char key and mouse events
  2019-11-27 10:45         ` Mattias Engdegård
@ 2019-11-28  4:17           ` Richard Stallman
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Stallman @ 2019-11-28  4:17 UTC (permalink / raw)
  To: Mattias Engdegård; +Cc: alan, 38296

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

It sounds like this could be useful on all platforms -- so let's do it
that way.  Can people please work on extending it to all platforms,
rather than to NS alone?

I think it would be correct to change the variable names so that they don't
say "mac-".


-- 
Dr Richard Stallman
Founder, Free Software Foundation (https://gnu.org, https://fsf.org)
Internet Hall-of-Famer (https://internethalloffame.org)







^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2019-11-28  4:17 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-20 10:55 bug#38296: Allow Option key to be modifier for non-char key and mouse events Mattias Engdegård
2019-11-21 18:39 ` Mattias Engdegård
2019-11-21 21:12   ` Alan Third
2019-11-22 20:01     ` Mattias Engdegård
2019-11-25 19:15     ` Mattias Engdegård
2019-11-26 20:33       ` Alan Third
2019-11-26 21:36         ` Mattias Engdegård
2019-11-26 22:03           ` Alan Third
2019-11-27 10:50             ` Mattias Engdegård
2019-11-27  4:51           ` Eli Zaretskii
2019-11-27  6:40       ` Richard Stallman
2019-11-27 10:45         ` Mattias Engdegård
2019-11-28  4:17           ` Richard Stallman

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).