emacs-diffs
[Top][All Lists]
Advanced

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

master 3b41141708: Expose the name of an event's input device to Lisp


From: Po Lu
Subject: master 3b41141708: Expose the name of an event's input device to Lisp
Date: Thu, 7 Apr 2022 09:36:21 -0400 (EDT)

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

    Expose the name of an event's input device to Lisp
    
    This name can be used to identify the device for special
    treatment, i.e. only interpolating scrolls coming from mice and
    not touchpads inside pixel-scroll-precision-mode.
    
    * doc/lispref/commands.texi (Command Loop Info): Document new
    variable `last-event-device'.
    * etc/NEWS: Announce new variable `last-event-device'.
    * src/frame.h (struct frame): New field `last_mouse_device'.
    * src/keyboard.c (read_char): Clear last-event-device.
    (kbd_buffer_get_event): Set last-event-device to the event's
    recorded device.
    (init_keyboard): Clear last-event-device.
    (syms_of_keyboard): New defvar `last-event-device'.
    * src/termhooks.h (struct input_event): New field `device'.
    (EVENT_INIT): Set it to the special value `Qt' by default.
    * src/xterm.c (x_init_master_valuators): Record the device's
    name.
    (x_dnd_begin_drag_and_drop): Only preserve last event device if
    the mouse ended up in the source frame.
    (x_note_mouse_movement): New argument `source'.
    (handle_one_xevent): Set input event sources whenever
    appropriate.
    (mark_xterm): Mark device names.
    
    * src/xterm.h (struct xi_device_t): New field `name'.
---
 doc/lispref/commands.texi |  14 ++++++
 etc/NEWS                  |   5 ++
 src/frame.h               |   4 ++
 src/keyboard.c            |  46 +++++++++++++++++
 src/termhooks.h           |  10 +++-
 src/xterm.c               | 124 +++++++++++++++++++++++++++++++++++++++-------
 src/xterm.h               |   2 +
 7 files changed, 186 insertions(+), 19 deletions(-)

diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi
index a4ae68af5b..74bf0f4869 100644
--- a/doc/lispref/commands.texi
+++ b/doc/lispref/commands.texi
@@ -1127,6 +1127,20 @@ frame, the value is the frame to which the event was 
redirected.
 If the last event came from a keyboard macro, the value is @code{macro}.
 @end defvar
 
+@defvar last-event-device
+This variable records the name of the input device from which the last
+input event read was generated.  It is @code{nil} if no such device
+exists, i.e., the last input event was read from
+@code{unread-command-events}, or it came from a keyboard macro.
+
+When the X Input Extension is being used on X Windows, the device name
+is a string that is unique to each physical keyboard, pointing device
+and touchscreen attached to the X server.  Otherwise, it is either the
+string @samp{"Virtual core pointer"} or @samp{"Virtual core
+keyboard"}, depending on whether the event was generated by a pointing
+device (such as a mouse) or a keyboard.
+@end defvar
+
 @node Adjusting Point
 @section Adjusting Point After Commands
 @cindex adjusting point
diff --git a/etc/NEWS b/etc/NEWS
index 564bd16022..85ed817e05 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1353,6 +1353,11 @@ functions.
 
 * Lisp Changes in Emacs 29.1
 
++++
+** New variable 'last-event-device'.
+On X Windows, this specifies the input extension device from which the
+last input event originated.
+
 +++
 ** 'track-mouse' can be a new value 'drag-source'.
 This means the same as 'dropping', but modifies the mouse position
diff --git a/src/frame.h b/src/frame.h
index 61df57e966..4942e640d2 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -102,6 +102,10 @@ struct frame
   Lisp_Object parent_frame;
 #endif /* HAVE_WINDOW_SYSTEM */
 
+  /* Last device to move over this frame.  Any value that isn't a
+     string means the "Virtual core pointer".  */
+  Lisp_Object last_mouse_device;
+
   /* The frame which should receive keystrokes that occur in this
      frame, or nil if they should go to the frame itself.  This is
      usually nil, but if the frame is minibufferless, we can use this
diff --git a/src/keyboard.c b/src/keyboard.c
index d99fe4be09..8142ffec2d 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -336,6 +336,11 @@ static struct timespec timer_idleness_start_time;
 
 static struct timespec timer_last_idleness_start_time;
 
+/* Predefined strings for core device names.  */
+
+static Lisp_Object virtual_core_pointer_name;
+static Lisp_Object virtual_core_keyboard_name;
+
 
 /* Global variable declarations.  */
 
@@ -2520,6 +2525,8 @@ read_char (int commandflag, Lisp_Object map,
       goto reread_for_input_method;
     }
 
+  Vlast_event_device = Qnil;
+
   if (!NILP (Vexecuting_kbd_macro))
     {
       /* We set this to Qmacro; since that's not a frame, nobody will
@@ -4118,6 +4125,15 @@ kbd_buffer_get_event (KBOARD **kbp,
            obj = make_lispy_switch_frame (frame);
          internal_last_event_frame = frame;
 
+         if (EQ (event->ie.device, Qt))
+           Vlast_event_device = ((event->ie.kind == ASCII_KEYSTROKE_EVENT
+                                  || event->ie.kind == 
MULTIBYTE_CHAR_KEYSTROKE_EVENT
+                                  || event->ie.kind == 
NON_ASCII_KEYSTROKE_EVENT)
+                                 ? virtual_core_keyboard_name
+                                 : virtual_core_pointer_name);
+         else
+           Vlast_event_device = event->ie.device;
+
          /* If we didn't decide to make a switch-frame event, go ahead
             and build a real event from the queue entry.  */
          if (NILP (obj))
@@ -4173,6 +4189,10 @@ kbd_buffer_get_event (KBOARD **kbp,
                      XSETCAR (Fnthcdr (make_fixnum (3),
                                        maybe_event->ie.arg),
                               make_float (fmod (pinch_angle, 360.0)));
+
+                     if (!EQ (maybe_event->ie.device, Qt))
+                       Vlast_event_device = maybe_event->ie.device;
+
                      maybe_event = next_kbd_event (event);
                    }
                }
@@ -4296,6 +4316,11 @@ kbd_buffer_get_event (KBOARD **kbp,
         return a mouse-motion event.  */
       if (!NILP (x) && NILP (obj))
        obj = make_lispy_movement (f, bar_window, part, x, y, t);
+
+      if (!NILP (obj))
+       Vlast_event_device = (STRINGP (f->last_mouse_device)
+                             ? f->last_mouse_device
+                             : virtual_core_pointer_name);
     }
   else
     /* We were promised by the above while loop that there was
@@ -11805,6 +11830,10 @@ init_keyboard (void)
   interrupt_input_blocked = 0;
   pending_signals = false;
 
+  virtual_core_pointer_name = build_string ("Virtual core pointer");
+  virtual_core_keyboard_name = build_string ("Virtual core keyboard");
+  Vlast_event_device = Qnil;
+
   /* This means that command_loop_1 won't try to select anything the first
      time through.  */
   internal_last_event_frame = Qnil;
@@ -12225,6 +12254,12 @@ syms_of_keyboard (void)
   staticpro (&poll_timer_time);
 #endif
 
+  virtual_core_pointer_name = Qnil;
+  staticpro (&virtual_core_pointer_name);
+
+  virtual_core_keyboard_name = Qnil;
+  staticpro (&virtual_core_keyboard_name);
+
   defsubr (&Scurrent_idle_time);
   defsubr (&Sevent_symbol_parse_modifiers);
   defsubr (&Sevent_convert_list);
@@ -12423,6 +12458,17 @@ This does not include events generated by keyboard 
macros.  */);
 If the last event came from a keyboard macro, this is set to `macro'.  */);
   Vlast_event_frame = Qnil;
 
+  DEFVAR_LISP ("last-event-device", Vlast_event_device,
+              doc: /* The name of the input device of the most recently read 
event.
+When the input extension is being used on X, this is the name of the X
+Input Extension device from which the last event was generated as a
+string.  Otherwise, this is "Virtual core keyboard" for keyboard input
+events, and "Virtual core pointer" for other events.
+
+It is nil if the last event did not come from an input device (i.e. it
+came from `unread-command-events' instead).  */);
+  Vlast_event_device = Qnil;
+
   /* This variable is set up in sysdep.c.  */
   DEFVAR_LISP ("tty-erase-char", Vtty_erase_char,
               doc: /* The ERASE character as set by the user with stty.  */);
diff --git a/src/termhooks.h b/src/termhooks.h
index 0f02b56e9e..8c193914ba 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -392,9 +392,17 @@ struct input_event
      when building events.  Unfortunately some events have to pass much
      more data than it's reasonable to pack directly into this structure.  */
   Lisp_Object arg;
+
+  /* The name of the device from which this event originated.
+
+     It can either be a string, or Qt, which means to use the name
+     "Virtual core pointer" for all events other than keystroke
+     events, and "Virtual core keyboard" for those.  */
+  Lisp_Object device;
 };
 
-#define EVENT_INIT(event) memset (&(event), 0, sizeof (struct input_event))
+#define EVENT_INIT(event) (memset (&(event), 0, sizeof (struct input_event)), \
+                          (event).device = Qt)
 
 /* Bits in the modifiers member of the input_event structure.
    Note that reorder_modifiers assumes that the bits are in canonical
diff --git a/src/xterm.c b/src/xterm.c
index 57a64cb5d1..d4a5e0ab3d 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -3922,6 +3922,7 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
 #ifdef HAVE_XINPUT2_2
          xi_device->direct_p = false;
 #endif
+         xi_device->name = build_string (device->name);
 
          for (int c = 0; c < device->num_classes; ++c)
            {
@@ -9653,6 +9654,12 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, 
Atom xaction,
   if (x_dnd_return_frame == 3
       && FRAME_LIVE_P (x_dnd_return_frame_object))
     {
+      /* Deliberately preserve the last device if
+        x_dnd_return_frame_object is the drag source.  */
+
+      if (x_dnd_return_frame_object != x_dnd_frame)
+       x_dnd_return_frame_object->last_mouse_device = Qnil;
+
       x_dnd_return_frame_object->mouse_moved = true;
 
       XSETFRAME (action, x_dnd_return_frame_object);
@@ -10170,7 +10177,8 @@ x_construct_mouse_click (struct input_event *result,
    XI_Enter and XI_Leave labels inside `handle_one_xevent'.  */
 
 static bool
-x_note_mouse_movement (struct frame *frame, const XMotionEvent *event)
+x_note_mouse_movement (struct frame *frame, const XMotionEvent *event,
+                      Lisp_Object device)
 {
   XRectangle *r;
   struct x_display_info *dpyinfo;
@@ -10187,6 +10195,7 @@ x_note_mouse_movement (struct frame *frame, const 
XMotionEvent *event)
   if (event->window != FRAME_X_WINDOW (frame))
     {
       frame->mouse_moved = true;
+      frame->last_mouse_device = device;
       dpyinfo->last_mouse_scroll_bar = NULL;
       note_mouse_highlight (frame, -1, -1);
       dpyinfo->last_mouse_glyph_frame = NULL;
@@ -10201,6 +10210,7 @@ x_note_mouse_movement (struct frame *frame, const 
XMotionEvent *event)
       || event->y < r->y || event->y >= r->y + r->height)
     {
       frame->mouse_moved = true;
+      frame->last_mouse_device = device;
       dpyinfo->last_mouse_scroll_bar = NULL;
       note_mouse_highlight (frame, event->x, event->y);
       /* Remember which glyph we're now on.  */
@@ -14788,12 +14798,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
       /* EnterNotify counts as mouse movement,
         so update things that depend on mouse position.  */
       if (f && !f->output_data.x->hourglass_p)
-       x_note_mouse_movement (f, &event->xmotion);
+       x_note_mouse_movement (f, &event->xmotion, Qnil);
 #ifdef USE_GTK
       /* We may get an EnterNotify on the buttons in the toolbar.  In that
          case we moved out of any highlighted area and need to note this.  */
       if (!f && dpyinfo->last_mouse_glyph_frame)
-        x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, 
&event->xmotion);
+        x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, 
&event->xmotion,
+                              Qnil);
 #endif
       goto OTHER;
 
@@ -14884,7 +14895,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef USE_GTK
       /* See comment in EnterNotify above */
       else if (dpyinfo->last_mouse_glyph_frame)
-        x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, 
&event->xmotion);
+        x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame,
+                              &event->xmotion, Qnil);
 #endif
       goto OTHER;
 
@@ -15123,7 +15135,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                last_mouse_window = window;
              }
 
-            if (!x_note_mouse_movement (f, &xmotion))
+            if (!x_note_mouse_movement (f, &xmotion, Qnil))
              help_echo_string = previous_help_echo_string;
           }
         else
@@ -15903,8 +15915,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
            {
              XIEnterEvent *enter = (XIEnterEvent *) xi_event;
              XMotionEvent ev;
+             struct xi_device_t *source;
 
              any = x_top_window_to_frame (dpyinfo, enter->event);
+             source = xi_device_from_id (dpyinfo, enter->sourceid);
              ev.x = lrint (enter->event_x);
              ev.y = lrint (enter->event_y);
              ev.window = enter->event;
@@ -15972,12 +15986,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              /* EnterNotify counts as mouse movement,
                 so update things that depend on mouse position.  */
              if (f && !f->output_data.x->hourglass_p)
-               x_note_mouse_movement (f, &ev);
+               x_note_mouse_movement (f, &ev, source ? source->name : Qnil);
 #ifdef USE_GTK
              /* We may get an EnterNotify on the buttons in the toolbar.  In 
that
                 case we moved out of any highlighted area and need to note 
this.  */
              if (!f && dpyinfo->last_mouse_glyph_frame)
-               x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
+               x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
+                                      source ? source->name : Qnil);
 #endif
              goto XI_OTHER;
            }
@@ -15985,6 +16000,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
          case XI_Leave:
            {
              XILeaveEvent *leave = (XILeaveEvent *) xi_event;
+             struct xi_device_t *source;
 #ifdef USE_GTK
              XMotionEvent ev;
 
@@ -15995,6 +16011,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #endif
 
              any = x_top_window_to_frame (dpyinfo, leave->event);
+             source = xi_device_from_id (dpyinfo, leave->sourceid);
 
              /* This allows us to catch LeaveNotify events generated by
                 popup menu grabs.  FIXME: this is right when there is a
@@ -16098,14 +16115,15 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef USE_GTK
              /* See comment in EnterNotify above */
              else if (dpyinfo->last_mouse_glyph_frame)
-               x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev);
+               x_note_mouse_movement (dpyinfo->last_mouse_glyph_frame, &ev,
+                                      source ? source->name : Qnil);
 #endif
              goto XI_OTHER;
            }
 
          case XI_Motion:
            {
-             struct xi_device_t *device;
+             struct xi_device_t *device, *source;
 #ifdef HAVE_XINPUT2_1
              XIValuatorState *states;
              double *values;
@@ -16117,6 +16135,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              xm_top_level_enter_message emsg;
              xm_drag_motion_message dmsg;
 
+             source = xi_device_from_id (dpyinfo, xev->sourceid);
 
 #ifdef HAVE_XINPUT2_1
              states = &xev->valuators;
@@ -16333,6 +16352,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                          XSETFRAME (inev.ie.frame_or_window, f);
                        }
 
+                     if (source && source->name)
+                       inev.ie.device = source->name;
+
                      goto XI_OTHER;
                    }
 #ifdef HAVE_XWIDGETS
@@ -16588,13 +16610,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                        {
                          inev.ie.kind = SELECT_WINDOW_EVENT;
                          inev.ie.frame_or_window = window;
+
+                         if (source)
+                           inev.ie.device = source->name;
                        }
 
                      /* Remember the last window where we saw the mouse.  */
                      last_mouse_window = window;
                    }
 
-                 if (!x_note_mouse_movement (f, &ev))
+                 if (!x_note_mouse_movement (f, &ev, source ? source->name : 
Qnil))
                    help_echo_string = previous_help_echo_string;
                }
              else
@@ -16628,7 +16653,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              Lisp_Object tab_bar_arg = Qnil;
              bool tab_bar_p = false;
              bool tool_bar_p = false;
-             struct xi_device_t *device;
+             struct xi_device_t *device, *source;
 #ifdef HAVE_XWIDGETS
              struct xwidget_view *xvw;
 #endif
@@ -16837,6 +16862,8 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              if (xev->evtype == XI_ButtonPress)
                x_display_set_last_user_time (dpyinfo, xev->time);
 
+             source = xi_device_from_id (dpyinfo, xev->sourceid);
+
 #ifdef HAVE_XWIDGETS
              xvw = xwidget_view_from_window (xev->event);
              if (xvw)
@@ -16849,6 +16876,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                    {
                      inev.ie.kind = SELECT_WINDOW_EVENT;
                      inev.ie.frame_or_window = xvw->w;
+
+                     if (source)
+                       inev.ie.device = source->name;
                    }
 
                  *finish = X_EVENT_DROP;
@@ -16918,6 +16948,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                          else
                            inev.ie.kind = HORIZ_WHEEL_EVENT;
 
+                         if (source)
+                           inev.ie.device = source->name;
+
                          inev.ie.timestamp = xev->time;
 
                          XSETINT (inev.ie.x, real_x);
@@ -16953,6 +16986,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                          else
                            inev.ie.kind = HORIZ_WHEEL_EVENT;
 
+                         if (source)
+                           inev.ie.device = source->name;
+
                          inev.ie.timestamp = xev->time;
 
                          XSETINT (inev.ie.x, lrint (xev->event_x));
@@ -17070,6 +17106,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                  device->grab &= ~(1 << xev->detail);
                }
 
+             if (source && inev.ie.kind != NO_EVENT)
+               inev.ie.device = source->name;
+
              if (f)
                f->mouse_moved = false;
 
@@ -17108,11 +17147,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
              char *copy_bufptr = copy_buffer;
              int copy_bufsiz = sizeof (copy_buffer);
              ptrdiff_t i;
-             struct xi_device_t *device;
+             struct xi_device_t *device, *source;
 
              coding = Qlatin_1;
 
              device = xi_device_from_id (dpyinfo, xev->deviceid);
+             source = xi_device_from_id (dpyinfo, xev->sourceid);
 
              if (!device)
                goto XI_OTHER;
@@ -17350,6 +17390,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                      inev.ie.kind = ASCII_KEYSTROKE_EVENT;
                      inev.ie.code = keysym;
 
+                     if (source)
+                       inev.ie.device = source->name;
+
                      goto xi_done_keysym;
                    }
 
@@ -17360,6 +17403,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                        inev.ie.kind = ASCII_KEYSTROKE_EVENT;
                      else
                        inev.ie.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+
+                     if (source)
+                       inev.ie.device = source->name;
+
                      inev.ie.code = keysym & 0xFFFFFF;
                      goto xi_done_keysym;
                    }
@@ -17375,6 +17422,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                                      ? ASCII_KEYSTROKE_EVENT
                                      : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
                      inev.ie.code = XFIXNAT (c);
+
+                     if (source)
+                       inev.ie.device = source->name;
+
                      goto xi_done_keysym;
                    }
 
@@ -17479,6 +17530,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                         key.  */
                      inev.ie.kind = NON_ASCII_KEYSTROKE_EVENT;
                      inev.ie.code = keysym;
+
+                     if (source)
+                       inev.ie.device = source->name;
+
                      goto xi_done_keysym;
                    }
 
@@ -17494,6 +17549,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
                      Fput_text_property (make_fixnum (0), make_fixnum (nbytes),
                                          Qcoding, coding, inev.ie.arg);
+
+                     if (source)
+                       inev.ie.device = source->name;
                    }
                  goto xi_done_keysym;
                }
@@ -17688,12 +17746,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 #ifdef HAVE_XINPUT2_2
          case XI_TouchBegin:
            {
-             struct xi_device_t *device;
+             struct xi_device_t *device, *source;
              bool menu_bar_p = false, tool_bar_p = false;
 #ifdef HAVE_GTK3
              GdkRectangle test_rect;
 #endif
              device = xi_device_from_id (dpyinfo, xev->deviceid);
+             source = xi_device_from_id (dpyinfo, xev->sourceid);
              x_display_set_last_user_time (dpyinfo, xev->time);
 
              if (!device)
@@ -17741,6 +17800,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                          XSETINT (inev.ie.x, lrint (xev->event_x));
                          XSETINT (inev.ie.y, lrint (xev->event_y));
                          XSETINT (inev.ie.arg, xev->detail);
+
+                         if (source)
+                           inev.ie.device = source->name;
                        }
                      x_uncatch_errors_after_check ();
                    }
@@ -17774,11 +17836,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
          case XI_TouchUpdate:
            {
-             struct xi_device_t *device;
+             struct xi_device_t *device, *source;
              struct xi_touch_point_t *touchpoint;
              Lisp_Object arg = Qnil;
 
              device = xi_device_from_id (dpyinfo, xev->deviceid);
+             source = xi_device_from_id (dpyinfo, xev->sourceid);
              x_display_set_last_user_time (dpyinfo, xev->time);
 
              if (!device)
@@ -17809,6 +17872,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                                   arg);
                    }
 
+                 if (source)
+                   inev.ie.device = source->name;
+
                  inev.ie.arg = arg;
                }
 
@@ -17817,10 +17883,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
 
          case XI_TouchEnd:
            {
-             struct xi_device_t *device;
+             struct xi_device_t *device, *source;
              bool unlinked_p;
 
              device = xi_device_from_id (dpyinfo, xev->deviceid);
+             source = xi_device_from_id (dpyinfo, xev->sourceid);
              x_display_set_last_user_time (dpyinfo, xev->time);
 
              if (!device)
@@ -17836,10 +17903,14 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                    {
                      inev.ie.kind = TOUCHSCREEN_END_EVENT;
                      inev.ie.timestamp = xev->time;
+
                      XSETFRAME (inev.ie.frame_or_window, f);
                      XSETINT (inev.ie.x, lrint (xev->event_x));
                      XSETINT (inev.ie.y, lrint (xev->event_y));
                      XSETINT (inev.ie.arg, xev->detail);
+
+                     if (source)
+                       inev.ie.device = source->name;
                    }
                }
 
@@ -17852,10 +17923,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
          case XI_GesturePinchBegin:
          case XI_GesturePinchUpdate:
            {
-             x_display_set_last_user_time (dpyinfo, xi_event->time);
-
              XIGesturePinchEvent *pev = (XIGesturePinchEvent *) xi_event;
-             struct xi_device_t *device = xi_device_from_id (dpyinfo, 
pev->deviceid);
+             struct xi_device_t *device, *source;
+
+             device = xi_device_from_id (dpyinfo, pev->deviceid);
+             source = xi_device_from_id (dpyinfo, pev->sourceid);
+             x_display_set_last_user_time (dpyinfo, xi_event->time);
 
              if (!device)
                goto XI_OTHER;
@@ -17884,6 +17957,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
                                       make_float (pev->delta_y),
                                       make_float (pev->scale),
                                       make_float (pev->delta_angle));
+
+                 if (source)
+                   inev.ie.device = source->name;
                }
 
              /* Once again GTK seems to crash when confronted by
@@ -23142,6 +23218,10 @@ void
 mark_xterm (void)
 {
   Lisp_Object val;
+#ifdef HAVE_XINPUT2
+  struct x_display_info *dpyinfo;
+  int i;
+#endif
 
   if (x_dnd_return_frame_object)
     {
@@ -23154,6 +23234,14 @@ mark_xterm (void)
       XSETFRAME (val, x_dnd_movement_frame);
       mark_object (val);
     }
+
+#ifdef HAVE_XINPUT2
+  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+    {
+      for (i = 0; i < dpyinfo->num_devices; ++i)
+       mark_object (dpyinfo->devices[i].name);
+    }
+#endif
 }
 
 void
diff --git a/src/xterm.h b/src/xterm.h
index d8898162d1..c12fd6c3fe 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -244,6 +244,8 @@ struct xi_device_t
 #ifdef HAVE_XINPUT2_2
   struct xi_touch_point_t *touchpoints;
 #endif
+
+  Lisp_Object name;
 };
 #endif
 



reply via email to

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