Subject: bug#76669: read_key_sequence discards events without attempting remapping

From: Daniel Colascione <[email-masked]>
Date: Sun, 02 Mar 2025 02:02:50 -0500

Eli Zaretskii <[email-masked]> writes:

>> From: Daniel Colascione <[email-masked]>
>> Date: Sat, 01 Mar 2025 18:35:31 -0500
>> 
>> Suppose we want to use local-function-key-map to translate
>> s-<down-mouse-3> to <down-mouse-3>.  If we don't have a concrete binding
>> for s-<down-mouse-3>, we never attempt to translate it: instead,
>> read_key_sequence discards the down event and skips right to
>> s-<mouse-3>, which we *can* translate.
>
> I think it's ambiguous which one should come first: the discarding of
> 'down' modifier or translation via that map.  The ELisp manual says:
>
>      The function ‘read-key-sequence’ ignores any button-down events that
>   don't have command bindings; therefore, the Emacs command loop ignores
>   them too.  This means that you need not worry about defining button-down
>   events unless you want them to do something.  The usual reason to define
>   a button-down event is so that you can track mouse motion (by reading
>   motion events) until the button is released.  *Note Motion Events::.
>
> And also:
>
>      If an input character is upper-case (or has the shift modifier) and
>   has no key binding, but its lower-case equivalent has one, then
>   ‘read-key-sequence’ converts the character to lower case.  (This
>   behavior can be disabled by setting the
>   ‘translate-upper-case-key-bindings’ user option to ‘nil’.)  Note that
>   ‘lookup-key’ does not perform case conversion in this way.
>
>      When reading input results in such a “shift-translation”, Emacs sets
>   the variable ‘this-command-keys-shift-translated’ to a non-‘nil’ value.
>   Lisp programs can examine this variable if they need to modify their
>   behavior when invoked by shift-translated keys.  For example, the
>   function ‘handle-shift-selection’ examines the value of this variable to
>   determine how to activate or deactivate the region (*note
>   handle-shift-selection: The Mark.).
>
>      The function ‘read-key-sequence’ also transforms some mouse events.
>   It converts unbound drag events into click events, and discards unbound
>   button-down events entirely.  It also reshuffles focus events and
>   miscellaneous window events so that they never appear in a key sequence
>   with any other events.
>
> Adding Stefan to the discussion.

Ambiguity aside, it's useful to translate down-mouse and other
discardable events like other events.  Consider trying to make a
local-function-key-map that translates super-modified mouse events to
unmodified mouse events without overriding explicit super-modified
bindings.  This translation can't translate s-down-mouse-1 to
down-mouse-1 unless there's a binding for down-mouse-1 (which defeats
the purpose of a translation).

Wouldn't it be simpler and more powerful to get the modifier-munging
stuff out of the main read_key_sequence loop and implement the down
event dropping in access_keymap_keyremap?