[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 16702f183f: Fix Motif menu and menu bar dismissal on XI2
From: |
Po Lu |
Subject: |
master 16702f183f: Fix Motif menu and menu bar dismissal on XI2 |
Date: |
Sat, 26 Feb 2022 21:37:54 -0500 (EST) |
branch: master
commit 16702f183f34cba880a04e08db9d6b644b38b424
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Fix Motif menu and menu bar dismissal on XI2
* src/xmenu.c (x_activate_menubar): Improve ungrabbing logic on
XI2.
(server_timestamp_predicate): New function.
(create_and_show_popup_menu): If the display supports XI2, make
sure the timestamps are correct by dispatching a PropertyNotify
event to Xt.
* src/xterm.c (handle_one_xevent): Translate XI_ButtonRelease
events into core events before dispatching them to Xt.
---
src/xmenu.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++------------
src/xterm.c | 49 +++++++++++++++++++++++++++++++++++++++++--
2 files changed, 104 insertions(+), 15 deletions(-)
diff --git a/src/xmenu.c b/src/xmenu.c
index 21e8f0f9ec..2bc9f5a93a 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -572,11 +572,11 @@ x_activate_menubar (struct frame *f)
{
for (int i = 0; i < dpyinfo->num_devices; ++i)
{
-#ifndef USE_MOTIF
if (dpyinfo->devices[i].grab)
-#endif
- XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
- CurrentTime);
+ {
+ XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id,
+ CurrentTime);
+ }
}
}
#endif
@@ -1514,6 +1514,23 @@ pop_down_menu (int id)
popup_activated_flag = 0;
}
+#ifdef HAVE_XINPUT2
+static Bool
+server_timestamp_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ XID *args = (XID *) arg;
+
+ if (xevent->type == PropertyNotify
+ && xevent->xproperty.window == args[0]
+ && xevent->xproperty.atom == args[1])
+ return True;
+
+ return False;
+}
+#endif
+
/* Pop up the menu for frame F defined by FIRST_WV at X/Y and loop until the
menu pops down.
menu_item_selection will be set to the selection. */
@@ -1529,6 +1546,10 @@ create_and_show_popup_menu (struct frame *f,
widget_value *first_wv,
LWLIB_ID menu_id;
Widget menu;
Window dummy_window;
+#ifdef HAVE_XINPUT2
+ XEvent property_dummy;
+ Atom property_atom;
+#endif
eassert (FRAME_X_P (f));
@@ -1609,14 +1630,37 @@ create_and_show_popup_menu (struct frame *f,
widget_value *first_wv,
}
if (any_xi_grab_p)
- XGrabPointer (dpyinfo->display,
- FRAME_X_WINDOW (f),
- False, (PointerMotionMask
- | PointerMotionHintMask
- | ButtonReleaseMask
- | ButtonPressMask),
- GrabModeSync, GrabModeAsync,
- None, None, CurrentTime);
+ {
+#ifndef USE_MOTIF
+ XGrabPointer (dpyinfo->display,
+ FRAME_X_WINDOW (f),
+ False, (PointerMotionMask
+ | PointerMotionHintMask
+ | ButtonReleaseMask
+ | ButtonPressMask),
+ GrabModeSync, GrabModeAsync,
+ None, None, CurrentTime);
+#endif
+ }
+
+ if (dpyinfo->supports_xi2)
+ {
+ /* Dispatch a PropertyNotify to Xt with the current server time.
+ Motif tries to set a grab with the timestamp of the last event
+ processed by Xt, but Xt doesn't consider GenericEvents, so the
+ timestamp is always less than the last grab time. */
+
+ property_atom = XInternAtom (dpyinfo->display, "EMACS_SERVER_TIME_PROP",
False);
+
+ XChangeProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ property_atom, XA_ATOM, 32,
+ PropModeReplace, (unsigned char *) &property_atom, 1);
+
+ XIfEvent (dpyinfo->display, &property_dummy, server_timestamp_predicate,
+ (XPointer) &(XID[]) {(XID) FRAME_OUTER_WINDOW (f), (XID)
property_atom});
+
+ XtDispatchEvent (&property_dummy);
+ }
if (dpyinfo->supports_xi2)
XUngrabServer (dpyinfo->display);
@@ -1626,7 +1670,7 @@ create_and_show_popup_menu (struct frame *f, widget_value
*first_wv,
lw_popup_menu (menu, &dummy);
popup_activated_flag = 1;
-#ifdef HAVE_XINPUT2
+#if defined HAVE_XINPUT2 && !defined USE_MOTIF
if (any_xi_grab_p)
XAllowEvents (dpyinfo->display, AsyncPointer, CurrentTime);
#endif
diff --git a/src/xterm.c b/src/xterm.c
index 040397777b..33a6613e14 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -9513,6 +9513,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
XEvent configureEvent;
XEvent next_event;
Lisp_Object coding;
+#ifdef USE_MOTIF
+ /* Some XInput 2 events are important for Motif menu bars to work
+ correctly, so they must be translated into core events before
+ being passed to XtDispatchEvent. */
+ bool use_copy = false;
+ XEvent copy;
+#endif
*finish = X_EVENT_NORMAL;
@@ -10924,7 +10931,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_display_set_last_user_time (dpyinfo, event->xbutton.time);
#ifdef HAVE_XWIDGETS
- struct xwidget_view *xvw = xwidget_view_from_window
(event->xmotion.window);
+ struct xwidget_view *xvw = xwidget_view_from_window
(event->xbutton.window);
if (xvw)
{
@@ -11659,6 +11666,38 @@ handle_one_xevent (struct x_display_info *dpyinfo,
struct xwidget_view *xvw;
#endif
+#ifdef USE_MOTIF
+ if (popup_activated ())
+ {
+ use_copy = true;
+ copy.xbutton.type = ButtonRelease;
+ copy.xbutton.serial = xev->serial;
+ copy.xbutton.send_event = xev->send_event;
+ copy.xbutton.display = dpyinfo->display;
+ copy.xbutton.window = xev->event;
+ copy.xbutton.root = xev->root;
+ copy.xbutton.subwindow = xev->child;
+ copy.xbutton.time = xev->time;
+ copy.xbutton.x = lrint (xev->event_x);
+ copy.xbutton.y = lrint (xev->event_y);
+ copy.xbutton.x_root = lrint (xev->root_x);
+ copy.xbutton.y_root = lrint (xev->root_y);
+ copy.xbutton.state = xev->mods.effective;
+ copy.xbutton.button = xev->detail;
+ copy.xbutton.same_screen = True;
+
+ if (xev->buttons.mask_len)
+ {
+ if (XIMaskIsSet (xev->buttons.mask, 1))
+ copy.xbutton.state |= Button1Mask;
+ if (XIMaskIsSet (xev->buttons.mask, 2))
+ copy.xbutton.state |= Button2Mask;
+ if (XIMaskIsSet (xev->buttons.mask, 3))
+ copy.xbutton.state |= Button3Mask;
+ }
+ }
+#endif
+
#ifdef HAVE_XINPUT2_1
/* Ignore emulated scroll events when XI2 native
scroll events are present. */
@@ -12699,7 +12738,13 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (event->type != ConfigureNotify
|| (event->xconfigure.width != 0
&& event->xconfigure.height != 0))
- XtDispatchEvent ((XEvent *) event);
+ {
+#ifdef USE_MOTIF
+ XtDispatchEvent (use_copy ? © : (XEvent *) event);
+#else
+ XtDispatchEvent ((XEvent *) event);
+#endif
+ }
}
unblock_input ();
#endif /* USE_X_TOOLKIT */
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 16702f183f: Fix Motif menu and menu bar dismissal on XI2,
Po Lu <=