qt: reparent video window to root whence UI closes
authorRémi Denis-Courmont <remi@remlab.net>
Fri, 5 Feb 2021 17:46:15 +0000 (19:46 +0200)
committerSebastian Ramacher <sramacher@debian.org>
Tue, 9 Mar 2021 16:42:00 +0000 (16:42 +0000)
The video window has to exist until it is closed by its owner, i.e.
WindowClose() is called. If it stayed as a child of the main UI window,
it would be destroyed with the main UI window.

This reparents it (back) to the root window before the main UI window
gets destroyed. This works around #21875.

Gbp-Pq: Name 0006-qt-reparent-video-window-to-root-whence-UI-closes.patch

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

index 0dbefd1da6e7191206ba8a4bd321a60a5eedc32f..cfebe61474d50e0b4ab422bd43ebd05ed782f485 100644 (file)
@@ -228,6 +228,7 @@ QSize VideoWidget::physicalSize() const
 }
 
 void WindowResized(vout_window_t *, const QSize&);
+void WindowReleased(vout_window_t *);
 
 void VideoWidget::reportSize()
 {
@@ -377,6 +378,7 @@ void VideoWidget::release( void )
 
     if( stable )
     {
+        WindowReleased(p_window);
         layout->removeWidget( stable );
         stable->deleteLater();
         stable = NULL;
index bb5dad81a482483ea7b909ba65e6643713b117c2..1f29f5eff3fd1fde278f4a22134fb54646d13251 100644 (file)
@@ -1664,6 +1664,8 @@ void MainInterface::closeEvent( QCloseEvent *e )
 //  hide();
     if ( b_minimalView )
         setMinimalView( false );
+    if( videoWidget )
+        releaseVideoSlot();
     emit askToQuit(); /* ask THEDP to quit, so we have a unique method */
     /* Accept session quit. Otherwise we break the desktop mamager. */
     e->accept();
index b900e749d46b7dcc91ae80ba812ba3b93e767e87..7f4c550a87ec4e2bfc189476454ea89e0e284c38 100644 (file)
@@ -714,6 +714,8 @@ typedef struct {
 #ifdef QT5_HAS_X11
     Display *dpy;
 #endif
+    bool orphaned;
+    QMutex lock;
 } vout_window_qt_t;
 
 static int WindowOpen( vout_window_t *p_wnd, const vout_window_cfg_t *cfg )
@@ -748,6 +750,7 @@ 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;
+    sys->orphaned = false;
     p_wnd->sys = (vout_window_sys_t *)sys;
     msg_Dbg( p_wnd, "requesting video window..." );
 
@@ -785,6 +788,8 @@ static int WindowOpen( vout_window_t *p_wnd, const vout_window_cfg_t *cfg )
 #ifdef QT5_HAS_X11
     if (QX11Info::isPlatformX11())
     {
+        QMutexLocker locker2(&sys->lock);
+
         XReparentWindow(sys->dpy, xid, p_wnd->handle.xid, 0, 0);
         XMapWindow(sys->dpy, xid);
         XSync(sys->dpy, True);
@@ -824,6 +829,26 @@ static int WindowControl( vout_window_t *p_wnd, int i_query, va_list args )
     return sys->mi->controlVideo(i_query, args);
 }
 
+void WindowReleased(vout_window_t *wnd)
+{
+    vout_window_qt_t *sys = (vout_window_qt_t *)wnd->sys;
+    QMutexLocker locker(&sys->lock);
+
+    msg_Warn(wnd, "orphaned video window");
+    sys->orphaned = true;
+#if defined (QT5_HAS_X11)
+    if (QX11Info::isPlatformX11())
+    {   /* In the unlikely event that WindowOpen() has not yet reparented the
+         * window, WindowOpen() will skip reparenting. Then this call will be
+         * a no-op.
+         */
+        XReparentWindow(sys->dpy, wnd->handle.xid,
+                        RootWindow(sys->dpy, DefaultScreen(sys->dpy)), 0, 0);
+        XSync(sys->dpy, True);
+    }
+#endif
+}
+
 static void WindowClose( vout_window_t *p_wnd )
 {
     vout_window_qt_t *sys = (vout_window_qt_t *)p_wnd->sys;