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
From fbc65309c609ff1f2362259e1125108208781502 Mon Sep 17 00:00:00 2001
From: Jeffy Chen <jeffy.chen@rock-chips.com>
Date: Mon, 15 Jun 2020 10:11:42 +0800
Subject: [PATCH 09/31] waylandsink: Support setting toplevel window position
 
Needs hacked wayland server, tested with:
   waylandsink render-rectangle="<100,200,300,400>"
 
Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
---
 ext/wayland/gstwaylandsink.c | 32 ++++++++++++++++++++------------
 ext/wayland/gstwaylandsink.h |  1 +
 ext/wayland/wlwindow.c       | 29 ++++++++++++++++++++++-------
 ext/wayland/wlwindow.h       |  5 +++--
 4 files changed, 46 insertions(+), 21 deletions(-)
 
diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c
index 9e55e4f..6647123 100644
--- a/ext/wayland/gstwaylandsink.c
+++ b/ext/wayland/gstwaylandsink.c
@@ -63,7 +63,8 @@ enum
 {
   PROP_0,
   PROP_DISPLAY,
-  PROP_FULLSCREEN
+  PROP_FULLSCREEN,
+  PROP_LAST
 };
 
 GST_DEBUG_CATEGORY (gstwayland_debug);
@@ -212,6 +213,8 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
           "Whether the surface should be made fullscreen ", FALSE,
           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);
 }
 
@@ -275,7 +278,8 @@ gst_wayland_sink_set_property (GObject * object,
       GST_OBJECT_UNLOCK (sink);
       break;
     default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value))
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
 }
@@ -721,7 +725,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->video_info, sink->fullscreen, &sink->render_lock,
+          &sink->render_rectangle);
       g_signal_connect_object (sink->window, "closed",
           G_CALLBACK (on_window_closed), sink, 0);
     }
@@ -994,16 +999,19 @@ gst_wayland_sink_set_render_rectangle (GstVideoOverlay * overlay,
   g_return_if_fail (sink != NULL);
 
   g_mutex_lock (&sink->render_lock);
-  if (!sink->window) {
-    g_mutex_unlock (&sink->render_lock);
-    GST_WARNING_OBJECT (sink,
-        "set_render_rectangle called without window, ignoring");
-    return;
-  }
 
-  GST_DEBUG_OBJECT (sink, "window geometry changed to (%d, %d) %d x %d",
-      x, y, w, h);
-  gst_wl_window_set_render_rectangle (sink->window, x, y, w, h);
+  if (sink->window) {
+    GST_DEBUG_OBJECT (sink, "window geometry changed to (%d, %d) %d x %d",
+        x, y, w, h);
+    gst_wl_window_set_render_rectangle (sink->window, x, y, w, h, TRUE);
+  } else {
+    GST_DEBUG_OBJECT (sink, "caching window geometry (%d, %d) %d x %d",
+        x, y, w, h);
+    sink->render_rectangle.x = x;
+    sink->render_rectangle.y = y;
+    sink->render_rectangle.w = w;
+    sink->render_rectangle.h = h;
+  }
 
   g_mutex_unlock (&sink->render_lock);
 }
diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h
index 1c5fb07..9872c29 100644
--- a/ext/wayland/gstwaylandsink.h
+++ b/ext/wayland/gstwaylandsink.h
@@ -69,6 +69,7 @@ struct _GstWaylandSink
   gboolean redraw_pending;
   GMutex render_lock;
   GstBuffer *last_buffer;
+  GstVideoRectangle render_rectangle;
 
   struct wl_callback *callback;
 };
diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c
index 57b5491..7814cb8 100644
--- a/ext/wayland/wlwindow.c
+++ b/ext/wayland/wlwindow.c
@@ -79,7 +79,7 @@ handle_xdg_toplevel_configure (void *data, struct xdg_toplevel *xdg_toplevel,
   if (width <= 0 || height <= 0)
     return;
 
-  gst_wl_window_set_render_rectangle (window, 0, 0, width, height);
+  gst_wl_window_set_render_rectangle (window, 0, 0, width, height, FALSE);
 }
 
 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
@@ -123,7 +123,7 @@ handle_configure (void *data, struct wl_shell_surface *wl_shell_surface,
   if (width == 0 || height == 0)
     return;
 
-  gst_wl_window_set_render_rectangle (window, 0, 0, width, height);
+  gst_wl_window_set_render_rectangle (window, 0, 0, width, height, FALSE);
 }
 
 static void
@@ -256,7 +256,8 @@ 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, GMutex * render_lock,
+    GstVideoRectangle * render_rectangle)
 {
   GstWlWindow *window;
 
@@ -325,12 +326,22 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info,
   }
 
   /* render_rectangle is already set via toplevel_configure in
-   * xdg_shell fullscreen mode */
-  if (!(display->xdg_wm_base && fullscreen)) {
+   * fullscreen mode */
+  if (fullscreen)
+    return window;
+
+  if (render_rectangle->w || render_rectangle->h) {
+    /* apply cached position and size */
+    GST_DEBUG ("Applying window position (%d, %d)",
+        render_rectangle->x, render_rectangle->y);
+    gst_wl_window_set_render_rectangle (window, render_rectangle->x,
+        render_rectangle->y, render_rectangle->w, render_rectangle->h, TRUE);
+  } else {
     /* set the initial size to be the same as the reported video size */
     gint width =
         gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
-    gst_wl_window_set_render_rectangle (window, 0, 0, width, info->height);
+    gst_wl_window_set_render_rectangle (window, 0, 0,
+        width, info->height, FALSE);
   }
 
   return window;
@@ -546,7 +557,7 @@ gst_wl_window_update_borders (GstWlWindow * window)
 
 void
 gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
-    gint w, gint h)
+    gint w, gint h, gboolean with_position)
 {
   g_return_if_fail (window != NULL);
 
@@ -559,6 +570,10 @@ gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
   window->render_rectangle.w = w;
   window->render_rectangle.h = h;
 
+  /* try to position the xdg surface with hacked wayland server API */
+  if (with_position && window->xdg_surface)
+    xdg_surface_set_window_geometry (window->xdg_surface, x, y, 0, 0);
+
   /* position the area inside the parent - needs a parent commit to apply */
   if (window->area_subsurface)
     wl_subsurface_set_position (window->area_subsurface, x, y);
diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h
index 303c336..ba61d7a 100644
--- a/ext/wayland/wlwindow.h
+++ b/ext/wayland/wlwindow.h
@@ -83,7 +83,8 @@ GType gst_wl_window_get_type (void);
 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);
+        const GstVideoInfo * info, gboolean fullscreen, GMutex * render_lock,
+        GstVideoRectangle * render_rectangle);
 GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display,
         struct wl_surface * parent, GMutex * render_lock);
 
@@ -94,7 +95,7 @@ gboolean gst_wl_window_is_toplevel (GstWlWindow *window);
 void gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer,
         const GstVideoInfo * info);
 void gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
-        gint w, gint h);
+        gint w, gint h, gboolean with_position);
 
 G_END_DECLS
 
-- 
2.20.1