&& 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);
{
KeySym keysym;
- if (!event.xcookie.data
- && XGetEventData (dpyinfo->display, &event.xcookie))
- cookie_claimed_p = true;
-
xev = (XIDeviceEvent *) event.xcookie.data;
copy.xkey.type = KeyPress;
{
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 ();
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;
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
#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);
#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;
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
{
/* 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);