aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2021-12-17 14:23:07 +0800
committerPo Lu2021-12-17 14:23:07 +0800
commit5e5cde55e5be6e2d388252c3ccb0d019aee6b89e (patch)
tree339463076073de968bfe854c4813f0d47b6e34d5 /src
parent32b9b22f66b1afcc614d5f76860d56d5630c5bc4 (diff)
parentf6339412eebdc027b00263ae2b5c38a029e2f7b4 (diff)
downloademacs-5e5cde55e5be6e2d388252c3ccb0d019aee6b89e.tar.gz
emacs-5e5cde55e5be6e2d388252c3ccb0d019aee6b89e.zip
Merge remote-tracking branch 'origin/master' into feature/pgtk
Diffstat (limited to 'src')
-rw-r--r--src/keyboard.c43
-rw-r--r--src/systime.h3
-rw-r--r--src/termhooks.h13
-rw-r--r--src/timefns.c73
-rw-r--r--src/xfns.c21
-rw-r--r--src/xterm.c604
-rw-r--r--src/xterm.h11
7 files changed, 507 insertions, 261 deletions
diff --git a/src/keyboard.c b/src/keyboard.c
index df07cf290b8..821a1b576be 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -6013,6 +6013,46 @@ make_lispy_event (struct input_event *event)
6013 return list2 (Qtouch_end, position); 6013 return list2 (Qtouch_end, position);
6014 } 6014 }
6015 6015
6016 case TOUCHSCREEN_BEGIN_EVENT:
6017 case TOUCHSCREEN_END_EVENT:
6018 {
6019 Lisp_Object x, y, id, position;
6020 struct frame *f = XFRAME (event->frame_or_window);
6021
6022 id = event->arg;
6023 x = event->x;
6024 y = event->y;
6025
6026 position = make_lispy_position (f, x, y, event->timestamp);
6027
6028 return list2 (((event->kind
6029 == TOUCHSCREEN_BEGIN_EVENT)
6030 ? Qtouchscreen_begin
6031 : Qtouchscreen_end),
6032 Fcons (id, position));
6033 }
6034
6035 case TOUCHSCREEN_UPDATE_EVENT:
6036 {
6037 Lisp_Object x, y, id, position, tem, it, evt;
6038 struct frame *f = XFRAME (event->frame_or_window);
6039 evt = Qnil;
6040
6041 for (tem = event->arg; CONSP (tem); tem = XCDR (tem))
6042 {
6043 it = XCAR (tem);
6044
6045 x = XCAR (it);
6046 y = XCAR (XCDR (it));
6047 id = XCAR (XCDR (XCDR (it)));
6048
6049 position = make_lispy_position (f, x, y, event->timestamp);
6050 evt = Fcons (Fcons (id, position), evt);
6051 }
6052
6053 return list2 (Qtouchscreen_update, evt);
6054 }
6055
6016#ifdef USE_TOOLKIT_SCROLL_BARS 6056#ifdef USE_TOOLKIT_SCROLL_BARS
6017 6057
6018 /* We don't have down and up events if using toolkit scroll bars, 6058 /* We don't have down and up events if using toolkit scroll bars,
@@ -12266,6 +12306,9 @@ See also `pre-command-hook'. */);
12266 doc: /* Normal hook run when clearing the echo area. */); 12306 doc: /* Normal hook run when clearing the echo area. */);
12267#endif 12307#endif
12268 DEFSYM (Qecho_area_clear_hook, "echo-area-clear-hook"); 12308 DEFSYM (Qecho_area_clear_hook, "echo-area-clear-hook");
12309 DEFSYM (Qtouchscreen_begin, "touchscreen-begin");
12310 DEFSYM (Qtouchscreen_end, "touchscreen-end");
12311 DEFSYM (Qtouchscreen_update, "touchscreen-update");
12269 Fset (Qecho_area_clear_hook, Qnil); 12312 Fset (Qecho_area_clear_hook, Qnil);
12270 12313
12271 DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag, 12314 DEFVAR_LISP ("lucid-menu-bar-dirty-flag", Vlucid_menu_bar_dirty_flag,
diff --git a/src/systime.h b/src/systime.h
index 08ab5bdde33..ce9403c931d 100644
--- a/src/systime.h
+++ b/src/systime.h
@@ -80,8 +80,7 @@ struct lisp_time
80 /* Clock count as a Lisp integer. */ 80 /* Clock count as a Lisp integer. */
81 Lisp_Object ticks; 81 Lisp_Object ticks;
82 82
83 /* Clock frequency (ticks per second) as a positive Lisp integer. 83 /* Clock frequency (ticks per second) as a positive Lisp integer. */
84 (TICKS . HZ) is a valid Lisp timestamp unless HZ < 65536. */
85 Lisp_Object hz; 84 Lisp_Object hz;
86}; 85};
87 86
diff --git a/src/termhooks.h b/src/termhooks.h
index b124e995292..9f22187b841 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -280,6 +280,19 @@ enum event_kind
280 In the future, this may take into account other multi-touch 280 In the future, this may take into account other multi-touch
281 events generated from touchscreens and such. */ 281 events generated from touchscreens and such. */
282 , TOUCH_END_EVENT 282 , TOUCH_END_EVENT
283
284 /* In a TOUCHSCREEN_UPDATE_EVENT, ARG is a list of elements of the
285 form (X Y ID), where X and Y are the coordinates of the
286 touchpoint relative to the top-left corner of the frame, and ID
287 is a unique number identifying the touchpoint.
288
289 In TOUCHSCREEN_BEGIN_EVENT and TOUCHSCREEN_END_EVENT, ARG is the
290 unique ID of the touchpoint, and X and Y are the frame-relative
291 positions of the touchpoint. */
292
293 , TOUCHSCREEN_UPDATE_EVENT
294 , TOUCHSCREEN_BEGIN_EVENT
295 , TOUCHSCREEN_END_EVENT
283}; 296};
284 297
285/* Bit width of an enum event_kind tag at the start of structs and unions. */ 298/* Bit width of an enum event_kind tag at the start of structs and unions. */
diff --git a/src/timefns.c b/src/timefns.c
index a9921cdc108..74b5ca8d515 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -69,16 +69,6 @@ enum { TM_YEAR_BASE = 1900 };
69# define FASTER_TIMEFNS 1 69# define FASTER_TIMEFNS 1
70#endif 70#endif
71 71
72/* Whether to warn about Lisp timestamps (TICKS . HZ) that may be
73 instances of obsolete-format timestamps (HI . LO) where HI is
74 the high-order bits and LO the low-order 16 bits. Currently this
75 is true, but it should change to false in a future version of
76 Emacs. Compile with -DWARN_OBSOLETE_TIMESTAMPS=0 to see what the
77 future will be like. */
78#ifndef WARN_OBSOLETE_TIMESTAMPS
79enum { WARN_OBSOLETE_TIMESTAMPS = true };
80#endif
81
82/* Although current-time etc. generate list-format timestamps 72/* Although current-time etc. generate list-format timestamps
83 (HI LO US PS), the plan is to change these functions to generate 73 (HI LO US PS), the plan is to change these functions to generate
84 frequency-based timestamps (TICKS . HZ) in a future release. 74 frequency-based timestamps (TICKS . HZ) in a future release.
@@ -817,14 +807,10 @@ decode_time_components (enum timeform form,
817 return decode_ticks_hz (make_integer_mpz (), hz, result, dresult); 807 return decode_ticks_hz (make_integer_mpz (), hz, result, dresult);
818} 808}
819 809
820enum { DECODE_SECS_ONLY = WARN_OBSOLETE_TIMESTAMPS + 1 };
821
822/* Decode a Lisp timestamp SPECIFIED_TIME that represents a time. 810/* Decode a Lisp timestamp SPECIFIED_TIME that represents a time.
823 811
824 FLAGS specifies conversion flags. If FLAGS & DECODE_SECS_ONLY, 812 If DECODE_SECS_ONLY, ignore and do not validate any sub-second
825 ignore and do not validate any sub-second components of an 813 components of an old-format SPECIFIED_TIME.
826 old-format SPECIFIED_TIME. If FLAGS & WARN_OBSOLETE_TIMESTAMPS,
827 diagnose what could be obsolete (HIGH . LOW) timestamps.
828 814
829 If RESULT is not null, store into *RESULT the converted time; 815 If RESULT is not null, store into *RESULT the converted time;
830 otherwise, store into *DRESULT the number of seconds since the 816 otherwise, store into *DRESULT the number of seconds since the
@@ -833,7 +819,7 @@ enum { DECODE_SECS_ONLY = WARN_OBSOLETE_TIMESTAMPS + 1 };
833 819
834 Return the form of SPECIFIED-TIME. Signal an error if unsuccessful. */ 820 Return the form of SPECIFIED-TIME. Signal an error if unsuccessful. */
835static enum timeform 821static enum timeform
836decode_lisp_time (Lisp_Object specified_time, int flags, 822decode_lisp_time (Lisp_Object specified_time, bool decode_secs_only,
837 struct lisp_time *result, double *dresult) 823 struct lisp_time *result, double *dresult)
838{ 824{
839 Lisp_Object high = make_fixnum (0); 825 Lisp_Object high = make_fixnum (0);
@@ -854,7 +840,7 @@ decode_lisp_time (Lisp_Object specified_time, int flags,
854 { 840 {
855 Lisp_Object low_tail = XCDR (low); 841 Lisp_Object low_tail = XCDR (low);
856 low = XCAR (low); 842 low = XCAR (low);
857 if (! (flags & DECODE_SECS_ONLY)) 843 if (! decode_secs_only)
858 { 844 {
859 if (CONSP (low_tail)) 845 if (CONSP (low_tail))
860 { 846 {
@@ -877,9 +863,6 @@ decode_lisp_time (Lisp_Object specified_time, int flags,
877 } 863 }
878 else 864 else
879 { 865 {
880 if (flags & WARN_OBSOLETE_TIMESTAMPS
881 && RANGED_FIXNUMP (0, low, (1 << LO_TIME_BITS) - 1))
882 message ("obsolete timestamp with cdr %"pI"d", XFIXNUM (low));
883 form = TIMEFORM_TICKS_HZ; 866 form = TIMEFORM_TICKS_HZ;
884 } 867 }
885 868
@@ -1008,8 +991,7 @@ static struct lisp_time
1008lisp_time_struct (Lisp_Object specified_time, enum timeform *pform) 991lisp_time_struct (Lisp_Object specified_time, enum timeform *pform)
1009{ 992{
1010 struct lisp_time t; 993 struct lisp_time t;
1011 enum timeform form 994 enum timeform form = decode_lisp_time (specified_time, false, &t, 0);
1012 = decode_lisp_time (specified_time, WARN_OBSOLETE_TIMESTAMPS, &t, 0);
1013 if (pform) 995 if (pform)
1014 *pform = form; 996 *pform = form;
1015 return t; 997 return t;
@@ -1034,9 +1016,8 @@ lisp_time_argument (Lisp_Object specified_time)
1034static time_t 1016static time_t
1035lisp_seconds_argument (Lisp_Object specified_time) 1017lisp_seconds_argument (Lisp_Object specified_time)
1036{ 1018{
1037 int flags = WARN_OBSOLETE_TIMESTAMPS | DECODE_SECS_ONLY;
1038 struct lisp_time lt; 1019 struct lisp_time lt;
1039 decode_lisp_time (specified_time, flags, &lt, 0); 1020 decode_lisp_time (specified_time, true, &lt, 0);
1040 struct timespec t = lisp_to_timespec (lt); 1021 struct timespec t = lisp_to_timespec (lt);
1041 if (! timespec_valid_p (t)) 1022 if (! timespec_valid_p (t))
1042 time_overflow (); 1023 time_overflow ();
@@ -1138,24 +1119,6 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1138 mpz_t *ihz = &mpz[0]; 1119 mpz_t *ihz = &mpz[0];
1139 mpz_mul (*ihz, *fa, *db); 1120 mpz_mul (*ihz, *fa, *db);
1140 1121
1141 /* When warning about obsolete timestamps, if the smaller
1142 denominator comes from a non-(TICKS . HZ) timestamp and could
1143 generate a (TICKS . HZ) timestamp that would look obsolete,
1144 arrange for the result to have a higher HZ to avoid a
1145 spurious warning by a later consumer of this function's
1146 returned value. */
1147 verify (1 << LO_TIME_BITS <= ULONG_MAX);
1148 if (WARN_OBSOLETE_TIMESTAMPS
1149 && (da_lt_db ? aform : bform) == TIMEFORM_FLOAT
1150 && (da_lt_db ? bform : aform) != TIMEFORM_TICKS_HZ
1151 && mpz_cmp_ui (*hzmin, 1) > 0
1152 && mpz_cmp_ui (*hzmin, 1 << LO_TIME_BITS) < 0)
1153 {
1154 mpz_t *hzmin1 = &mpz[2 - da_lt_db];
1155 mpz_set_ui (*hzmin1, 1 << LO_TIME_BITS);
1156 hzmin = hzmin1;
1157 }
1158
1159 /* iticks = (fb * na) OP (fa * nb), where OP is + or -. */ 1122 /* iticks = (fb * na) OP (fa * nb), where OP is + or -. */
1160 mpz_t const *na = bignum_integer (iticks, ta.ticks); 1123 mpz_t const *na = bignum_integer (iticks, ta.ticks);
1161 mpz_mul (*iticks, *fb, *na); 1124 mpz_mul (*iticks, *fb, *na);
@@ -1177,8 +1140,7 @@ time_arith (Lisp_Object a, Lisp_Object b, bool subtract)
1177 upwards by multiplying the normalized numerator and denominator 1140 upwards by multiplying the normalized numerator and denominator
1178 so that the resulting denominator becomes at least hzmin. 1141 so that the resulting denominator becomes at least hzmin.
1179 This rescaling avoids returning a timestamp that is less precise 1142 This rescaling avoids returning a timestamp that is less precise
1180 than both a and b, or a timestamp that looks obsolete when that 1143 than both a and b. */
1181 might be a problem. */
1182 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0) 1144 if (!FASTER_TIMEFNS || mpz_cmp (*ihz, *hzmin) < 0)
1183 { 1145 {
1184 /* Rescale straightforwardly. Although this might not 1146 /* Rescale straightforwardly. Although this might not
@@ -1303,7 +1265,7 @@ or (if you need time as a string) `format-time-string'. */)
1303 (Lisp_Object specified_time) 1265 (Lisp_Object specified_time)
1304{ 1266{
1305 double t; 1267 double t;
1306 decode_lisp_time (specified_time, 0, 0, &t); 1268 decode_lisp_time (specified_time, false, 0, &t);
1307 return make_float (t); 1269 return make_float (t);
1308} 1270}
1309 1271
@@ -1651,12 +1613,11 @@ saving flag to be guessed.
1651 1613
1652As an obsolescent calling convention, if this function is called with 1614As an obsolescent calling convention, if this function is called with
16536 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR, 16156 or more arguments, the first 6 arguments are SECOND, MINUTE, HOUR,
1654DAY, MONTH, and YEAR, and specify the components of a decoded time, 1616DAY, MONTH, and YEAR, and specify the components of a decoded time.
1655where DST assumed to be -1 and FORM is omitted. If there are more 1617If there are more than 6 arguments the *last* argument is used as ZONE
1656than 6 arguments the *last* argument is used as ZONE and any other 1618and any other extra arguments are ignored, so that (apply
1657extra arguments are ignored, so that (apply #\\='encode-time 1619#\\='encode-time (decode-time ...)) works. In this obsolescent
1658(decode-time ...)) works. In this obsolescent convention, DST and 1620convention, DST and ZONE default to -1 and nil respectively.
1659ZONE default to -1 and nil respectively.
1660 1621
1661Years before 1970 are not guaranteed to work. On some systems, 1622Years before 1970 are not guaranteed to work. On some systems,
1662year values as low as 1901 do work. 1623year values as low as 1901 do work.
@@ -1703,7 +1664,7 @@ usage: (encode-time TIME &rest OBSOLESCENT-ARGUMENTS) */)
1703 1664
1704 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */ 1665 /* Let SEC = floor (LT.ticks / HZ), with SUBSECTICKS the remainder. */
1705 struct lisp_time lt; 1666 struct lisp_time lt;
1706 decode_lisp_time (secarg, 0, &lt, 0); 1667 decode_lisp_time (secarg, false, &lt, 0);
1707 Lisp_Object hz = lt.hz, sec, subsecticks; 1668 Lisp_Object hz = lt.hz, sec, subsecticks;
1708 if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1))) 1669 if (FASTER_TIMEFNS && EQ (hz, make_fixnum (1)))
1709 { 1670 {
@@ -1756,9 +1717,7 @@ Truncate the returned value toward minus infinity.
1756If FORM is nil (the default), return the same form as `current-time'. 1717If FORM is nil (the default), return the same form as `current-time'.
1757If FORM is a positive integer, return a pair of integers (TICKS . FORM), 1718If FORM is a positive integer, return a pair of integers (TICKS . FORM),
1758where TICKS is the number of clock ticks and FORM is the clock frequency 1719where TICKS is the number of clock ticks and FORM is the clock frequency
1759in ticks per second. (Currently the positive integer should be at least 1720in ticks per second. If FORM is t, return (TICKS . PHZ), where
176065536 if the returned value is expected to be given to standard functions
1761expecting Lisp timestamps.) If FORM is t, return (TICKS . PHZ), where
1762PHZ is a suitable clock frequency in ticks per second. If FORM is 1721PHZ is a suitable clock frequency in ticks per second. If FORM is
1763`integer', return an integer count of seconds. If FORM is `list', 1722`integer', return an integer count of seconds. If FORM is `list',
1764return an integer list (HIGH LOW USEC PSEC), where HIGH has the most 1723return an integer list (HIGH LOW USEC PSEC), where HIGH has the most
@@ -1767,7 +1726,7 @@ bits, and USEC and PSEC are the microsecond and picosecond counts. */)
1767 (Lisp_Object time, Lisp_Object form) 1726 (Lisp_Object time, Lisp_Object form)
1768{ 1727{
1769 struct lisp_time t; 1728 struct lisp_time t;
1770 enum timeform input_form = decode_lisp_time (time, 0, &t, 0); 1729 enum timeform input_form = decode_lisp_time (time, false, &t, 0);
1771 if (NILP (form)) 1730 if (NILP (form))
1772 form = CURRENT_TIME_LIST ? Qlist : Qt; 1731 form = CURRENT_TIME_LIST ? Qlist : Qt;
1773 if (EQ (form, Qlist)) 1732 if (EQ (form, Qlist))
diff --git a/src/xfns.c b/src/xfns.c
index b5694829aef..dc25d7bfca2 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -2916,7 +2916,7 @@ initial_set_up_x_back_buffer (struct frame *f)
2916 unblock_input (); 2916 unblock_input ();
2917} 2917}
2918 2918
2919#if defined HAVE_XINPUT2 && !defined USE_GTK 2919#if defined HAVE_XINPUT2
2920static void 2920static void
2921setup_xi_event_mask (struct frame *f) 2921setup_xi_event_mask (struct frame *f)
2922{ 2922{
@@ -2927,6 +2927,9 @@ setup_xi_event_mask (struct frame *f)
2927 mask.mask = m = alloca (l); 2927 mask.mask = m = alloca (l);
2928 memset (m, 0, l); 2928 memset (m, 0, l);
2929 mask.mask_len = l; 2929 mask.mask_len = l;
2930
2931 block_input ();
2932#ifndef USE_GTK
2930 mask.deviceid = XIAllMasterDevices; 2933 mask.deviceid = XIAllMasterDevices;
2931 2934
2932 XISetMask (m, XI_ButtonPress); 2935 XISetMask (m, XI_ButtonPress);
@@ -2945,14 +2948,25 @@ setup_xi_event_mask (struct frame *f)
2945 &mask, 1); 2948 &mask, 1);
2946 2949
2947 memset (m, 0, l); 2950 memset (m, 0, l);
2951#endif /* !USE_GTK */
2952
2948 mask.deviceid = XIAllDevices; 2953 mask.deviceid = XIAllDevices;
2949 2954
2950 XISetMask (m, XI_PropertyEvent); 2955 XISetMask (m, XI_PropertyEvent);
2951 XISetMask (m, XI_HierarchyChanged); 2956 XISetMask (m, XI_HierarchyChanged);
2952 XISetMask (m, XI_DeviceChanged); 2957 XISetMask (m, XI_DeviceChanged);
2958#ifdef XI_TouchBegin
2959 if (FRAME_DISPLAY_INFO (f)->xi2_version >= 2)
2960 {
2961 XISetMask (m, XI_TouchBegin);
2962 XISetMask (m, XI_TouchUpdate);
2963 XISetMask (m, XI_TouchEnd);
2964 }
2965#endif
2953 XISelectEvents (FRAME_X_DISPLAY (f), 2966 XISelectEvents (FRAME_X_DISPLAY (f),
2954 FRAME_X_WINDOW (f), 2967 FRAME_X_WINDOW (f),
2955 &mask, 1); 2968 &mask, 1);
2969 unblock_input ();
2956} 2970}
2957#endif 2971#endif
2958 2972
@@ -3249,6 +3263,11 @@ x_window (struct frame *f)
3249 unblock_input (); 3263 unblock_input ();
3250 } 3264 }
3251#endif 3265#endif
3266
3267#ifdef HAVE_XINPUT2
3268 if (FRAME_DISPLAY_INFO (f)->supports_xi2)
3269 setup_xi_event_mask (f);
3270#endif
3252} 3271}
3253 3272
3254#else /*! USE_GTK */ 3273#else /*! USE_GTK */
diff --git a/src/xterm.c b/src/xterm.c
index 646985bdc20..fa60a4e8745 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -353,6 +353,8 @@ x_extension_initialize (struct x_display_info *dpyinfo)
353static void 353static void
354x_free_xi_devices (struct x_display_info *dpyinfo) 354x_free_xi_devices (struct x_display_info *dpyinfo)
355{ 355{
356 struct xi_touch_point_t *tem, *last;
357
356 block_input (); 358 block_input ();
357 359
358 if (dpyinfo->num_devices) 360 if (dpyinfo->num_devices)
@@ -362,6 +364,14 @@ x_free_xi_devices (struct x_display_info *dpyinfo)
362 XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id, 364 XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
363 CurrentTime); 365 CurrentTime);
364 xfree (dpyinfo->devices[i].valuators); 366 xfree (dpyinfo->devices[i].valuators);
367
368 tem = dpyinfo->devices[i].touchpoints;
369 while (tem)
370 {
371 last = tem;
372 tem = tem->next;
373 xfree (last);
374 }
365 } 375 }
366 376
367 xfree (dpyinfo->devices); 377 xfree (dpyinfo->devices);
@@ -407,7 +417,7 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
407 block_input (); 417 block_input ();
408 x_free_xi_devices (dpyinfo); 418 x_free_xi_devices (dpyinfo);
409 infos = XIQueryDevice (dpyinfo->display, 419 infos = XIQueryDevice (dpyinfo->display,
410 XIAllMasterDevices, 420 XIAllDevices,
411 &ndevices); 421 &ndevices);
412 422
413 if (!ndevices) 423 if (!ndevices)
@@ -432,6 +442,10 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
432 xi_device->grab = 0; 442 xi_device->grab = 0;
433 xi_device->valuators = 443 xi_device->valuators =
434 xmalloc (sizeof *xi_device->valuators * device->num_classes); 444 xmalloc (sizeof *xi_device->valuators * device->num_classes);
445 xi_device->touchpoints = NULL;
446 xi_device->master_p = (device->use == XIMasterKeyboard
447 || device->use == XIMasterPointer);
448 xi_device->direct_p = false;
435 449
436 for (int c = 0; c < device->num_classes; ++c) 450 for (int c = 0; c < device->num_classes; ++c)
437 { 451 {
@@ -442,22 +456,36 @@ x_init_master_valuators (struct x_display_info *dpyinfo)
442 { 456 {
443 XIScrollClassInfo *info = 457 XIScrollClassInfo *info =
444 (XIScrollClassInfo *) device->classes[c]; 458 (XIScrollClassInfo *) device->classes[c];
445 struct xi_scroll_valuator_t *valuator = 459 struct xi_scroll_valuator_t *valuator;
446 &xi_device->valuators[actual_valuator_count++]; 460
447 461 if (xi_device->master_p)
448 valuator->horizontal 462 {
449 = (info->scroll_type == XIScrollTypeHorizontal); 463 valuator = &xi_device->valuators[actual_valuator_count++];
450 valuator->invalid_p = true; 464 valuator->horizontal
451 valuator->emacs_value = DBL_MIN; 465 = (info->scroll_type == XIScrollTypeHorizontal);
452 valuator->increment = info->increment; 466 valuator->invalid_p = true;
453 valuator->number = info->number; 467 valuator->emacs_value = DBL_MIN;
468 valuator->increment = info->increment;
469 valuator->number = info->number;
470 }
471
454 break; 472 break;
455 } 473 }
456#endif 474#endif
475#ifdef XITouchClass /* XInput 2.2 */
476 case XITouchClass:
477 {
478 XITouchClassInfo *info;
479
480 info = (XITouchClassInfo *) device->classes[c];
481 xi_device->direct_p = info->mode == XIDirectTouch;
482 }
483#endif
457 default: 484 default:
458 break; 485 break;
459 } 486 }
460 } 487 }
488
461 xi_device->scroll_valuator_count = actual_valuator_count; 489 xi_device->scroll_valuator_count = actual_valuator_count;
462 } 490 }
463 } 491 }
@@ -484,7 +512,7 @@ x_get_scroll_valuator_delta (struct x_display_info *dpyinfo, int device_id,
484 { 512 {
485 struct xi_device_t *device = &dpyinfo->devices[i]; 513 struct xi_device_t *device = &dpyinfo->devices[i];
486 514
487 if (device->device_id == device_id) 515 if (device->device_id == device_id && device->master_p)
488 { 516 {
489 for (int j = 0; j < device->scroll_valuator_count; ++j) 517 for (int j = 0; j < device->scroll_valuator_count; ++j)
490 { 518 {
@@ -534,6 +562,61 @@ xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
534 return NULL; 562 return NULL;
535} 563}
536 564
565#ifdef XI_TouchBegin
566
567static void
568xi_link_touch_point (struct xi_device_t *device,
569 int detail, double x, double y)
570{
571 struct xi_touch_point_t *touchpoint;
572
573 touchpoint = xmalloc (sizeof *touchpoint);
574 touchpoint->next = device->touchpoints;
575 touchpoint->x = x;
576 touchpoint->y = y;
577 touchpoint->number = detail;
578
579 device->touchpoints = touchpoint;
580}
581
582static void
583xi_unlink_touch_point (int detail,
584 struct xi_device_t *device)
585{
586 struct xi_touch_point_t *last, *tem;
587
588 for (last = NULL, tem = device->touchpoints; tem;
589 last = tem, tem = tem->next)
590 {
591 if (tem->number == detail)
592 {
593 if (!last)
594 device->touchpoints = tem->next;
595 else
596 last->next = tem->next;
597
598 xfree (tem);
599 return;
600 }
601 }
602}
603
604static struct xi_touch_point_t *
605xi_find_touch_point (struct xi_device_t *device, int detail)
606{
607 struct xi_touch_point_t *point;
608
609 for (point = device->touchpoints; point; point = point->next)
610 {
611 if (point->number == detail)
612 return point;
613 }
614
615 return NULL;
616}
617
618#endif /* XI_TouchBegin */
619
537static void 620static void
538xi_grab_or_ungrab_device (struct xi_device_t *device, 621xi_grab_or_ungrab_device (struct xi_device_t *device,
539 struct x_display_info *dpyinfo, 622 struct x_display_info *dpyinfo,
@@ -570,7 +653,7 @@ xi_reset_scroll_valuators_for_device_id (struct x_display_info *dpyinfo, int id)
570 struct xi_device_t *device = xi_device_from_id (dpyinfo, id); 653 struct xi_device_t *device = xi_device_from_id (dpyinfo, id);
571 struct xi_scroll_valuator_t *valuator; 654 struct xi_scroll_valuator_t *valuator;
572 655
573 if (!device) 656 if (!device || !device->master_p)
574 return; 657 return;
575 658
576 if (!device->scroll_valuator_count) 659 if (!device->scroll_valuator_count)
@@ -9981,242 +10064,250 @@ handle_one_xevent (struct x_display_info *dpyinfo,
9981#endif 10064#endif
9982 goto XI_OTHER; 10065 goto XI_OTHER;
9983 case XI_Motion: 10066 case XI_Motion:
9984 states = &xev->valuators; 10067 {
9985 values = states->values; 10068 struct xi_device_t *device;
9986 10069
9987 x_display_set_last_user_time (dpyinfo, xi_event->time); 10070 states = &xev->valuators;
10071 values = states->values;
10072 device = xi_device_from_id (dpyinfo, xev->deviceid);
10073
10074 if (!device || !device->master_p)
10075 goto XI_OTHER;
10076
10077 x_display_set_last_user_time (dpyinfo, xi_event->time);
9988 10078
9989#ifdef HAVE_XWIDGETS 10079#ifdef HAVE_XWIDGETS
9990 struct xwidget_view *xv = xwidget_view_from_window (xev->event); 10080 struct xwidget_view *xv = xwidget_view_from_window (xev->event);
9991 double xv_total_x = 0.0; 10081 double xv_total_x = 0.0;
9992 double xv_total_y = 0.0; 10082 double xv_total_y = 0.0;
9993#endif 10083#endif
9994 10084
9995 for (int i = 0; i < states->mask_len * 8; i++) 10085 for (int i = 0; i < states->mask_len * 8; i++)
9996 { 10086 {
9997 if (XIMaskIsSet (states->mask, i)) 10087 if (XIMaskIsSet (states->mask, i))
9998 { 10088 {
9999 struct xi_scroll_valuator_t *val; 10089 struct xi_scroll_valuator_t *val;
10000 double delta, scroll_unit; 10090 double delta, scroll_unit;
10001 int scroll_height; 10091 int scroll_height;
10002 Lisp_Object window; 10092 Lisp_Object window;
10003 10093
10004 10094
10005 /* See the comment on top of 10095 /* See the comment on top of
10006 x_init_master_valuators for more details on how 10096 x_init_master_valuators for more details on how
10007 scroll wheel movement is reported on XInput 2. */ 10097 scroll wheel movement is reported on XInput 2. */
10008 delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid, 10098 delta = x_get_scroll_valuator_delta (dpyinfo, xev->deviceid,
10009 i, *values, &val); 10099 i, *values, &val);
10010 10100
10011 if (delta != DBL_MAX) 10101 if (delta != DBL_MAX)
10012 { 10102 {
10013#ifdef HAVE_XWIDGETS 10103#ifdef HAVE_XWIDGETS
10014 if (xv) 10104 if (xv)
10015 { 10105 {
10016 if (val->horizontal) 10106 if (val->horizontal)
10017 xv_total_x += delta; 10107 xv_total_x += delta;
10018 else 10108 else
10019 xv_total_y += delta; 10109 xv_total_y += delta;
10020 10110
10021 found_valuator = true; 10111 found_valuator = true;
10022 10112
10023 if (delta == 0.0) 10113 if (delta == 0.0)
10024 any_stop_p = true; 10114 any_stop_p = true;
10025 10115
10026 continue; 10116 continue;
10027 } 10117 }
10028#endif 10118#endif
10029 if (!f) 10119 if (!f)
10030 { 10120 {
10031 f = x_any_window_to_frame (dpyinfo, xev->event); 10121 f = x_any_window_to_frame (dpyinfo, xev->event);
10032 10122
10033 if (!f) 10123 if (!f)
10034 goto XI_OTHER; 10124 goto XI_OTHER;
10035 } 10125 }
10036 10126
10037 found_valuator = true; 10127 found_valuator = true;
10038 10128
10039 if (signbit (delta) != signbit (val->emacs_value)) 10129 if (signbit (delta) != signbit (val->emacs_value))
10040 val->emacs_value = 0; 10130 val->emacs_value = 0;
10041 10131
10042 val->emacs_value += delta; 10132 val->emacs_value += delta;
10043 10133
10044 if (mwheel_coalesce_scroll_events 10134 if (mwheel_coalesce_scroll_events
10045 && (fabs (val->emacs_value) < 1) 10135 && (fabs (val->emacs_value) < 1)
10046 && (fabs (delta) > 0)) 10136 && (fabs (delta) > 0))
10047 continue; 10137 continue;
10048 10138
10049 bool s = signbit (val->emacs_value); 10139 bool s = signbit (val->emacs_value);
10050 inev.ie.kind = (fabs (delta) > 0 10140 inev.ie.kind = (fabs (delta) > 0
10051 ? (val->horizontal 10141 ? (val->horizontal
10052 ? HORIZ_WHEEL_EVENT 10142 ? HORIZ_WHEEL_EVENT
10053 : WHEEL_EVENT) 10143 : WHEEL_EVENT)
10054 : TOUCH_END_EVENT); 10144 : TOUCH_END_EVENT);
10055 inev.ie.timestamp = xev->time; 10145 inev.ie.timestamp = xev->time;
10056 10146
10057 XSETINT (inev.ie.x, lrint (xev->event_x)); 10147 XSETINT (inev.ie.x, lrint (xev->event_x));
10058 XSETINT (inev.ie.y, lrint (xev->event_y)); 10148 XSETINT (inev.ie.y, lrint (xev->event_y));
10059 XSETFRAME (inev.ie.frame_or_window, f); 10149 XSETFRAME (inev.ie.frame_or_window, f);
10060 10150
10061 if (fabs (delta) > 0) 10151 if (fabs (delta) > 0)
10062 { 10152 {
10063 inev.ie.modifiers = !s ? up_modifier : down_modifier; 10153 inev.ie.modifiers = !s ? up_modifier : down_modifier;
10064 inev.ie.modifiers 10154 inev.ie.modifiers
10065 |= x_x_to_emacs_modifiers (dpyinfo, 10155 |= x_x_to_emacs_modifiers (dpyinfo,
10066 xev->mods.effective); 10156 xev->mods.effective);
10067 } 10157 }
10068 10158
10069 window = window_from_coordinates (f, xev->event_x, 10159 window = window_from_coordinates (f, xev->event_x,
10070 xev->event_y, NULL, 10160 xev->event_y, NULL,
10071 false, false); 10161 false, false);
10072 10162
10073 if (WINDOWP (window)) 10163 if (WINDOWP (window))
10074 scroll_height = XWINDOW (window)->pixel_height; 10164 scroll_height = XWINDOW (window)->pixel_height;
10075 else 10165 else
10076 /* EVENT_X and EVENT_Y can be outside the 10166 /* EVENT_X and EVENT_Y can be outside the
10077 frame if F holds the input grab, so fall 10167 frame if F holds the input grab, so fall
10078 back to the height of the frame instead. */ 10168 back to the height of the frame instead. */
10079 scroll_height = FRAME_PIXEL_HEIGHT (f); 10169 scroll_height = FRAME_PIXEL_HEIGHT (f);
10080 10170
10081 scroll_unit = pow (scroll_height, 2.0 / 3.0); 10171 scroll_unit = pow (scroll_height, 2.0 / 3.0);
10082 10172
10083 if (NUMBERP (Vx_scroll_event_delta_factor)) 10173 if (NUMBERP (Vx_scroll_event_delta_factor))
10084 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor); 10174 scroll_unit *= XFLOATINT (Vx_scroll_event_delta_factor);
10085 10175
10086 if (fabs (delta) > 0) 10176 if (fabs (delta) > 0)
10087 { 10177 {
10088 if (val->horizontal) 10178 if (val->horizontal)
10089 { 10179 {
10090 inev.ie.arg 10180 inev.ie.arg
10091 = list3 (Qnil, 10181 = list3 (Qnil,
10092 make_float (val->emacs_value 10182 make_float (val->emacs_value
10093 * scroll_unit), 10183 * scroll_unit),
10094 make_float (0)); 10184 make_float (0));
10095 } 10185 }
10096 else 10186 else
10097 { 10187 {
10098 inev.ie.arg = list3 (Qnil, make_float (0), 10188 inev.ie.arg = list3 (Qnil, make_float (0),
10099 make_float (val->emacs_value 10189 make_float (val->emacs_value
10100 * scroll_unit)); 10190 * scroll_unit));
10101 } 10191 }
10102 } 10192 }
10103 else 10193 else
10104 { 10194 {
10105 inev.ie.arg = Qnil; 10195 inev.ie.arg = Qnil;
10106 } 10196 }
10107 10197
10108 kbd_buffer_store_event_hold (&inev.ie, hold_quit); 10198 kbd_buffer_store_event_hold (&inev.ie, hold_quit);
10109 10199
10110 val->emacs_value = 0; 10200 val->emacs_value = 0;
10111 } 10201 }
10112 values++; 10202 values++;
10113 } 10203 }
10114 10204
10115 inev.ie.kind = NO_EVENT; 10205 inev.ie.kind = NO_EVENT;
10116 } 10206 }
10117 10207
10118#ifdef HAVE_XWIDGETS 10208#ifdef HAVE_XWIDGETS
10119 if (xv) 10209 if (xv)
10120 { 10210 {
10121 if (found_valuator) 10211 if (found_valuator)
10122 xwidget_scroll (xv, xev->event_x, xev->event_y, 10212 xwidget_scroll (xv, xev->event_x, xev->event_y,
10123 xv_total_x, xv_total_y, xev->mods.effective, 10213 xv_total_x, xv_total_y, xev->mods.effective,
10124 xev->time, any_stop_p); 10214 xev->time, any_stop_p);
10125 else 10215 else
10126 xwidget_motion_notify (xv, xev->event_x, xev->event_y, 10216 xwidget_motion_notify (xv, xev->event_x, xev->event_y,
10127 xev->mods.effective, xev->time); 10217 xev->mods.effective, xev->time);
10128 10218
10129 goto XI_OTHER; 10219 goto XI_OTHER;
10130 } 10220 }
10131#endif 10221#endif
10132 if (found_valuator) 10222 if (found_valuator)
10133 goto XI_OTHER; 10223 goto XI_OTHER;
10134 10224
10135 ev.x = lrint (xev->event_x); 10225 ev.x = lrint (xev->event_x);
10136 ev.y = lrint (xev->event_y); 10226 ev.y = lrint (xev->event_y);
10137 ev.window = xev->event; 10227 ev.window = xev->event;
10138 ev.time = xev->time; 10228 ev.time = xev->time;
10139 10229
10140 previous_help_echo_string = help_echo_string; 10230 previous_help_echo_string = help_echo_string;
10141 help_echo_string = Qnil; 10231 help_echo_string = Qnil;
10142 10232
10143 if (hlinfo->mouse_face_hidden) 10233 if (hlinfo->mouse_face_hidden)
10144 { 10234 {
10145 hlinfo->mouse_face_hidden = false; 10235 hlinfo->mouse_face_hidden = false;
10146 clear_mouse_face (hlinfo); 10236 clear_mouse_face (hlinfo);
10147 } 10237 }
10148 10238
10149 f = mouse_or_wdesc_frame (dpyinfo, xev->event); 10239 f = mouse_or_wdesc_frame (dpyinfo, xev->event);
10150 10240
10151#ifdef USE_GTK 10241#ifdef USE_GTK
10152 if (f && xg_event_is_for_scrollbar (f, event)) 10242 if (f && xg_event_is_for_scrollbar (f, event))
10153 f = 0; 10243 f = 0;
10154#endif 10244#endif
10155 if (f) 10245 if (f)
10156 { 10246 {
10157 /* Maybe generate a SELECT_WINDOW_EVENT for 10247 /* Maybe generate a SELECT_WINDOW_EVENT for
10158 `mouse-autoselect-window' but don't let popup menus 10248 `mouse-autoselect-window' but don't let popup menus
10159 interfere with this (Bug#1261). */ 10249 interfere with this (Bug#1261). */
10160 if (!NILP (Vmouse_autoselect_window) 10250 if (!NILP (Vmouse_autoselect_window)
10161 && !popup_activated () 10251 && !popup_activated ()
10162 /* Don't switch if we're currently in the minibuffer. 10252 /* Don't switch if we're currently in the minibuffer.
10163 This tries to work around problems where the 10253 This tries to work around problems where the
10164 minibuffer gets unselected unexpectedly, and where 10254 minibuffer gets unselected unexpectedly, and where
10165 you then have to move your mouse all the way down to 10255 you then have to move your mouse all the way down to
10166 the minibuffer to select it. */ 10256 the minibuffer to select it. */
10167 && !MINI_WINDOW_P (XWINDOW (selected_window)) 10257 && !MINI_WINDOW_P (XWINDOW (selected_window))
10168 /* With `focus-follows-mouse' non-nil create an event 10258 /* With `focus-follows-mouse' non-nil create an event
10169 also when the target window is on another frame. */ 10259 also when the target window is on another frame. */
10170 && (f == XFRAME (selected_frame) 10260 && (f == XFRAME (selected_frame)
10171 || !NILP (focus_follows_mouse))) 10261 || !NILP (focus_follows_mouse)))
10172 { 10262 {
10173 static Lisp_Object last_mouse_window; 10263 static Lisp_Object last_mouse_window;
10174 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false); 10264 Lisp_Object window = window_from_coordinates (f, ev.x, ev.y, 0, false, false);
10175 10265
10176 /* A window will be autoselected only when it is not 10266 /* A window will be autoselected only when it is not
10177 selected now and the last mouse movement event was 10267 selected now and the last mouse movement event was
10178 not in it. The remainder of the code is a bit vague 10268 not in it. The remainder of the code is a bit vague
10179 wrt what a "window" is. For immediate autoselection, 10269 wrt what a "window" is. For immediate autoselection,
10180 the window is usually the entire window but for GTK 10270 the window is usually the entire window but for GTK
10181 where the scroll bars don't count. For delayed 10271 where the scroll bars don't count. For delayed
10182 autoselection the window is usually the window's text 10272 autoselection the window is usually the window's text
10183 area including the margins. */ 10273 area including the margins. */
10184 if (WINDOWP (window) 10274 if (WINDOWP (window)
10185 && !EQ (window, last_mouse_window) 10275 && !EQ (window, last_mouse_window)
10186 && !EQ (window, selected_window)) 10276 && !EQ (window, selected_window))
10187 { 10277 {
10188 inev.ie.kind = SELECT_WINDOW_EVENT; 10278 inev.ie.kind = SELECT_WINDOW_EVENT;
10189 inev.ie.frame_or_window = window; 10279 inev.ie.frame_or_window = window;
10190 } 10280 }
10191 10281
10192 /* Remember the last window where we saw the mouse. */ 10282 /* Remember the last window where we saw the mouse. */
10193 last_mouse_window = window; 10283 last_mouse_window = window;
10194 } 10284 }
10195 10285
10196 if (!x_note_mouse_movement (f, &ev)) 10286 if (!x_note_mouse_movement (f, &ev))
10197 help_echo_string = previous_help_echo_string; 10287 help_echo_string = previous_help_echo_string;
10198 } 10288 }
10199 else 10289 else
10200 { 10290 {
10201#ifndef USE_TOOLKIT_SCROLL_BARS 10291#ifndef USE_TOOLKIT_SCROLL_BARS
10202 struct scroll_bar *bar 10292 struct scroll_bar *bar
10203 = x_window_to_scroll_bar (xi_event->display, xev->event, 2); 10293 = x_window_to_scroll_bar (xi_event->display, xev->event, 2);
10204 10294
10205 if (bar) 10295 if (bar)
10206 x_scroll_bar_note_movement (bar, &ev); 10296 x_scroll_bar_note_movement (bar, &ev);
10207#endif /* USE_TOOLKIT_SCROLL_BARS */ 10297#endif /* USE_TOOLKIT_SCROLL_BARS */
10208 10298
10209 /* If we move outside the frame, then we're 10299 /* If we move outside the frame, then we're
10210 certainly no longer on any text in the frame. */ 10300 certainly no longer on any text in the frame. */
10211 clear_mouse_face (hlinfo); 10301 clear_mouse_face (hlinfo);
10212 } 10302 }
10213 10303
10214 /* If the contents of the global variable help_echo_string 10304 /* If the contents of the global variable help_echo_string
10215 has changed, generate a HELP_EVENT. */ 10305 has changed, generate a HELP_EVENT. */
10216 if (!NILP (help_echo_string) 10306 if (!NILP (help_echo_string)
10217 || !NILP (previous_help_echo_string)) 10307 || !NILP (previous_help_echo_string))
10218 do_help = 1; 10308 do_help = 1;
10219 goto XI_OTHER; 10309 goto XI_OTHER;
10310 }
10220 case XI_ButtonRelease: 10311 case XI_ButtonRelease:
10221 case XI_ButtonPress: 10312 case XI_ButtonPress:
10222 { 10313 {
@@ -10242,6 +10333,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10242 10333
10243 device = xi_device_from_id (dpyinfo, xev->deviceid); 10334 device = xi_device_from_id (dpyinfo, xev->deviceid);
10244 10335
10336 if (!device || !device->master_p)
10337 goto XI_OTHER;
10338
10245 bv.button = xev->detail; 10339 bv.button = xev->detail;
10246 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease; 10340 bv.type = xev->evtype == XI_ButtonPress ? ButtonPress : ButtonRelease;
10247 bv.x = lrint (xev->event_x); 10341 bv.x = lrint (xev->event_x);
@@ -10408,6 +10502,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10408 int copy_bufsiz = sizeof (copy_buffer); 10502 int copy_bufsiz = sizeof (copy_buffer);
10409 ptrdiff_t i; 10503 ptrdiff_t i;
10410 int nchars, len; 10504 int nchars, len;
10505 struct xi_device_t *device;
10506
10507 device = xi_device_from_id (dpyinfo, xev->deviceid);
10508
10509 if (!device || !device->master_p)
10510 goto XI_OTHER;
10411 10511
10412#if defined (USE_X_TOOLKIT) || defined (USE_GTK) 10512#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
10413 /* Dispatch XI_KeyPress events when in menu. */ 10513 /* Dispatch XI_KeyPress events when in menu. */
@@ -10765,6 +10865,108 @@ handle_one_xevent (struct x_display_info *dpyinfo,
10765 case XI_DeviceChanged: 10865 case XI_DeviceChanged:
10766 x_init_master_valuators (dpyinfo); 10866 x_init_master_valuators (dpyinfo);
10767 goto XI_OTHER; 10867 goto XI_OTHER;
10868#ifdef XI_TouchBegin
10869 case XI_TouchBegin:
10870 {
10871 struct xi_device_t *device;
10872 device = xi_device_from_id (dpyinfo, xev->deviceid);
10873
10874 if (!device)
10875 goto XI_OTHER;
10876
10877 if (xi_find_touch_point (device, xev->detail))
10878 emacs_abort ();
10879
10880 f = x_any_window_to_frame (dpyinfo, xev->event);
10881
10882 if (f && device->direct_p)
10883 {
10884 xi_link_touch_point (device, xev->detail, xev->event_x,
10885 xev->event_y);
10886
10887 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
10888 inev.ie.timestamp = xev->time;
10889 XSETFRAME (inev.ie.frame_or_window, f);
10890 XSETINT (inev.ie.x, lrint (xev->event_x));
10891 XSETINT (inev.ie.y, lrint (xev->event_y));
10892 XSETINT (inev.ie.arg, xev->detail);
10893
10894 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
10895 xev->detail, xev->event, XIAcceptTouch);
10896 }
10897 else
10898 XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
10899 xev->detail, xev->event, XIRejectTouch);
10900
10901 goto XI_OTHER;
10902 }
10903 case XI_TouchUpdate:
10904 {
10905 struct xi_device_t *device;
10906 struct xi_touch_point_t *touchpoint;
10907 Lisp_Object arg = Qnil;
10908
10909 device = xi_device_from_id (dpyinfo, xev->deviceid);
10910
10911 if (!device)
10912 goto XI_OTHER;
10913
10914 touchpoint = xi_find_touch_point (device, xev->detail);
10915
10916 if (!touchpoint)
10917 emacs_abort ();
10918
10919 touchpoint->x = xev->event_x;
10920 touchpoint->y = xev->event_y;
10921
10922 f = x_any_window_to_frame (dpyinfo, xev->event);
10923
10924 if (f && device->direct_p)
10925 {
10926 inev.ie.kind = TOUCHSCREEN_UPDATE_EVENT;
10927 inev.ie.timestamp = xev->time;
10928 XSETFRAME (inev.ie.frame_or_window, f);
10929
10930 for (touchpoint = device->touchpoints;
10931 touchpoint; touchpoint = touchpoint->next)
10932 {
10933 arg = Fcons (list3i (lrint (touchpoint->x),
10934 lrint (touchpoint->y),
10935 lrint (touchpoint->number)),
10936 arg);
10937 }
10938
10939 inev.ie.arg = arg;
10940 }
10941
10942 goto XI_OTHER;
10943 }
10944 case XI_TouchEnd:
10945 {
10946 struct xi_device_t *device;
10947
10948 device = xi_device_from_id (dpyinfo, xev->deviceid);
10949
10950 if (!device)
10951 goto XI_OTHER;
10952
10953 xi_unlink_touch_point (xev->detail, device);
10954
10955 f = x_any_window_to_frame (dpyinfo, xev->event);
10956
10957 if (f && device->direct_p)
10958 {
10959 inev.ie.kind = TOUCHSCREEN_END_EVENT;
10960 inev.ie.timestamp = xev->time;
10961 XSETFRAME (inev.ie.frame_or_window, f);
10962 XSETINT (inev.ie.x, lrint (xev->event_x));
10963 XSETINT (inev.ie.y, lrint (xev->event_y));
10964 XSETINT (inev.ie.arg, xev->detail);
10965 }
10966
10967 goto XI_OTHER;
10968 }
10969#endif
10768 default: 10970 default:
10769 goto XI_OTHER; 10971 goto XI_OTHER;
10770 } 10972 }
diff --git a/src/xterm.h b/src/xterm.h
index 7abe168bc6f..d9ace002d58 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -179,13 +179,24 @@ struct xi_scroll_valuator_t
179 int horizontal; 179 int horizontal;
180}; 180};
181 181
182struct xi_touch_point_t
183{
184 struct xi_touch_point_t *next;
185
186 int number;
187 double x, y;
188};
189
182struct xi_device_t 190struct xi_device_t
183{ 191{
184 int device_id; 192 int device_id;
185 int scroll_valuator_count; 193 int scroll_valuator_count;
186 int grab; 194 int grab;
195 bool master_p;
196 bool direct_p;
187 197
188 struct xi_scroll_valuator_t *valuators; 198 struct xi_scroll_valuator_t *valuators;
199 struct xi_touch_point_t *touchpoints;
189}; 200};
190#endif 201#endif
191 202