]> git.sesse.net Git - vlc/commitdiff
Simplified/fixed qt4 fullscreen implementation.
authorLaurent Aimar <fenrir@videolan.org>
Tue, 8 Jun 2010 18:29:17 +0000 (20:29 +0200)
committerLaurent Aimar <fenrir@videolan.org>
Tue, 8 Jun 2010 22:30:11 +0000 (00:30 +0200)
 It removes the need of the reparentable widget (it is not needed
to reparent at all) and so simplify the code.
 It fixes win32 fullscreen support and improves win7 transitions.
 It avoids the need of an extra fullscreen widget, which is consistant
with the other media players I have tested.

modules/gui/qt4/components/interface_widgets.cpp
modules/gui/qt4/components/interface_widgets.hpp
modules/gui/qt4/main_interface.cpp
modules/gui/qt4/main_interface.hpp
modules/gui/qt4/menus.cpp

index 806142fd0547fc7282c3bdecc7bad017650cefb3..60b844b7b69a223681e7970977605f84c2c5c301 100644 (file)
 #include <QBitmap>
 
 #ifdef Q_WS_X11
-# include <X11/Xlib.h>
-# include <qx11info_x11.h>
-static void videoSync( void )
-{
-    /* Make sure the X server has processed all requests.
-     * This protects other threads using distinct connections from getting
-     * the video widget window in an inconsistent states. */
-    XSync( QX11Info::display(), False );
-}
-#else
-# define videoSync() (void)0
+#   include <X11/Xlib.h>
+#   include <qx11info_x11.h>
 #endif
 
 #include <math.h>
 #include <assert.h>
 
-class ReparentableWidget : public QWidget
-{
-private:
-    VideoWidget *owner;
-public:
-    ReparentableWidget( VideoWidget *owner ) : owner( owner )
-    {}
-};
-
 /**********************************************************************
  * Video Widget. A simple frame on which video is drawn
  * This class handles resize issues
@@ -84,7 +66,6 @@ public:
 VideoWidget::VideoWidget( intf_thread_t *_p_i )
     : QFrame( NULL )
       , p_intf( _p_i )
-      , reparentable( NULL )
 {
     /* Set the policy to expand in both directions */
     // setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
@@ -92,12 +73,23 @@ VideoWidget::VideoWidget( intf_thread_t *_p_i )
     layout = new QHBoxLayout( this );
     layout->setContentsMargins( 0, 0, 0, 0 );
     setLayout( layout );
+    stable = NULL;
 }
 
 VideoWidget::~VideoWidget()
 {
     /* Ensure we are not leaking the video output. This would crash. */
-    assert( reparentable == NULL );
+    assert( !stable );
+}
+
+void VideoWidget::sync( void )
+{
+#ifdef Q_WS_X11
+    /* Make sure the X server has processed all requests.
+     * This protects other threads using distinct connections from getting
+     * the video widget window in an inconsistent states. */
+    XSync( QX11Info::display(), False );
+#endif
 }
 
 /**
@@ -109,7 +101,7 @@ WId VideoWidget::request( int *pi_x, int *pi_y,
 {
     msg_Dbg( p_intf, "Video was requested %i, %i", *pi_x, *pi_y );
 
-    if( reparentable != NULL )
+    if( stable )
     {
         msg_Dbg( p_intf, "embedded video already in use" );
         return NULL;
@@ -120,20 +112,10 @@ WId VideoWidget::request( int *pi_x, int *pi_y,
         *pi_height = size().height();
     }
 
-    /* The Qt4 UI needs a fixed a widget ("this"), so that the parent layout is
-     * not messed up when we the video is reparented. Hence, we create an extra
-     * reparentable widget, that will be within the VideoWidget in windowed
-     * mode, and within the root window (NULL parent) in full-screen mode.
-     */
-    reparentable = new ReparentableWidget( this );
-    reparentable->installEventFilter(this );
-    QLayout *innerLayout = new QHBoxLayout( reparentable );
-    innerLayout->setContentsMargins( 0, 0, 0, 0 );
-
     /* The owner of the video window needs a stable handle (WinId). Reparenting
      * in Qt4-X11 changes the WinId of the widget, so we need to create another
      * dummy widget that stays within the reparentable widget. */
-    QWidget *stable = new QWidget();
+    stable = new QWidget();
     QPalette plt = palette();
     plt.setColor( QPalette::Window, Qt::black );
     stable->setPalette( plt );
@@ -147,9 +129,7 @@ WId VideoWidget::request( int *pi_x, int *pi_y,
     stable->setAttribute( Qt::WA_PaintOnScreen, true );
 #endif
 
-    innerLayout->addWidget( stable );
-
-    layout->addWidget( reparentable );
+    layout->addWidget( stable );
 
 #ifdef Q_WS_X11
     /* HACK: Only one X11 client can subscribe to mouse button press events.
@@ -163,7 +143,7 @@ WId VideoWidget::request( int *pi_x, int *pi_y,
     attr.your_event_mask &= ~(ButtonPressMask|ButtonReleaseMask);
     XSelectInput( dpy, w, attr.your_event_mask );
 #endif
-    videoSync();
+    sync();
 #ifndef NDEBUG
     msg_Dbg( p_intf, "embedded video ready (handle %p)",
              (void *)stable->winId() );
@@ -176,8 +156,6 @@ WId VideoWidget::request( int *pi_x, int *pi_y,
    Parent has to care about resizing itself */
 void VideoWidget::SetSizing( unsigned int w, unsigned int h )
 {
-    if (reparentable->windowState() & Qt::WindowFullScreen )
-        return;
     if( !isVisible() ) show();
     resize( w, h );
     emit sizeChanged( w, h );
@@ -188,105 +166,22 @@ void VideoWidget::SetSizing( unsigned int w, unsigned int h )
      */
     if( size().width() == w && size().height() == h )
         updateGeometry();
-    videoSync();
-}
-
-void VideoWidget::SetFullScreen( bool b_fs, bool b_ontop )
-{
-    const Qt::WindowStates curstate = reparentable->windowState();
-    Qt::WindowStates newstate = curstate;
-    Qt::WindowFlags  newflags = reparentable->windowFlags();
-
-
-    if( b_fs )
-    {
-        newstate |= Qt::WindowFullScreen;
-        if( b_ontop )
-            newflags |= Qt::WindowStaysOnTopHint;
-    }
-    else
-    {
-        newstate &= ~Qt::WindowFullScreen;
-        newflags &= ~Qt::WindowStaysOnTopHint;
-    }
-    if( newstate == curstate )
-        return; /* no changes needed */
-
-    if( b_fs )
-    {   /* Go full-screen */
-        int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
-        /* if user hasn't defined screennumber, or screennumber that is bigger
-         * than current number of screens, take screennumber where current interface
-         * is
-         */
-        if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
-            numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
-
-        QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
-
-        /* To be sure window is on proper-screen in xinerama */
-        if( !screenres.contains( reparentable->pos() ) )
-        {
-            msg_Dbg( p_intf, "Moving video to correct screen");
-            reparentable->move( QPoint( screenres.x(), screenres.y() ) );
-        }
-        reparentable->setParent( NULL, newflags );
-        reparentable->setWindowState( newstate );
-
-        /* FIXME: inherit from the vout window, not the interface */
-        char *title = var_InheritString( p_intf, "video-title" );
-        reparentable->setWindowTitle( qfu(title ? title : _("Video")) );
-        free( title );
-
-        reparentable->show();
-        reparentable->activateWindow();
-        reparentable->raise();
-    }
-    else
-    {   /* Go windowed */
-        reparentable->setWindowFlags( newflags );
-        reparentable->setWindowState( newstate );
-        layout->addWidget( reparentable );
-    }
-    videoSync();
+    sync();
 }
 
 void VideoWidget::release( void )
 {
     msg_Dbg( p_intf, "Video is not needed anymore" );
-    //layout->removeWidget( reparentable );
 
-    reparentable->deleteLater();
-    reparentable = NULL;
+    assert( stable );
+    layout->removeWidget( stable );
+    stable->deleteLater();
+    stable = NULL;
+
     updateGeometry();
     hide();
 }
 
-#undef KeyPress
-bool VideoWidget::eventFilter(QObject *obj, QEvent *event)
-{
-    if( obj == reparentable )
-    {
-        if (event->type() == QEvent::Close)
-        {
-            THEDP->quit();
-            return true;
-        }
-        else if( event->type() == QEvent::KeyPress )
-        {
-            emit keyPressed( static_cast<QKeyEvent *>(event) );
-            return true;
-        }
-        else if( event->type() == QEvent::Wheel )
-        {
-            int i_vlckey = qtWheelEventToVLCKey( static_cast<QWheelEvent *>(event) );
-            var_SetInteger( p_intf->p_libvlc, "key-pressed", i_vlckey );
-            return true;
-        }
-    }
-    return false;
-}
-
 /**********************************************************************
  * Background Widget. Show a simple image background. Currently,
  * it's album art if present or cone.
index 7b9e2b92b69a5654022458edd587e4aeed8a98e5..16af5fe99effbdadfcfe28ea6e0f7d74c31be6b3 100644 (file)
@@ -46,14 +46,11 @@ class QPixmap;
 class QHBoxLayout;
 class QMenu;
 class QSlider;
-class ReparentableWidget;
 
 /******************** Video Widget ****************/
 class VideoWidget : public QFrame
 {
     Q_OBJECT
-friend class ReparentableWidget;
-
 public:
     VideoWidget( intf_thread_t * );
     virtual ~VideoWidget();
@@ -61,7 +58,7 @@ public:
     WId request( int *, int *, unsigned int *, unsigned int *, bool );
     void  release( void );
     int   control( void *, int, va_list );
-    void SetFullScreen( bool, bool );
+    void  sync( void );
 
 protected:
     virtual QPaintEngine *paintEngine() const
@@ -72,11 +69,9 @@ protected:
 private:
     intf_thread_t *p_intf;
 
-    QWidget *reparentable;
+    QWidget *stable;
     QLayout *layout;
-    virtual bool eventFilter ( QObject * watched, QEvent * event );
 signals:
-    void keyPressed( QKeyEvent * );
     void sizeChanged( int, int );
 
 public slots:
index 7627de0bf7fe52619e3858bf22f27af2d6870932..93588b4facd05a70dc930c9457cb72961c9d59a1 100644 (file)
@@ -110,7 +110,7 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
     b_autoresize = var_InheritBool( p_intf, "qt-video-autoresize" );
 
     /* Are we in the enhanced always-video mode or not ? */
-    i_visualmode = var_InheritBool( p_intf, "qt-minimal-view" );
+    b_minimalView = var_InheritBool( p_intf, "qt-minimal-view" );
 
     /* Do we want anoying popups or not */
     b_notificationEnabled = var_InheritBool( p_intf, "qt-notification" );
@@ -219,8 +219,6 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
         }
         CONNECT( this, askVideoSetFullScreen( bool ),
                  this, setVideoFullScreen( bool ) );
-        CONNECT( videoWidget, keyPressed( QKeyEvent * ),
-                 this, handleKeyPress( QKeyEvent * ) );
     }
 
     CONNECT( THEDP, toolBarConfUpdated(), this, recreateToolbars() );
@@ -246,6 +244,8 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
     QVLCTools::restoreWidgetPosition( settings, this, QSize(400, 100) );
     settings->endGroup();
 
+    b_interfaceFullScreen = isFullScreen();
+
     /* Final sizing and showing */
     setVisible( !b_hideAfterCreation );
 
@@ -253,7 +253,7 @@ MainInterface::MainInterface( intf_thread_t *_p_intf ) : QVLCMW( _p_intf )
                             menuBar()->sizeHint().width() ) + 30 );
 
     /* Switch to minimal view if needed, must be called after the show() */
-    if( i_visualmode )
+    if( b_minimalView )
         toggleMinimalView( true );
 }
 
@@ -583,6 +583,7 @@ void MainInterface::releaseVideoSlot( void )
 {
     videoWidget->release();
     setVideoOnTop( false );
+    setVideoFullScreen( false );
 
     if( stackCentralW->currentWidget() == videoWidget )
         restoreStackOldWidget();
@@ -593,17 +594,42 @@ void MainInterface::releaseVideoSlot( void )
 
 void MainInterface::setVideoSize( unsigned int w, unsigned int h )
 {
-    if( isFullScreen() || isMaximized() )
-        showNormal();
-    videoWidget->SetSizing( w, h );
+    if( !isFullScreen() && !isMaximized() )
+        videoWidget->SetSizing( w, h );
 }
 
 void MainInterface::setVideoFullScreen( bool fs )
 {
     b_videoFullScreen = fs;
-    /* refresh main interface on-top status if needed */
-    setVideoOnTop( b_videoOnTop );
-    videoWidget->SetFullScreen( fs, b_videoOnTop );
+    if( fs )
+    {
+        int numscreen = var_InheritInteger( p_intf, "qt-fullscreen-screennumber" );
+        /* if user hasn't defined screennumber, or screennumber that is bigger
+         * than current number of screens, take screennumber where current interface
+         * is
+         */
+        if( numscreen == -1 || numscreen > QApplication::desktop()->numScreens() )
+            numscreen = QApplication::desktop()->screenNumber( p_intf->p_sys->p_mi );
+
+        QRect screenres = QApplication::desktop()->screenGeometry( numscreen );
+
+        /* To be sure window is on proper-screen in xinerama */
+        if( !screenres.contains( pos() ) )
+        {
+            msg_Dbg( p_intf, "Moving video to correct screen");
+            move( QPoint( screenres.x(), screenres.y() ) );
+        }
+        setMinimalView( true );
+        setInterfaceFullScreen( true );
+    }
+    else
+    {
+        /* TODO do we want to restore screen and position ? (when
+         * qt-fullscreen-screennumber is forced) */
+        setMinimalView( b_minimalView );
+        setInterfaceFullScreen( b_interfaceFullScreen );
+    }
+    videoWidget->sync();
 }
 
 /* Slot to change the video always-on-top flag.
@@ -611,14 +637,10 @@ void MainInterface::setVideoFullScreen( bool fs )
 void MainInterface::setVideoOnTop( bool on_top )
 {
     b_videoOnTop = on_top;
-    /* The main interface is not always-on-top if it does not contain
-     * the video (which is to say in fullscreen mode). */
-    if( b_videoFullScreen )
-        on_top = false;
 
     Qt::WindowFlags oldflags = windowFlags(), newflags;
 
-    if( on_top )
+    if( b_videoOnTop )
         newflags = oldflags | Qt::WindowStaysOnTopHint;
     else
         newflags = oldflags & ~Qt::WindowStaysOnTopHint;
@@ -754,12 +776,20 @@ void MainInterface::dockPlaylist( bool p_docked )
     playlistVisible = true;
 }
 
+void MainInterface::setMinimalView( bool b_minimal )
+{
+    menuBar()->setVisible( !b_minimal );
+    controls->setVisible( !b_minimal );
+    statusBar()->setVisible( !b_minimal );
+    inputC->setVisible( !b_minimal );
+}
+
 /*
-  If b_switch is false, then we are normalView
+  If b_minimal is false, then we are normalView
  */
-void MainInterface::toggleMinimalView( bool b_switch )
+void MainInterface::toggleMinimalView( bool b_minimal )
 {
-    if( i_visualmode == 0 && b_autoresize ) /* Normal mode */
+    if( !b_minimalView && b_autoresize ) /* Normal mode */
     {
         if( stackCentralW->currentWidget() == bgWidget )
         {
@@ -769,13 +799,11 @@ void MainInterface::toggleMinimalView( bool b_switch )
             }
         }
     }
+    b_minimalView = b_minimal;
+    if( !b_videoFullScreen )
+        setMinimalView( b_minimalView );
 
-    menuBar()->setVisible( !b_switch );
-    controls->setVisible( !b_switch );
-    statusBar()->setVisible( !b_switch );
-    inputC->setVisible( !b_switch );
-
-    emit minimalViewToggled( b_switch );
+    emit minimalViewToggled( b_minimalView );
 }
 
 /* toggling advanced controls buttons */
@@ -1070,10 +1098,9 @@ void MainInterface::keyPressEvent( QKeyEvent *e )
 
 void MainInterface::handleKeyPress( QKeyEvent *e )
 {
-    if( ( e->modifiers() &  Qt::ControlModifier ) && ( e->key() == Qt::Key_H )
-          && !menuBar()->isVisible() )
+    if( ( e->modifiers() &  Qt::ControlModifier ) && ( e->key() == Qt::Key_H ) )
     {
-        toggleMinimalView( false );
+        toggleMinimalView( !b_minimalView );
         e->accept();
     }
 
@@ -1101,18 +1128,19 @@ void MainInterface::closeEvent( QCloseEvent *e )
     THEDP->quit();
 }
 
-void MainInterface::toggleFullScreen()
+void MainInterface::setInterfaceFullScreen( bool fs )
 {
-    if( isFullScreen() )
-    {
-        showNormal();
-        emit fullscreenInterfaceToggled( false );
-    }
-    else
-    {
+    if( fs )
         showFullScreen();
-        emit fullscreenInterfaceToggled( true );
-    }
+    else
+        showNormal();
+}
+void MainInterface::toggleInterfaceFullScreen()
+{
+    b_interfaceFullScreen = !b_interfaceFullScreen;
+    if( !b_videoFullScreen )
+        setInterfaceFullScreen( b_interfaceFullScreen );
+    emit fullscreenInterfaceToggled( b_interfaceFullScreen );
 }
 
 /*****************************************************************************
index 3d97838c565255d0ce0253f43fca2cd875cfc58b..e2a59852f1bed0494d9d12aa2d2a5955c2e580e2 100644 (file)
@@ -86,6 +86,7 @@ public:
 #endif
     int getControlsVisibilityStatus();
     bool isPlDocked() { return ( b_plDocked != false ); }
+    bool isInterfaceFullScreen() { return b_interfaceFullScreen; }
 
 protected:
     void dropEventPlay( QDropEvent *, bool);
@@ -116,6 +117,10 @@ private:
     void showVideo();
     void restoreStackOldWidget();
 
+    /* */
+    void setMinimalView( bool );
+    void setInterfaceFullScreen( bool );
+
     /* */
     QSettings           *settings;
 #ifndef HAVE_MAEMO
@@ -153,7 +158,8 @@ private:
     bool                 b_videoFullScreen;     ///< --fullscreen
     bool                 b_videoOnTop;          ///< --video-on-top
     bool                 b_hideAfterCreation;
-    int                  i_visualmode;          ///< Visual Mode
+    bool                 b_minimalView;         ///< Minimal video
+    bool                 b_interfaceFullScreen;
 
     /* States */
     bool                 playlistVisible;       ///< Is the playlist visible ?
@@ -177,7 +183,7 @@ public slots:
     void toggleUpdateSystrayMenu();
 #endif
     void toggleAdvancedButtons();
-    void toggleFullScreen();
+    void toggleInterfaceFullScreen();
     void toggleFSC();
 
     void popupMenu( const QPoint& );
@@ -210,7 +216,7 @@ private slots:
 
     void resizeStack( int w, int h ) {
         if( !isFullScreen() && !isMaximized() )
-            if( i_visualmode == 1 ) resize( w, h ); /* Oh yes, it shouldn't
+            if( b_minimalView ) resize( 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 ) );
index 13a38959288f442b4095bed593411ec1ea318257..23025596d89eeb84f84d20509b9a372ae466cee7 100644 (file)
@@ -465,9 +465,9 @@ QMenu *QVLCMenu::ViewMenu( intf_thread_t *p_intf, QMenu *current, MainInterface
 
     /* FullScreen View */
     action = menu->addAction( qtr( "&Fullscreen Interface" ), mi,
-            SLOT( toggleFullScreen() ), QString( "F11" ) );
+            SLOT( toggleInterfaceFullScreen() ), QString( "F11" ) );
     action->setCheckable( true );
-    action->setChecked( mi->isFullScreen() );
+    action->setChecked( mi->isInterfaceFullScreen() );
     CONNECT( mi, fullscreenInterfaceToggled( bool ),
              action, setChecked( bool ) );