From 203c503ff22e6c3c7b75d0e30d1974bb0ca9e60a Mon Sep 17 00:00:00 2001 From: Po Lu Date: Thu, 14 Apr 2022 16:02:12 +0800 Subject: [PATCH] Minor fixes to menus on XI2 * src/xfns.c (Fx_create_frame): Populate `xi_masks'. * src/xmenu.c (x_activate_menubar) (create_and_show_popup_menu, x_menu_show): Only clear input extension grabs if we (or the toolkit) actually selected for XI_ButtonPress events. * src/xterm.c (xi_frame_selected_for): New function. (xi_populate_device_from_info, handle_one_xevent): Store device use instead of just whether or not it's a master device. (x_dnd_begin_drag_and_drop): Clean up block_input stuff. * src/xterm.h: Update prototypes. (struct xi_device_t): Rename `master_p' to `use'. --- src/xfns.c | 7 +++++++ src/xmenu.c | 19 +++++++++++-------- src/xterm.c | 49 +++++++++++++++++++++++++++++++++++++++---------- src/xterm.h | 9 +++++++-- 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/xfns.c b/src/xfns.c index 5cf3eb41996..195af1381b9 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -4845,6 +4845,13 @@ This function is an internal primitive--use `make-frame' instead. */) x_icon (f, parms); x_make_gc (f); +#ifdef HAVE_XINPUT2 + if (dpyinfo->supports_xi2) + FRAME_X_OUTPUT (f)->xi_masks + = XIGetSelectedEvents (dpyinfo->display, FRAME_X_WINDOW (f), + &FRAME_X_OUTPUT (f)->num_xi_masks); +#endif + /* Now consider the frame official. */ f->terminal->reference_count++; FRAME_DISPLAY_INFO (f)->reference_count++; diff --git a/src/xmenu.c b/src/xmenu.c index d19fe13c295..94cd9dab69b 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -634,15 +634,15 @@ x_activate_menubar (struct frame *f) Otherwise some versions of Motif will emit a warning and hang, and lwlib will fail to destroy the menu window. */ - if (dpyinfo->num_devices) + if (dpyinfo->supports_xi2 + && xi_frame_selected_for (f, XI_ButtonPress)) { for (int i = 0; i < dpyinfo->num_devices; ++i) { if (dpyinfo->devices[i].grab) - { - XIUngrabDevice (dpyinfo->display, dpyinfo->devices[i].device_id, - CurrentTime); - } + XIUngrabDevice (dpyinfo->display, + dpyinfo->devices[i].device_id, + CurrentTime); } } #endif @@ -1528,7 +1528,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, } #if !defined HAVE_GTK3 && defined HAVE_XINPUT2 - if (FRAME_DISPLAY_INFO (f)->num_devices) + if (FRAME_DISPLAY_INFO (f)->supports_xi2 + && xi_frame_selected_for (f, XI_ButtonPress)) { for (int i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i) { @@ -1696,7 +1697,8 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, if (dpyinfo->supports_xi2) XGrabServer (dpyinfo->display); - if (dpyinfo->num_devices) + if (dpyinfo->supports_xi2 + && xi_frame_selected_for (f, XI_ButtonPress)) { for (int i = 0; i < dpyinfo->num_devices; ++i) { @@ -2677,7 +2679,8 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, struct x_display_info *dpyinfo = FRAME_DISPLAY_INFO (f); /* Clear the XI2 grab so a core grab can be set. */ - if (dpyinfo->num_devices) + if (dpyinfo->supports_xi2 + && xi_frame_selected_for (f, XI_ButtonPress)) { for (int i = 0; i < dpyinfo->num_devices; ++i) { diff --git a/src/xterm.c b/src/xterm.c index 367659d3c1c..94f8ce33bb0 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -3704,6 +3704,29 @@ record_event (char *locus, int type) #endif +#ifdef HAVE_XINPUT2 +bool +xi_frame_selected_for (struct frame *f, unsigned long event) +{ + XIEventMask *masks; + int i; + + masks = FRAME_X_OUTPUT (f)->xi_masks; + + if (!masks) + return false; + + for (i = 0; i < FRAME_X_OUTPUT (f)->num_xi_masks; ++i) + { + if (masks[i].mask_len >= XIMaskLen (event) + && XIMaskIsSet (masks[i].mask, event)) + return true; + } + + return false; +} +#endif + static void x_toolkit_position (struct frame *f, int x, int y, bool *menu_bar_p, bool *tool_bar_p) @@ -3886,8 +3909,7 @@ xi_populate_device_from_info (struct xi_device_t *xi_device, xi_device->touchpoints = NULL; #endif - xi_device->master_p = (device->use == XIMasterKeyboard - || device->use == XIMasterPointer); + xi_device->use = device->use; #ifdef HAVE_XINPUT2_2 xi_device->direct_p = false; #endif @@ -9559,7 +9581,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, the root window, so we can get notified when window stacking changes, a common operation during drag-and-drop. */ - block_input (); XGetWindowAttributes (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, &root_window_attrs); @@ -9581,6 +9602,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, current_hold_quit = &hold_quit; #endif + block_input (); #ifdef USE_GTK gtk_main_iteration (); #else @@ -9612,6 +9634,7 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, &next_event, &finish, &hold_quit); #endif #endif + unblock_input (); if (x_dnd_movement_frame) { @@ -9712,7 +9735,6 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, XSelectInput (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, root_window_attrs.your_event_mask); - unblock_input (); quit (); } } @@ -9725,11 +9747,11 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction, #endif x_dnd_movement_frame = NULL; + block_input (); /* Restore the old event mask. */ XSelectInput (FRAME_X_DISPLAY (f), FRAME_DISPLAY_INFO (f)->root_window, root_window_attrs.your_event_mask); - unblock_input (); if (x_dnd_return_frame == 3 @@ -18024,8 +18046,7 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (info) { if (device && info->enabled) - device->master_p = (info->use == XIMasterKeyboard - || info->use == XIMasterPointer); + device->use = info->use; else if (device) disabled[n_disabled++] = hev->info[i].deviceid; @@ -21666,9 +21687,6 @@ x_free_frame_resources (struct frame *f) #ifdef HAVE_X_I18N if (FRAME_XIC (f)) free_frame_xic (f); - - if (f->output_data.x->preedit_chars) - xfree (f->output_data.x->preedit_chars); #endif #ifdef USE_CAIRO @@ -21821,6 +21839,17 @@ x_destroy_window (struct frame *f) xfree (f->output_data.x->saved_menu_event); xfree (f->output_data.x); + +#ifdef HAVE_X_I18N + if (f->output_data.x->preedit_chars) + xfree (f->output_data.x->preedit_chars); +#endif + +#ifdef HAVE_XINPUT2 + if (f->output_data.x->xi_masks) + XFree (f->output_data.x->xi_masks); +#endif + f->output_data.x = NULL; dpyinfo->reference_count--; diff --git a/src/xterm.h b/src/xterm.h index 75094082683..defeaacc0d7 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -232,8 +232,7 @@ struct xi_device_t #ifdef HAVE_XINPUT2_1 int scroll_valuator_count; #endif - int grab; - bool master_p; + int grab, use; #ifdef HAVE_XINPUT2_2 bool direct_p; #endif @@ -977,6 +976,11 @@ struct x_output bool preedit_active; int preedit_caret; #endif + +#ifdef HAVE_XINPUT2 + XIEventMask *xi_masks; + int num_xi_masks; +#endif }; enum @@ -1571,6 +1575,7 @@ extern struct frame *x_dnd_frame; #ifdef HAVE_XINPUT2 struct xi_device_t *xi_device_from_id (struct x_display_info *, int); +bool xi_frame_selected_for (struct frame *, unsigned long); #endif extern void mark_xterm (void); -- 2.39.5