unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
@ 2023-02-02 22:28 Adrián Medraño Calvo
  2023-02-04  8:25 ` Eli Zaretskii
  2023-02-05 19:04 ` Adrián Medraño Calvo
  0 siblings, 2 replies; 7+ messages in thread
From: Adrián Medraño Calvo @ 2023-02-02 22:28 UTC (permalink / raw)
  To: 61241

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

For the implementation of `mouse-autoselect-window', the entered window
is remembered and then compared when an mouse motion event is received.
Up to Emacs 28, this value was stored in a static local variable named
`last_mouse_window' in the block handling MotionNotify within
`handle_one_xevent'.  With the introduction of XInput 2,
`handle_one_xevent' was adjusted to account for XI_Motion events, with
the oversight that a new local static `last_mouse_window' variable was
declared in the new handler block for XI_Motion.  As a result, when
Emacs receives motion events from XInput and XInput2 sources
alternatively the value of each `last_mouse_window’ differs, leading to
the window under the motion sometimes not being selected, as the
value `last_mouse_window' is out-of-date for the particular XInput
version.

This bug impacts the GNU ELPA package EXWM.  EXWM tries to extrapolate
applicable Emacs functionality to X window management; among others
assigns an Emacs buffer to each managed X window, and positions the X
window over the Emacs window in which the buffer is displayed.  When
`mouse-autoselect-windows’ and the user moves the mouse pointer over one
X window managed by EXWM, this X window receives the mouse events and not
Emacs, therefore the Emacs window is not selected.  In order to overcome
this, EXWM sends a synthetic MotionNotify event to Emacs.

The attached patch fixes the issue.

Thank you,
Adrián Medraño Calvo.


[-- Attachment #2: 0001-Fix-mouse-autoselect-window-for-alternating-XInput-a.patch --]
[-- Type: application/octet-stream, Size: 1883 bytes --]

From e16d6ddbfdc4110fbbbcf763cff5a72b0f0df92c Mon Sep 17 00:00:00 2001
Message-Id: <e16d6ddbfdc4110fbbbcf763cff5a72b0f0df92c.1675376734.git.adrian@medranocalvo.com>
From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?=
 <adrian@medranocalvo.com>
Date: Wed, 1 Feb 2023 00:00:00 +0000
Subject: [PATCH] Fix `mouse-autoselect-window' for alternating XInput and
 XInput 2 events

* src/xterm.c (handle_one_xevent): Move `last_mouse_window' to
main function scope to share value between XInput and XInput 2
handlers.
---
 src/xterm.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index 6a4b84babe4..dd20c8c7fe5 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -18364,6 +18364,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
   GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
 #endif
   int dx, dy;
+  /* Holds the last window the mouse moved over, used for
+     `mouse-autoselect-window' */
+  static Lisp_Object last_mouse_window;
 
   /* Avoid warnings when SAFE_ALLOCA is not actually used.  */
 #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
@@ -20677,8 +20680,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		&& (f == XFRAME (selected_frame)
 		    || !NILP (focus_follows_mouse)))
 	      {
-		static Lisp_Object last_mouse_window;
-
 		if (xmotion.window != FRAME_X_WINDOW (f))
 		  {
 		    x_translate_coordinates (f, xmotion.x_root, xmotion.y_root,
@@ -22587,7 +22588,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      && (f == XFRAME (selected_frame)
 			  || !NILP (focus_follows_mouse)))
 		    {
-		      static Lisp_Object last_mouse_window;
 		      Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
 
 		      /* A window will be autoselected only when it is not
-- 
2.39.1


[-- Attachment #3: Type: text/plain, Size: 3516 bytes --]



In GNU Emacs 29.0.60 (build 1, x86_64-apple-darwin22.2.0, cairo version
 1.17.6) of 2023-01-26 built on amcmac
Repository revision: f8c95d1a7681e861fc22d2a040cda0ddfe23eff4
Repository branch: master
Windowing system distributor 'The X.Org Foundation', version 11.0.12101006
System Description:  macOS 13.2

Configured using:
 'configure --prefix=/Volumes/sys/repos/emacs-cairo/rel
 --without-makeinfo --without-dbus --without-ns --with-x-toolkit=no
 --with-cairo
 PKG_CONFIG_PATH=/opt/X11/lib/pkgconfig:/usr/local/opt/freetype/lib/pkgconfig:/usr/local/opt/fontconfig/lib/pkgconfig:/usr/local/opt/ncurses/lib/pkgconfig:/usr/local/opt/libxml2/lib/pkgconfig:/usr/local/Cellar/jpeg/9d/lib/pkgconfig:/usr/local/Cellar/libtiff/4.3.0/lib/pkgconfig:/usr/local/opt/harfbuzz/lib/pkgconfig/:/usr/local/opt/harfbuzz/lib/pkgconfig/
 'CFLAGS=-Og -g3' --without-jpeg --without-gif --without-xpm
 --without-tiff'

Configured features:
ACL CAIRO FREETYPE GLIB GMP GNUTLS GSETTINGS HARFBUZZ JSON LCMS2 LIBXML2
MODULES NOTIFY KQUEUE OLDXMENU PDUMPER PNG RSVG SQLITE3 THREADS WEBP X11
XDBE XIM XINPUT2 ZLIB

Important settings:
  value of $LC_ALL: en_US.UTF-8
  value of $LANG: en_US
  value of $XMODIFIERS: @im=exwm-xim
  locale-coding-system: utf-8-unix

Major mode: Lisp Interaction

Minor modes in effect:
  tooltip-mode: t
  global-eldoc-mode: t
  eldoc-mode: t
  show-paren-mode: t
  electric-indent-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  line-number-mode: t
  indent-tabs-mode: t
  transient-mark-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t

Load-path shadows:
None found.

Features:
(shadow sort mail-extr emacsbug message mailcap yank-media puny dired
dired-loaddefs rfc822 mml mml-sec password-cache epa derived epg rfc6068
epg-config gnus-util text-property-search time-date subr-x mm-decode
mm-bodies mm-encode mail-parse rfc2231 mailabbrev gmm-utils mailheader
cl-loaddefs cl-lib sendmail rfc2047 rfc2045 ietf-drums mm-util
mail-prsvr mail-utils rmc iso-transl tooltip cconv eldoc paren electric
uniquify ediff-hook vc-hooks lisp-float-type elisp-mode mwheel
term/x-win x-win term/common-win x-dnd tool-bar dnd fontset image
regexp-opt fringe tabulated-list replace newcomment text-mode lisp-mode
prog-mode register page tab-bar menu-bar rfn-eshadow isearch easymenu
timer select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew greek
romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button loaddefs
theme-loaddefs faces cus-face macroexp files window text-properties
overlay sha1 md5 base64 format env code-pages mule custom widget keymap
hashtable-print-readable backquote threads kqueue lcms2 dynamic-setting
system-font-setting font-render-setting cairo xinput2 x multi-tty
make-network-process emacs)

Memory information:
((conses 16 38318 8147)
 (symbols 48 5108 0)
 (strings 32 12656 2131)
 (string-bytes 1 362604)
 (vectors 16 10252)
 (vector-slots 8 147251 15877)
 (floats 8 42 19)
 (intervals 56 263 0)
 (buffers 976 10))

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

* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
  2023-02-02 22:28 bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2 Adrián Medraño Calvo
@ 2023-02-04  8:25 ` Eli Zaretskii
  2023-02-04  8:43   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-02-05 19:04 ` Adrián Medraño Calvo
  1 sibling, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2023-02-04  8:25 UTC (permalink / raw)
  To: Adrián Medraño Calvo, Po Lu; +Cc: 61241

> From: Adrián Medraño Calvo
>  <adrian@medranocalvo.com>
> Date: Thu, 2 Feb 2023 23:28:01 +0100
> 
> For the implementation of `mouse-autoselect-window', the entered window
> is remembered and then compared when an mouse motion event is received.
> Up to Emacs 28, this value was stored in a static local variable named
> `last_mouse_window' in the block handling MotionNotify within
> `handle_one_xevent'.  With the introduction of XInput 2,
> `handle_one_xevent' was adjusted to account for XI_Motion events, with
> the oversight that a new local static `last_mouse_window' variable was
> declared in the new handler block for XI_Motion.  As a result, when
> Emacs receives motion events from XInput and XInput2 sources
> alternatively the value of each `last_mouse_window’ differs, leading to
> the window under the motion sometimes not being selected, as the
> value `last_mouse_window' is out-of-date for the particular XInput
> version.
> 
> This bug impacts the GNU ELPA package EXWM.  EXWM tries to extrapolate
> applicable Emacs functionality to X window management; among others
> assigns an Emacs buffer to each managed X window, and positions the X
> window over the Emacs window in which the buffer is displayed.  When
> `mouse-autoselect-windows’ and the user moves the mouse pointer over one
> X window managed by EXWM, this X window receives the mouse events and not
> Emacs, therefore the Emacs window is not selected.  In order to overcome
> this, EXWM sends a synthetic MotionNotify event to Emacs.
> 
> The attached patch fixes the issue.
> 
> Thank you,
> Adrián Medraño Calvo.
> 
> From e16d6ddbfdc4110fbbbcf763cff5a72b0f0df92c Mon Sep 17 00:00:00 2001
> Message-Id: <e16d6ddbfdc4110fbbbcf763cff5a72b0f0df92c.1675376734.git.adrian@medranocalvo.com>
> From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?=
>  <adrian@medranocalvo.com>
> Date: Wed, 1 Feb 2023 00:00:00 +0000
> Subject: [PATCH] Fix `mouse-autoselect-window' for alternating XInput and
>  XInput 2 events
> 
> * src/xterm.c (handle_one_xevent): Move `last_mouse_window' to
> main function scope to share value between XInput and XInput 2
> handlers.
> ---
>  src/xterm.c | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/src/xterm.c b/src/xterm.c
> index 6a4b84babe4..dd20c8c7fe5 100644
> --- a/src/xterm.c
> +++ b/src/xterm.c
> @@ -18364,6 +18364,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
>    GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display);
>  #endif
>    int dx, dy;
> +  /* Holds the last window the mouse moved over, used for
> +     `mouse-autoselect-window' */
> +  static Lisp_Object last_mouse_window;
>  
>    /* Avoid warnings when SAFE_ALLOCA is not actually used.  */
>  #if defined HAVE_XINPUT2 || defined HAVE_XKB || defined HAVE_X_I18N
> @@ -20677,8 +20680,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
>  		&& (f == XFRAME (selected_frame)
>  		    || !NILP (focus_follows_mouse)))
>  	      {
> -		static Lisp_Object last_mouse_window;
> -
>  		if (xmotion.window != FRAME_X_WINDOW (f))
>  		  {
>  		    x_translate_coordinates (f, xmotion.x_root, xmotion.y_root,
> @@ -22587,7 +22588,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
>  		      && (f == XFRAME (selected_frame)
>  			  || !NILP (focus_follows_mouse)))
>  		    {
> -		      static Lisp_Object last_mouse_window;
>  		      Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
>  
>  		      /* A window will be autoselected only when it is not
> -- 
> 2.39.1

Po Lu, any comments, or should this go in?





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

* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
  2023-02-04  8:25 ` Eli Zaretskii
@ 2023-02-04  8:43   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 7+ messages in thread
From: Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-04  8:43 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 61241, Adrián Medraño Calvo

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Adrián Medraño Calvo
>>  <adrian@medranocalvo.com>
>> Date: Thu, 2 Feb 2023 23:28:01 +0100
>> 
>> For the implementation of `mouse-autoselect-window', the entered window
>> is remembered and then compared when an mouse motion event is received.
>> Up to Emacs 28, this value was stored in a static local variable named
>> `last_mouse_window' in the block handling MotionNotify within
>> `handle_one_xevent'.  With the introduction of XInput 2,
>> `handle_one_xevent' was adjusted to account for XI_Motion events, with
>> the oversight that a new local static `last_mouse_window' variable was
>> declared in the new handler block for XI_Motion.  As a result, when
>> Emacs receives motion events from XInput and XInput2 sources
>> alternatively the value of each `last_mouse_window’ differs, leading to
>> the window under the motion sometimes not being selected, as the
>> value `last_mouse_window' is out-of-date for the particular XInput
>> version.
>> 
>> This bug impacts the GNU ELPA package EXWM.  EXWM tries to extrapolate
>> applicable Emacs functionality to X window management; among others
>> assigns an Emacs buffer to each managed X window, and positions the X
>> window over the Emacs window in which the buffer is displayed.  When
>> `mouse-autoselect-windows’ and the user moves the mouse pointer over one
>> X window managed by EXWM, this X window receives the mouse events and not
>> Emacs, therefore the Emacs window is not selected.  In order to overcome
>> this, EXWM sends a synthetic MotionNotify event to Emacs.
>> 
>> The attached patch fixes the issue.

Thanks.  But first of all, Emacs is not at all prepared to receive both
MotionNotify events and XI_Motion events on a frame at the same time in
other areas as well, such as focus tracking.

This is not possible under an X server.

So EXWM should send XI_Motion events when the X server supports XInput 2
(they are Generic Events, and XCB lets you send them, though not Xlib
because nobody has written a working event to wire function yet.)

Or alternatively, why doesn't exwm just focus the window itself?





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

* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
  2023-02-02 22:28 bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2 Adrián Medraño Calvo
  2023-02-04  8:25 ` Eli Zaretskii
@ 2023-02-05 19:04 ` Adrián Medraño Calvo
  2023-02-06  1:40   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  1 sibling, 1 reply; 7+ messages in thread
From: Adrián Medraño Calvo @ 2023-02-05 19:04 UTC (permalink / raw)
  To: Po Lu; +Cc: 61241, Eli Zaretskii


Please see below.

> Am 04.02.2023 um 09:45 schrieb Po Lu <luangruo@yahoo.com>:
> Eli Zaretskii <eliz@gnu.org> writes:
> 
>>> From: Adrián Medraño Calvo
>>> <adrian@medranocalvo.com>
>>> Date: Thu, 2 Feb 2023 23:28:01 +0100
>>> For the implementation of `mouse-autoselect-window', the entered window
>>> is remembered and then compared when an mouse motion event is received.
>>> Up to Emacs 28, this value was stored in a static local variable named
>>> `last_mouse_window' in the block handling MotionNotify within
>>> `handle_one_xevent'.  With the introduction of XInput 2,
>>> `handle_one_xevent' was adjusted to account for XI_Motion events, with
>>> the oversight that a new local static `last_mouse_window' variable was
>>> declared in the new handler block for XI_Motion.  As a result, when
>>> Emacs receives motion events from XInput and XInput2 sources
>>> alternatively the value of each `last_mouse_window’ differs, leading to
>>> the window under the motion sometimes not being selected, as the
>>> value `last_mouse_window' is out-of-date for the particular XInput
>>> version.
>>> This bug impacts the GNU ELPA package EXWM.  EXWM tries to extrapolate
>>> applicable Emacs functionality to X window management; among others
>>> assigns an Emacs buffer to each managed X window, and positions the X
>>> window over the Emacs window in which the buffer is displayed.  When
>>> `mouse-autoselect-windows’ and the user moves the mouse pointer over one
>>> X window managed by EXWM, this X window receives the mouse events and not
>>> Emacs, therefore the Emacs window is not selected.  In order to overcome
>>> this, EXWM sends a synthetic MotionNotify event to Emacs.
>>> The attached patch fixes the issue.
> 
> Thanks.  But first of all, Emacs is not at all prepared to receive both
> MotionNotify events and XI_Motion events on a frame at the same time in
> other areas as well, such as focus tracking.
> 
> This is not possible under an X server.

Thank you. I thought already about fixing this in EXWM by sending the XI_Motion event when Emacs uses XInput 2 (as you propose below), but thought that other users might be in a similar situation. For example, a user using xdotool (I must say that I don't know whether xdotool relies on XInput, XInput 2, XTest or something else, but for the sake of this example please assume the former) would observe the same behaviour as us.

If I understand correctly, an XInput 2 enabled Emacs must handle regular events as well because some of its frames might be in terminals supporting only Xinput 1. If that's the case, would it be possible to drop/reject corresponding regular events (e.g. MotionNotifiy) on terminals supporting XInput 2? If that's not possible, I’d say it’s better applying the patch (or similar) so that, even while unsupported, we do a best effort in reducing inconsistency.

> So EXWM should send XI_Motion events when the X server supports XInput 2
> (they are Generic Events, and XCB lets you send them, though not Xlib
> because nobody has written a working event to wire function yet.)

I'll implement your suggestion in EXWM shortly, in any case before Emacs 29 is released. How can I detect whether Emacs uses XInput 2 in a particular terminal?

> Or alternatively, why doesn't exwm just focus the window itself?

(I’m not sure whether I understand your question, please clarify if you think I missed it.) Just focusing the X window (and selecting the related Emacs window) is not enough for integrating `mouse-autoselect-window', precisely because `last_mouse_window' gets out-of-sync, leading to the user being unable to select back the last Emacs window by moving the mouse over it. A possible solution to this would be to expose `last_mouse_window' to Lisp (e.g. `mouse-autoselect-last-window'); presumably EXWM could then set its value as part of the above steps and have focus follow the pointer. I’d say this is my preferred solution, what do you think about this?







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

* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
  2023-02-05 19:04 ` Adrián Medraño Calvo
@ 2023-02-06  1:40   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2023-08-22  5:45     ` Adrián Medraño Calvo
  0 siblings, 1 reply; 7+ messages in thread
From: Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-02-06  1:40 UTC (permalink / raw)
  To: Adrián Medraño Calvo; +Cc: 61241, Eli Zaretskii

Adrián Medraño Calvo <adrian@medranocalvo.com> writes:

> Thank you. I thought already about fixing this in EXWM by sending the
> XI_Motion event when Emacs uses XInput 2 (as you propose below), but
> thought that other users might be in a similar situation. For example,
> a user using xdotool (I must say that I don't know whether xdotool
> relies on XInput, XInput 2, XTest or something else, but for the sake
> of this example please assume the former) would observe the same
> behaviour as us.

These tools should use the record or test extensions, which will not
have these problems.

> If I understand correctly, an XInput 2 enabled Emacs must handle
> regular events as well because some of its frames might be in
> terminals supporting only Xinput 1. If that's the case, would it be
> possible to drop/reject corresponding regular events
> (e.g. MotionNotifiy) on terminals supporting XInput 2? If that's not
> possible, I’d say it’s better applying the patch (or similar) so that,
> even while unsupported, we do a best effort in reducing inconsistency.

XInput 1.x is not supported by Emacs.  You probably mean the X11 core
protocol.

It is ok for MotionNotify events to arrive on a display that has not
selected for input extension events, since Emacs does not keep track of
much state globally across displays.

But once they do on a display that has, then a lot can go wrong.

> I'll implement your suggestion in EXWM shortly, in any case before
> Emacs 29 is released. How can I detect whether Emacs uses XInput 2 in
> a particular terminal?

The function `x-server-input-extension-version'.

> (I’m not sure whether I understand your question, please clarify if
> you think I missed it.) Just focusing the X window (and selecting the
> related Emacs window) is not enough for integrating
> `mouse-autoselect-window', precisely because `last_mouse_window' gets
> out-of-sync, leading to the user being unable to select back the last
> Emacs window by moving the mouse over it. A possible solution to this
> would be to expose `last_mouse_window' to Lisp
> (e.g. `mouse-autoselect-last-window'); presumably EXWM could then set
> its value as part of the above steps and have focus follow the
> pointer. I’d say this is my preferred solution, what do you think
> about this?

Sounds reasonable, except it is too late in the Emacs 29 release cycle
to implement this there.





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

* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
  2023-02-06  1:40   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2023-08-22  5:45     ` Adrián Medraño Calvo
  2023-08-22  6:59       ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 7+ messages in thread
From: Adrián Medraño Calvo @ 2023-08-22  5:45 UTC (permalink / raw)
  To: Po Lu; +Cc: 61241, Eli Zaretskii

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

Dear Po Lu,

> On 6. Feb 2023, at 02:40, Po Lu <luangruo@yahoo.com> wrote:
> 
> Adrián Medraño Calvo <adrian@medranocalvo.com> writes:
> 
>> Thank you. I thought already about fixing this in EXWM by sending the
>> XI_Motion event when Emacs uses XInput 2 (as you propose below), but
>> thought that other users might be in a similar situation. For example,
>> a user using xdotool (I must say that I don't know whether xdotool
>> relies on XInput, XInput 2, XTest or something else, but for the sake
>> of this example please assume the former) would observe the same
>> behaviour as us.
> 
> These tools should use the record or test extensions, which will not
> have these problems.

I’ve tried implementing your suggestion to send an XI_Motion event to Emacs when the mouse enters the X window managed by EXWM—to no avail:

1. Using SendEvent: XI2 events are GenericEvents, Xorg disallows sending GenericEvents within SendEvent.  The following seem to be the cause:
- https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/dix/events.c#L5517, and especially
- https://gitlab.freedesktop.org/xorg/xserver/-/blob/master/dix/events.c#L5541

2. Using XTest: although undocumented (as far as I could see), XTest does support sending XI device events.  The issue is that EXWM wants to, when entering a managed X window, send XI_Motion events to Emacs as well so as to trick it into thinking that the pointer entered the Emacs window corresponding to the mentioned X window; which marks this Emacs window the last Emacs window the pointer was over.  The last think is critical for focus-follows-mouse to work on EXWM. The obstacle I find with XTest is that XTest just mimics moving the pointer so, when moving the pointer to an X window and then using XTest to simulate moving the pointer there (again), nothing changes: the XI_Motion events are again sent to this topmost X Window.  I couldn’t think of a way of having the XTest events lead to XI_Motion reaching Emacs in such a situation. 

3. I also tried using XWrapPointer which of course does not help as it generates no motion events.

Can you think of a way forward?

>> If I understand correctly, an XInput 2 enabled Emacs must handle
>> regular events as well because some of its frames might be in
>> terminals supporting only Xinput 1. If that's the case, would it be
>> possible to drop/reject corresponding regular events
>> (e.g. MotionNotifiy) on terminals supporting XInput 2? If that's not
>> possible, I’d say it’s better applying the patch (or similar) so that,
>> even while unsupported, we do a best effort in reducing inconsistency.
> 
> XInput 1.x is not supported by Emacs.  You probably mean the X11 core
> protocol.
> 
> It is ok for MotionNotify events to arrive on a display that has not
> selected for input extension events, since Emacs does not keep track of
> much state globally across displays.
> 
> But once they do on a display that has, then a lot can go wrong.
> 
>> I'll implement your suggestion in EXWM shortly, in any case before
>> Emacs 29 is released. How can I detect whether Emacs uses XInput 2 in
>> a particular terminal?
> 
> The function `x-server-input-extension-version'.
> 
>> (I’m not sure whether I understand your question, please clarify if
>> you think I missed it.) Just focusing the X window (and selecting the
>> related Emacs window) is not enough for integrating
>> `mouse-autoselect-window', precisely because `last_mouse_window' gets
>> out-of-sync, leading to the user being unable to select back the last
>> Emacs window by moving the mouse over it. A possible solution to this
>> would be to expose `last_mouse_window' to Lisp
>> (e.g. `mouse-autoselect-last-window'); presumably EXWM could then set
>> its value as part of the above steps and have focus follow the
>> pointer. I’d say this is my preferred solution, what do you think
>> about this?
> 
> Sounds reasonable, except it is too late in the Emacs 29 release cycle
> to implement this there.

I prepared a patch (attached below) introducing a new lisp variable holding the last "mouse-autoselected” window.  With this patch EXWM can simply select the Emacs window corresponding to the managed X window and set it as last “mouse-autoselected” window; mouse-autoselect works normally after that.  No more sending Motion events.

Using a single variable introduces a significant change, though: when `mouse-autoselect-window’ is enabled and emacs runs in different terminals, “mouse-autoselecting” a window on a terminal changes the last “mouse-autoselected” window for all other terminals.  Slightly moving the mouse in a different terminal (within a single Emacs window) will “mouse-autoselect” that window, whereas that would not have been the case before this patch, as the last “mouse-autoselected” window was terminal-specific.  It’s not clear to me whether this behaviour will be beneficial, neutral or unacceptable.  Moreover, this behaviour is consistent with the behaviour introduced in the first patch I sent, where I proposed to merge the last “mouse-autoselected” window for Motion and XI_Motion events (other terminals were not affected).

Please let me know your thoughts.

Regards,
Adrián.


[-- Attachment #2: 0001-Expose-last-window-under-pointer-to-Lisp.patch --]
[-- Type: application/octet-stream, Size: 12723 bytes --]

From d845f06a8155a35fe93769e600b79b951f723863 Mon Sep 17 00:00:00 2001
Message-ID: <d845f06a8155a35fe93769e600b79b951f723863.1692630504.git.adrian@medranocalvo.com>
From: =?UTF-8?q?Adri=C3=A1n=20Medra=C3=B1o=20Calvo?=
 <adrian@medranocalvo.com>
Date: Tue, 15 Aug 2023 00:00:00 +0000
Subject: [PATCH] Expose last window under pointer to Lisp

* src/xdisp.c (syms_of_xdisp): Add defvar
`Vmouse_autoselect_window_last_window'.
* src/haikuterm.c (haiku_read_socket):
* src/msdos.c (dos_rawgetc):
* src/nsterm.m ([EmacsView mouseMoved:]):
* src/pgtkterm.c (motion_notify_event):
* src/w32inevt.c (do_mouse_event):
* src/w32term.c (w32_read_socket):
* src/xterm.c (handle_one_xevent): Use it replacing static
`last_mouse_window'.

* lisp/window.el (mouse-autoselect-window-window)
(mouse-autoselect-window-previous-window): Rename variable.
---
 lisp/window.el  |  8 +++++---
 src/haikuterm.c |  5 ++---
 src/msdos.c     |  6 ++----
 src/nsterm.m    |  5 ++---
 src/pgtkterm.c  |  5 ++---
 src/w32inevt.c  |  7 ++-----
 src/w32term.c   |  5 ++---
 src/xdisp.c     |  7 +++++++
 src/xterm.c     | 11 ++++-------
 9 files changed, 28 insertions(+), 31 deletions(-)

diff --git a/lisp/window.el b/lisp/window.el
index 16f16a75418..b2677ea99f3 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -10391,8 +10391,10 @@ mouse-autoselect-window-position-1
 (defvar mouse-autoselect-window-position nil
   "Last mouse position recorded by delayed window autoselection.")
 
-(defvar mouse-autoselect-window-window nil
+(defvar mouse-autoselect-window-previous-window nil
   "Last window recorded by delayed window autoselection.")
+(define-obsolete-variable-alias 'mouse-autoselect-window-window
+  'mouse-autoselect-window-previous-window "29.1")
 
 (defvar mouse-autoselect-window-state nil
   "When non-nil, special state of delayed window autoselection.
@@ -10425,7 +10427,7 @@ mouse-autoselect-window-start
 means suspend autoselection."
   ;; Record values for MOUSE-POSITION, WINDOW, and SUSPEND.
   (setq mouse-autoselect-window-position mouse-position)
-  (when window (setq mouse-autoselect-window-window window))
+  (when window (setq mouse-autoselect-window-previous-window window))
   (setq mouse-autoselect-window-state (when suspend 'suspend))
   ;; Install timer which runs `mouse-autoselect-window-select' after
   ;; `mouse-autoselect-window' seconds.
@@ -10473,7 +10475,7 @@ mouse-autoselect-window-select
                (and (>= mouse-autoselect-window 0)
                     ;; If `mouse-autoselect-window' is non-negative,
                     ;; select window if it's the same as before.
-                    (eq window mouse-autoselect-window-window))
+                    (eq window mouse-autoselect-window-previous-window))
                ;; Otherwise select window iff the mouse is at the same
                ;; position as before.  Observe that the first test
                ;; after starting autoselection usually fails since the
diff --git a/src/haikuterm.c b/src/haikuterm.c
index 8733b82fb2b..8341fd4cc53 100644
--- a/src/haikuterm.c
+++ b/src/haikuterm.c
@@ -3471,11 +3471,10 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 
 		if (!NILP (Vmouse_autoselect_window))
 		  {
-		    static Lisp_Object last_mouse_window;
 		    Lisp_Object window = window_from_coordinates (f, b->x, b->y, 0, 0, 0);
 
 		    if (WINDOWP (window)
-			&& !EQ (window, last_mouse_window)
+			&& !EQ (window, Vmouse_autoselect_window_last_window)
 			&& !EQ (window, selected_window)
 			&& !popup_activated_p
 			&& !MINI_WINDOW_P (XWINDOW (selected_window))
@@ -3486,7 +3485,7 @@ haiku_read_socket (struct terminal *terminal, struct input_event *hold_quit)
 			inev2.frame_or_window = window;
 		      }
 
-		    last_mouse_window = window;
+		    Vmouse_autoselect_window_last_window = window;
 		  }
 
 		if (f->auto_raise)
diff --git a/src/msdos.c b/src/msdos.c
index 75a39045cee..333fd9d59e6 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -2652,8 +2652,6 @@ dos_rawgetc (void)
 	  /* Generate SELECT_WINDOW_EVENTs when needed.  */
 	  if (!NILP (Vmouse_autoselect_window))
 	    {
-	      static Lisp_Object last_mouse_window;
-
 	      mouse_window = window_from_coordinates
 		(SELECTED_FRAME (), mouse_last_x, mouse_last_y, 0, 0, 0);
 	      /* A window will be selected only when it is not
@@ -2661,7 +2659,7 @@ dos_rawgetc (void)
 		 not in it.  A minibuffer window will be selected iff
 		 it is active.  */
 	      if (WINDOWP (mouse_window)
-		  && !EQ (mouse_window, last_mouse_window)
+		  && !EQ (mouse_window, Vmouse_autoselect_window_last_window)
 		  && !EQ (mouse_window, selected_window))
 		{
 		  event.kind = SELECT_WINDOW_EVENT;
@@ -2671,7 +2669,7 @@ dos_rawgetc (void)
 		  kbd_buffer_store_event (&event);
 		}
 	      /* Remember the last window where we saw the mouse.  */
-	      last_mouse_window = mouse_window;
+	      Vmouse_autoselect_window_last_window = mouse_window;
 	    }
 
 	  previous_help_echo_string = help_echo_string;
diff --git a/src/nsterm.m b/src/nsterm.m
index c809c0b824a..060898bb842 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -7530,12 +7530,11 @@ - (void)mouseMoved: (NSEvent *)e
   if (!NILP (Vmouse_autoselect_window))
     {
       NSTRACE_MSG ("mouse_autoselect_window");
-      static Lisp_Object last_mouse_window;
       Lisp_Object window
 	= window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0, 0);
 
       if (WINDOWP (window)
-          && !EQ (window, last_mouse_window)
+          && !EQ (window, Vmouse_autoselect_window_last_window)
           && !EQ (window, selected_window)
 	  && !MINI_WINDOW_P (XWINDOW (selected_window))
           && (!NILP (focus_follows_mouse)
@@ -7548,7 +7547,7 @@ - (void)mouseMoved: (NSEvent *)e
           EV_TRAILER2 (e);
         }
       /* Remember the last window where we saw the mouse.  */
-      last_mouse_window = window;
+      Vmouse_autoselect_window_last_window = window;
     }
 
   dragging = (e.type == NSEventTypeLeftMouseDragged);
diff --git a/src/pgtkterm.c b/src/pgtkterm.c
index e767e15cc07..b343bd99fbe 100644
--- a/src/pgtkterm.c
+++ b/src/pgtkterm.c
@@ -5889,7 +5889,6 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
 	     also when the target window is on another frame.  */
 	  && (f == XFRAME (selected_frame) || !NILP (focus_follows_mouse)))
 	{
-	  static Lisp_Object last_mouse_window;
 	  Lisp_Object window = window_from_coordinates
 	    (f, event->motion.x, event->motion.y, 0, false, false);
 
@@ -5902,7 +5901,7 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
 	     autoselection the window is usually the window's text
 	     area including the margins.  */
 	  if (WINDOWP (window)
-	      && !EQ (window, last_mouse_window)
+	      && !EQ (window, Vmouse_autoselect_window_last_window)
 	      && !EQ (window, selected_window))
 	    {
 	      inev.ie.kind = SELECT_WINDOW_EVENT;
@@ -5910,7 +5909,7 @@ motion_notify_event (GtkWidget *widget, GdkEvent *event,
 	    }
 
 	  /* Remember the last window where we saw the mouse.  */
-	  last_mouse_window = window;
+	  Vmouse_autoselect_window_last_window = window;
 	}
 
       if (!note_mouse_movement (f, &event->motion))
diff --git a/src/w32inevt.c b/src/w32inevt.c
index 29717954cfd..c800291c2f8 100644
--- a/src/w32inevt.c
+++ b/src/w32inevt.c
@@ -467,7 +467,6 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
 		struct input_event *emacs_ev)
 {
   static DWORD button_state = 0;
-  static Lisp_Object last_mouse_window;
   DWORD but_change, mask, flags = event->dwEventFlags;
   int i;
 
@@ -502,7 +501,7 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
 		   not in it.  A minibuffer window will be selected iff
 		   it is active.  */
 		if (WINDOWP (mouse_window)
-		    && !EQ (mouse_window, last_mouse_window)
+		    && !EQ (mouse_window, Vmouse_autoselect_window_last_window)
 		    && !EQ (mouse_window, selected_window))
 		  {
 		    struct input_event event;
@@ -514,10 +513,8 @@ do_mouse_event (MOUSE_EVENT_RECORD *event,
 		    event.timestamp = movement_time;
 		    kbd_buffer_store_event (&event);
 		  }
-		last_mouse_window = mouse_window;
+		Vmouse_autoselect_window_last_window = mouse_window;
 	      }
-	    else
-	      last_mouse_window = Qnil;
 
 	    previous_help_echo_string = help_echo_string;
 	    help_echo_string = help_echo_object = help_echo_window = Qnil;
diff --git a/src/w32term.c b/src/w32term.c
index 2899e82b295..f9d86637024 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -5333,7 +5333,6 @@ w32_read_socket (struct terminal *terminal,
 		      || (!NILP (focus_follows_mouse)
 			  && !FRAME_NO_ACCEPT_FOCUS (f))))
 		{
-		  static Lisp_Object last_mouse_window;
 		  Lisp_Object window = window_from_coordinates
 		    (f, LOWORD (msg.msg.lParam), HIWORD (msg.msg.lParam), 0, 0, 0);
 
@@ -5342,7 +5341,7 @@ w32_read_socket (struct terminal *terminal,
 		     not in it.  Minibuffer window will be selected
 		     only when it is active.  */
 		  if (WINDOWP (window)
-		      && !EQ (window, last_mouse_window)
+		      && !EQ (window, Vmouse_autoselect_window_last_window)
 		      && !EQ (window, selected_window))
 		    {
 		      inev.kind = SELECT_WINDOW_EVENT;
@@ -5350,7 +5349,7 @@ w32_read_socket (struct terminal *terminal,
 		    }
 
 		  /* Remember the last window where we saw the mouse.  */
-		  last_mouse_window = window;
+		  Vmouse_autoselect_window_last_window = window;
 		}
 
 	      if (!w32_note_mouse_movement (f, &msg.msg))
diff --git a/src/xdisp.c b/src/xdisp.c
index 9cddcfeda27..dc0cbb658f6 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -36854,6 +36854,13 @@ syms_of_xdisp (void)
 of your window manager.  */);
   Vmouse_autoselect_window = Qnil;
 
+  DEFVAR_LISP ("mouse-autoselect-window-last-window",
+	       Vmouse_autoselect_window_last_window,
+    doc: /* Last window entered by the the mouse pointer.
+This variable is tracked only when both `mouse-autoselect-window' and
+`focus-follows-mouse' are non-nil. */);
+  Vmouse_autoselect_window_last_window = Qnil;
+
   DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
     doc: /* Non-nil means automatically resize tab-bars.
 This dynamically changes the tab-bar's height to the minimum height
diff --git a/src/xterm.c b/src/xterm.c
index 5840b15bcb7..36ba3103a70 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -20681,8 +20681,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		&& (f == XFRAME (selected_frame)
 		    || !NILP (focus_follows_mouse)))
 	      {
-		static Lisp_Object last_mouse_window;
-
 		if (xmotion.window != FRAME_X_WINDOW (f))
 		  {
 		    x_translate_coordinates (f, xmotion.x_root, xmotion.y_root,
@@ -20702,7 +20700,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		   autoselection the window is usually the window's text
 		   area including the margins.  */
 		if (WINDOWP (window)
-		    && !EQ (window, last_mouse_window)
+		    && !EQ (window, Vmouse_autoselect_window_last_window)
 		    && !EQ (window, selected_window))
 		  {
 		    inev.ie.kind = SELECT_WINDOW_EVENT;
@@ -20710,7 +20708,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		  }
 
 		/* Remember the last window where we saw the mouse.  */
-		last_mouse_window = window;
+		Vmouse_autoselect_window_last_window = window;
 	      }
 
             if (!x_note_mouse_movement (f, &xmotion, Qnil))
@@ -22593,7 +22591,6 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 		      && (f == XFRAME (selected_frame)
 			  || !NILP (focus_follows_mouse)))
 		    {
-		      static Lisp_Object last_mouse_window;
 		      Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
 
 		      /* A window will be autoselected only when it is not
@@ -22605,7 +22602,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			 autoselection the window is usually the window's text
 			 area including the margins.  */
 		      if (WINDOWP (window)
-			  && !EQ (window, last_mouse_window)
+			  && !EQ (window, Vmouse_autoselect_window_last_window)
 			  && !EQ (window, selected_window))
 			{
 			  inev.ie.kind = SELECT_WINDOW_EVENT;
@@ -22616,7 +22613,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 			}
 
 		      /* Remember the last window where we saw the mouse.  */
-		      last_mouse_window = window;
+		      Vmouse_autoselect_window_last_window = window;
 		    }
 
 		  if (!x_note_mouse_movement (f, &ev, source ? source->name : Qnil))
-- 
2.41.0


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

* bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2
  2023-08-22  5:45     ` Adrián Medraño Calvo
@ 2023-08-22  6:59       ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 0 replies; 7+ messages in thread
From: Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2023-08-22  6:59 UTC (permalink / raw)
  To: Adrián Medraño Calvo; +Cc: 61241, Eli Zaretskii

Adrián Medraño Calvo <adrian@medranocalvo.com> writes:

> I prepared a patch (attached below) introducing a new lisp variable
> holding the last "mouse-autoselected” window.  With this patch EXWM
> can simply select the Emacs window corresponding to the managed X
> window and set it as last “mouse-autoselected” window;
> mouse-autoselect works normally after that.  No more sending Motion
> events.
>
> Using a single variable introduces a significant change, though: when
> `mouse-autoselect-window’ is enabled and emacs runs in different
> terminals, “mouse-autoselecting” a window on a terminal changes the
> last “mouse-autoselected” window for all other terminals.  Slightly
> moving the mouse in a different terminal (within a single Emacs
> window) will “mouse-autoselect” that window, whereas that would not
> have been the case before this patch, as the last “mouse-autoselected”
> window was terminal-specific.  It’s not clear to me whether this
> behaviour will be beneficial, neutral or unacceptable.  Moreover, this
> behaviour is consistent with the behaviour introduced in the first
> patch I sent, where I proposed to merge the last “mouse-autoselected”
> window for Motion and XI_Motion events (other terminals were not
> affected).

Thanks.  Taking into account your experiences with the TEST extension,
I'm inclined towards believing that such a change is TRT, but the
variable should be made terminal-local instead.  (Emacs Lisp does
provide such a facility.)

Also, there are a few difficulties with the patch you attached.  First
of all, it obsoletes an existing variable without due reason, and that
should be avoided.  Secondly, :version specifiers within the patch
should be revised to mention Emacs 30, since such a large change is not
apposite for the release branch.

Finally, you missed the new terminal backend introduced in Emacs 30,
src/androidterm.c.





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

end of thread, other threads:[~2023-08-22  6:59 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-02 22:28 bug#61241: 29.0.60; Incoherent last_mouse_window (xterm.c) between XInput and XInput 2 Adrián Medraño Calvo
2023-02-04  8:25 ` Eli Zaretskii
2023-02-04  8:43   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-02-05 19:04 ` Adrián Medraño Calvo
2023-02-06  1:40   ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors
2023-08-22  5:45     ` Adrián Medraño Calvo
2023-08-22  6:59       ` Po Lu via Bug reports for GNU Emacs, the Swiss army knife of text editors

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