1From 26f367d760afdf598f62d205da5c825ee48a727d Mon Sep 17 00:00:00 2001
2From: Jeffy Chen <jeffy.chen@rock-chips.com>
3Date: Mon, 15 Jun 2020 10:11:42 +0800
4Subject: [PATCH 09/33] waylandsink: Support setting toplevel window position
5
6Needs hacked wayland server, tested with:
7	waylandsink render-rectangle="<100,200,300,400>"
8
9Signed-off-by: Jeffy Chen <jeffy.chen@rock-chips.com>
10---
11 ext/wayland/gstwaylandsink.c | 32 ++++++++++++++++++++------------
12 ext/wayland/gstwaylandsink.h |  1 +
13 ext/wayland/wlwindow.c       | 29 ++++++++++++++++++++++-------
14 ext/wayland/wlwindow.h       |  5 +++--
15 4 files changed, 46 insertions(+), 21 deletions(-)
16
17diff --git a/ext/wayland/gstwaylandsink.c b/ext/wayland/gstwaylandsink.c
18index 9e55e4f..6647123 100644
19--- a/ext/wayland/gstwaylandsink.c
20+++ b/ext/wayland/gstwaylandsink.c
21@@ -63,7 +63,8 @@ enum
22 {
23   PROP_0,
24   PROP_DISPLAY,
25-  PROP_FULLSCREEN
26+  PROP_FULLSCREEN,
27+  PROP_LAST
28 };
29
30 GST_DEBUG_CATEGORY (gstwayland_debug);
31@@ -212,6 +213,8 @@ gst_wayland_sink_class_init (GstWaylandSinkClass * klass)
32           "Whether the surface should be made fullscreen ", FALSE,
33           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
34
35+  gst_video_overlay_install_properties (gobject_class, PROP_LAST);
36+
37   gst_type_mark_as_plugin_api (GST_TYPE_WAYLAND_VIDEO, 0);
38 }
39
40@@ -275,7 +278,8 @@ gst_wayland_sink_set_property (GObject * object,
41       GST_OBJECT_UNLOCK (sink);
42       break;
43     default:
44-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
45+      if (!gst_video_overlay_set_property (object, PROP_LAST, prop_id, value))
46+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
47       break;
48   }
49 }
50@@ -721,7 +725,8 @@ gst_wayland_sink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
51     if (!sink->window) {
52       /* if we were not provided a window, create one ourselves */
53       sink->window = gst_wl_window_new_toplevel (sink->display,
54-          &sink->video_info, sink->fullscreen, &sink->render_lock);
55+          &sink->video_info, sink->fullscreen, &sink->render_lock,
56+          &sink->render_rectangle);
57       g_signal_connect_object (sink->window, "closed",
58           G_CALLBACK (on_window_closed), sink, 0);
59     }
60@@ -994,16 +999,19 @@ gst_wayland_sink_set_render_rectangle (GstVideoOverlay * overlay,
61   g_return_if_fail (sink != NULL);
62
63   g_mutex_lock (&sink->render_lock);
64-  if (!sink->window) {
65-    g_mutex_unlock (&sink->render_lock);
66-    GST_WARNING_OBJECT (sink,
67-        "set_render_rectangle called without window, ignoring");
68-    return;
69-  }
70
71-  GST_DEBUG_OBJECT (sink, "window geometry changed to (%d, %d) %d x %d",
72-      x, y, w, h);
73-  gst_wl_window_set_render_rectangle (sink->window, x, y, w, h);
74+  if (sink->window) {
75+    GST_DEBUG_OBJECT (sink, "window geometry changed to (%d, %d) %d x %d",
76+        x, y, w, h);
77+    gst_wl_window_set_render_rectangle (sink->window, x, y, w, h, TRUE);
78+  } else {
79+    GST_DEBUG_OBJECT (sink, "caching window geometry (%d, %d) %d x %d",
80+        x, y, w, h);
81+    sink->render_rectangle.x = x;
82+    sink->render_rectangle.y = y;
83+    sink->render_rectangle.w = w;
84+    sink->render_rectangle.h = h;
85+  }
86
87   g_mutex_unlock (&sink->render_lock);
88 }
89diff --git a/ext/wayland/gstwaylandsink.h b/ext/wayland/gstwaylandsink.h
90index 1c5fb07..9872c29 100644
91--- a/ext/wayland/gstwaylandsink.h
92+++ b/ext/wayland/gstwaylandsink.h
93@@ -69,6 +69,7 @@ struct _GstWaylandSink
94   gboolean redraw_pending;
95   GMutex render_lock;
96   GstBuffer *last_buffer;
97+  GstVideoRectangle render_rectangle;
98
99   struct wl_callback *callback;
100 };
101diff --git a/ext/wayland/wlwindow.c b/ext/wayland/wlwindow.c
102index 57b5491..7814cb8 100644
103--- a/ext/wayland/wlwindow.c
104+++ b/ext/wayland/wlwindow.c
105@@ -79,7 +79,7 @@ handle_xdg_toplevel_configure (void *data, struct xdg_toplevel *xdg_toplevel,
106   if (width <= 0 || height <= 0)
107     return;
108
109-  gst_wl_window_set_render_rectangle (window, 0, 0, width, height);
110+  gst_wl_window_set_render_rectangle (window, 0, 0, width, height, FALSE);
111 }
112
113 static const struct xdg_toplevel_listener xdg_toplevel_listener = {
114@@ -123,7 +123,7 @@ handle_configure (void *data, struct wl_shell_surface *wl_shell_surface,
115   if (width == 0 || height == 0)
116     return;
117
118-  gst_wl_window_set_render_rectangle (window, 0, 0, width, height);
119+  gst_wl_window_set_render_rectangle (window, 0, 0, width, height, FALSE);
120 }
121
122 static void
123@@ -256,7 +256,8 @@ gst_wl_window_ensure_fullscreen (GstWlWindow * window, gboolean fullscreen)
124
125 GstWlWindow *
126 gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info,
127-    gboolean fullscreen, GMutex * render_lock)
128+    gboolean fullscreen, GMutex * render_lock,
129+    GstVideoRectangle * render_rectangle)
130 {
131   GstWlWindow *window;
132
133@@ -325,12 +326,22 @@ gst_wl_window_new_toplevel (GstWlDisplay * display, const GstVideoInfo * info,
134   }
135
136   /* render_rectangle is already set via toplevel_configure in
137-   * xdg_shell fullscreen mode */
138-  if (!(display->xdg_wm_base && fullscreen)) {
139+   * fullscreen mode */
140+  if (fullscreen)
141+    return window;
142+
143+  if (render_rectangle->w || render_rectangle->h) {
144+    /* apply cached position and size */
145+    GST_DEBUG ("Applying window position (%d, %d)",
146+        render_rectangle->x, render_rectangle->y);
147+    gst_wl_window_set_render_rectangle (window, render_rectangle->x,
148+        render_rectangle->y, render_rectangle->w, render_rectangle->h, TRUE);
149+  } else {
150     /* set the initial size to be the same as the reported video size */
151     gint width =
152         gst_util_uint64_scale_int_round (info->width, info->par_n, info->par_d);
153-    gst_wl_window_set_render_rectangle (window, 0, 0, width, info->height);
154+    gst_wl_window_set_render_rectangle (window, 0, 0,
155+        width, info->height, FALSE);
156   }
157
158   return window;
159@@ -546,7 +557,7 @@ gst_wl_window_update_borders (GstWlWindow * window)
160
161 void
162 gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
163-    gint w, gint h)
164+    gint w, gint h, gboolean with_position)
165 {
166   g_return_if_fail (window != NULL);
167
168@@ -559,6 +570,10 @@ gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
169   window->render_rectangle.w = w;
170   window->render_rectangle.h = h;
171
172+  /* try to position the xdg surface with hacked wayland server API */
173+  if (with_position && window->xdg_surface)
174+    xdg_surface_set_window_geometry (window->xdg_surface, x, y, 0, 0);
175+
176   /* position the area inside the parent - needs a parent commit to apply */
177   if (window->area_subsurface)
178     wl_subsurface_set_position (window->area_subsurface, x, y);
179diff --git a/ext/wayland/wlwindow.h b/ext/wayland/wlwindow.h
180index 303c336..ba61d7a 100644
181--- a/ext/wayland/wlwindow.h
182+++ b/ext/wayland/wlwindow.h
183@@ -83,7 +83,8 @@ GType gst_wl_window_get_type (void);
184 void gst_wl_window_ensure_fullscreen (GstWlWindow * window,
185         gboolean fullscreen);
186 GstWlWindow *gst_wl_window_new_toplevel (GstWlDisplay * display,
187-        const GstVideoInfo * info, gboolean fullscreen, GMutex * render_lock);
188+        const GstVideoInfo * info, gboolean fullscreen, GMutex * render_lock,
189+        GstVideoRectangle * render_rectangle);
190 GstWlWindow *gst_wl_window_new_in_surface (GstWlDisplay * display,
191         struct wl_surface * parent, GMutex * render_lock);
192
193@@ -94,7 +95,7 @@ gboolean gst_wl_window_is_toplevel (GstWlWindow *window);
194 void gst_wl_window_render (GstWlWindow * window, GstWlBuffer * buffer,
195         const GstVideoInfo * info);
196 void gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
197-        gint w, gint h);
198+        gint w, gint h, gboolean with_position);
199
200 G_END_DECLS
201
202--
2032.20.1
204
205