[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master 759d337b0d: Fix key navigation of Lucid menus on XI2
From: |
Po Lu |
Subject: |
master 759d337b0d: Fix key navigation of Lucid menus on XI2 |
Date: |
Sat, 23 Apr 2022 07:59:06 -0400 (EDT) |
branch: master
commit 759d337b0d05f3164bf90dd980a079cd412f9de1
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Fix key navigation of Lucid menus on XI2
* src/xmenu.c (popup_get_selection): Fix cookie claiming of
input extension events.
(Fx_menu_bar_open_internal): Use right timestamps on XI2.
* src/xterm.c (handle_one_xevent): Dispatch XI2 key events via
Xt when popup is active.
---
src/xmenu.c | 47 +++++++++++++++++++++++++++++-------
src/xterm.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++-----------
2 files changed, 104 insertions(+), 22 deletions(-)
diff --git a/src/xmenu.c b/src/xmenu.c
index 94cd9dab69..316dacee5b 100644
--- a/src/xmenu.c
+++ b/src/xmenu.c
@@ -365,16 +365,16 @@ popup_get_selection (XEvent *initial_event, struct
x_display_info *dpyinfo,
&& event.xgeneric.display == dpyinfo->display
&& event.xgeneric.extension == dpyinfo->xi2_opcode)
{
+ if (!event.xcookie.data
+ && XGetEventData (dpyinfo->display, &event.xcookie))
+ cookie_claimed_p = true;
+
if (event.xcookie.data)
{
switch (event.xgeneric.evtype)
{
case XI_ButtonRelease:
{
- if (!event.xcookie.data
- && XGetEventData (dpyinfo->display, &event.xcookie))
- cookie_claimed_p = true;
-
xev = (XIDeviceEvent *) event.xcookie.data;
device = xi_device_from_id (dpyinfo, xev->deviceid);
@@ -424,10 +424,6 @@ popup_get_selection (XEvent *initial_event, struct
x_display_info *dpyinfo,
{
KeySym keysym;
- if (!event.xcookie.data
- && XGetEventData (dpyinfo->display, &event.xcookie))
- cookie_claimed_p = true;
-
xev = (XIDeviceEvent *) event.xcookie.data;
copy.xkey.type = KeyPress;
@@ -473,6 +469,9 @@ DEFUN ("x-menu-bar-open-internal",
Fx_menu_bar_open_internal, Sx_menu_bar_open_i
{
XEvent ev;
struct frame *f = decode_window_system_frame (frame);
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
+#endif
Widget menubar;
block_input ();
@@ -485,12 +484,44 @@ DEFUN ("x-menu-bar-open-internal",
Fx_menu_bar_open_internal, Sx_menu_bar_open_i
Window child;
bool error_p = false;
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ /* Clear the XI2 grab so Motif or lwlib can set a core grab.
+ Otherwise some versions of Motif will emit a warning and hang,
+ and lwlib will fail to destroy the menu window. */
+
+ if (dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_ButtonPress))
+ {
+ for (int i = 0; i < dpyinfo->num_devices; ++i)
+ {
+ /* The keyboard grab matters too, in this specific
+ case. */
+#ifndef USE_LUCID
+ if (dpyinfo->devices[i].grab)
+#endif
+ {
+ XIUngrabDevice (dpyinfo->display,
+ dpyinfo->devices[i].device_id,
+ CurrentTime);
+ dpyinfo->devices[i].grab = 0;
+ }
+ }
+ }
+#endif
+
x_catch_errors (FRAME_X_DISPLAY (f));
memset (&ev, 0, sizeof ev);
ev.xbutton.display = FRAME_X_DISPLAY (f);
ev.xbutton.window = XtWindow (menubar);
ev.xbutton.root = FRAME_DISPLAY_INFO (f)->root_window;
+#ifndef HAVE_XINPUT2
ev.xbutton.time = XtLastTimestampProcessed (FRAME_X_DISPLAY (f));
+#else
+ ev.xbutton.time = ((dpyinfo->supports_xi2
+ && xi_frame_selected_for (f, XI_KeyPress))
+ ? dpyinfo->last_user_time
+ : XtLastTimestampProcessed (dpyinfo->display));
+#endif
ev.xbutton.button = Button1;
ev.xbutton.x = ev.xbutton.y = FRAME_MENUBAR_HEIGHT (f) / 2;
ev.xbutton.same_screen = True;
diff --git a/src/xterm.c b/src/xterm.c
index 1b1074b2f4..8b813210b7 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -13833,10 +13833,10 @@ handle_one_xevent (struct x_display_info *dpyinfo,
XEvent configureEvent;
XEvent next_event;
Lisp_Object coding;
-#if defined USE_MOTIF && defined HAVE_XINPUT2
- /* 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. */
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
+ /* Some XInput 2 events are important for Motif and Lucid menu bars
+ to work correctly, so they must be translated into core events
+ before being passed to XtDispatchEvent. */
bool use_copy = false;
XEvent copy;
#elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2
@@ -17746,7 +17746,41 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
/* Dispatch XI_KeyPress events when in menu. */
if (popup_activated ())
- goto XI_OTHER;
+ {
+#ifdef USE_LUCID
+ /* This makes key navigation work inside menus. */
+ use_copy = true;
+ copy.xkey.type = KeyPress;
+ copy.xkey.serial = xev->serial;
+ copy.xkey.send_event = xev->send_event;
+ copy.xkey.display = dpyinfo->display;
+ copy.xkey.window = xev->event;
+ copy.xkey.root = xev->root;
+ copy.xkey.subwindow = xev->child;
+ copy.xkey.time = xev->time;
+ copy.xkey.state = ((xev->mods.effective & ~(1 << 13 | 1 <<
14))
+ | (xev->group.effective << 13));
+
+ copy.xkey.x = lrint (xev->event_x);
+ copy.xkey.y = lrint (xev->event_y);
+ copy.xkey.x_root = lrint (xev->root_x);
+ copy.xkey.y_root = lrint (xev->root_y);
+
+ if (xev->buttons.mask_len)
+ {
+ if (XIMaskIsSet (xev->buttons.mask, 1))
+ copy.xkey.state |= Button1Mask;
+ if (XIMaskIsSet (xev->buttons.mask, 2))
+ copy.xkey.state |= Button2Mask;
+ if (XIMaskIsSet (xev->buttons.mask, 3))
+ copy.xkey.state |= Button3Mask;
+ }
+
+ copy.xkey.keycode = xev->detail;
+ copy.xkey.same_screen = True;
+#endif
+ goto XI_OTHER;
+ }
#endif
x_display_set_last_user_time (dpyinfo, xev->time);
@@ -18193,7 +18227,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#endif
case XI_KeyRelease:
-#if defined HAVE_X_I18N || defined USE_GTK
+#if defined HAVE_X_I18N || defined USE_GTK || defined USE_LUCID
{
XKeyPressedEvent xkey;
@@ -18229,14 +18263,31 @@ handle_one_xevent (struct x_display_info *dpyinfo,
xkey.keycode = xev->detail;
xkey.same_screen = True;
+#ifdef USE_LUCID
+ if (!popup_activated ())
+ {
+#endif
#ifdef HAVE_X_I18N
- if (x_filter_event (dpyinfo, (XEvent *) &xkey))
- *finish = X_EVENT_DROP;
-#else
- f = x_any_window_to_frame (xkey->event);
+ if (x_filter_event (dpyinfo, (XEvent *) &xkey))
+ *finish = X_EVENT_DROP;
+#elif defined USE_GTK
+ f = x_any_window_to_frame (xkey->event);
- if (f && xg_filter_key (f, event))
- *finish = X_EVENT_DROP;
+ if (f && xg_filter_key (f, event))
+ *finish = X_EVENT_DROP;
+#endif
+#ifdef USE_LUCID
+ }
+ else
+ {
+ /* FIXME: the Lucid menu bar pops down upon any key
+ release event, so we don't dispatch these events
+ at all, which doesn't seem to be the right
+ solution.
+
+ use_copy = true;
+ copy.xkey = xkey; */
+ }
#endif
}
#endif
@@ -19009,12 +19060,12 @@ handle_one_xevent (struct x_display_info *dpyinfo,
{
/* Ignore some obviously bogus ConfigureNotify events that
other clients have been known to send Emacs.
- (bug#54051)*/
+ (bug#54051) */
if (event->type != ConfigureNotify
|| (event->xconfigure.width != 0
&& event->xconfigure.height != 0))
{
-#if defined USE_MOTIF && defined HAVE_XINPUT2
+#if defined USE_X_TOOLKIT && defined HAVE_XINPUT2
XtDispatchEvent (use_copy ? © : (XEvent *) event);
#else
XtDispatchEvent ((XEvent *) event);
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- master 759d337b0d: Fix key navigation of Lucid menus on XI2,
Po Lu <=