From 9187b702bac58d0a0af323514f3d221852a40a5b Mon Sep 17 00:00:00 2001 From: Jeffy Chen Date: Mon, 15 Jun 2020 10:11:42 +0800 Subject: [PATCH 18/40] waylandsink: Support setting toplevel window position Needs hacked wayland server, tested with: waylandsink render-rectangle="<100,200,300,400>" Signed-off-by: Jeffy Chen --- 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 9630adc..9dbd898 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); @@ -210,6 +211,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); } @@ -273,7 +276,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; } } @@ -719,7 +723,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); } @@ -992,16 +997,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 0ec444d..194e5bc 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 0ce55bb..c70ca33 100644 --- a/ext/wayland/wlwindow.c +++ b/ext/wayland/wlwindow.c @@ -77,7 +77,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 = { @@ -121,7 +121,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 @@ -258,7 +258,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; @@ -327,12 +328,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; @@ -543,7 +554,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); @@ -552,6 +563,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 c3f0172..6e553af 100644 --- a/ext/wayland/wlwindow.h +++ b/ext/wayland/wlwindow.h @@ -84,7 +84,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); @@ -95,7 +96,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.17.1