mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-20 11:57:36 +00:00
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.
This commit is contained in:
parent
132fa71615
commit
759d337b0d
2 changed files with 104 additions and 22 deletions
47
src/xmenu.c
47
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;
|
||||
|
|
|
|||
79
src/xterm.c
79
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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue