glimagesink: implement gst_video_overlay_handle_events

https://bugzilla.gnome.org/show_bug.cgi?id=736035
This commit is contained in:
Lubosz Sarnecki 2014-10-29 12:24:16 +01:00 committed by Tim-Philipp Müller
parent f1365f1051
commit 64dd17bde6
5 changed files with 89 additions and 3 deletions

View file

@ -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 <julien.isorce@gmail.com>");
@ -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)
{

View file

@ -65,6 +65,7 @@ struct _GstGLImageSink
GstGLDisplay *display;
GstGLContext *context;
GstGLContext *other_context;
gboolean handle_events;
GstGLUpload *upload;
guint next_tex;

View file

@ -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);
}

View file

@ -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);

View file

@ -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)
{