diff options
| author | Po Lu | 2023-01-17 18:28:37 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-17 18:30:40 +0800 |
| commit | b9025c507a3a7dae4de19b18cafaa09b18183832 (patch) | |
| tree | f4c8713acac5af7287a12b7f713611593747c441 /src | |
| parent | bb383a54910c3094e5d228e0af62bf70e36203ca (diff) | |
| download | emacs-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.c | 155 | ||||
| -rw-r--r-- | src/xterm.h | 17 |
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 | ||
| 5751 | static void | 5751 | static void |
| 5752 | xi_link_touch_point (struct xi_device_t *device, | 5752 | xi_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 | |||
| 5796 | static void | ||
| 5797 | xi_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 | |||
| 5790 | static struct xi_touch_point_t * | 5822 | static struct xi_touch_point_t * |
| 5791 | xi_find_touch_point (struct xi_device_t *device, int detail) | 5823 | xi_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 | ||
| 258 | struct xi_touch_point_t | 258 | struct 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 | ||
| 1300 | enum | 1317 | enum |