1From 11a6d4a05620d9a30c0b322930064a8161adfb1c 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 19/41] 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 gst-libs/gst/wayland/gstwlwindow.c | 40 ++++++++++++++++++++++-
16 gst-libs/gst/wayland/gstwlwindow.h | 15 +++++++--
17 4 files changed, 103 insertions(+), 5 deletions(-)
18
19diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c
20index 7917c69..56a6849 100644
21--- a/ext/wayland/gstwaylandsink.c
22+++ b/ext/wayland/gstwaylandsink.c
23@@ -61,6 +61,7 @@ enum
24   PROP_DISPLAY,
25   PROP_FULLSCREEN,
26   PROP_ROTATE_METHOD,
27+  PROP_LAYER,
28   PROP_LAST
29 };
30
31@@ -116,6 +117,24 @@ G_DEFINE_TYPE_WITH_CODE (GstWaylandSink, gst_wayland_sink, GST_TYPE_VIDEO_SINK,
32 GST_ELEMENT_REGISTER_DEFINE (waylandsink, "waylandsink", GST_RANK_MARGINAL,
33     GST_TYPE_WAYLAND_SINK);
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@@ -177,6 +196,12 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
57           GST_TYPE_VIDEO_ORIENTATION_METHOD, GST_VIDEO_ORIENTATION_IDENTITY,
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  /**
67   * waylandsink:render-rectangle:
68   *
69@@ -195,6 +220,7 @@ gst_wayland_sink_init (GstWaylandSink * self)
70   g_mutex_init (&self->render_lock);
71
72   self->window_handle = 1;
73+  self->layer = GST_WL_WINDOW_LAYER_NORMAL;
74 }
75
76 static void
77@@ -246,6 +272,18 @@ gst_wayland_sink_set_rotate_method (GstWaylandSink * self,
78   GST_OBJECT_UNLOCK (self);
79 }
80
81+static void
82+gst_wayland_sink_set_layer (GstWaylandSink * self, GstWlWindowLayer layer)
83+{
84+  if (layer == self->layer)
85+    return;
86+
87+  g_mutex_lock (&self->render_lock);
88+  self->layer = layer;
89+  gst_wl_window_ensure_layer (self->window, layer);
90+  g_mutex_unlock (&self->render_lock);
91+}
92+
93 static void
94 gst_wayland_sink_get_property (GObject * object,
95     guint prop_id, GValue * value, GParamSpec * pspec)
96@@ -268,6 +306,11 @@ gst_wayland_sink_get_property (GObject * object,
97       g_value_set_enum (value, self->current_rotate_method);
98       GST_OBJECT_UNLOCK (self);
99       break;
100+    case PROP_LAYER:
101+      GST_OBJECT_LOCK (self);
102+      g_value_set_enum (value, self->layer);
103+      GST_OBJECT_UNLOCK (self);
104+      break;
105     default:
106       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
107       break;
108@@ -295,6 +338,11 @@ gst_wayland_sink_set_property (GObject * object,
109       gst_wayland_sink_set_rotate_method (self, g_value_get_enum (value),
110           FALSE);
111       break;
112+    case PROP_LAYER:
113+      GST_OBJECT_LOCK (self);
114+      gst_wayland_sink_set_layer (self, g_value_get_enum (value));
115+      GST_OBJECT_UNLOCK (self);
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@@ -773,8 +821,8 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
121     if (!self->window) {
122       /* if we were not provided a window, create one ourselves */
123       self->window = gst_wl_window_new_toplevel (self->display,
124-          &self->video_info, self->fullscreen, &self->render_lock,
125-          &self->render_rectangle);
126+          &self->video_info, self->fullscreen, self->layer,
127+          &self->render_lock, &self->render_rectangle);
128       g_signal_connect_object (self->window, "closed",
129           G_CALLBACK (on_window_closed), self, 0);
130       gst_wl_window_set_rotate_method (self->window,
131diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h
132index d4c3764..a417788 100644
133--- a/ext/wayland/gstwaylandsink.h
134+++ b/ext/wayland/gstwaylandsink.h
135@@ -57,6 +57,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/gst-libs/gst/wayland/gstwlwindow.c b/gst-libs/gst/wayland/gstwlwindow.c
144index dd6e1c2..fed1c97 100644
145--- a/gst-libs/gst/wayland/gstwlwindow.c
146+++ b/gst-libs/gst/wayland/gstwlwindow.c
147@@ -252,6 +252,43 @@ gst_wl_window_new_internal (GstWlDisplay * display, GMutex * render_lock)
148   return self;
149 }
150
151+static void
152+gst_wl_window_set_config (GstWlWindow * self, const char *config)
153+{
154+  GstWlWindowPrivate *priv;
155+
156+  /* TODO: support non-toplevel */
157+  if (!gst_wl_window_is_toplevel (self))
158+    return;
159+
160+  priv = gst_wl_window_get_instance_private (self);
161+
162+  /* HACK: set window config through title */
163+  xdg_toplevel_set_title (priv->xdg_toplevel, config);
164+}
165+
166+void
167+gst_wl_window_ensure_layer (GstWlWindow * self, GstWlWindowLayer layer)
168+{
169+  char s[128] = "flags=";
170+
171+  switch (layer) {
172+    case GST_WL_WINDOW_LAYER_TOP:
173+      strcat (s, "stay-on-top|-stay-on-bottom");
174+      break;
175+    case GST_WL_WINDOW_LAYER_NORMAL:
176+      strcat (s, "-stay-on-top|-stay-on-bottom");
177+      break;
178+    case GST_WL_WINDOW_LAYER_BOTTOM:
179+      strcat (s, "-stay-on-top|stay-on-bottom");
180+      break;
181+    default:
182+      return;
183+  }
184+
185+  gst_wl_window_set_config (self, s);
186+}
187+
188 void
189 gst_wl_window_ensure_fullscreen (GstWlWindow * self, gboolean fullscreen)
190 {
191@@ -269,7 +306,7 @@ gst_wl_window_ensure_fullscreen (GstWlWindow * self, gboolean fullscreen)
192
193 GstWlWindow *
194 gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info,
195-    gboolean fullscreen, GMutex * render_lock,
196+    gboolean fullscreen, GstWlWindowLayer layer, GMutex * render_lock,
197     GstVideoRectangle * render_rectangle)
198 {
199   GstWlWindow *self;
200@@ -306,6 +343,7 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info,
201         &xdg_toplevel_listener, self);
202
203     gst_wl_window_ensure_fullscreen (self, fullscreen);
204+    gst_wl_window_ensure_layer (self, layer);
205
206     /* Finally, commit the xdg_surface state as toplevel */
207     priv->configured = FALSE;
208diff --git a/gst-libs/gst/wayland/gstwlwindow.h b/gst-libs/gst/wayland/gstwlwindow.h
209index 2bbd643..a0b05c3 100644
210--- a/gst-libs/gst/wayland/gstwlwindow.h
211+++ b/gst-libs/gst/wayland/gstwlwindow.h
212@@ -28,19 +28,30 @@ G_BEGIN_DECLS
213 #define GST_TYPE_WL_WINDOW (gst_wl_window_get_type ())
214 G_DECLARE_FINAL_TYPE (GstWlWindow, gst_wl_window, GST, WL_WINDOW, GObject);
215
216+typedef enum
217+{
218+  GST_WL_WINDOW_LAYER_TOP = 0,
219+  GST_WL_WINDOW_LAYER_NORMAL = 1,
220+  GST_WL_WINDOW_LAYER_BOTTOM = 2,
221+} GstWlWindowLayer;
222+
223 struct _GstWlWindow
224 {
225   GObject parent_instance;
226 };
227
228+GST_WL_API
229+void gst_wl_window_ensure_layer (GstWlWindow * self,
230+        GstWlWindowLayer layer);
231+
232 GST_WL_API
233 void gst_wl_window_ensure_fullscreen (GstWlWindow * self,
234         gboolean fullscreen);
235
236 GST_WL_API
237 GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display,
238-        const GstVideoInfo * info, gboolean fullscreen, GMutex * render_lock,
239-        GstVideoRectangle * render_rectangle);
240+        const GstVideoInfo * info, gboolean fullscreen, GstWlWindowLayer layer,
241+        GMutex * render_lock, GstVideoRectangle * render_rectangle);
242
243 GST_WL_API
244 GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display,
245--
2462.20.1
247
248