hc
2023-12-09 b22da3d8526a935aa31e086e63f60ff3246cb61c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
From 3458bc718bf4044e870e188a2d49d4b13365dac4 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Fri, 5 Mar 2021 10:15:51 +0800
Subject: [PATCH 18/31] 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 <jeffy.chen@rock-chips.com>
---
 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