[vlc-commits] xdg-shell: report window size correctly

Rémi Denis-Courmont git at videolan.org
Mon Jun 18 20:05:57 CEST 2018


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Mon Jun 18 20:52:04 2018 +0300| [15b4e1b7ca2f82701c90e839dc93e86bb4208224] | committer: Rémi Denis-Courmont

xdg-shell: report window size correctly

If a dimension is zero, then we get to choose it, so we pick the last
dimension requested by the core - rather than the current dimension.

If a dimension is non-zero, we have to use the value regardless of what
the core requested. This fixes incorrect video sizes in fullscreen,
maximized or tiled windows.

Note: Some window managers may exhibit a bug here, whereby they do not
reset the window dimensions to zero after leaving fullscreen/maximized
state.

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=15b4e1b7ca2f82701c90e839dc93e86bb4208224
---

 modules/video_output/wayland/xdg-shell.c | 81 +++++++++++++++++++++-----------
 1 file changed, 53 insertions(+), 28 deletions(-)

diff --git a/modules/video_output/wayland/xdg-shell.c b/modules/video_output/wayland/xdg-shell.c
index dd95fac9f7..03cc5475a2 100644
--- a/modules/video_output/wayland/xdg-shell.c
+++ b/modules/video_output/wayland/xdg-shell.c
@@ -81,9 +81,22 @@ struct vout_window_sys_t
 
     uint32_t default_output;
 
-    unsigned width;
-    unsigned height;
-    bool fullscreen;
+    struct
+    {
+        unsigned width;
+        unsigned height;
+    } set;
+    struct
+    {
+        unsigned width;
+        unsigned height;
+        struct
+        {
+            unsigned width;
+            unsigned height;
+            bool fullscreen;
+         } latch;
+    } wm;
 # ifdef XDG_SHELL_UNSTABLE
     bool unstable;
 #endif
@@ -94,6 +107,7 @@ struct vout_window_sys_t
     struct wl_cursor *cursor;
     struct wl_surface *cursor_surface;
 
+    vlc_mutex_t lock;
     vlc_thread_t thread;
 };
 
@@ -144,6 +158,18 @@ static void *Thread(void *data)
     //return NULL;
 }
 
+static void ReportSize(vout_window_t *wnd)
+{
+    vout_window_sys_t *sys = wnd->sys;
+    /* Zero wm.width or zero wm.height means the client should choose.
+     * DO NOT REPORT those values to video output... */
+    unsigned width = sys->wm.width ? sys->wm.width : sys->set.width;
+    unsigned height = sys->wm.height ? sys->wm.height : sys->set.height;
+
+    vout_window_ReportSize(wnd, width, height);
+    xdg_surface_set_window_geometry(sys->surface, 0, 0, width, height);
+}
+
 static int Control(vout_window_t *wnd, int cmd, va_list ap)
 {
     vout_window_sys_t *sys = wnd->sys;
@@ -159,16 +185,11 @@ static int Control(vout_window_t *wnd, int cmd, va_list ap)
             unsigned width = va_arg(ap, unsigned);
             unsigned height = va_arg(ap, unsigned);
 
-            /* Unlike X11, the client basically gets to choose its size, which
-             * is the size of the buffer attached to the surface.
-             * Note that it is unspecified who "wins" in case of a race
-             * (e.g. if trying to resize the window, and changing the zoom
-             * at the same time). With X11, the race is arbitrated by the X11
-             * server. With Wayland, it is arbitrated in the client windowing
-             * code. In this case, it is arbitrated by the window core code.
-             */
-            vout_window_ReportSize(wnd, width, height);
-            xdg_surface_set_window_geometry(sys->surface, 0, 0, width, height);
+            vlc_mutex_lock(&sys->lock);
+            sys->set.width = width;
+            sys->set.height = height;
+            ReportSize(wnd);
+            vlc_mutex_unlock(&sys->lock);
             break;
         }
 
@@ -222,8 +243,10 @@ static void xdg_toplevel_configure_cb(void *data,
     const uint32_t *state;
 
     msg_Dbg(wnd, "new configuration: %"PRId32"x%"PRId32, width, height);
+    sys->wm.latch.width = width;
+    sys->wm.latch.height = height;
+    sys->wm.latch.fullscreen = false;
 
-    sys->fullscreen = false;
     wl_array_for_each(state, states)
     {
         msg_Dbg(wnd, " - state 0x%04"PRIX32, *state);
@@ -231,18 +254,11 @@ static void xdg_toplevel_configure_cb(void *data,
         switch (*state)
         {
             case XDG_TOPLEVEL_STATE_FULLSCREEN:
-                sys->fullscreen = true;
+                sys->wm.latch.fullscreen = true;
                 break;
         }
     }
 
-    /* Zero width or zero height means client (we) should choose.
-     * DO NOT REPORT those values to video output... */
-    if (width != 0)
-        sys->width = width;
-    if (height != 0)
-        sys->height = height;
-
     (void) toplevel;
 }
 
@@ -266,14 +282,17 @@ static void xdg_surface_configure_cb(void *data, struct xdg_surface *surface,
     vout_window_t *wnd = data;
     vout_window_sys_t *sys = wnd->sys;
 
-    vout_window_ReportSize(wnd, sys->width, sys->height);
+    vlc_mutex_lock(&sys->lock);
+    sys->wm.width = sys->wm.latch.width;
+    sys->wm.height = sys->wm.latch.height;
+    ReportSize(wnd);
+    vlc_mutex_unlock(&sys->lock);
 
-    if (sys->fullscreen)
+    if (sys->wm.latch.fullscreen)
         vout_window_ReportFullscreen(wnd, NULL);
     else
         vout_window_ReportWindowed(wnd);
 
-    xdg_surface_set_window_geometry(surface, 0, 0, sys->width, sys->height);
     xdg_surface_ack_configure(surface, serial);
 }
 
@@ -448,11 +467,16 @@ static int Open(vout_window_t *wnd, const vout_window_cfg_t *cfg)
     sys->deco_manager = NULL;
     sys->deco = NULL;
     sys->default_output = var_InheritInteger(wnd, "wl-output");
-    sys->width = cfg->width;
-    sys->height = cfg->height;
-    sys->fullscreen = false;
+    sys->wm.width = 0;
+    sys->wm.height = 0;
+    sys->wm.latch.width = 0;
+    sys->wm.latch.height = 0;
+    sys->wm.latch.fullscreen = false;
+    sys->set.width = cfg->width;
+    sys->set.height = cfg->height;
     wl_list_init(&sys->outputs);
     wl_list_init(&sys->seats);
+    vlc_mutex_init(&sys->lock);
     wnd->sys = sys;
     wnd->handle.wl = NULL;
 
@@ -613,6 +637,7 @@ static void Close(vout_window_t *wnd)
     vlc_cancel(sys->thread);
     vlc_join(sys->thread, NULL);
 
+    vlc_mutex_destroy(&sys->lock);
     seat_destroy_all(&sys->seats);
     output_destroy_all(&sys->outputs);
     if (sys->deco != NULL)



More information about the vlc-commits mailing list