From c31eb56a5a9ee52efacf0589c3fcfcde92375422 Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Fri, 5 Mar 2021 10:15:51 +0800 Subject: [PATCH 18/33] waylandsink: Support window layer property Support setting top|normal|bottom window layer. Tested with: gst-launch-1.0 videotestsrc ! waylandsink layer=top Signed-off-by: Jeffy Chen --- ext/wayland/gstwaylandsink.c | 52 ++++++++++++++++++++++++++++++++++-- ext/wayland/gstwaylandsink.h | 1 + ext/wayland/wlwindow.c | 39 ++++++++++++++++++++++++++- ext/wayland/wlwindow.h | 13 +++++++-- 4 files changed, 100 insertions(+), 5 deletions(-) diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c index 4577e6c..1bf4511 100644 --- a/ext/wayland/gstwaylandsink.c +++ b/ext/wayland/gstwaylandsink.c @@ -64,6 +64,7 @@ enum PROP_0, PROP_DISPLAY, PROP_FULLSCREEN, + PROP_LAYER, PROP_LAST }; @@ -165,6 +166,24 @@ gst_wayland_pool_init (GstWaylandPool * pool) { } +#define GST_TYPE_WL_WINDOW_LAYER (gst_wl_window_layer_get_type ()) +static GType +gst_wl_window_layer_get_type (void) +{ + static GType layer = 0; + + if (!layer) { + static const GEnumValue layers[] = { + {GST_WL_WINDOW_LAYER_TOP, "Top", "top"}, + {GST_WL_WINDOW_LAYER_NORMAL, "Normal", "normal"}, + {GST_WL_WINDOW_LAYER_BOTTOM, "Bottom", "bottom"}, + {0, NULL, NULL} + }; + layer = g_enum_register_static ("GstWlWindowLayer", layers); + } + return layer; +} + static void gst_wayland_sink_class_init (GstWaylandSinkClass * klass) { @@ -213,6 +232,12 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass) "Whether the surface should be made fullscreen ", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_LAYER, + g_param_spec_enum ("layer", "Window layer", + "Wayland window layer", + GST_TYPE_WL_WINDOW_LAYER, GST_WL_WINDOW_LAYER_NORMAL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gst_video_overlay_install_properties (gobject_class, PROP_LAST); gst_type_mark_as_plugin_api (GST_TYPE_WAYLAND_VIDEO, 0); @@ -225,6 +250,7 @@ gst_wayland_sink_init (GstWaylandSink * sink) g_mutex_init (&sink->render_lock); sink->window_handle = 1; + sink->layer = GST_WL_WINDOW_LAYER_NORMAL; } static void @@ -239,6 +265,18 @@ gst_wayland_sink_set_fullscreen (GstWaylandSink * sink, gboolean fullscreen) g_mutex_unlock (&sink->render_lock); } +static void +gst_wayland_sink_set_layer (GstWaylandSink * sink, GstWlWindowLayer layer) +{ + if (layer == sink->layer) + return; + + g_mutex_lock (&sink->render_lock); + sink->layer = layer; + gst_wl_window_ensure_layer (sink->window, layer); + g_mutex_unlock (&sink->render_lock); +} + static void gst_wayland_sink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) @@ -256,6 +294,11 @@ gst_wayland_sink_get_property (GObject * object, g_value_set_boolean (value, sink->fullscreen); GST_OBJECT_UNLOCK (sink); break; + case PROP_LAYER: + GST_OBJECT_LOCK (sink); + g_value_set_enum (value, sink->layer); + GST_OBJECT_UNLOCK (sink); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -279,6 +322,11 @@ gst_wayland_sink_set_property (GObject * object, gst_wayland_sink_set_fullscreen (sink, g_value_get_boolean (value)); GST_OBJECT_UNLOCK (sink); break; + case PROP_LAYER: + GST_OBJECT_LOCK (sink); + gst_wayland_sink_set_layer (sink, g_value_get_enum (value)); + GST_OBJECT_UNLOCK (sink); + break; default: if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value)) G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -733,8 +781,8 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) if (!sink->window) { /* if we were not provided a window, create one ourselves */ sink->window = gst_wl_window_new_toplevel (sink->display, - &sink->video_info, sink->fullscreen, &sink->render_lock, - &sink->render_rectangle); + &sink->video_info, sink->fullscreen, sink->layer, + &sink->render_lock, &sink->render_rectangle); g_signal_connect_object (sink->window, "closed", G_CALLBACK (on_window_closed), sink, 0); } diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h index 9872c29..3adddf2 100644 --- a/ext/wayland/gstwaylandsink.h +++ b/ext/wayland/gstwaylandsink.h @@ -62,6 +62,7 @@ struct _GstWaylandSink gboolean video_info_changed; GstVideoInfo video_info; gboolean fullscreen; + GstWlWindowLayer layer; gchar *display_name; diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c index 7814cb8..7f7f3b6 100644 --- a/ext/wayland/wlwindow.c +++ b/ext/wayland/wlwindow.c @@ -234,6 +234,42 @@ gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock) return window; } +static void +gst_wl_window_set_flags (GstWlWindow * window, const char *flags) +{ + /* HACK: set window flags through title */ + char s[128] = "flags="; + strcat (s, flags); + + if (!window) + return; + + if (window->xdg_toplevel) + xdg_toplevel_set_title (window->xdg_toplevel, s); + else if (window->wl_shell_surface) + wl_shell_surface_set_title (window->wl_shell_surface, s); +} + +void +gst_wl_window_ensure_layer (GstWlWindow * window, GstWlWindowLayer layer) +{ + char s[128] = "flags="; + + switch (layer) { + case GST_WL_WINDOW_LAYER_TOP: + strcat (s, "stay-on-top|-stay-on-bottom"); + break; + case GST_WL_WINDOW_LAYER_NORMAL: + strcat (s, "-stay-on-top|-stay-on-bottom"); + break; + case GST_WL_WINDOW_LAYER_BOTTOM: + strcat (s, "-stay-on-top|stay-on-bottom"); + break; + default: + return; + } +} + void gst_wl_window_ensure_fullscreen (GstWlWindow * window, gboolean fullscreen) { @@ -256,7 +292,7 @@ gst_wl_window_ensure_fullscreen (GstWlWindow * window, gboolean fullscreen) GstWlWindow * gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info, - gboolean fullscreen, GMutex * render_lock, + gboolean fullscreen, GstWlWindowLayer layer, GMutex * render_lock, GstVideoRectangle * render_rectangle) { GstWlWindow *window; @@ -287,6 +323,7 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info, &xdg_toplevel_listener, window); gst_wl_window_ensure_fullscreen (window, fullscreen); + gst_wl_window_ensure_layer (window, layer); /* Finally, commit the xdg_surface state as toplevel */ window->configured = FALSE; diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h index ba61d7a..97ea79e 100644 --- a/ext/wayland/wlwindow.h +++ b/ext/wayland/wlwindow.h @@ -80,11 +80,20 @@ struct _GstWlWindowClass GType gst_wl_window_get_type (void); +typedef enum +{ + GST_WL_WINDOW_LAYER_TOP = 0, + GST_WL_WINDOW_LAYER_NORMAL = 1, + GST_WL_WINDOW_LAYER_BOTTOM = 2, +} GstWlWindowLayer; + +void gst_wl_window_ensure_layer (GstWlWindow * window, + GstWlWindowLayer layer); void gst_wl_window_ensure_fullscreen (GstWlWindow * window, gboolean fullscreen); GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display, - const GstVideoInfo * info, gboolean fullscreen, GMutex * render_lock, - GstVideoRectangle * render_rectangle); + const GstVideoInfo * info, gboolean fullscreen, GstWlWindowLayer layer, + GMutex * render_lock, GstVideoRectangle * render_rectangle); GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display, struct wl_surface * parent, GMutex * render_lock); -- 2.20.1