qt: create another indirection X11 window
authorRémi Denis-Courmont <remi@remlab.net>
Fri, 5 Feb 2021 17:25:48 +0000 (19:25 +0200)
committerSebastian Ramacher <sramacher@debian.org>
Tue, 9 Mar 2021 16:42:00 +0000 (16:42 +0000)
The main window may be destroyed before the video window. This notably
occurs if the user requests to close the main UI via window decorations.
While Qt allows those requests to be rejected, doing so would
reintroduce obnoxious bug #4606.

The Qt-X11 display connection will be closed as well as it belongs to
the QApplication instance.

This creates a separate window belonging to a separate display
connection, and which is not tied to the QApplication and QMainWindow
instances. Unfortunately, this adds yet another connection to the X11
display server in the VLC process in addition to QApplication's and the
video display's. And that connection won't process events.

Refs #21875.

Gbp-Pq: Name 0005-qt-create-another-indirection-X11-window.patch

modules/gui/qt/components/interface_widgets.cpp
modules/gui/qt/qt.cpp

index bcf65d2aa4a2f2e30f4b529340bdff237bbb090e..0dbefd1da6e7191206ba8a4bd321a60a5eedc32f 100644 (file)
@@ -227,13 +227,15 @@ QSize VideoWidget::physicalSize() const
     return current_size;
 }
 
+void WindowResized(vout_window_t *, const QSize&);
+
 void VideoWidget::reportSize()
 {
     if( !p_window )
         return;
 
     QSize size = physicalSize();
-    vout_window_ReportSize( p_window, size.width(), size.height() );
+    WindowResized(p_window, size);
 }
 
 /* Set the Widget to the correct Size */
index d5a22d9509474e1368883b68d5661ff161a0f3da..b900e749d46b7dcc91ae80ba812ba3b93e767e87 100644 (file)
@@ -361,6 +361,7 @@ static void Abort( void *obj )
 
 #if defined (QT5_HAS_X11)
 # include <vlc_xlib.h>
+# include <QX11Info>
 
 static void *ThreadXCB( void *data )
 {
@@ -710,6 +711,9 @@ static int WindowControl( vout_window_t *, int i_query, va_list );
 
 typedef struct {
     MainInterface *mi;
+#ifdef QT5_HAS_X11
+    Display *dpy;
+#endif
 } vout_window_qt_t;
 
 static int WindowOpen( vout_window_t *p_wnd, const vout_window_cfg_t *cfg )
@@ -744,20 +748,69 @@ static int WindowOpen( vout_window_t *p_wnd, const vout_window_cfg_t *cfg )
     vout_window_qt_t *sys = new vout_window_qt_t;
 
     sys->mi = p_intf->p_sys->p_mi;
+    p_wnd->sys = (vout_window_sys_t *)sys;
     msg_Dbg( p_wnd, "requesting video window..." );
 
+#ifdef QT5_HAS_X11
+    Window xid;
+
+    if (QX11Info::isPlatformX11())
+    {
+        sys->dpy = XOpenDisplay(NULL);
+        if (unlikely(sys->dpy == NULL))
+        {
+            delete sys;
+            return VLC_EGENERIC;
+        }
+
+        int snum = DefaultScreen(sys->dpy);
+        unsigned long black = BlackPixel(sys->dpy, snum);
+
+        xid = XCreateSimpleWindow(sys->dpy, RootWindow(sys->dpy, snum),
+                                  0, 0, cfg->width, cfg->height,
+                                  0, black, black);
+    }
+#endif
+
     if (!sys->mi->getVideo(p_wnd, cfg->width, cfg->height, cfg->is_fullscreen))
     {
+#ifdef QT5_HAS_X11
+        if (QX11Info::isPlatformX11())
+            XCloseDisplay(sys->dpy);
+#endif
         delete sys;
         return VLC_EGENERIC;
     }
 
+#ifdef QT5_HAS_X11
+    if (QX11Info::isPlatformX11())
+    {
+        XReparentWindow(sys->dpy, xid, p_wnd->handle.xid, 0, 0);
+        XMapWindow(sys->dpy, xid);
+        XSync(sys->dpy, True);
+        p_wnd->handle.xid = xid;
+    }
+#endif
     p_wnd->info.has_double_click = true;
     p_wnd->control = WindowControl;
-    p_wnd->sys = (vout_window_sys_t *)sys;
     return VLC_SUCCESS;
 }
 
+void WindowResized(vout_window_t *wnd, const QSize& size)
+{
+#ifdef QT5_HAS_X11
+    vout_window_qt_t *sys = (vout_window_qt_t *)wnd->sys;
+
+    if (QX11Info::isPlatformX11())
+    {
+        XResizeWindow(sys->dpy, wnd->handle.xid, size.width(), size.height());
+        XClearWindow(sys->dpy, wnd->handle.xid);
+        XSync(sys->dpy, True);
+    }
+#endif
+    vout_window_ReportSize(wnd, size.width(), size.height());
+}
+
 static int WindowControl( vout_window_t *p_wnd, int i_query, va_list args )
 {
     vout_window_qt_t *sys = (vout_window_qt_t *)p_wnd->sys;
@@ -793,5 +846,9 @@ static void WindowClose( vout_window_t *p_wnd )
     else
         msg_Warn (p_wnd, "video already released");
 
+#if defined (QT5_HAS_X11)
+    if (QX11Info::isPlatformX11())
+        XCloseDisplay(sys->dpy);
+#endif
     delete sys;
 }