summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPo Lu <luangruo@yahoo.com>2021-12-18 20:45:11 +0800
committerPo Lu <luangruo@yahoo.com>2021-12-18 20:46:50 +0800
commit4544651b3f62ce4a104a058e8c6aee42c23b76bc (patch)
treeabc5c19ab2a1ff562c7fde46bd2d011ccb615206
parentd99aa9461b1348741ee2df7b6c7a197005191716 (diff)
downloademacs-4544651b3f62ce4a104a058e8c6aee42c23b76bc.tar.gz
Work around some mysterious touch ownership race on GNOME Shell
* src/xterm.c (x_unlink_touch_point): Return if touchpoint was actually unlinked. (handle_one_xevent): Catch and ignore errors during touch sequence grabbing.
-rw-r--r--src/xterm.c88
1 files changed, 51 insertions, 37 deletions
diff --git a/src/xterm.c b/src/xterm.c
index 03f509ba868..7456b3b6beb 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -579,7 +579,7 @@ xi_link_touch_point (struct xi_device_t *device,
device->touchpoints = touchpoint;
}
-static void
+static bool
xi_unlink_touch_point (int detail,
struct xi_device_t *device)
{
@@ -596,9 +596,11 @@ xi_unlink_touch_point (int detail,
last->next = tem->next;
xfree (tem);
- return;
+ return true;
}
}
+
+ return false;
}
static struct xi_touch_point_t *
@@ -10887,37 +10889,45 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (f && device->direct_p)
{
- xi_link_touch_point (device, xev->detail, xev->event_x,
- xev->event_y);
+ x_catch_errors (dpyinfo->display);
+ XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+ xev->detail, xev->event, XIAcceptTouch);
+ if (!x_had_errors_p (dpyinfo->display))
+ {
+ xi_link_touch_point (device, xev->detail, xev->event_x,
+ xev->event_y);
#ifdef HAVE_GTK3
- if (FRAME_X_OUTPUT (f)->menubar_widget
- && xg_event_is_for_menubar (f, event))
- {
- bool was_waiting_for_input = waiting_for_input;
- /* This hack was adopted from the NS port. Whether
- or not it is actually safe is a different story
- altogether. */
- if (waiting_for_input)
- waiting_for_input = 0;
- set_frame_menubar (f, true);
- waiting_for_input = was_waiting_for_input;
- }
+ if (FRAME_X_OUTPUT (f)->menubar_widget
+ && xg_event_is_for_menubar (f, event))
+ {
+ bool was_waiting_for_input = waiting_for_input;
+ /* This hack was adopted from the NS port. Whether
+ or not it is actually safe is a different story
+ altogether. */
+ if (waiting_for_input)
+ waiting_for_input = 0;
+ set_frame_menubar (f, true);
+ waiting_for_input = was_waiting_for_input;
+ }
#endif
- inev.ie.kind = TOUCHSCREEN_BEGIN_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);
-
- XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
- xev->detail, xev->event, XIAcceptTouch);
+ inev.ie.kind = TOUCHSCREEN_BEGIN_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);
+ }
+ x_uncatch_errors_after_check ();
}
else
- XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
- xev->detail, xev->event, XIRejectTouch);
+ {
+ x_catch_errors (dpyinfo->display);
+ XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
+ xev->detail, xev->event, XIRejectTouch);
+ x_uncatch_errors ();
+ }
goto XI_OTHER;
}
@@ -10965,24 +10975,28 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case XI_TouchEnd:
{
struct xi_device_t *device;
+ bool unlinked_p;
device = xi_device_from_id (dpyinfo, xev->deviceid);
if (!device)
goto XI_OTHER;
- xi_unlink_touch_point (xev->detail, device);
-
- f = x_any_window_to_frame (dpyinfo, xev->event);
+ unlinked_p = xi_unlink_touch_point (xev->detail, device);
- if (f && device->direct_p)
+ if (unlinked_p)
{
- 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);
+ f = x_any_window_to_frame (dpyinfo, xev->event);
+
+ if (f && device->direct_p)
+ {
+ 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);
+ }
}
goto XI_OTHER;