diff --git a/ext/gl/gstglimagesink.c b/ext/gl/gstglimagesink.c index 7367f29822..bc4945dcc8 100644 --- a/ext/gl/gstglimagesink.c +++ b/ext/gl/gstglimagesink.c @@ -151,6 +151,10 @@ static void gst_glimage_sink_set_window_handle (GstVideoOverlay * overlay, guintptr id); static void gst_glimage_sink_expose (GstVideoOverlay * overlay); +static void +gst_glimage_sink_handle_events (GstVideoOverlay * overlay, + gboolean handle_events); + static GstStaticPadTemplate gst_glimage_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -173,7 +177,8 @@ enum ARG_DISPLAY, PROP_FORCE_ASPECT_RATIO, PROP_PIXEL_ASPECT_RATIO, - PROP_CONTEXT + PROP_CONTEXT, + PROP_HANDLE_EVENTS }; enum @@ -282,6 +287,11 @@ gst_glimage_sink_class_init (GstGLImageSinkClass * klass) "Get OpenGL context", GST_GL_TYPE_CONTEXT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS, + g_param_spec_boolean ("handle-events", "Handle XEvents", + "When enabled, XEvents will be selected and handled", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gst_element_class_set_metadata (element_class, "OpenGL video sink", "Sink/Video", "A videosink based on OpenGL", "Julien Isorce "); @@ -356,6 +366,8 @@ gst_glimage_sink_init (GstGLImageSink * glimage_sink) glimage_sink->redisplay_texture = 0; g_mutex_init (&glimage_sink->drawing_lock); + + gst_glimage_sink_handle_events (GST_VIDEO_OVERLAY (glimage_sink), TRUE); } static void @@ -386,6 +398,10 @@ gst_glimage_sink_set_property (GObject * object, guint prop_id, glimage_sink->par_d = gst_value_get_fraction_denominator (value); break; } + case PROP_HANDLE_EVENTS: + gst_glimage_sink_handle_events (GST_VIDEO_OVERLAY (glimage_sink), + g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -437,6 +453,9 @@ gst_glimage_sink_get_property (GObject * object, guint prop_id, case PROP_CONTEXT: g_value_set_object (value, glimage_sink->context); break; + case PROP_HANDLE_EVENTS: + g_value_set_boolean (value, glimage_sink->handle_events); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -911,6 +930,7 @@ static void gst_glimage_sink_video_overlay_init (GstVideoOverlayInterface * iface) { iface->set_window_handle = gst_glimage_sink_set_window_handle; + iface->handle_events = gst_glimage_sink_handle_events; iface->expose = gst_glimage_sink_expose; } @@ -950,6 +970,24 @@ gst_glimage_sink_expose (GstVideoOverlay * overlay) } } +static void +gst_glimage_sink_handle_events (GstVideoOverlay * overlay, + gboolean handle_events) +{ + GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay); + + glimage_sink->handle_events = handle_events; + + _ensure_gl_setup (glimage_sink); + + if (G_LIKELY (glimage_sink->context)) { + GstGLWindow *window; + window = gst_gl_context_get_window (glimage_sink->context); + gst_gl_window_handle_events (window, handle_events); + gst_object_unref (window); + } +} + static gboolean gst_glimage_sink_propose_allocation (GstBaseSink * bsink, GstQuery * query) { diff --git a/ext/gl/gstglimagesink.h b/ext/gl/gstglimagesink.h index 45d95152da..4c1842dbac 100644 --- a/ext/gl/gstglimagesink.h +++ b/ext/gl/gstglimagesink.h @@ -65,6 +65,7 @@ struct _GstGLImageSink GstGLDisplay *display; GstGLContext *context; GstGLContext *other_context; + gboolean handle_events; GstGLUpload *upload; guint next_tex; diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 43f3bab061..ba406f0801 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -972,3 +972,26 @@ gst_gl_window_send_mouse_event (GstGLWindow * window, const char *event_type, g_signal_emit (window, gst_gl_window_signals[EVENT_MOUSE_SIGNAL], 0, event_type, button, posx, posy); } + +/** + * gst_gl_window_handle_events: + * @window: a #GstGLWindow + * @handle_events: a #gboolean indicating if events should be handled or not. + * ++ * Tell a @window that it should handle events from the window system. These ++ * events are forwarded upstream as navigation events. In some window systems ++ * events are not propagated in the window hierarchy if a client is listening ++ * for them. This method allows you to disable events handling completely ++ * from the @window. + */ +void +gst_gl_window_handle_events (GstGLWindow * window, gboolean handle_events) +{ + GstGLWindowClass *window_class; + + g_return_if_fail (GST_GL_IS_WINDOW (window)); + window_class = GST_GL_WINDOW_GET_CLASS (window); + g_return_if_fail (window_class->handle_events != NULL); + + window_class->handle_events (window, handle_events); +} diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index 6f244eadef..17ea287d5b 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -131,6 +131,7 @@ struct _GstGLWindowClass { gboolean (*open) (GstGLWindow *window, GError **error); void (*close) (GstGLWindow *window); void (*get_surface_dimensions) (GstGLWindow *window, guint *width, guint *height); + void (*handle_events) (GstGLWindow *window, gboolean handle_events); /*< private >*/ gpointer _reserved[GST_PADDING]; @@ -173,6 +174,7 @@ void gst_gl_window_send_message_async (GstGLWindow *window, GstGLWindowCB guintptr gst_gl_window_get_display (GstGLWindow *window); void gst_gl_window_get_surface_dimensions (GstGLWindow * window, guint * width, guint * height); +void gst_gl_window_handle_events (GstGLWindow * window, gboolean handle_events); GstGLContext * gst_gl_window_get_context (GstGLWindow *window); diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.c b/gst-libs/gst/gl/x11/gstglwindow_x11.c index 84c71af165..ef93650d12 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.c +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.c @@ -79,6 +79,8 @@ gboolean gst_gl_window_x11_open (GstGLWindow * window, GError ** error); void gst_gl_window_x11_close (GstGLWindow * window); static void gst_gl_window_x11_get_surface_dimensions (GstGLWindow * window, guint * width, guint * height); +void gst_gl_window_x11_handle_events (GstGLWindow * window, + gboolean handle_events); static void gst_gl_window_x11_finalize (GObject * object) @@ -113,6 +115,8 @@ gst_gl_window_x11_class_init (GstGLWindowX11Class * klass) window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_x11_close); window_class->get_surface_dimensions = GST_DEBUG_FUNCPTR (gst_gl_window_x11_get_surface_dimensions); + window_class->handle_events = + GST_DEBUG_FUNCPTR (gst_gl_window_x11_handle_events); } static void @@ -211,8 +215,7 @@ gst_gl_window_x11_create_window (GstGLWindowX11 * window_x11) window_x11->visual_info->bits_per_rgb); win_attr.event_mask = - StructureNotifyMask | ExposureMask | VisibilityChangeMask | KeyPressMask | - KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask; + StructureNotifyMask | ExposureMask | VisibilityChangeMask; win_attr.do_not_propagate_mask = NoEventMask; win_attr.background_pixmap = None; @@ -498,6 +501,25 @@ event_type_to_string (guint type) } } +void +gst_gl_window_x11_handle_events (GstGLWindow * window, gboolean handle_events) +{ + GstGLWindowX11 *window_x11; + + g_return_if_fail (window != NULL); + + window_x11 = GST_GL_WINDOW_X11 (window); + + if (handle_events) { + XSelectInput (window_x11->device, window_x11->internal_win_id, + StructureNotifyMask | ExposureMask | VisibilityChangeMask | + PointerMotionMask | KeyPressMask | KeyReleaseMask); + } else { + XSelectInput (window_x11->device, window_x11->internal_win_id, + StructureNotifyMask | ExposureMask | VisibilityChangeMask); + } +} + gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11) {