emacs-diffs
[Top][All Lists]
Advanced

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

master b9025c507a: Correctly handle touches on the tool bar


From: Po Lu
Subject: master b9025c507a: Correctly handle touches on the tool bar
Date: Tue, 17 Jan 2023 05:30:57 -0500 (EST)

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

    Correctly handle touches on the tool bar
    
    * src/xterm.c (xi_link_touch_point): New argument `frame'.  Set
    new field `touchpoint->frame' to it.
    (xi_unlink_touch_points): New function.
    (xi_disable_devices): Clear the tool bar device on frames whose
    tool bar device matches this field.
    (handle_one_xevent): If an XI_TouchBegin event lands on the tool
    bar, then simulate a pointer click.  Ignore future events from
    that touchpoint from there onwards.
    (x_make_frame_invisible, x_free_frame_resources): Unlink touch
    points associated with the frame.
    
    * src/xterm.h (struct xi_touch_point_t): New field `frame'.
    (struct x_output): New fields for keeping track of tool bar
    touches.
---
 src/xterm.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 src/xterm.h |  17 +++++++
 2 files changed, 163 insertions(+), 9 deletions(-)

diff --git a/src/xterm.c b/src/xterm.c
index 028bb7582c..6ae7e97f45 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5750,7 +5750,8 @@ xi_device_from_id (struct x_display_info *dpyinfo, int 
deviceid)
 
 static void
 xi_link_touch_point (struct xi_device_t *device,
-                    int detail, double x, double y)
+                    int detail, double x, double y,
+                    struct frame *frame)
 {
   struct xi_touch_point_t *touchpoint;
 
@@ -5759,6 +5760,7 @@ xi_link_touch_point (struct xi_device_t *device,
   touchpoint->x = x;
   touchpoint->y = y;
   touchpoint->number = detail;
+  touchpoint->frame = frame;
 
   device->touchpoints = touchpoint;
 }
@@ -5787,6 +5789,36 @@ xi_unlink_touch_point (int detail,
   return false;
 }
 
+/* Unlink all touch points associated with the frame F.
+   This is done upon unmapping or destroying F's window, because
+   touch point delivery after that point is undefined.  */
+
+static void
+xi_unlink_touch_points (struct frame *f)
+{
+  struct xi_device_t *device;
+  struct xi_touch_point_t **next, *last;
+  int i;
+
+  for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
+    {
+      device = &FRAME_DISPLAY_INFO (f)->devices[i];
+
+      /* Now unlink all touch points on DEVICE matching F.  */
+
+      for (next = &device->touchpoints; (last = *next);)
+       {
+         if (last->frame == f)
+           {
+             *next = last->next;
+             xfree (last);
+           }
+         else
+           next = &last->next;
+       }
+    }
+}
+
 static struct xi_touch_point_t *
 xi_find_touch_point (struct xi_device_t *device, int detail)
 {
@@ -13535,6 +13567,10 @@ xi_disable_devices (struct x_display_info *dpyinfo,
 #ifdef HAVE_XINPUT2_2
   struct xi_touch_point_t *tem, *last;
 #endif
+#if defined HAVE_XINPUT2_2 && !defined HAVE_EXT_TOOL_BAR
+  struct x_output *output;
+  Lisp_Object tail, frame;
+#endif
 
   /* Don't pointlessly copy dpyinfo->devices if there are no devices
      to disable.  */
@@ -13577,6 +13613,34 @@ xi_disable_devices (struct x_display_info *dpyinfo,
                  tem = tem->next;
                  xfree (last);
                }
+
+#ifndef HAVE_EXT_TOOL_BAR
+
+             /* Now look through each frame on DPYINFO.  If it has an
+                outstanding tool bar press for this device, release
+                the tool bar.  */
+
+             FOR_EACH_FRAME (tail, frame)
+               {
+                 if (!FRAME_X_P (XFRAME (frame))
+                     || (FRAME_DISPLAY_INFO (XFRAME (frame))
+                         != dpyinfo))
+                   continue;
+
+                 output = FRAME_OUTPUT_DATA (XFRAME (frame));
+
+                 if (output->tool_bar_touch_device
+                     == dpyinfo->devices[i].device_id)
+                   {
+                     if (XFRAME (frame)->last_tool_bar_item != -1
+                         && WINDOWP (XFRAME (frame)->tool_bar_window))
+                       handle_tool_bar_click (XFRAME (frame), 0, 0,
+                                              false, 0);
+
+                     output->tool_bar_touch_device = 0;
+                   }
+               }
+#endif
 #endif
 
              goto out;
@@ -24209,6 +24273,48 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                }
 #endif
 
+#ifndef HAVE_EXT_TOOL_BAR
+             /* Is this a touch from a direct touch device that is in
+                the tool-bar?  */
+             if (device->direct_p
+                 && WINDOWP (f->tool_bar_window)
+                 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
+               {
+                 Lisp_Object window;
+                 int x = xev->event_x;
+                 int y = xev->event_y;
+
+                 window = window_from_coordinates (f, x, y, 0, true, true);
+                 /* Ignore button release events if the mouse
+                    wasn't previously pressed on the tool bar.
+                    We do this because otherwise selecting some
+                    text with the mouse and then releasing it on
+                    the tool bar doesn't stop selecting text,
+                    since the tool bar eats the button up
+                    event.  */
+                 tool_bar_p = EQ (window, f->tool_bar_window);
+
+                 /* If this touch has started in the tool bar, do not
+                    send it to Lisp.  Instead, simulate a tool bar
+                    click, releasing it once it goes away.  */
+
+                 if (tool_bar_p)
+                   {
+                     handle_tool_bar_click (f, x, y, true, 0);
+
+                     /* Record the device and the touch ID on the
+                        frame.  That way, Emacs knows when to dismiss
+                        the tool bar click later.  */
+
+                     FRAME_OUTPUT_DATA (f)->tool_bar_touch_device
+                       = device->device_id;
+                     FRAME_OUTPUT_DATA (f)->tool_bar_touch_id = xev->detail;
+
+                     goto XI_OTHER;
+                   }
+               }
+#endif
+
              if (!menu_bar_p && !tool_bar_p)
                {
                  if (f && device->direct_p)
@@ -24218,13 +24324,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                      x_catch_errors (dpyinfo->display);
 
                      if (x_input_grab_touch_events)
-                       XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
-                                           xev->detail, xev->event, 
XIAcceptTouch);
+                       XIAllowTouchEvents (dpyinfo->display,
+                                           xev->deviceid,
+                                           xev->detail, xev->event,
+                                           XIAcceptTouch);
 
                      if (!x_had_errors_p (dpyinfo->display))
                        {
-                         xi_link_touch_point (device, xev->detail, 
xev->event_x,
-                                              xev->event_y);
+                         xi_link_touch_point (device, xev->detail,
+                                              xev->event_x,
+                                              xev->event_y, f);
 
                          inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
                          inev.ie.timestamp = xev->time;
@@ -24299,10 +24408,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                  for (touchpoint = device->touchpoints;
                       touchpoint; touchpoint = touchpoint->next)
                    {
-                     arg = Fcons (list3i (lrint (touchpoint->x),
-                                          lrint (touchpoint->y),
-                                          lrint (touchpoint->number)),
-                                  arg);
+                     if (touchpoint->frame == f)
+                       arg = Fcons (list3i (lrint (touchpoint->x),
+                                            lrint (touchpoint->y),
+                                            lrint (touchpoint->number)),
+                                    arg);
                    }
 
                  if (source)
@@ -24348,6 +24458,23 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                    }
                }
 
+             /* Now see if the touchpoint was previously on the tool bar.
+                If it was, release the tool bar.  */
+
+             if (!f)
+               f = x_window_to_frame (dpyinfo, xev->event);
+
+             if (f && (FRAME_OUTPUT_DATA (f)->tool_bar_touch_id
+                       == xev->detail))
+               {
+                 if (f->last_tool_bar_item != -1)
+                   handle_tool_bar_click (f, xev->event_x, xev->event_y,
+                                          false, 0);
+
+                 /* Now clear the tool bar device.  */
+                 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0;
+               }
+
              goto XI_OTHER;
            }
 
@@ -28453,6 +28580,11 @@ x_make_frame_invisible (struct frame *f)
 
   block_input ();
 
+#ifdef HAVE_XINPUT2_2
+  /* Remove any touch points associated with F.  */
+  xi_unlink_touch_points (f);
+#endif
+
   /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
      that the current position of the window is user-specified, rather than
      program-specified, so that when the window is mapped again, it will be
@@ -28658,6 +28790,11 @@ x_free_frame_resources (struct frame *f)
   xi_handle_delete_frame (dpyinfo, f);
 #endif
 
+#ifdef HAVE_XINPUT2_2
+  /* Remove any touch points associated with F.  */
+  xi_unlink_touch_points (f);
+#endif
+
   /* If a display connection is dead, don't try sending more
      commands to the X server.  */
   if (dpyinfo->display)
diff --git a/src/xterm.h b/src/xterm.h
index d768ba7ff8..28ae00ca19 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -257,10 +257,17 @@ struct xi_scroll_valuator_t
 
 struct xi_touch_point_t
 {
+  /* The next touch point in this list.  */
   struct xi_touch_point_t *next;
 
+  /* The touchpoint detail.  */
   int number;
+
+  /* The last known X and Y position of the touchpoint.  */
   double x, y;
+
+  /* The frame associated with this touch point.  */
+  struct frame *frame;
 };
 
 #endif
@@ -1295,6 +1302,16 @@ struct x_output
      VisibilityFullyObscured, but is set to something else in
      handle_one_xevent.  */
   int visibility_state;
+
+#ifdef HAVE_XINPUT2_2
+  /* The touch ID of the last touch point to have touched the tool
+     bar.  */
+  int tool_bar_touch_id;
+
+  /* The device that last touched the tool bar.  0 if no device
+     touched the tool bar.  */
+  int tool_bar_touch_device;
+#endif
 };
 
 enum



reply via email to

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