unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: "Mattias Engdegård" <mattiase@acm.org>
To: Alan Third <alan@idiocy.org>
Cc: 38296@debbugs.gnu.org
Subject: bug#38296: Allow Option key to be modifier for non-char key and mouse events
Date: Fri, 22 Nov 2019 21:01:17 +0100	[thread overview]
Message-ID: <EF5B4321-05FA-4B95-8F3D-E0F1D020F390@acm.org> (raw)
In-Reply-To: <20191121211207.GA96045@breton.holly.idiocy.org>

[-- 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)


  reply	other threads:[~2019-11-22 20:01 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 [this message]
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=EF5B4321-05FA-4B95-8F3D-E0F1D020F390@acm.org \
    --to=mattiase@acm.org \
    --cc=38296@debbugs.gnu.org \
    --cc=alan@idiocy.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).