From: Po Lu Date: Wed, 9 Mar 2022 13:29:17 +0000 (+0800) Subject: Make XInput 2 features work on GTK 2 builds X-Git-Tag: emacs-29.0.90~1941 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=fe8d49e1add8421afb16f5666bdbbabc7704f9c1;p=emacs.git Make XInput 2 features work on GTK 2 builds * src/xfns.c (setup_xi_event_mask): On GTK 2, select for button, motion, entry/exit and key events. * src/xmenu.c (create_and_show_popup_menu): Clear XI grab if appropriate. * src/xterm.c (handle_one_xevent): Pass some kinds of input extension events to GTK manually on versions of GTK+ that don't understand them. --- diff --git a/src/xfns.c b/src/xfns.c index cf5823c645b..a3236efbcc6 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -3579,7 +3579,7 @@ setup_xi_event_mask (struct frame *f) mask.mask_len = l; block_input (); -#ifndef USE_GTK +#ifndef HAVE_GTK3 mask.deviceid = XIAllMasterDevices; XISetMask (m, XI_ButtonPress); @@ -3587,8 +3587,10 @@ setup_xi_event_mask (struct frame *f) XISetMask (m, XI_Motion); XISetMask (m, XI_Enter); XISetMask (m, XI_Leave); +#ifndef USE_GTK XISetMask (m, XI_FocusIn); XISetMask (m, XI_FocusOut); +#endif XISetMask (m, XI_KeyPress); XISetMask (m, XI_KeyRelease); XISelectEvents (FRAME_X_DISPLAY (f), @@ -3596,7 +3598,7 @@ setup_xi_event_mask (struct frame *f) &mask, 1); memset (m, 0, l); -#endif /* !USE_GTK */ +#endif /* !HAVE_GTK3 */ #ifdef USE_X_TOOLKIT XISetMask (m, XI_KeyPress); diff --git a/src/xmenu.c b/src/xmenu.c index 4d0e5bd81c2..d19fe13c295 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -1527,6 +1527,23 @@ create_and_show_popup_menu (struct frame *f, widget_value *first_wv, if (i == 5) i = 0; } +#if !defined HAVE_GTK3 && defined HAVE_XINPUT2 + if (FRAME_DISPLAY_INFO (f)->num_devices) + { + for (int i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i) + { + if (FRAME_DISPLAY_INFO (f)->devices[i].grab) + { + FRAME_DISPLAY_INFO (f)->devices[i].grab = 0; + + XIUngrabDevice (FRAME_X_DISPLAY (f), + FRAME_DISPLAY_INFO (f)->devices[i].device_id, + CurrentTime); + } + } + } +#endif + /* Display the menu. */ gtk_widget_show_all (menu); diff --git a/src/xterm.c b/src/xterm.c index 772a9238a7e..68f7588af4a 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -10021,6 +10021,9 @@ handle_one_xevent (struct x_display_info *dpyinfo, being passed to XtDispatchEvent. */ bool use_copy = false; XEvent copy; +#elif defined USE_GTK && !defined HAVE_GTK3 && defined HAVE_XINPUT2 + GdkEvent *copy = NULL; + GdkDisplay *gdpy = gdk_x11_lookup_xdisplay (dpyinfo->display); #endif *finish = X_EVENT_NORMAL; @@ -12186,6 +12189,20 @@ handle_one_xevent (struct x_display_info *dpyinfo, { x_display_set_last_user_time (dpyinfo, xev->time); +#if defined USE_GTK && !defined HAVE_GTK3 + /* Unlike on Motif, we can't select for XI + events on the scroll bar window under GTK+ 2. + So instead of that, just ignore XI wheel + events which land on a scroll bar. + + Here we assume anything which isn't the edit + widget window is a scroll bar. */ + + if (xev->child != None + && xev->child != FRAME_X_WINDOW (f)) + goto OTHER; +#endif + if (fabs (total_x) > 0 || fabs (total_y) > 0) { inev.ie.kind = (fabs (total_y) >= fabs (total_x) @@ -12390,6 +12407,37 @@ handle_one_xevent (struct x_display_info *dpyinfo, if (XIMaskIsSet (xev->buttons.mask, 3)) copy.xbutton.state |= Button3Mask; } +#elif defined USE_GTK && !defined HAVE_GTK3 + copy = gdk_event_new (xev->evtype == XI_ButtonPress + ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE); + + copy->button.window = gdk_x11_window_lookup_for_display (gdpy, xev->event); + copy->button.send_event = xev->send_event; + copy->button.time = xev->time; + copy->button.x = xev->event_x; + copy->button.y = xev->event_y; + copy->button.x_root = xev->root_x; + copy->button.y_root = xev->root_y; + copy->button.state = xev->mods.effective; + copy->button.button = xev->detail; + + if (xev->buttons.mask_len) + { + if (XIMaskIsSet (xev->buttons.mask, 1)) + copy->button.state |= GDK_BUTTON1_MASK; + if (XIMaskIsSet (xev->buttons.mask, 2)) + copy->button.state |= GDK_BUTTON2_MASK; + if (XIMaskIsSet (xev->buttons.mask, 3)) + copy->button.state |= GDK_BUTTON3_MASK; + } + + if (!copy->button.window) + emacs_abort (); + + g_object_ref (copy->button.window); + + gtk_main_do_event (copy); + gdk_event_free (copy); #endif #ifdef HAVE_XINPUT2_1