1From c31eb56a5a9ee52efacf0589c3fcfcde92375422 Mon Sep 17 00:00:00 2001 2From: Jeffy Chen <jeffy.chen@rock-chips.com> 3Date: Fri, 5 Mar 2021 10:15:51 +0800 4Subject: [PATCH 18/33] waylandsink: Support window layer property 5 6Support setting top|normal|bottom window layer. 7 8Tested with: 9gst-launch-1.0 videotestsrc ! waylandsink layer=top 10 11Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com> 12--- 13 ext/wayland/gstwaylandsink.c | 52 ++++++++++++++++++++++++++++++++++-- 14 ext/wayland/gstwaylandsink.h | 1 + 15 ext/wayland/wlwindow.c | 39 ++++++++++++++++++++++++++- 16 ext/wayland/wlwindow.h | 13 +++++++-- 17 4 files changed, 100 insertions(+), 5 deletions(-) 18 19diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c 20index 4577e6c..1bf4511 100644 21--- a/ext/wayland/gstwaylandsink.c 22+++ b/ext/wayland/gstwaylandsink.c 23@@ -64,6 +64,7 @@ enum 24 PROP_0, 25 PROP_DISPLAY, 26 PROP_FULLSCREEN, 27+ PROP_LAYER, 28 PROP_LAST 29 }; 30 31@@ -165,6 +166,24 @@ gst_wayland_pool_init (GstWaylandPool * pool) 32 { 33 } 34 35+#define GST_TYPE_WL_WINDOW_LAYER (gst_wl_window_layer_get_type ()) 36+static GType 37+gst_wl_window_layer_get_type (void) 38+{ 39+ static GType layer = 0; 40+ 41+ if (!layer) { 42+ static const GEnumValue layers[] = { 43+ {GST_WL_WINDOW_LAYER_TOP, "Top", "top"}, 44+ {GST_WL_WINDOW_LAYER_NORMAL, "Normal", "normal"}, 45+ {GST_WL_WINDOW_LAYER_BOTTOM, "Bottom", "bottom"}, 46+ {0, NULL, NULL} 47+ }; 48+ layer = g_enum_register_static ("GstWlWindowLayer", layers); 49+ } 50+ return layer; 51+} 52+ 53 static void 54 gst_wayland_sink_class_init (GstWaylandSinkClass * klass) 55 { 56@@ -213,6 +232,12 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass) 57 "Whether the surface should be made fullscreen ", FALSE, 58 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 59 60+ g_object_class_install_property (gobject_class, PROP_LAYER, 61+ g_param_spec_enum ("layer", "Window layer", 62+ "Wayland window layer", 63+ GST_TYPE_WL_WINDOW_LAYER, GST_WL_WINDOW_LAYER_NORMAL, 64+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); 65+ 66 gst_video_overlay_install_properties (gobject_class, PROP_LAST); 67 68 gst_type_mark_as_plugin_api (GST_TYPE_WAYLAND_VIDEO, 0); 69@@ -225,6 +250,7 @@ gst_wayland_sink_init (GstWaylandSink * sink) 70 g_mutex_init (&sink->render_lock); 71 72 sink->window_handle = 1; 73+ sink->layer = GST_WL_WINDOW_LAYER_NORMAL; 74 } 75 76 static void 77@@ -239,6 +265,18 @@ gst_wayland_sink_set_fullscreen (GstWaylandSink * sink, gboolean fullscreen) 78 g_mutex_unlock (&sink->render_lock); 79 } 80 81+static void 82+gst_wayland_sink_set_layer (GstWaylandSink * sink, GstWlWindowLayer layer) 83+{ 84+ if (layer == sink->layer) 85+ return; 86+ 87+ g_mutex_lock (&sink->render_lock); 88+ sink->layer = layer; 89+ gst_wl_window_ensure_layer (sink->window, layer); 90+ g_mutex_unlock (&sink->render_lock); 91+} 92+ 93 static void 94 gst_wayland_sink_get_property (GObject * object, 95 guint prop_id, GValue * value, GParamSpec * pspec) 96@@ -256,6 +294,11 @@ gst_wayland_sink_get_property (GObject * object, 97 g_value_set_boolean (value, sink->fullscreen); 98 GST_OBJECT_UNLOCK (sink); 99 break; 100+ case PROP_LAYER: 101+ GST_OBJECT_LOCK (sink); 102+ g_value_set_enum (value, sink->layer); 103+ GST_OBJECT_UNLOCK (sink); 104+ break; 105 default: 106 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 107 break; 108@@ -279,6 +322,11 @@ gst_wayland_sink_set_property (GObject * object, 109 gst_wayland_sink_set_fullscreen (sink, g_value_get_boolean (value)); 110 GST_OBJECT_UNLOCK (sink); 111 break; 112+ case PROP_LAYER: 113+ GST_OBJECT_LOCK (sink); 114+ gst_wayland_sink_set_layer (sink, g_value_get_enum (value)); 115+ GST_OBJECT_UNLOCK (sink); 116+ break; 117 default: 118 if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value)) 119 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 120@@ -733,8 +781,8 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer) 121 if (!sink->window) { 122 /* if we were not provided a window, create one ourselves */ 123 sink->window = gst_wl_window_new_toplevel (sink->display, 124- &sink->video_info, sink->fullscreen, &sink->render_lock, 125- &sink->render_rectangle); 126+ &sink->video_info, sink->fullscreen, sink->layer, 127+ &sink->render_lock, &sink->render_rectangle); 128 g_signal_connect_object (sink->window, "closed", 129 G_CALLBACK (on_window_closed), sink, 0); 130 } 131diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h 132index 9872c29..3adddf2 100644 133--- a/ext/wayland/gstwaylandsink.h 134+++ b/ext/wayland/gstwaylandsink.h 135@@ -62,6 +62,7 @@ struct _GstWaylandSink 136 gboolean video_info_changed; 137 GstVideoInfo video_info; 138 gboolean fullscreen; 139+ GstWlWindowLayer layer; 140 141 gchar *display_name; 142 143diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c 144index 7814cb8..7f7f3b6 100644 145--- a/ext/wayland/wlwindow.c 146+++ b/ext/wayland/wlwindow.c 147@@ -234,6 +234,42 @@ gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock) 148 return window; 149 } 150 151+static void 152+gst_wl_window_set_flags (GstWlWindow * window, const char *flags) 153+{ 154+ /* HACK: set window flags through title */ 155+ char s[128] = "flags="; 156+ strcat (s, flags); 157+ 158+ if (!window) 159+ return; 160+ 161+ if (window->xdg_toplevel) 162+ xdg_toplevel_set_title (window->xdg_toplevel, s); 163+ else if (window->wl_shell_surface) 164+ wl_shell_surface_set_title (window->wl_shell_surface, s); 165+} 166+ 167+void 168+gst_wl_window_ensure_layer (GstWlWindow * window, GstWlWindowLayer layer) 169+{ 170+ char s[128] = "flags="; 171+ 172+ switch (layer) { 173+ case GST_WL_WINDOW_LAYER_TOP: 174+ strcat (s, "stay-on-top|-stay-on-bottom"); 175+ break; 176+ case GST_WL_WINDOW_LAYER_NORMAL: 177+ strcat (s, "-stay-on-top|-stay-on-bottom"); 178+ break; 179+ case GST_WL_WINDOW_LAYER_BOTTOM: 180+ strcat (s, "-stay-on-top|stay-on-bottom"); 181+ break; 182+ default: 183+ return; 184+ } 185+} 186+ 187 void 188 gst_wl_window_ensure_fullscreen (GstWlWindow * window, gboolean fullscreen) 189 { 190@@ -256,7 +292,7 @@ gst_wl_window_ensure_fullscreen (GstWlWindow * window, gboolean fullscreen) 191 192 GstWlWindow * 193 gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info, 194- gboolean fullscreen, GMutex * render_lock, 195+ gboolean fullscreen, GstWlWindowLayer layer, GMutex * render_lock, 196 GstVideoRectangle * render_rectangle) 197 { 198 GstWlWindow *window; 199@@ -287,6 +323,7 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info, 200 &xdg_toplevel_listener, window); 201 202 gst_wl_window_ensure_fullscreen (window, fullscreen); 203+ gst_wl_window_ensure_layer (window, layer); 204 205 /* Finally, commit the xdg_surface state as toplevel */ 206 window->configured = FALSE; 207diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h 208index ba61d7a..97ea79e 100644 209--- a/ext/wayland/wlwindow.h 210+++ b/ext/wayland/wlwindow.h 211@@ -80,11 +80,20 @@ struct _GstWlWindowClass 212 213 GType gst_wl_window_get_type (void); 214 215+typedef enum 216+{ 217+ GST_WL_WINDOW_LAYER_TOP = 0, 218+ GST_WL_WINDOW_LAYER_NORMAL = 1, 219+ GST_WL_WINDOW_LAYER_BOTTOM = 2, 220+} GstWlWindowLayer; 221+ 222+void gst_wl_window_ensure_layer (GstWlWindow * window, 223+ GstWlWindowLayer layer); 224 void gst_wl_window_ensure_fullscreen (GstWlWindow * window, 225 gboolean fullscreen); 226 GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display, 227- const GstVideoInfo * info, gboolean fullscreen, GMutex * render_lock, 228- GstVideoRectangle * render_rectangle); 229+ const GstVideoInfo * info, gboolean fullscreen, GstWlWindowLayer layer, 230+ GMutex * render_lock, GstVideoRectangle * render_rectangle); 231 GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display, 232 struct wl_surface * parent, GMutex * render_lock); 233 234-- 2352.20.1 236 237