From 68740117211a104ffd59b570aa40d1b5cfcef93e Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 1 Mar 2022 13:48:36 +0800 Subject: [PATCH] Fix C-g inside toolkit file dialogs with XI2 * src/xfns.c (Fx_file_dialog): Handle GenericEvents when looking for quit character. * src/xmenu.c (x_menu_wait_for_event): If data is non-nil, use XPending. --- src/xfns.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++------- src/xmenu.c | 4 +-- 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index 03adb5ab8d7..65218b3fc07 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -8381,20 +8381,84 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, result = 0; while (result == 0) { - XEvent event; + XEvent event, copy; +#ifdef HAVE_XINPUT2 + x_menu_wait_for_event (FRAME_X_DISPLAY (f)); +#else x_menu_wait_for_event (0); - XtAppNextEvent (Xt_app_con, &event); - if (event.type == KeyPress - && FRAME_X_DISPLAY (f) == event.xkey.display) - { - KeySym keysym = XLookupKeysym (&event.xkey, 0); +#endif - /* Pop down on C-g. */ - if (keysym == XK_g && (event.xkey.state & ControlMask) != 0) - XtUnmanageChild (dialog); - } + if ( +#ifndef HAVE_XINPUT2 + XtAppPending (Xt_app_con) +#else + XPending (FRAME_X_DISPLAY (f)) +#endif + ) + { +#ifndef HAVE_XINPUT2 + XtAppNextEvent (Xt_app_con, &event); +#else + XNextEvent (FRAME_X_DISPLAY (f), &event); +#endif + + copy = event; + if (event.type == KeyPress + && FRAME_X_DISPLAY (f) == event.xkey.display) + { + KeySym keysym = XLookupKeysym (&event.xkey, 0); - (void) x_dispatch_event (&event, FRAME_X_DISPLAY (f)); + /* Pop down on C-g. */ + if (keysym == XK_g && (event.xkey.state & ControlMask) != 0) + XtUnmanageChild (dialog); + } +#ifdef HAVE_XINPUT2 + else if (event.type == GenericEvent + && FRAME_X_DISPLAY (f) == event.xgeneric.display + && FRAME_DISPLAY_INFO (f)->supports_xi2 + && (event.xgeneric.extension + == FRAME_DISPLAY_INFO (f)->xi2_opcode) + && event.xgeneric.evtype == XI_KeyPress) + { + KeySym keysym; + XIDeviceEvent *xev; + + if (event.xcookie.data) + emacs_abort (); + + if (XGetEventData (FRAME_X_DISPLAY (f), &event.xcookie)) + { + xev = (XIDeviceEvent *) event.xcookie.data; + + copy.xkey.type = KeyPress; + copy.xkey.serial = xev->serial; + copy.xkey.send_event = xev->send_event; + copy.xkey.display = FRAME_X_DISPLAY (f); + copy.xkey.window = xev->event; + copy.xkey.root = xev->root; + copy.xkey.subwindow = xev->child; + copy.xkey.time = xev->time; + 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); + copy.xkey.state = xev->mods.effective; + copy.xkey.keycode = xev->detail; + copy.xkey.same_screen = True; + + keysym = XLookupKeysym (©.xkey, 0); + + if (keysym == XK_g + && (copy.xkey.state & ControlMask) != 0) /* Any escape, ignore modifiers. */ + XtUnmanageChild (dialog); + + XFreeEventData (FRAME_X_DISPLAY (f), &event.xcookie); + } + } +#endif + + (void) x_dispatch_event (©, FRAME_X_DISPLAY (f)); + } } /* Get the result. */ diff --git a/src/xmenu.c b/src/xmenu.c index 4683e856c2e..a8185d8346e 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -184,8 +184,8 @@ x_menu_wait_for_event (void *data) instead of the small ifdefs below. */ while ( -#ifdef USE_X_TOOLKIT - ! XtAppPending (Xt_app_con) +#if defined USE_X_TOOLKIT + ! (data ? XPending (data) : XtAppPending (Xt_app_con)) #elif defined USE_GTK ! gtk_events_pending () #else -- 2.39.5