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