From db9b9435cddb1201bc57c65f44f90208e7047582 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Tue, 1 Mar 2022 14:44:02 +0800 Subject: [PATCH] Fix old X menu on builds with XI2 * oldXMenu/Activate.c (XMenuActivateSetTranslateFunction): New function. (XMenuActivate): Handle generic events. * oldXMenu/XMenu.h: New prototypes. (Translate_func): New type. * src/xmenu.c (x_menu_wait_translate_generic_event): New function. (x_menu_show): Set translate function. --- oldXMenu/Activate.c | 13 ++++++++++ oldXMenu/XMenu.h | 6 +++++ src/xmenu.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) diff --git a/oldXMenu/Activate.c b/oldXMenu/Activate.c index 646631df84b..447b7398ca2 100644 --- a/oldXMenu/Activate.c +++ b/oldXMenu/Activate.c @@ -121,6 +121,7 @@ int x_menu_grab_keyboard = 1; static Wait_func wait_func; static void* wait_data; +static Translate_func translate_func = NULL; void XMenuActivateSetWaitFunction (Wait_func func, void *data) @@ -129,6 +130,12 @@ XMenuActivateSetWaitFunction (Wait_func func, void *data) wait_data = data; } +void +XMenuActivateSetTranslateFunction (Translate_func func) +{ + translate_func = func; +} + int XMenuActivate( register Display *display, /* Display to put menu on. */ @@ -515,6 +522,12 @@ XMenuActivate( feq = feq_tmp; } else if (_XMEventHandler) (*_XMEventHandler)(&event); + break; +#ifdef HAVE_XINPUT2 + case GenericEvent: + if (translate_func) + translate_func (&event); +#endif } /* * If a selection has been made, break out of the event loop. diff --git a/oldXMenu/XMenu.h b/oldXMenu/XMenu.h index 50ea6834090..2eee18a3844 100644 --- a/oldXMenu/XMenu.h +++ b/oldXMenu/XMenu.h @@ -255,6 +255,11 @@ typedef struct _xmenu { typedef void (*Wait_func)(void*); +/* Function for translating GenericEvents. It is should call + XPutBackEvent on an equivalent artificial core event on any + function it wants to translate. */ +typedef void (*Translate_func)(XEvent *); + /* * XMenu library routine declarations. */ @@ -274,6 +279,7 @@ void XMenuEventHandler(int (*handler) (XEvent *)); int XMenuLocate(Display *display, XMenu *menu, int p_num, int s_num, int x_pos, int y_pos, int *ul_x, int *ul_y, int *width, int *height); void XMenuSetFreeze(XMenu *menu, int freeze); void XMenuActivateSetWaitFunction(Wait_func func, void *data); +void XMenuActivateSetTranslateFunction(Translate_func func); int XMenuActivate(Display *display, XMenu *menu, int *p_num, int *s_num, int x_pos, int y_pos, unsigned int event_mask, char **data, void (*help_callback) (char const *, int, int)); char *XMenuPost(Display *display, XMenu *menu, int *p_num, int *s_num, int x_pos, int y_pos, int event_mask); int XMenuDeletePane(Display *display, XMenu *menu, int p_num); diff --git a/src/xmenu.c b/src/xmenu.c index e483c8f73b0..fb80221e15b 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -222,6 +222,64 @@ x_menu_wait_for_event (void *data) #endif } } + +#if !defined USE_GTK && !defined USE_X_TOOLKIT && defined HAVE_XINPUT2 +static void +x_menu_translate_generic_event (XEvent *event) +{ + struct x_display_info *dpyinfo; + XEvent copy; + XIDeviceEvent *xev; + + dpyinfo = x_display_info_for_display (event->xgeneric.display); + + if (event->xgeneric.extension == dpyinfo->xi2_opcode) + { + eassert (!event->xcookie.data); + + if (XGetEventData (dpyinfo->display, &event->xcookie)) + { + switch (event->xcookie.evtype) + { + case XI_ButtonPress: + case XI_ButtonRelease: + xev = (XIDeviceEvent *) event->xcookie.data; + copy.xbutton.type = (event->xcookie.evtype == XI_ButtonPress + ? ButtonPress : ButtonRelease); + copy.xbutton.serial = xev->serial; + copy.xbutton.send_event = xev->send_event; + copy.xbutton.display = dpyinfo->display; + copy.xbutton.window = xev->event; + copy.xbutton.root = xev->root; + copy.xbutton.subwindow = xev->child; + copy.xbutton.time = xev->time; + copy.xbutton.x = lrint (xev->event_x); + copy.xbutton.y = lrint (xev->event_y); + copy.xbutton.x_root = lrint (xev->root_x); + copy.xbutton.y_root = lrint (xev->root_y); + copy.xbutton.state = xev->mods.effective; + copy.xbutton.button = xev->detail; + copy.xbutton.same_screen = True; + + if (xev->buttons.mask_len) + { + if (XIMaskIsSet (xev->buttons.mask, 1)) + copy.xbutton.state |= Button1Mask; + if (XIMaskIsSet (xev->buttons.mask, 2)) + copy.xbutton.state |= Button2Mask; + if (XIMaskIsSet (xev->buttons.mask, 3)) + copy.xbutton.state |= Button3Mask; + } + + XPutBackEvent (dpyinfo->display, ©); + + break; + } + XFreeEventData (dpyinfo->display, &event->xcookie); + } + } +} +#endif #endif /* ! MSDOS */ @@ -2568,6 +2626,9 @@ x_menu_show (struct frame *f, int x, int y, int menuflags, #ifndef MSDOS XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f)); +#ifdef HAVE_XINPUT2 + XMenuActivateSetTranslateFunction (x_menu_translate_generic_event); +#endif #endif record_unwind_protect_ptr (pop_down_menu, -- 2.39.5