gl/x11: use xcb instead of libX11

- xcb is supposedly thread-safe!

videotestsrc ! glimagesink now doesn't spuriously result in a
'call XInitThreads()' error however if anybody else is using X11,
then XInitThreads() still needs to be called and multiple glimagesink's
still need XInitThreads().

Everything still takes libX11 handles as they are compatible with the xcb
variants.  Unfortunately we cannot move fully over to xcb due to GLX being
entirely based on Xlib.  It's also impossible to transform a xcb_connection
to a Display which means we require X11 handles.
This commit is contained in:
Matthew Waters 2016-07-01 00:07:23 +10:00 committed by Tim-Philipp Müller
parent af493eb6b2
commit 0e56bead42
6 changed files with 270 additions and 201 deletions

View file

@ -5,11 +5,11 @@ noinst_LTLIBRARIES = libgstgl-x11.la
libgstgl_x11_la_SOURCES = \ libgstgl_x11_la_SOURCES = \
gstgldisplay_x11.c \ gstgldisplay_x11.c \
gstglwindow_x11.c \ gstglwindow_x11.c \
x11_event_source.c xcb_event_source.c
noinst_HEADERS = \ noinst_HEADERS = \
gstglwindow_x11.h \ gstglwindow_x11.h \
x11_event_source.h xcb_event_source.h
libgstgl_x11includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl/x11 libgstgl_x11includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl/x11
libgstgl_x11include_HEADERS = \ libgstgl_x11include_HEADERS = \

View file

@ -23,6 +23,8 @@
#endif #endif
#include <gst/gl/x11/gstgldisplay_x11.h> #include <gst/gl/x11/gstgldisplay_x11.h>
#include <gst/gl/x11/gstglwindow_x11.h>
#include "xcb_event_source.h"
GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
#define GST_CAT_DEFAULT gst_gl_display_debug #define GST_CAT_DEFAULT gst_gl_display_debug
@ -32,6 +34,10 @@ G_DEFINE_TYPE (GstGLDisplayX11, gst_gl_display_x11, GST_TYPE_GL_DISPLAY);
static void gst_gl_display_x11_finalize (GObject * object); static void gst_gl_display_x11_finalize (GObject * object);
static guintptr gst_gl_display_x11_get_handle (GstGLDisplay * display); static guintptr gst_gl_display_x11_get_handle (GstGLDisplay * display);
gboolean gst_gl_display_x11_handle_event (GstGLDisplayX11 * display_x11);
extern gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11,
xcb_generic_event_t * event);
static void static void
gst_gl_display_x11_class_init (GstGLDisplayX11Class * klass) gst_gl_display_x11_class_init (GstGLDisplayX11Class * klass)
{ {
@ -58,6 +64,7 @@ gst_gl_display_x11_finalize (GObject * object)
g_free (display_x11->name); g_free (display_x11->name);
if (!display_x11->foreign_display && display_x11->display) { if (!display_x11->foreign_display && display_x11->display) {
XSync (display_x11->display, FALSE);
XCloseDisplay (display_x11->display); XCloseDisplay (display_x11->display);
} }
@ -86,8 +93,23 @@ gst_gl_display_x11_new (const gchar * name)
if (!ret->display) { if (!ret->display) {
GST_ERROR ("Failed to open X11 display connection with name, \'%s\'", name); GST_ERROR ("Failed to open X11 display connection with name, \'%s\'", name);
gst_object_unref (ret);
return NULL;
} }
ret->xcb_connection = XGetXCBConnection (ret->display);
if (!ret->xcb_connection) {
GST_ERROR ("Failed to open retieve XCB connection from X11 Display");
gst_object_unref (ret);
return NULL;
}
XSetEventQueueOwner (ret->display, XCBOwnsEventQueue);
GST_GL_DISPLAY (ret)->event_source = xcb_event_source_new (ret);
g_source_attach (GST_GL_DISPLAY (ret)->event_source,
GST_GL_DISPLAY (ret)->main_context);
return ret; return ret;
} }
@ -112,6 +134,14 @@ gst_gl_display_x11_new_with_display (Display * display)
ret->name = g_strdup (DisplayString (display)); ret->name = g_strdup (DisplayString (display));
ret->display = display; ret->display = display;
ret->xcb_connection = XGetXCBConnection (ret->display);
if (!ret->xcb_connection) {
GST_ERROR ("Failed to open retieve XCB connection from X11 Display");
gst_object_unref (ret);
return NULL;
}
ret->foreign_display = TRUE; ret->foreign_display = TRUE;
return ret; return ret;
@ -122,3 +152,85 @@ gst_gl_display_x11_get_handle (GstGLDisplay * display)
{ {
return (guintptr) GST_GL_DISPLAY_X11 (display)->display; return (guintptr) GST_GL_DISPLAY_X11 (display)->display;
} }
static int
_compare_xcb_window (GstGLWindowX11 * window_x11, xcb_window_t * window_id)
{
return window_x11->internal_win_id - *window_id;
}
static GstGLWindowX11 *
_find_window_from_xcb_window (GstGLDisplayX11 * display_x11,
xcb_window_t window_id)
{
GstGLDisplay *display = GST_GL_DISPLAY (display_x11);
GstGLWindowX11 *ret = NULL;
GList *l;
if (!window_id)
return NULL;
GST_OBJECT_LOCK (display);
l = g_list_find_custom (display->windows, &window_id,
(GCompareFunc) _compare_xcb_window);
if (l)
ret = gst_object_ref (l->data);
GST_OBJECT_UNLOCK (display);
return ret;
}
static GstGLWindowX11 *
_window_from_event (GstGLDisplayX11 * display_x11, xcb_generic_event_t * event)
{
uint8_t event_code = event->response_type & 0x7f;
switch (event_code) {
/* *INDENT-OFF* */
#define WIN_FROM_EVENT(case_val,event_type,window_field) \
case case_val:{ \
event_type * real_event = (event_type *) event; \
return _find_window_from_xcb_window (display_x11, real_event->window_field); \
}
WIN_FROM_EVENT (XCB_CLIENT_MESSAGE, xcb_client_message_event_t, window)
WIN_FROM_EVENT (XCB_CONFIGURE_NOTIFY, xcb_configure_notify_event_t, window)
WIN_FROM_EVENT (XCB_EXPOSE, xcb_expose_event_t, window)
WIN_FROM_EVENT (XCB_KEY_PRESS, xcb_key_press_event_t, event)
WIN_FROM_EVENT (XCB_KEY_RELEASE, xcb_key_release_event_t, event)
WIN_FROM_EVENT (XCB_BUTTON_PRESS, xcb_button_press_event_t, event)
WIN_FROM_EVENT (XCB_BUTTON_RELEASE, xcb_button_release_event_t, event)
WIN_FROM_EVENT (XCB_MOTION_NOTIFY, xcb_motion_notify_event_t, event)
#undef WIN_FROM_EVENT
/* *INDENT-ON* */
default:
return NULL;
}
}
gboolean
gst_gl_display_x11_handle_event (GstGLDisplayX11 * display_x11)
{
xcb_connection_t *connection = display_x11->xcb_connection;
xcb_generic_event_t *event;
gboolean ret = TRUE;
while ((event = xcb_poll_for_event (connection))) {
GstGLWindowX11 *window_x11 = _window_from_event (display_x11, event);
GST_TRACE_OBJECT (display_x11, "got event %p to window %" GST_PTR_FORMAT,
event, window_x11);
if (window_x11) {
ret = gst_gl_window_x11_handle_event (window_x11, event);
} else {
/* unknown window, ignore */
ret = TRUE;
}
if (window_x11)
gst_object_unref (window_x11);
g_free (event);
}
return ret;
}

View file

@ -23,8 +23,7 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <X11/Xlib.h> #include <X11/Xlib-xcb.h>
#include <X11/Xutil.h>
#include <gst/gl/gstgl_fwd.h> #include <gst/gl/gstgl_fwd.h>
#include <gst/gl/gstgldisplay.h> #include <gst/gl/gstgldisplay.h>
@ -56,6 +55,7 @@ struct _GstGLDisplayX11
/* <private> */ /* <private> */
gchar *name; gchar *name;
Display *display; Display *display;
xcb_connection_t *xcb_connection;
gboolean foreign_display; gboolean foreign_display;
gpointer _padding[GST_PADDING]; gpointer _padding[GST_PADDING];

View file

@ -28,7 +28,6 @@
#include <gst/gst.h> #include <gst/gst.h>
#include <locale.h> #include <locale.h>
#include "x11_event_source.h"
#include "gstglwindow_x11.h" #include "gstglwindow_x11.h"
#include "gstgldisplay_x11.h" #include "gstgldisplay_x11.h"
/* for XkbKeycodeToKeysym */ /* for XkbKeycodeToKeysym */
@ -42,12 +41,13 @@
#define gst_gl_window_x11_parent_class parent_class #define gst_gl_window_x11_parent_class parent_class
G_DEFINE_TYPE (GstGLWindowX11, gst_gl_window_x11, GST_TYPE_GL_WINDOW); G_DEFINE_TYPE (GstGLWindowX11, gst_gl_window_x11, GST_TYPE_GL_WINDOW);
gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11,
xcb_generic_event_t * event);
/* X error trap */ /* X error trap */
static int TrappedErrorCode = 0; static int TrappedErrorCode = 0;
static int (*old_error_handler) (Display *, XErrorEvent *); static int (*old_error_handler) (Display *, XErrorEvent *);
gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11);
enum enum
{ {
ARG_0, ARG_0,
@ -139,8 +139,8 @@ gst_gl_window_x11_open (GstGLWindow * window, GError ** error)
GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window);
GstGLDisplayX11 *display_x11 = (GstGLDisplayX11 *) window->display; GstGLDisplayX11 *display_x11 = (GstGLDisplayX11 *) window->display;
window_x11->device = XOpenDisplay (display_x11->name); window_x11->device = display_x11->display;
// window_x11->device = display_x11->display; // window_x11->device = XOpenDisplay (display_x11->name);
if (window_x11->device == NULL) { if (window_x11->device == NULL) {
g_set_error (error, GST_GL_WINDOW_ERROR, g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
@ -148,8 +148,6 @@ gst_gl_window_x11_open (GstGLWindow * window, GError ** error)
goto failure; goto failure;
} }
XSynchronize (window_x11->device, FALSE);
GST_LOG ("gl device id: %ld", (gulong) window_x11->device); GST_LOG ("gl device id: %ld", (gulong) window_x11->device);
window_x11->screen = DefaultScreenOfDisplay (window_x11->device); window_x11->screen = DefaultScreenOfDisplay (window_x11->device);
@ -168,18 +166,9 @@ gst_gl_window_x11_open (GstGLWindow * window, GError ** error)
window_x11->device_height = window_x11->device_height =
DisplayHeight (window_x11->device, window_x11->screen_num); DisplayHeight (window_x11->device, window_x11->screen_num);
if (!GST_GL_WINDOW_CLASS (parent_class)->open (window, error))
return FALSE;
if (!display_x11->foreign_display) {
window_x11->x11_source = x11_event_source_new (window_x11);
g_source_attach (window_x11->x11_source,
g_main_context_get_thread_default ());
}
window_x11->allow_extra_expose_events = TRUE; window_x11->allow_extra_expose_events = TRUE;
return TRUE; return GST_GL_WINDOW_CLASS (parent_class)->open (window, error);
failure: failure:
return FALSE; return FALSE;
@ -265,39 +254,18 @@ void
gst_gl_window_x11_close (GstGLWindow * window) gst_gl_window_x11_close (GstGLWindow * window)
{ {
GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window);
GstGLDisplay *display = window->display;
XEvent event;
if (window_x11->device) { if (window_x11->device) {
/* Avoid BadDrawable Errors... */ if (window_x11->internal_win_id) {
if (gst_gl_display_get_handle_type (display) & GST_GL_DISPLAY_TYPE_X11)
XSync (GST_GL_DISPLAY_X11 (display)->display, FALSE);
if (window_x11->internal_win_id)
XUnmapWindow (window_x11->device, window_x11->internal_win_id); XUnmapWindow (window_x11->device, window_x11->internal_win_id);
XFree (window_x11->visual_info);
if (window_x11->internal_win_id) {
XReparentWindow (window_x11->device, window_x11->internal_win_id,
window_x11->root, 0, 0);
XDestroyWindow (window_x11->device, window_x11->internal_win_id); XDestroyWindow (window_x11->device, window_x11->internal_win_id);
} }
XSync (window_x11->device, FALSE); XFree (window_x11->visual_info);
while (XPending (window_x11->device))
XNextEvent (window_x11->device, &event);
XCloseDisplay (window_x11->device);
GST_DEBUG ("display receiver closed"); GST_DEBUG ("display receiver closed");
} }
if (window_x11->x11_source) {
g_source_destroy (window_x11->x11_source);
g_source_unref (window_x11->x11_source);
window_x11->x11_source = NULL;
}
window_x11->running = FALSE; window_x11->running = FALSE;
GST_GL_WINDOW_CLASS (parent_class)->close (window); GST_GL_WINDOW_CLASS (parent_class)->close (window);
@ -308,24 +276,25 @@ void
gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr id) gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr id)
{ {
GstGLWindowX11 *window_x11; GstGLWindowX11 *window_x11;
XWindowAttributes attr; gint width, height;
window_x11 = GST_GL_WINDOW_X11 (window); window_x11 = GST_GL_WINDOW_X11 (window);
window_x11->parent_win = (Window) id; window_x11->parent_win = (Window) id;
/* XXX: seems to be needed for the difference between gtk videooverlay and if (window_x11->parent_win) {
* the embedding gl into gtk directly */ XWindowAttributes attr;
if (id && !window_x11->x11_source) {
window_x11->x11_source = x11_event_source_new (window_x11); XGetWindowAttributes (window_x11->device, window_x11->parent_win, &attr);
g_source_attach (window_x11->x11_source, width = attr.width;
g_main_context_get_thread_default ()); height = attr.height;
} else {
width = window_x11->priv->preferred_width;
height = window_x11->priv->preferred_height;
} }
XGetWindowAttributes (window_x11->device, window_x11->parent_win, &attr);
XResizeWindow (window_x11->device, window_x11->internal_win_id, XResizeWindow (window_x11->device, window_x11->internal_win_id,
attr.width, attr.height); width, height);
XReparentWindow (window_x11->device, window_x11->internal_win_id, XReparentWindow (window_x11->device, window_x11->internal_win_id,
window_x11->parent_win, 0, 0); window_x11->parent_win, 0, 0);
@ -359,21 +328,15 @@ _show_window (GstGLWindow * window)
GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window);
guint width = window_x11->priv->preferred_width; guint width = window_x11->priv->preferred_width;
guint height = window_x11->priv->preferred_height; guint height = window_x11->priv->preferred_height;
XWindowAttributes attr;
XGetWindowAttributes (window_x11->device, window_x11->internal_win_id, &attr);
if (!window_x11->visible) { if (!window_x11->visible) {
if (!window_x11->parent_win) { if (!window_x11->parent_win) {
attr.width = width;
attr.height = height;
XResizeWindow (window_x11->device, window_x11->internal_win_id, XResizeWindow (window_x11->device, window_x11->internal_win_id,
attr.width, attr.height); width, height);
XSync (window_x11->device, FALSE);
} }
XMapWindow (window_x11->device, window_x11->internal_win_id); XMapWindow (window_x11->device, window_x11->internal_win_id);
XSync (window_x11->device, FALSE);
window_x11->visible = TRUE; window_x11->visible = TRUE;
} }
} }
@ -384,6 +347,17 @@ gst_gl_window_x11_show (GstGLWindow * window)
gst_gl_window_send_message (window, (GstGLWindowCB) _show_window, window); gst_gl_window_send_message (window, (GstGLWindowCB) _show_window, window);
} }
static void
_context_draw (GstGLContext * context, GstGLWindow * window)
{
GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
window->draw (window->draw_data);
context_class->swap_buffers (context);
gst_object_unref (context);
}
static void static void
draw_cb (gpointer data) draw_cb (gpointer data)
{ {
@ -396,11 +370,14 @@ draw_cb (gpointer data)
XGetWindowAttributes (window_x11->device, window_x11->internal_win_id, XGetWindowAttributes (window_x11->device, window_x11->internal_win_id,
&attr); &attr);
GST_TRACE_OBJECT (window, "window size %ux%u", attr.width, attr.height);
if (window_x11->parent_win) { if (window_x11->parent_win) {
XWindowAttributes attr_parent; XWindowAttributes attr_parent;
XGetWindowAttributes (window_x11->device, window_x11->parent_win, XGetWindowAttributes (window_x11->device, window_x11->parent_win,
&attr_parent); &attr_parent);
GST_TRACE_OBJECT (window, "parent window size %ux%u", attr_parent.width,
attr_parent.height);
if (attr.width != attr_parent.width || attr.height != attr_parent.height) { if (attr.width != attr_parent.width || attr.height != attr_parent.height) {
XMoveResizeWindow (window_x11->device, window_x11->internal_win_id, XMoveResizeWindow (window_x11->device, window_x11->internal_win_id,
@ -428,12 +405,8 @@ draw_cb (gpointer data)
if (window->draw) { if (window->draw) {
GstGLContext *context = gst_gl_window_get_context (window); GstGLContext *context = gst_gl_window_get_context (window);
GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
window->draw (window->draw_data); _context_draw (context, window);
context_class->swap_buffers (context);
gst_object_unref (context);
} }
} }
} }
@ -514,125 +487,105 @@ gst_gl_window_x11_handle_events (GstGLWindow * window, gboolean handle_events)
} }
gboolean gboolean
gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11) gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11,
xcb_generic_event_t * event)
{ {
GstGLContext *context; GstGLWindow *window = GST_GL_WINDOW (window_x11);
GstGLContextClass *context_class; GstGLDisplayX11 *display_x11 = GST_GL_DISPLAY_X11 (window->display);
GstGLWindow *window; xcb_connection_t *connection = display_x11->xcb_connection;
gboolean ret = TRUE; uint8_t event_code = event->response_type & 0x7f;
window = GST_GL_WINDOW (window_x11); switch (event_code) {
case XCB_CLIENT_MESSAGE:{
xcb_client_message_event_t *client_event;
xcb_intern_atom_cookie_t cookie;
xcb_intern_atom_reply_t *reply;
if (gst_gl_window_is_running (window) client_event = (xcb_client_message_event_t *) event;
&& XPending (window_x11->device)) { cookie = xcb_intern_atom (connection, 0, 16, "WM_DELETE_WINDOW");
XEvent event; reply = xcb_intern_atom_reply (connection, cookie, 0);
/* XSendEvent (which are called in other threads) are done from another display structure */ if (client_event->data.data32[0] == reply->atom) {
XNextEvent (window_x11->device, &event); GST_INFO_OBJECT (window_x11, "Close requested");
window_x11->allow_extra_expose_events = XPending (window_x11->device) <= 2; if (window->close)
window->close (window->close_data);
GST_LOG ("got event %s", event_type_to_string (event.type)); gst_gl_display_remove_window (GST_GL_DISPLAY (display_x11),
GST_GL_WINDOW (window_x11));
switch (event.type) {
case ClientMessage:
{
Atom wm_delete =
XInternAtom (window_x11->device, "WM_DELETE_WINDOW", True);
if (wm_delete == None)
GST_DEBUG ("Cannot create WM_DELETE_WINDOW");
/* User clicked on the cross */
if (wm_delete != None && (Atom) event.xclient.data.l[0] == wm_delete) {
GST_DEBUG ("Close %lud", (gulong) window_x11->internal_win_id);
if (window->close)
window->close (window->close_data);
ret = FALSE;
}
break;
} }
case CreateNotify: g_free (reply);
case ConfigureNotify: break;
{ }
gst_gl_window_resize (window, event.xconfigure.width, case XCB_CONFIGURE_NOTIFY:{
event.xconfigure.height); xcb_configure_notify_event_t *configure_event;
break;
}
case DestroyNotify: configure_event = (xcb_configure_notify_event_t *) event;
gst_gl_window_resize (window, configure_event->width,
configure_event->height);
gst_gl_window_draw (window);
break;
}
case XCB_EXPOSE:{
xcb_expose_event_t *expose_event = (xcb_expose_event_t *) event;
/* non-zero means that other Expose follows
* so just wait for the last one
* in theory we should not receive non-zero because
* we have no sub areas here but just in case */
if (expose_event->count != 0)
break; break;
case Expose: gst_gl_window_draw (window);
/* non-zero means that other Expose follows break;
* so just wait for the last one }
* in theory we should not receive non-zero because case XCB_KEY_PRESS:
* we have no sub areas here but just in case */ case XCB_KEY_RELEASE:{
if (event.xexpose.count != 0) { xcb_key_press_event_t *kp = (xcb_key_press_event_t *) event;
break; const gchar *event_type_str;
} gchar *key_str;
KeySym keysym;
/* We need to redraw on expose */ keysym = XkbKeycodeToKeysym (window_x11->device, kp->detail, 0, 0);
if (window->draw) { key_str = XKeysymToString (keysym);
context = gst_gl_window_get_context (window);
context_class = GST_GL_CONTEXT_GET_CLASS (context);
window->draw (window->draw_data); if (event_code == XCB_KEY_PRESS)
context_class->swap_buffers (context); event_type_str = "key-press";
else
event_type_str = "key-release";
gst_object_unref (context); gst_gl_window_send_key_event (window, event_type_str, key_str);
} break;
break; }
case XCB_BUTTON_PRESS:
case XCB_BUTTON_RELEASE:{
xcb_button_press_event_t *bp = (xcb_button_press_event_t *) event;
const gchar *event_type_str;
case VisibilityNotify: if (event_code == XCB_BUTTON_PRESS)
/* actually nothing to do here */ event_type_str = "mouse-button-press";
break; else
case KeyPress: event_type_str = "mouse-button-release";
case KeyRelease:
{
const char *key_str = NULL, *key_type = NULL;
KeySym keysym;
keysym = XkbKeycodeToKeysym (window_x11->device, gst_gl_window_send_mouse_event (window, event_type_str, bp->detail,
event.xkey.keycode, 0, 0); (double) bp->event_x, (double) bp->event_y);
key_str = XKeysymToString (keysym); break;
key_type = event.type == KeyPress ? "key-press" : "key-release"; }
GST_DEBUG ("input event key %d %s over window at %d,%d (%s)", case XCB_MOTION_NOTIFY:{
event.xkey.keycode, key_type, event.xkey.x, event.xkey.y, key_str); xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *) event;
gst_gl_window_send_key_event_async (window, key_type, key_str);
break;
}
case ButtonPress:
case ButtonRelease:{
const char *mouse_type = NULL;
mouse_type = event.type == gst_gl_window_send_mouse_event (window, "mouse-move", 0,
ButtonPress ? "mouse-button-press" : "mouse-button-release"; (double) motion->event_x, (double) motion->event_y);
break;
}
default:
GST_TRACE ("unhandled XCB event: %u", event_code);
break;
}
GST_DEBUG ("input event mouse button %d %s over window at %d,%d", return TRUE;
event.xbutton.button, mouse_type, event.xbutton.x, event.xbutton.y);
gst_gl_window_send_mouse_event_async (window, mouse_type,
event.xbutton.button, event.xbutton.x, event.xbutton.y);
break;
}
case MotionNotify:
GST_DEBUG ("input event pointer moved over window at %d,%d",
event.xmotion.x, event.xmotion.y);
gst_gl_window_send_mouse_event_async (window, "mouse-move", 0,
event.xbutton.x, event.xbutton.y);
break;
default:
GST_DEBUG ("unknown XEvent type: %u", event.type);
break;
} // switch
} // while running
return ret;
} }
static int static int

View file

@ -25,36 +25,35 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "x11_event_source.h" #include "xcb_event_source.h"
#include "gstgldisplay_x11.h" #include "gstgldisplay_x11.h"
#include "gstglwindow_x11.h"
extern gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11); extern gboolean gst_gl_display_x11_handle_event (GstGLDisplayX11 * display_x11);
typedef struct _X11EventSource typedef struct _XCBEventSource
{ {
GSource source; GSource source;
GPollFD pfd; GPollFD pfd;
uint32_t mask; uint32_t mask;
GstGLWindowX11 *window; GstGLDisplayX11 *display_x11;
} X11EventSource; } XCBEventSource;
static gboolean static gboolean
x11_event_source_prepare (GSource * base, gint * timeout) xcb_event_source_prepare (GSource * base, gint * timeout)
{ {
X11EventSource *source = (X11EventSource *) base; XCBEventSource *source = (XCBEventSource *) base;
gboolean retval;
xcb_flush (source->display_x11->xcb_connection);
*timeout = -1; *timeout = -1;
return FALSE;
retval = XPending (source->window->device);
return retval;
} }
static gboolean static gboolean
x11_event_source_check (GSource * base) xcb_event_source_check (GSource * base)
{ {
X11EventSource *source = (X11EventSource *) base; XCBEventSource *source = (XCBEventSource *) base;
gboolean retval; gboolean retval;
retval = source->pfd.revents; retval = source->pfd.revents;
@ -63,11 +62,13 @@ x11_event_source_check (GSource * base)
} }
static gboolean static gboolean
x11_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data) xcb_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data)
{ {
X11EventSource *source = (X11EventSource *) base; XCBEventSource *source = (XCBEventSource *) base;
gboolean ret = gst_gl_window_x11_handle_event (source->window); gboolean ret = gst_gl_display_x11_handle_event (source->display_x11);
source->pfd.revents = 0;
if (callback) if (callback)
callback (data); callback (data);
@ -75,22 +76,26 @@ x11_event_source_dispatch (GSource * base, GSourceFunc callback, gpointer data)
return ret; return ret;
} }
static GSourceFuncs x11_event_source_funcs = { static GSourceFuncs xcb_event_source_funcs = {
x11_event_source_prepare, xcb_event_source_prepare,
x11_event_source_check, xcb_event_source_check,
x11_event_source_dispatch, xcb_event_source_dispatch,
NULL NULL
}; };
GSource * GSource *
x11_event_source_new (GstGLWindowX11 * window_x11) xcb_event_source_new (GstGLDisplayX11 * display_x11)
{ {
X11EventSource *source; xcb_connection_t *connection;
XCBEventSource *source;
source = (X11EventSource *) connection = display_x11->xcb_connection;
g_source_new (&x11_event_source_funcs, sizeof (X11EventSource)); g_return_val_if_fail (connection != NULL, NULL);
source->window = window_x11;
source->pfd.fd = ConnectionNumber (source->window->device); source = (XCBEventSource *)
g_source_new (&xcb_event_source_funcs, sizeof (XCBEventSource));
source->display_x11 = display_x11;
source->pfd.fd = xcb_get_file_descriptor (connection);
source->pfd.events = G_IO_IN | G_IO_ERR; source->pfd.events = G_IO_IN | G_IO_ERR;
g_source_add_poll (&source->source, &source->pfd); g_source_add_poll (&source->source, &source->pfd);

View file

@ -18,13 +18,12 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
#ifndef __X11_EVENT_SOURCE_H__ #ifndef __XCB_EVENT_SOURCE_H__
#define __X11_EVENT_SOURCE_H__ #define __XCB_EVENT_SOURCE_H__
#include <glib-object.h> #include <glib-object.h>
#include "gstglwindow_x11.h" #include "gstgldisplay_x11.h"
GSource * GSource * xcb_event_source_new (GstGLDisplayX11 *display_x11);
x11_event_source_new (GstGLWindowX11 *window_x11);
#endif /* __WAYLAND_EVENT_SOURCE_H__ */ #endif /* __XCB_EVENT_SOURCE_H__ */