{
eassert (!event->xcookie.data);
- if (XGetEventData (dpyinfo->display, &event->xcookie))
+ switch (event->xcookie.evtype)
{
- 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 = xi_convert_event_state (xev);
- copy.xbutton.button = xev->detail;
- copy.xbutton.same_screen = True;
-
- device = xi_device_from_id (dpyinfo, xev->deviceid);
-
- /* I don't know the repercussions of changing
- device->grab on XI_ButtonPress events, so be safe and
- only do what is necessary to prevent the grab from
- being left invalid as XMenuActivate swallows
- events. */
- if (device && xev->evtype == XI_ButtonRelease)
- device->grab &= ~(1 << xev->detail);
-
- XPutBackEvent (dpyinfo->display, ©);
-
- break;
- }
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+
+ if (!XGetEventData (dpyinfo->display, &event->xcookie))
+ break;
+
+ 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 = xi_convert_event_state (xev);
+ copy.xbutton.button = xev->detail;
+ copy.xbutton.same_screen = True;
+
+ device = xi_device_from_id (dpyinfo, xev->deviceid);
+
+ /* I don't know the repercussions of changing
+ device->grab on XI_ButtonPress events, so be safe and
+ only do what is necessary to prevent the grab from
+ being left invalid as XMenuActivate swallows
+ events. */
+ if (device && xev->evtype == XI_ButtonRelease)
+ device->grab &= ~(1 << xev->detail);
+
+ XPutBackEvent (dpyinfo->display, ©);
XFreeEventData (dpyinfo->display, &event->xcookie);
+
+ break;
+
+ case XI_HierarchyChanged:
+ case XI_DeviceChanged:
+ /* These events must always be handled. */
+ x_dispatch_event (event, dpyinfo->display);
+ break;
}
}
}
DEFER_SELECTIONS;
XMenuActivateSetWaitFunction (x_menu_wait_for_event, FRAME_X_DISPLAY (f));
+ /* When the input extension is in use, the owner_events grab will
+ report extension events on frames, which the XMenu library does
+ not normally understand. */
#ifdef HAVE_XINPUT2
XMenuActivateSetTranslateFunction (x_menu_translate_generic_event);
#endif
bool must_free_data = false;
XIEvent *xi_event = (XIEvent *) event->xcookie.data;
+
/* Sometimes the event is already claimed by GTK, which
will free its data in due course. */
- if (!xi_event && XGetEventData (dpyinfo->display, &event->xcookie))
+ if (!xi_event)
{
- must_free_data = true;
+ if (XGetEventData (dpyinfo->display, &event->xcookie))
+ must_free_data = true;
+
xi_event = (XIEvent *) event->xcookie.data;
}
if (!xi_event)
{
- eassert (!must_free_data);
+ /* It may turn out that the event data has already been
+ implicitly freed for various reasons up to and
+ including XMenuActivate pushing some other event onto
+ the foreign-event queue, or x_menu_wait_for_events
+ calling XNextEvent through a timer that tries to wait
+ for input.
+
+ In that case, XGetEventData will return True, but
+ cookie->data will be NULL. Since handling such input
+ events is not really important, we can afford to
+ discard them.
+
+ The way Xlib is currently implemented makes calling
+ XFreeEventData unnecessary in this case, but call it
+ anyway, since not doing so may lead to a memory leak in
+ the future. */
+
+ if (must_free_data)
+ XFreeEventData (dpyinfo->display, &event->xcookie);
goto OTHER;
}