emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master fa9777b174: Fix treatment of input focus on MPX setups


From: Po Lu
Subject: master fa9777b174: Fix treatment of input focus on MPX setups
Date: Thu, 17 Nov 2022 02:15:21 -0500 (EST)

branch: master
commit fa9777b174ca330e3f5a75b431d8fe37771acdfa
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>

    Fix treatment of input focus on MPX setups
    
    * src/xterm.c (x_ewmh_activate_frame): Use x_set_input_focus
    instead of XSetInputFocus.
    (x_set_input_focus): New function.  Take into account the
    ``client pointer'' chosen by Emacs.
    (x_focus_frame): Use x_set_input_focus instead of
    XSetInputFocus.
---
 src/xterm.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 62 insertions(+), 16 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index d6ba532f16..55252d2201 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -1134,6 +1134,7 @@ static void x_clean_failable_requests (struct 
x_display_info *);
 static struct frame *x_tooltip_window_to_frame (struct x_display_info *,
                                                Window, bool *);
 static Window x_get_window_below (Display *, Window, int, int, int *, int *);
+static void x_set_input_focus (struct x_display_info *, Window, Time);
 
 #ifndef USE_TOOLKIT_SCROLL_BARS
 static void x_scroll_bar_redraw (struct scroll_bar *);
@@ -27535,11 +27536,10 @@ x_ewmh_activate_frame (struct frame *f)
            {
              time = x_get_server_time (f);
 
-             x_ignore_errors_for_next_request (dpyinfo);
-             XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
-                             RevertToParent, time);
+             x_set_input_focus (FRAME_DISPLAY_INFO (f),
+                                FRAME_OUTER_WINDOW (f),
+                                time);
              XRaiseWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f));
-             x_stop_ignoring_errors (dpyinfo);
 
              return;
            }
@@ -27584,6 +27584,57 @@ x_get_toplevel_parent (struct frame *f)
   return parent;
 }
 
+static void
+x_set_input_focus (struct x_display_info *dpyinfo, Window window,
+                  Time time)
+{
+#ifdef HAVE_XINPUT2
+  struct xi_device_t *device;
+#endif
+
+  /* Do the equivalent of XSetInputFocus with the specified window and
+     time, but use the attachment to the device that Emacs has
+     designated the client pointer on X Input Extension builds.
+     Asynchronously trap errors around the generated XI_SetFocus or
+     SetInputFocus request, in case the device has been destroyed or
+     the window obscured.
+
+     The revert_to will be set to RevertToParent for generated
+     SetInputFocus requests.  */
+
+#ifdef HAVE_XINPUT2
+  if (dpyinfo->supports_xi2
+      && dpyinfo->client_pointer_device != -1)
+    {
+      device = xi_device_from_id (dpyinfo, dpyinfo->client_pointer_device);
+
+      /* The device is a master pointer.  Use its attachment, which
+        should be the master keyboard.  */
+
+      if (device)
+       {
+         eassert (device->use == XIMasterPointer);
+
+         x_ignore_errors_for_next_request (dpyinfo);
+         XISetFocus (dpyinfo->display, device->attachment,
+                     /* Note that the input extension
+                        only supports RevertToParent-type
+                        behavior.  */
+                     window, time);
+         x_stop_ignoring_errors (dpyinfo);
+
+         return;
+       }
+    }
+#endif
+
+  /* Otherwise, use the pointer device that the X server says is the
+     client pointer.  */
+  x_ignore_errors_for_next_request (dpyinfo);
+  XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
+  x_stop_ignoring_errors (dpyinfo);
+}
+
 /* In certain situations, when the window manager follows a
    click-to-focus policy, there seems to be no way around calling
    XSetInputFocus to give another frame the input focus.
@@ -27653,20 +27704,15 @@ x_focus_frame (struct frame *f, bool noactivate)
             A BadMatch error can occur if the window was obscured
             after the time of the last user interaction without
             changing the last-focus-change-time.  */
-         x_ignore_errors_for_next_request (dpyinfo);
-         XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
-                         RevertToParent, time);
-         x_stop_ignoring_errors (dpyinfo);
+         x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
+                            time);
        }
       else
-       {
-         x_ignore_errors_for_next_request (dpyinfo);
-         XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
-                         /* But when no window manager is in use, we
-                            don't care.  */
-                         RevertToParent, CurrentTime);
-         x_stop_ignoring_errors (dpyinfo);
-       }
+       x_set_input_focus (FRAME_DISPLAY_INFO (f), FRAME_OUTER_WINDOW (f),
+                          /* But when no window manager is in use,
+                             respecting the ICCCM doesn't really
+                             matter.  */
+                          CurrentTime);
     }
 }
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]