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