[vlc-devel] [PATCH v3] qt: fix automatic resizes when windows is tiled on X11

Pierre Lamot pierre at videolabs.io
Tue Oct 24 14:20:14 CEST 2017


  This patch is a workaround https://bugreports.qt.io/browse/QTBUG-57608
  Qt assumes that all resize requests will succeed, which might not be
  the case with tiled windows

  Default resize behavior is working properly with QT 5.10 beta

  Fixes #18961
---
 modules/gui/qt/main_interface.cpp | 37 ++++++++++++++++++++++++++++++++-----
 modules/gui/qt/main_interface.hpp |  6 ++++--
 modules/gui/qt/qt.hpp             |  1 +
 3 files changed, 37 insertions(+), 7 deletions(-)

diff --git a/modules/gui/qt/main_interface.cpp b/modules/gui/qt/main_interface.cpp
index ddb60164ae..3ddde38cc7 100644
--- a/modules/gui/qt/main_interface.cpp
+++ b/modules/gui/qt/main_interface.cpp
@@ -63,6 +63,11 @@
 #include <QFileInfo>
 #endif
 
+#if ! HAS_QT510 && defined(QT5_HAS_X11)
+# include <QX11Info>
+# include <X11/Xlib.h>
+#endif
+
 #include <QTimer>
 
 #include <vlc_actions.h>                    /* Wheel event */
@@ -397,7 +402,7 @@ void MainInterface::showResumePanel( int64_t _time ) {
     else
     {
         if( !isFullScreen() && !isMaximized() )
-            resize( width(), height() + resumePanel->height() );
+            resizeWindow( width(), height() + resumePanel->height() );
         resumePanel->setVisible(true);
         resumeTimer->start();
     }
@@ -408,7 +413,7 @@ void MainInterface::hideResumePanel()
     if( resumePanel->isVisible() )
     {
         if( !isFullScreen() && !isMaximized() )
-            resize( width(), height() - resumePanel->height() );
+            resizeWindow( width(), height() - resumePanel->height() );
         resumePanel->hide();
         resumeTimer->stop();
     }
@@ -877,7 +882,7 @@ void MainInterface::setVideoFullScreen( bool fs )
         if( lastWinPosition.isNull() == false )
         {
             move( lastWinPosition );
-            resize( lastWinSize );
+            resizeWindow( lastWinSize.width(), lastWinSize.height() );
             lastWinPosition = QPoint();
             lastWinSize = QSize();
         }
@@ -1080,7 +1085,7 @@ void MainInterface::setMinimalView( bool b_minimal )
             i_heightChange += inputC->height();
 
         if( i_heightChange != 0 )
-            resize( width(), height() - i_heightChange );
+            resizeWindow( width(), height() - i_heightChange );
     }
 
     menuBar()->setVisible( !b_minimal );
@@ -1102,7 +1107,7 @@ void MainInterface::setMinimalView( bool b_minimal )
             i_heightChange += inputC->height();
 
         if( i_heightChange != 0 )
-            resize( width(), height() + i_heightChange );
+            resizeWindow( width(), height() + i_heightChange );
     }
 }
 
@@ -1257,6 +1262,28 @@ void MainInterface::toggleUpdateSystrayMenuWhenVisible()
     hide();
 }
 
+void MainInterface::resizeWindow(int w, int h)
+{
+#if ! HAS_QT510 && defined(QT5_HAS_X11)
+    if( QX11Info::isPlatformX11() )
+    {
+        QSize size(w, h);
+        size = size.boundedTo(maximumSize()).expandedTo(minimumSize());
+        /* X11 window managers are not required to accept geometry changes on
+         * the top-level window.  Unfortunately, Qt < 5.10 assumes that the
+         * change will succeed, and resizes all sub-windows unconditionally.
+         * By calling XMoveResizeWindow directly, Qt will not see our change
+         * request until the ConfigureNotify event on success
+         * and not at all if it is rejected. */
+        XMoveResizeWindow( QX11Info::display(), winId(),
+                          geometry().x(), geometry().y(),
+                          (unsigned int)size.width(), (unsigned int)size.height());
+        return;
+    }
+#endif
+    resize(w, h);
+}
+
 /**
  * Updates the Systray Icon's menu and toggle the main interface
  */
diff --git a/modules/gui/qt/main_interface.hpp b/modules/gui/qt/main_interface.hpp
index c0e2a207b1..c0fe178135 100644
--- a/modules/gui/qt/main_interface.hpp
+++ b/modules/gui/qt/main_interface.hpp
@@ -110,6 +110,8 @@ protected:
     bool eventFilter(QObject *, QEvent *) Q_DECL_OVERRIDE;
     virtual void toggleUpdateSystrayMenuWhenVisible();
 
+    void resizeWindow(int width, int height);
+
 protected:
     /* Main Widgets Creation */
     void createMainWidget( QSettings* );
@@ -235,11 +237,11 @@ protected slots:
         if( !isFullScreen() && !isMaximized() )
         {
             if( b_minimalView )
-                resize( w, h ); /* Oh yes, it shouldn't
+                resizeWindow( w, h ); /* Oh yes, it shouldn't
                                    be possible that size() - stackCentralW->size() < 0
                                    since stackCentralW is contained in the QMW... */
             else
-                resize( size() - stackCentralW->size() + QSize( w, h ) );
+                resizeWindow( width() - stackCentralW->width() + w, height() - stackCentralW->height() + h );
         }
         debug();
     }
diff --git a/modules/gui/qt/qt.hpp b/modules/gui/qt/qt.hpp
index 7b30ea8072..727ca8cf6a 100644
--- a/modules/gui/qt/qt.hpp
+++ b/modules/gui/qt/qt.hpp
@@ -47,6 +47,7 @@
 #endif
 
 #define HAS_QT56 ( QT_VERSION >= 0x050600 )
+#define HAS_QT510 ( QT_VERSION >= 0x051000 )
 
 enum {
     DialogEventTypeOffset = 0,
-- 
2.14.2



More information about the vlc-devel mailing list