This is not a real answer but it describes the current situation. (I hope I got it right.)
The following section of keyboard.c
is relevant for the mouse event messages:
/* If in middle of key sequence and minibuffer not active,
start echoing if enough time elapses. */
if (minibuf_level == 0
&& !end_time
&& !current_kboard->immediate_echo
&& (this_command_key_count > 0
|| !NILP (call0 (Qinternal_echo_keystrokes_prefix)))
&& ! noninteractive
&& echo_keystrokes_p ()
&& (/* No message. */
NILP (echo_area_buffer[0])
/* Or empty message. */
|| (BUF_BEG (XBUFFER (echo_area_buffer[0]))
== BUF_Z (XBUFFER (echo_area_buffer[0])))
/* Or already echoing from same kboard. */
|| (echo_kboard && ok_to_echo_at_next_pause == echo_kboard)
/* Or not echoing before and echoing allowed. */
|| (!echo_kboard && ok_to_echo_at_next_pause)))
{
/* After a mouse event, start echoing right away.
This is because we are probably about to display a menu,
and we don't want to delay before doing so. */
if (EVENT_HAS_PARAMETERS (prev_event))
echo_now ();
It shows that the menu key sequences are echoed even more direct than normal key strokes. The timer that ticks for normal keystrokes is bypassed for menu key sequences. BTW, echo_keystrokes_p()
just tests whether echo-keystrokes
is positive.
Now let us have a look at echo_now()
which is also defined in keyboard.c
:
/* Display the current echo string, and begin echoing if not already
doing so. */
static void
echo_now (void)
{
if (!current_kboard->immediate_echo
/* This test breaks calls that use `echo_now' to display the echo_prompt.
&& echo_keystrokes_p () */)
{
current_kboard->immediate_echo = true;
echo_update ();
/* Put a dash at the end to invite the user to type more. */
echo_dash ();
}
echoing = true;
/* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak). */
message3_nolog (KVAR (current_kboard, echo_string));
Most interesting is here the last comment. That comment explicitly states that advising message
has no effect. That is the reason why the filter approach does not work.
Furthermore, it shows that the developers already considered to make message filters work. If you deliver them one more good reason to do so maybe they will.
Finally, let us have a look at the Elisp function read-key
in subr.el
:
(defun read-key (&optional prompt)
"Read a key from the keyboard.
Contrary to `read-event' this will not return a raw event but instead will
obey the input decoding and translations usually done by `read-key-sequence'.
So escape sequences and keyboard encoding are taken into account.
When there's an ambiguity because the key looks like the prefix of
some sort of escape sequence, the ambiguity is resolved via `read-key-delay'."
;; This overriding-terminal-local-map binding also happens to
;; disable quail's input methods, so although read-key-sequence
;; always inherits the input method, in practice read-key does not
;; inherit the input method (at least not if it's based on quail).
(let ((overriding-terminal-local-map nil)
(overriding-local-map read-key-empty-map)
(echo-keystrokes 0)
...
Later on they read the actual key with read-key-sequence-vector
within the body of the let
-form.
The last let
-binding (echo-keystrokes 0)
is the most interesting part.
Locally let
-binding echo-keystrokes
to zero is the official way to suppress the echoing of keystrokes including menu key sequences while reading characters from the keyboard.
Pityingly, the interactive
special form does not take that measure.
It is also not possible to advice interactive
in any way since it is a special Elisp form:-(.