aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2023-01-17 18:28:37 +0800
committerPo Lu2023-01-17 18:30:40 +0800
commitb9025c507a3a7dae4de19b18cafaa09b18183832 (patch)
treef4c8713acac5af7287a12b7f713611593747c441 /src
parentbb383a54910c3094e5d228e0af62bf70e36203ca (diff)
downloademacs-b9025c507a3a7dae4de19b18cafaa09b18183832.tar.gz
emacs-b9025c507a3a7dae4de19b18cafaa09b18183832.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/xterm.c155
-rw-r--r--src/xterm.h17
2 files changed, 163 insertions, 9 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 028bb7582c4..6ae7e97f45a 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5750,7 +5750,8 @@ xi_device_from_id (struct x_display_info *dpyinfo, int deviceid)
5750 5750
5751static void 5751static void
5752xi_link_touch_point (struct xi_device_t *device, 5752xi_link_touch_point (struct xi_device_t *device,
5753 int detail, double x, double y) 5753 int detail, double x, double y,
5754 struct frame *frame)
5754{ 5755{
5755 struct xi_touch_point_t *touchpoint; 5756 struct xi_touch_point_t *touchpoint;
5756 5757
@@ -5759,6 +5760,7 @@ xi_link_touch_point (struct xi_device_t *device,
5759 touchpoint->x = x; 5760 touchpoint->x = x;
5760 touchpoint->y = y; 5761 touchpoint->y = y;
5761 touchpoint->number = detail; 5762 touchpoint->number = detail;
5763 touchpoint->frame = frame;
5762 5764
5763 device->touchpoints = touchpoint; 5765 device->touchpoints = touchpoint;
5764} 5766}
@@ -5787,6 +5789,36 @@ xi_unlink_touch_point (int detail,
5787 return false; 5789 return false;
5788} 5790}
5789 5791
5792/* Unlink all touch points associated with the frame F.
5793 This is done upon unmapping or destroying F's window, because
5794 touch point delivery after that point is undefined. */
5795
5796static void
5797xi_unlink_touch_points (struct frame *f)
5798{
5799 struct xi_device_t *device;
5800 struct xi_touch_point_t **next, *last;
5801 int i;
5802
5803 for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
5804 {
5805 device = &FRAME_DISPLAY_INFO (f)->devices[i];
5806
5807 /* Now unlink all touch points on DEVICE matching F. */
5808
5809 for (next = &device->touchpoints; (last = *next);)
5810 {
5811 if (last->frame == f)
5812 {
5813 *next = last->next;
5814 xfree (last);
5815 }
5816 else
5817 next = &last->next;
5818 }
5819 }
5820}
5821
5790static struct xi_touch_point_t * 5822static struct xi_touch_point_t *
5791xi_find_touch_point (struct xi_device_t *device, int detail) 5823xi_find_touch_point (struct xi_device_t *device, int detail)
5792{ 5824{
@@ -13535,6 +13567,10 @@ xi_disable_devices (struct x_display_info *dpyinfo,
13535#ifdef HAVE_XINPUT2_2 13567#ifdef HAVE_XINPUT2_2
13536 struct xi_touch_point_t *tem, *last; 13568 struct xi_touch_point_t *tem, *last;
13537#endif 13569#endif
13570#if defined HAVE_XINPUT2_2 && !defined HAVE_EXT_TOOL_BAR
13571 struct x_output *output;
13572 Lisp_Object tail, frame;
13573#endif
13538 13574
13539 /* Don't pointlessly copy dpyinfo->devices if there are no devices 13575 /* Don't pointlessly copy dpyinfo->devices if there are no devices
13540 to disable. */ 13576 to disable. */
@@ -13577,6 +13613,34 @@ xi_disable_devices (struct x_display_info *dpyinfo,
13577 tem = tem->next; 13613 tem = tem->next;
13578 xfree (last); 13614 xfree (last);
13579 } 13615 }
13616
13617#ifndef HAVE_EXT_TOOL_BAR
13618
13619 /* Now look through each frame on DPYINFO. If it has an
13620 outstanding tool bar press for this device, release
13621 the tool bar. */
13622
13623 FOR_EACH_FRAME (tail, frame)
13624 {
13625 if (!FRAME_X_P (XFRAME (frame))
13626 || (FRAME_DISPLAY_INFO (XFRAME (frame))
13627 != dpyinfo))
13628 continue;
13629
13630 output = FRAME_OUTPUT_DATA (XFRAME (frame));
13631
13632 if (output->tool_bar_touch_device
13633 == dpyinfo->devices[i].device_id)
13634 {
13635 if (XFRAME (frame)->last_tool_bar_item != -1
13636 && WINDOWP (XFRAME (frame)->tool_bar_window))
13637 handle_tool_bar_click (XFRAME (frame), 0, 0,
13638 false, 0);
13639
13640 output->tool_bar_touch_device = 0;
13641 }
13642 }
13643#endif
13580#endif 13644#endif
13581 13645
13582 goto out; 13646 goto out;
@@ -24209,6 +24273,48 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24209 } 24273 }
24210#endif 24274#endif
24211 24275
24276#ifndef HAVE_EXT_TOOL_BAR
24277 /* Is this a touch from a direct touch device that is in
24278 the tool-bar? */
24279 if (device->direct_p
24280 && WINDOWP (f->tool_bar_window)
24281 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
24282 {
24283 Lisp_Object window;
24284 int x = xev->event_x;
24285 int y = xev->event_y;
24286
24287 window = window_from_coordinates (f, x, y, 0, true, true);
24288 /* Ignore button release events if the mouse
24289 wasn't previously pressed on the tool bar.
24290 We do this because otherwise selecting some
24291 text with the mouse and then releasing it on
24292 the tool bar doesn't stop selecting text,
24293 since the tool bar eats the button up
24294 event. */
24295 tool_bar_p = EQ (window, f->tool_bar_window);
24296
24297 /* If this touch has started in the tool bar, do not
24298 send it to Lisp. Instead, simulate a tool bar
24299 click, releasing it once it goes away. */
24300
24301 if (tool_bar_p)
24302 {
24303 handle_tool_bar_click (f, x, y, true, 0);
24304
24305 /* Record the device and the touch ID on the
24306 frame. That way, Emacs knows when to dismiss
24307 the tool bar click later. */
24308
24309 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device
24310 = device->device_id;
24311 FRAME_OUTPUT_DATA (f)->tool_bar_touch_id = xev->detail;
24312
24313 goto XI_OTHER;
24314 }
24315 }
24316#endif
24317
24212 if (!menu_bar_p && !tool_bar_p) 24318 if (!menu_bar_p && !tool_bar_p)
24213 { 24319 {
24214 if (f && device->direct_p) 24320 if (f && device->direct_p)
@@ -24218,13 +24324,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24218 x_catch_errors (dpyinfo->display); 24324 x_catch_errors (dpyinfo->display);
24219 24325
24220 if (x_input_grab_touch_events) 24326 if (x_input_grab_touch_events)
24221 XIAllowTouchEvents (dpyinfo->display, xev->deviceid, 24327 XIAllowTouchEvents (dpyinfo->display,
24222 xev->detail, xev->event, XIAcceptTouch); 24328 xev->deviceid,
24329 xev->detail, xev->event,
24330 XIAcceptTouch);
24223 24331
24224 if (!x_had_errors_p (dpyinfo->display)) 24332 if (!x_had_errors_p (dpyinfo->display))
24225 { 24333 {
24226 xi_link_touch_point (device, xev->detail, xev->event_x, 24334 xi_link_touch_point (device, xev->detail,
24227 xev->event_y); 24335 xev->event_x,
24336 xev->event_y, f);
24228 24337
24229 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT; 24338 inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
24230 inev.ie.timestamp = xev->time; 24339 inev.ie.timestamp = xev->time;
@@ -24299,10 +24408,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24299 for (touchpoint = device->touchpoints; 24408 for (touchpoint = device->touchpoints;
24300 touchpoint; touchpoint = touchpoint->next) 24409 touchpoint; touchpoint = touchpoint->next)
24301 { 24410 {
24302 arg = Fcons (list3i (lrint (touchpoint->x), 24411 if (touchpoint->frame == f)
24303 lrint (touchpoint->y), 24412 arg = Fcons (list3i (lrint (touchpoint->x),
24304 lrint (touchpoint->number)), 24413 lrint (touchpoint->y),
24305 arg); 24414 lrint (touchpoint->number)),
24415 arg);
24306 } 24416 }
24307 24417
24308 if (source) 24418 if (source)
@@ -24348,6 +24458,23 @@ handle_one_xevent (struct x_display_info *dpyinfo,
24348 } 24458 }
24349 } 24459 }
24350 24460
24461 /* Now see if the touchpoint was previously on the tool bar.
24462 If it was, release the tool bar. */
24463
24464 if (!f)
24465 f = x_window_to_frame (dpyinfo, xev->event);
24466
24467 if (f && (FRAME_OUTPUT_DATA (f)->tool_bar_touch_id
24468 == xev->detail))
24469 {
24470 if (f->last_tool_bar_item != -1)
24471 handle_tool_bar_click (f, xev->event_x, xev->event_y,
24472 false, 0);
24473
24474 /* Now clear the tool bar device. */
24475 FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0;
24476 }
24477
24351 goto XI_OTHER; 24478 goto XI_OTHER;
24352 } 24479 }
24353 24480
@@ -28453,6 +28580,11 @@ x_make_frame_invisible (struct frame *f)
28453 28580
28454 block_input (); 28581 block_input ();
28455 28582
28583#ifdef HAVE_XINPUT2_2
28584 /* Remove any touch points associated with F. */
28585 xi_unlink_touch_points (f);
28586#endif
28587
28456 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim 28588 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim
28457 that the current position of the window is user-specified, rather than 28589 that the current position of the window is user-specified, rather than
28458 program-specified, so that when the window is mapped again, it will be 28590 program-specified, so that when the window is mapped again, it will be
@@ -28658,6 +28790,11 @@ x_free_frame_resources (struct frame *f)
28658 xi_handle_delete_frame (dpyinfo, f); 28790 xi_handle_delete_frame (dpyinfo, f);
28659#endif 28791#endif
28660 28792
28793#ifdef HAVE_XINPUT2_2
28794 /* Remove any touch points associated with F. */
28795 xi_unlink_touch_points (f);
28796#endif
28797
28661 /* If a display connection is dead, don't try sending more 28798 /* If a display connection is dead, don't try sending more
28662 commands to the X server. */ 28799 commands to the X server. */
28663 if (dpyinfo->display) 28800 if (dpyinfo->display)
diff --git a/src/xterm.h b/src/xterm.h
index d768ba7ff8d..28ae00ca190 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -257,10 +257,17 @@ struct xi_scroll_valuator_t
257 257
258struct xi_touch_point_t 258struct xi_touch_point_t
259{ 259{
260 /* The next touch point in this list. */
260 struct xi_touch_point_t *next; 261 struct xi_touch_point_t *next;
261 262
263 /* The touchpoint detail. */
262 int number; 264 int number;
265
266 /* The last known X and Y position of the touchpoint. */
263 double x, y; 267 double x, y;
268
269 /* The frame associated with this touch point. */
270 struct frame *frame;
264}; 271};
265 272
266#endif 273#endif
@@ -1295,6 +1302,16 @@ struct x_output
1295 VisibilityFullyObscured, but is set to something else in 1302 VisibilityFullyObscured, but is set to something else in
1296 handle_one_xevent. */ 1303 handle_one_xevent. */
1297 int visibility_state; 1304 int visibility_state;
1305
1306#ifdef HAVE_XINPUT2_2
1307 /* The touch ID of the last touch point to have touched the tool
1308 bar. */
1309 int tool_bar_touch_id;
1310
1311 /* The device that last touched the tool bar. 0 if no device
1312 touched the tool bar. */
1313 int tool_bar_touch_device;
1314#endif
1298}; 1315};
1299 1316
1300enum 1317enum