From: Stefan Monnier <monnier@iro.umontreal.ca>
To: Jared Finder <jared@finder.org>
Cc: Eli Zaretskii <eliz@gnu.org>, emacs-devel@gnu.org
Subject: Re: mouse-face and help echo support for xterm mouse
Date: Wed, 04 Nov 2020 13:47:29 -0500 [thread overview]
Message-ID: <jwvk0v1ngcc.fsf-monnier+emacs@gnu.org> (raw)
In-Reply-To: <5928a03c79bcf0afee270de1df4d9fa5@finder.org> (Jared Finder's message of "Wed, 04 Nov 2020 09:54:11 -0800")
>> - done:
>> - if (ie.kind != NO_EVENT)
>> + if (ie.kind != NO_EVENT) /* FIXME: We retest the previous if's
>> condition! */
>> {
>> + /* FIXME: `hold_quit` could already hold a previous event,
>> + so it risks crushing that previous event.
>> + What am I missing? */
>> kbd_buffer_store_event_hold (&ie, hold_quit);
>
> This is the meat of the refactor.
>
> Given the current code hold_quit will never hold a previous
> event. tty_read_avail_input initializes hold_quit right before calling
> handle_one_term_event and and sets kind to NO_EVENT. This is the first and
> only time in this function hold_quit is passed to any other function.
The way I read it:
EVENT_INIT (gpm_hold_quit);
gpm_hold_quit.kind = NO_EVENT;
[...]
while (gpm = Gpm_GetEvent (&event), gpm == 1) {
nread += handle_one_term_event (tty, &event, &gpm_hold_quit);
}
`gpm_hold_quit->kind` could hold a different value from `NO_EVENT` on the
second iteration (and subsequent ones) of the loop.
> Because it is the first time passed, we can safely deduce that
> hold_quit->kind will still be NO_EVENT *unless* a previous loop iteration
> changed it.
That's right.
> Because it is the only time passed, we can safely deduce that
> hold_quit->kind can only changed in a previous loop iteration by this
> function storing a quit event. However, this can not happen. hold_quit
> would get set by kbd_buffer_store_buffered_event which
> kbd_buffer_store_event_hold calls. To get set, the following must all be
> true:
>
> 1. An event of kind ASCII_KEYSTROKE_EVENT must be processed.
> 2. And that event's character code must be quit_char.
> 3. And that event must be on the current frame's KBOARD (not quite sure what
> this means).
>
> However, 1 will never be true as the only events that ever reach this point
> are of kind GPM_CLICK_EVENT, as deduced from the above asserts.
Oh, I see, indeed.
So we have the following:
if (event->type & (GPM_MOVE | GPM_DRAG))
{
[...]
eassert (ie.kind == NO_EVENT);
}
else
{
[...]
eassert (ie.kind == GPM_CLICK_EVENT);
}
if (ie.kind != NO_EVENT) /* FIXME: We retest the previous if's condition! */
{
kbd_buffer_store_event_hold (&ie, hold_quit);
count++;
}
where we can move the second `if` into the first (according to the FIXME)
if (event->type & (GPM_MOVE | GPM_DRAG))
{
[...]
eassert (ie.kind == NO_EVENT);
}
else
{
[...]
eassert (ie.kind == GPM_CLICK_EVENT);
kbd_buffer_store_event_hold (&ie, hold_quit);
count++;
}
and then we know that `hold_quit` starts at NO_EVENT and can only be
changed via this call to `kbd_buffer_store_event_hold`, but this call
will never change it because `ie.kind == GPM_CLICK_EVENT` and
kbd_buffer_store_event_hold would only ever touch it if the kind was
ASCII_KEYSTROKE_EVENT, so we know that `hold_quit->kind == NO_EVENT`
always holds and we can drop it.
The code is now (with added context):
if (event->type & (GPM_MOVE | GPM_DRAG))
{
[...]
eassert (ie.kind == NO_EVENT);
}
else
{
[...]
eassert (ie.kind == GPM_CLICK_EVENT);
kbd_buffer_store_event (&ie);
count++;
}
if (do_help
/* FIXME: `hold_quit` is never NULL?! */
&& !(hold_quit && hold_quit->kind != NO_EVENT))
{ ... }
and the last if's condition can now be simplified:
bool do_help = false;
[...]
if (event->type & (GPM_MOVE | GPM_DRAG))
{
[...]
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
do_help = true;
eassert (ie.kind == NO_EVENT);
}
else
{
[...]
eassert (ie.kind == GPM_CLICK_EVENT);
kbd_buffer_store_event (&ie);
count++;
}
if (do_help)
{ ... }
and now we can again fold the second move into the tail of the first:
bool do_help = false;
[...]
if (event->type & (GPM_MOVE | GPM_DRAG))
{
[...]
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
do_help = true;
eassert (ie.kind == NO_EVENT);
if (do_help)
{ ... }
}
else
{
[...]
eassert (ie.kind == GPM_CLICK_EVENT);
kbd_buffer_store_event (&ie);
count++;
}
and get rid of `do_help` altogether.
[...]
if (event->type & (GPM_MOVE | GPM_DRAG))
{
[...]
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
{ ... }
}
else
{
[...]
eassert (ie.kind == GPM_CLICK_EVENT);
kbd_buffer_store_event (&ie);
count++;
}
So, I installed the patch below.
Stefan
diff --git a/src/keyboard.c b/src/keyboard.c
index 2e0143379a..49a0a8bd23 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -7005,12 +7005,8 @@ tty_read_avail_input (struct terminal *terminal,
if (gpm_tty == tty)
{
Gpm_Event event;
- struct input_event gpm_hold_quit;
int gpm, fd = gpm_fd;
- EVENT_INIT (gpm_hold_quit);
- gpm_hold_quit.kind = NO_EVENT;
-
/* gpm==1 if event received.
gpm==0 if the GPM daemon has closed the connection, in which case
Gpm_GetEvent closes gpm_fd and clears it to -1, which is why
@@ -7018,13 +7014,11 @@ tty_read_avail_input (struct terminal *terminal,
select masks.
gpm==-1 if a protocol error or EWOULDBLOCK; the latter is normal. */
while (gpm = Gpm_GetEvent (&event), gpm == 1) {
- nread += handle_one_term_event (tty, &event, &gpm_hold_quit);
+ nread += handle_one_term_event (tty, &event);
}
if (gpm == 0)
/* Presumably the GPM daemon has closed the connection. */
close_gpm (fd);
- if (gpm_hold_quit.kind != NO_EVENT)
- kbd_buffer_store_event (&gpm_hold_quit);
if (nread)
return nread;
}
diff --git a/src/term.c b/src/term.c
index ff1aabfed2..3a13da165e 100644
--- a/src/term.c
+++ b/src/term.c
@@ -2550,67 +2550,63 @@ term_mouse_click (struct input_event *result, Gpm_Event *event,
}
int
-handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event,
- struct input_event *hold_quit)
+handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event)
{
struct frame *f = XFRAME (tty->top_frame);
struct input_event ie;
- bool do_help = 0;
int count = 0;
EVENT_INIT (ie);
ie.kind = NO_EVENT;
ie.arg = Qnil;
- if (event->type & (GPM_MOVE | GPM_DRAG)) {
- previous_help_echo_string = help_echo_string;
- help_echo_string = Qnil;
+ if (event->type & (GPM_MOVE | GPM_DRAG))
+ {
+ previous_help_echo_string = help_echo_string;
+ help_echo_string = Qnil;
- Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
+ Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
- if (!term_mouse_movement (f, event))
- help_echo_string = previous_help_echo_string;
+ if (!term_mouse_movement (f, event))
+ help_echo_string = previous_help_echo_string;
- /* If the contents of the global variable help_echo_string
- has changed, generate a HELP_EVENT. */
- if (!NILP (help_echo_string)
- || !NILP (previous_help_echo_string))
- do_help = 1;
+ /* If the contents of the global variable help_echo_string
+ has changed, generate a HELP_EVENT. */
+ if (!NILP (help_echo_string)
+ || !NILP (previous_help_echo_string))
+ {
+ Lisp_Object frame;
- goto done;
- }
- else {
- f->mouse_moved = 0;
- term_mouse_click (&ie, event, f);
- if (tty_handle_tab_bar_click (f, event->x, event->y,
- (ie.modifiers & down_modifier) != 0, &ie))
- {
- /* tty_handle_tab_bar_click stores 2 events in the event
- queue, so we are done here. */
- count += 2;
- return count;
- }
- }
+ if (f)
+ XSETFRAME (frame, f);
+ else
+ frame = Qnil;
- done:
- if (ie.kind != NO_EVENT)
- {
- kbd_buffer_store_event_hold (&ie, hold_quit);
- count++;
+ gen_help_event (help_echo_string, frame, help_echo_window,
+ help_echo_object, help_echo_pos);
+ count++;
+ }
}
-
- if (do_help
- && !(hold_quit && hold_quit->kind != NO_EVENT))
+ else
{
- Lisp_Object frame;
-
- if (f)
- XSETFRAME (frame, f);
- else
- frame = Qnil;
-
- gen_help_event (help_echo_string, frame, help_echo_window,
- help_echo_object, help_echo_pos);
+ f->mouse_moved = 0;
+ term_mouse_click (&ie, event, f);
+ /* eassert (ie.kind == GPM_CLICK_EVENT); */
+ if (tty_handle_tab_bar_click (f, event->x, event->y,
+ (ie.modifiers & down_modifier) != 0, &ie))
+ {
+ /* eassert (ie.kind == GPM_CLICK_EVENT
+ * || ie.kind == TAB_BAR_EVENT); */
+ /* tty_handle_tab_bar_click stores 2 events in the event
+ queue, so we are done here. */
+ /* FIXME: Actually, `tty_handle_tab_bar_click` returns true
+ without storing any events, when
+ (ie.modifiers & down_modifier) != 0 */
+ count += 2;
+ return count;
+ }
+ /* eassert (ie.kind == GPM_CLICK_EVENT); */
+ kbd_buffer_store_event (&ie);
count++;
}
diff --git a/src/termhooks.h b/src/termhooks.h
index d18b750c3a..6ab06ceff9 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -370,7 +370,7 @@ #define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
#ifdef HAVE_GPM
#include <gpm.h>
-extern int handle_one_term_event (struct tty_display_info *, Gpm_Event *, struct input_event *);
+extern int handle_one_term_event (struct tty_display_info *, Gpm_Event *);
#ifndef HAVE_WINDOW_SYSTEM
extern void term_mouse_moveto (int, int);
#endif
next prev parent reply other threads:[~2020-11-04 18:47 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-11-01 5:46 mouse-face and help echo support for xterm mouse Jared Finder via Emacs development discussions.
2020-11-01 13:39 ` Stefan Monnier
2020-11-01 15:56 ` Jared Finder via Emacs development discussions.
2020-11-04 6:54 ` Jared Finder via Emacs development discussions.
2020-11-04 14:13 ` Stefan Monnier
2020-11-04 15:46 ` Eli Zaretskii
2020-11-04 15:56 ` Stefan Monnier
2020-11-04 17:54 ` Jared Finder via Emacs development discussions.
2020-11-04 18:47 ` Stefan Monnier [this message]
2020-11-04 18:51 ` Eli Zaretskii
2020-11-04 19:05 ` Stefan Monnier
2020-11-04 19:10 ` Jared Finder via Emacs development discussions.
2020-11-04 15:19 ` Eli Zaretskii
2020-11-05 8:15 ` Jared Finder via Emacs development discussions.
2020-11-05 14:45 ` Stefan Monnier
2020-11-05 19:58 ` Jared Finder via Emacs development discussions.
2020-11-05 20:18 ` Stefan Monnier
2020-11-06 5:23 ` Jared Finder via Emacs development discussions.
2020-11-06 6:00 ` Eli Zaretskii
2020-11-06 6:46 ` Jared Finder via Emacs development discussions.
2020-11-06 7:39 ` Eli Zaretskii
2020-11-07 1:22 ` Jared Finder via Emacs development discussions.
2020-11-14 12:38 ` Eli Zaretskii
2020-11-14 12:35 ` Eli Zaretskii
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=jwvk0v1ngcc.fsf-monnier+emacs@gnu.org \
--to=monnier@iro.umontreal.ca \
--cc=eliz@gnu.org \
--cc=emacs-devel@gnu.org \
--cc=jared@finder.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 external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.