summaryrefslogtreecommitdiff
path: root/gst-libs/gst/gl/x11/gstgldisplay_x11.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst-libs/gst/gl/x11/gstgldisplay_x11.c')
-rw-r--r--gst-libs/gst/gl/x11/gstgldisplay_x11.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/gst-libs/gst/gl/x11/gstgldisplay_x11.c b/gst-libs/gst/gl/x11/gstgldisplay_x11.c
index 696929eb8..92101d45e 100644
--- a/gst-libs/gst/gl/x11/gstgldisplay_x11.c
+++ b/gst-libs/gst/gl/x11/gstgldisplay_x11.c
@@ -23,6 +23,8 @@
#endif
#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);
#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 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
gst_gl_display_x11_class_init (GstGLDisplayX11Class * klass)
{
@@ -58,6 +64,7 @@ gst_gl_display_x11_finalize (GObject * object)
g_free (display_x11->name);
if (!display_x11->foreign_display && display_x11->display) {
+ XSync (display_x11->display, FALSE);
XCloseDisplay (display_x11->display);
}
@@ -86,8 +93,23 @@ gst_gl_display_x11_new (const gchar * name)
if (!ret->display) {
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;
}
@@ -112,6 +134,14 @@ gst_gl_display_x11_new_with_display (Display * display)
ret->name = g_strdup (DisplayString (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;
return ret;
@@ -122,3 +152,85 @@ gst_gl_display_x11_get_handle (GstGLDisplay * 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;
+}