x11: Improve XGenericEventCookie data allocation

https://bugzilla.gnome.org/show_bug.cgi?id=654656

Clutter may be used together with GTK+, which indirectly may use
XInput2 too, so the cookie data must persist when both are handling
events.

What happens now in a nutshell is, Clutter is only guaranteed to allocate
the cookie itself after XNextEvent(), and only frees the cookie if its
XGetEventData() call allocated the cookie data.

The X[Get|Free]EventData() calls happen now in clutter-event-x11.c as
hypothetically different event translators could also handle other set
of X Generic Events, or other libraries handling events for that matter.
This commit is contained in:
Carlos Garnacho 2011-07-14 21:58:25 +02:00
parent c6a0427c69
commit 075a4ed86c
3 changed files with 46 additions and 13 deletions

View File

@ -562,27 +562,21 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
cookie = &xevent->xcookie; cookie = &xevent->xcookie;
if (!XGetEventData (backend_x11->xdpy, cookie))
return CLUTTER_TRANSLATE_CONTINUE;
if (cookie->type != GenericEvent || if (cookie->type != GenericEvent ||
cookie->extension != manager_xi2->opcode) cookie->extension != manager_xi2->opcode)
{ return CLUTTER_TRANSLATE_CONTINUE;
XFreeEventData (backend_x11->xdpy, cookie);
return CLUTTER_TRANSLATE_CONTINUE;
}
xi_event = (XIEvent *) cookie->data; xi_event = (XIEvent *) cookie->data;
if (!xi_event)
return CLUTTER_TRANSLATE_REMOVE;
if (!(xi_event->evtype == XI_HierarchyChanged || if (!(xi_event->evtype == XI_HierarchyChanged ||
xi_event->evtype == XI_DeviceChanged)) xi_event->evtype == XI_DeviceChanged))
{ {
stage = get_event_stage (translator, xi_event); stage = get_event_stage (translator, xi_event);
if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage)) if (stage == NULL || CLUTTER_ACTOR_IN_DESTRUCTION (stage))
{ return CLUTTER_TRANSLATE_CONTINUE;
XFreeEventData (backend_x11->xdpy, cookie);
return CLUTTER_TRANSLATE_CONTINUE;
}
else else
stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage)); stage_x11 = CLUTTER_STAGE_X11 (_clutter_stage_get_window (stage));
} }
@ -902,8 +896,6 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator,
break; break;
} }
XFreeEventData (backend_x11->xdpy, cookie);
return retval; return retval;
} }

View File

@ -240,10 +240,17 @@ events_queue (ClutterBackend *backend)
event = clutter_event_new (CLUTTER_NOTHING); event = clutter_event_new (CLUTTER_NOTHING);
#ifdef HAVE_XGE
XGetEventData (xdisplay, &xevent.xcookie);
#endif
if (_clutter_backend_translate_event (backend, &xevent, event)) if (_clutter_backend_translate_event (backend, &xevent, event))
_clutter_event_push (event, FALSE); _clutter_event_push (event, FALSE);
else else
clutter_event_free (event); clutter_event_free (event);
#ifdef HAVE_XGE
XFreeEventData (xdisplay, &xevent.xcookie);
#endif
} }
} }
@ -273,8 +280,13 @@ clutter_x11_handle_event (XEvent *xevent)
{ {
ClutterX11FilterReturn result; ClutterX11FilterReturn result;
ClutterBackend *backend; ClutterBackend *backend;
ClutterBackendX11 *backend_x11;
Display *xdisplay;
ClutterEvent *event; ClutterEvent *event;
gint spin = 1; gint spin = 1;
#ifdef HAVE_XGE
gboolean allocated_event;
#endif
/* The return values here are someone approximate; we return /* The return values here are someone approximate; we return
* CLUTTER_X11_FILTER_REMOVE if a clutter event is * CLUTTER_X11_FILTER_REMOVE if a clutter event is
@ -290,9 +302,15 @@ clutter_x11_handle_event (XEvent *xevent)
clutter_threads_enter (); clutter_threads_enter ();
backend = clutter_get_default_backend (); backend = clutter_get_default_backend ();
backend_x11 = CLUTTER_BACKEND_X11 (backend);
xdisplay = backend_x11->xdpy;
event = clutter_event_new (CLUTTER_NOTHING); event = clutter_event_new (CLUTTER_NOTHING);
#ifdef HAVE_XGE
allocated_event = XGetEventData (xdisplay, &xevent->xcookie);
#endif
if (_clutter_backend_translate_event (backend, xevent, event)) if (_clutter_backend_translate_event (backend, xevent, event))
{ {
_clutter_event_push (event, FALSE); _clutter_event_push (event, FALSE);
@ -323,6 +341,11 @@ clutter_x11_handle_event (XEvent *xevent)
} }
out: out:
#ifdef HAVE_XGE
if (allocated_event)
XFreeEventData (xdisplay, &xevent->xcookie);
#endif
clutter_threads_leave (); clutter_threads_leave ();
return result; return result;

View File

@ -592,6 +592,23 @@ AS_IF([test "x$SUPPORT_XLIB" = "x1"],
[AC_MSG_ERROR([not found])] [AC_MSG_ERROR([not found])]
) )
# X Generic Extensions (optional)
clutter_save_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $X11_CFLAGS"
clutter_save_LIBS="$LIBS"
LIBS="$LIBS $X11_LIBS"
have_xge=no
AC_CHECK_FUNC([XGetEventData],
[
AC_DEFINE(HAVE_XGE, 1, [Define to 1 if X Generic Extensions is available])
have_xge=yes
])
CPPFLAGS="$clutter_save_CPPFLAGS"
LIBS="$clutter_save_LIBS"
# XI (optional) # XI (optional)
AC_ARG_ENABLE([xinput], AC_ARG_ENABLE([xinput],
[AS_HELP_STRING([--enable-xinput], [Use the XI X extension])], [AS_HELP_STRING([--enable-xinput], [Use the XI X extension])],
@ -1020,6 +1037,7 @@ fi
if test "x$SUPPORT_XLIB" = "x1"; then if test "x$SUPPORT_XLIB" = "x1"; then
echo " Enable XComposite: ${have_xcomposite}" echo " Enable XComposite: ${have_xcomposite}"
echo " Enable XInput: ${have_xinput}" echo " Enable XInput: ${have_xinput}"
echo " Enable Xge: ${have_xge}"
echo " Enable XI2: ${have_xinput2}" echo " Enable XI2: ${have_xinput2}"
echo " Enable XKB: ${have_xkb}" echo " Enable XKB: ${have_xkb}"
echo " Enable X11 tests: ${x11_tests}" echo " Enable X11 tests: ${x11_tests}"