[vlc-devel] [PATCH 7/7] qt: provide detached video mode for win7

Pierre Lamot pierre at videolabs.io
Fri Aug 14 18:49:05 CEST 2020


---
 .../gui/qt/maininterface/compositor_win7.cpp  | 133 ++++++++++++++++--
 .../gui/qt/maininterface/compositor_win7.hpp  |  14 +-
 2 files changed, 132 insertions(+), 15 deletions(-)

diff --git a/modules/gui/qt/maininterface/compositor_win7.cpp b/modules/gui/qt/maininterface/compositor_win7.cpp
index dab17a6997..a250f340dc 100644
--- a/modules/gui/qt/maininterface/compositor_win7.cpp
+++ b/modules/gui/qt/maininterface/compositor_win7.cpp
@@ -30,16 +30,18 @@ int CompositorWin7::window_enable(struct vout_window_t * p_wnd, const vout_windo
 {
     CompositorWin7* that = static_cast<CompositorWin7*>(p_wnd->sys);
     msg_Dbg(that->m_intf, "window_enable");
-    that->m_qmlVideoSurfaceProvider->enable(p_wnd);
+    that->m_videoSurfaceProvider->enable(p_wnd);
+    that->setVideoSurface(VideoSurfaceTarget::EMBED);
     return VLC_SUCCESS;
 }
 
 void CompositorWin7::window_disable(struct vout_window_t * p_wnd)
 {
     CompositorWin7* that = static_cast<CompositorWin7*>(p_wnd->sys);
-    that->m_qmlVideoSurfaceProvider->disable();
-    that->m_videoWindowHandler->disable();
     msg_Dbg(that->m_intf, "window_disable");
+    that->setVideoSurface(VideoSurfaceTarget::UNDEF);
+    that->m_videoWindowHandler->disable();
+    that->m_videoSurfaceProvider->disable();
 }
 
 void CompositorWin7::window_resize(struct vout_window_t * p_wnd, unsigned width, unsigned height)
@@ -53,6 +55,7 @@ void CompositorWin7::window_destroy(struct vout_window_t * p_wnd)
 {
     CompositorWin7* that = static_cast<CompositorWin7*>(p_wnd->sys);
     msg_Dbg(that->m_intf, "window_destroy");
+    that->m_voutWindow = nullptr;
 }
 
 void CompositorWin7::window_set_state(struct vout_window_t * p_wnd, unsigned state)
@@ -149,7 +152,9 @@ MainInterface* CompositorWin7::makeMainInterface()
      * m_stable is not attached to the main interface because dialogs are attached to the mainInterface
      * and showing them would raise the video widget above the interface
      */
-    m_stable = new QWidget(nullptr, Qt::Tool | Qt::FramelessWindowHint);
+
+    m_videoWidget = new QWidget(nullptr, Qt::Tool | Qt::FramelessWindowHint);
+    m_stable = new QWidget();
     m_stable->setContextMenuPolicy( Qt::PreventContextMenu );
 
     QPalette plt = m_rootWindow->palette();
@@ -162,16 +167,24 @@ MainInterface* CompositorWin7::makeMainInterface()
     m_stable->setMouseTracking( true );
     m_stable->setWindowFlags( Qt::Tool | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus );
     m_stable->setAttribute( Qt::WA_ShowWithoutActivating );
-    m_stable->show();
+    m_stable->setVisible(true);
+
+    m_videoWidgetLayout = new QVBoxLayout();
+    m_videoWidgetLayout->setMargin(0);
+    m_videoWidgetLayout->setSpacing(0);
+    m_videoWidgetLayout->addWidget(m_stable);
 
-    m_videoWindowHWND = (HWND)m_stable->winId();
+    m_videoWidget->setLayout(m_videoWidgetLayout);
+    m_videoWidget->show();
+
+    m_videoWindowHWND = (HWND)m_videoWidget->winId();
 
     BOOL excluseFromPeek = TRUE;
     DwmSetWindowAttribute(m_videoWindowHWND, DWMWA_EXCLUDED_FROM_PEEK, &excluseFromPeek, sizeof(excluseFromPeek));
     DwmSetWindowAttribute(m_videoWindowHWND, DWMWA_DISALLOW_PEEK, &excluseFromPeek, sizeof(excluseFromPeek));
 
-    m_qmlVideoSurfaceProvider = std::make_unique<VideoSurfaceProvider>();
-    m_rootWindow->setVideoSurfaceProvider(m_qmlVideoSurfaceProvider.get());
+    m_videoSurfaceProvider = std::make_unique<VideoSurfaceProvider>();
+    m_rootWindow->setVideoSurfaceProvider(m_videoSurfaceProvider.get());
 
     m_qmlView = std::make_unique<QQuickView>();
     m_qmlView->setResizeMode(QQuickView::SizeRootObjectToView);
@@ -239,6 +252,7 @@ bool CompositorWin7::setupVoutWindow(vout_window_t *p_wnd)
     p_wnd->display.x11 = nullptr;
     p_wnd->ops = &ops;
     p_wnd->info.has_double_click = true;
+    m_voutWindow = p_wnd;
     return true;
 }
 
@@ -252,16 +266,16 @@ bool CompositorWin7::eventFilter(QObject*, QEvent* ev)
     case QEvent::Move:
     case QEvent::Resize:
     case QEvent::ApplicationStateChange:
-        m_stable->setGeometry(m_qmlView->geometry());
+        m_videoWidget->setGeometry(m_qmlView->geometry());
         resetVideoZOrder();
         break;
     case QEvent::WindowStateChange:
         if (m_qmlView->windowStates() & Qt::WindowMinimized)
-            m_stable->hide();
+            m_videoWidget->hide();
         else
         {
-            m_stable->show();
-            m_stable->setGeometry(m_qmlView->geometry());
+            m_videoWidget->show();
+            m_videoWidget->setGeometry(m_qmlView->geometry());
             resetVideoZOrder();
         }
         break;
@@ -270,11 +284,11 @@ bool CompositorWin7::eventFilter(QObject*, QEvent* ev)
         resetVideoZOrder();
         break;
     case QEvent::Show:
-        m_stable->show();
+        m_videoWidget->show();
         resetVideoZOrder();
         break;
     case QEvent::Hide:
-        m_stable->hide();
+        m_videoWidget->hide();
         break;
     default:
         break;
@@ -302,6 +316,97 @@ void CompositorWin7::resetVideoZOrder()
     );
 }
 
+
+Compositor::VideoSurfaceTarget CompositorWin7::getSupportedVideoSurfaceModes() const
+{
+    return static_cast<VideoSurfaceTarget>(VideoSurfaceTarget::EMBED | VideoSurfaceTarget::WINDOWED | VideoSurfaceTarget::FULLSCREEN);
+}
+
+void CompositorWin7::setVideoSurface(VideoSurfaceTarget target, QVariant targetParam)
+{
+    assert(m_stable != nullptr);
+    switch (m_currentVideoSurface)
+    {
+        case VideoSurfaceTarget::EMBED:
+            //no longer respond to events from the QML surface
+            m_videoSurfaceProvider->setVideoEmbed(false);
+            m_videoWindowHandler->setWindow(nullptr);
+            m_videoWidgetLayout->removeWidget(m_stable);
+            m_stable->setParent(nullptr);
+            msg_Dbg(m_intf, "disable EMBED video surface");
+        break;
+        case VideoSurfaceTarget::FULLSCREEN:
+        case VideoSurfaceTarget::WINDOWED:
+            assert(m_detachedVideoWindow);
+            m_videoWindowHandler->setWindow(nullptr);
+            ((QHBoxLayout*)m_detachedVideoWindow->layout())->removeWidget(m_stable);
+            //reset parent, otherwise m_stable is still attached to m_detachedVideoWindow
+            m_stable->setParent(nullptr);
+            m_detachedVideoWindow.reset();
+            msg_Dbg(m_intf, "disable WINDOWED video surface");
+        break;
+        default:
+        //N/A
+        break;
+    }
+
+    switch (target)
+    {
+        case VideoSurfaceTarget::EMBED:
+        {
+            m_videoWidgetLayout->addWidget(m_stable);
+            m_videoWindowHandler->setWindow(m_qmlView.get());
+            VideoSurfaceProvider* videoSurface = m_videoSurfaceProvider.get();
+            videoSurface->setVideoEmbed(true);
+        }
+        break;
+        case VideoSurfaceTarget::FULLSCREEN:
+        case VideoSurfaceTarget::WINDOWED:
+        {
+            m_detachedVideoWindow = std::make_unique<DetachedVideoWindow>(m_intf, m_voutWindow);
+            QHBoxLayout* detachedVideoWidgetlayout = new QHBoxLayout();
+            detachedVideoWidgetlayout->setContentsMargins( 0, 0, 0, 0 );
+            m_detachedVideoWindow->setLayout(detachedVideoWidgetlayout);
+            detachedVideoWidgetlayout->addWidget(m_stable);
+
+            connect(m_detachedVideoWindow.get(), &DetachedVideoWindow::windowClosed,
+                    this, [this]() {
+                this->setVideoSurface(vlc::Compositor::VideoSurfaceTarget::EMBED);
+            }, Qt::QueuedConnection);
+
+            if (target == VideoSurfaceTarget::FULLSCREEN)
+            {
+                QString screename = targetParam.toString();
+                //ensure that the window is actually created
+                m_detachedVideoWindow->winId();
+                m_detachedVideoWindow->showFSOnScreen(screename, m_qmlView.get());
+            }
+            else
+            {
+                m_detachedVideoWindow->resize(m_stable->size());
+                m_detachedVideoWindow->show();
+            }
+            m_videoWindowHandler->setWindow(m_detachedVideoWindow->windowHandle());
+
+            QSize windowSize = m_detachedVideoWindow->size() * m_detachedVideoWindow->devicePixelRatioF();
+            VideoSurfaceProvider* videoSurface = m_videoSurfaceProvider.get();
+            QMetaObject::invokeMethod(videoSurface, [videoSurface, windowSize]() {
+                videoSurface->onSurfaceSizeChanged(windowSize);
+            }, Qt::QueuedConnection);
+
+            break;
+        }
+        default:
+        //N/A
+        break;
+    }
+
+    m_currentVideoSurface = target;
+    m_currentVideoSurfaceParam = targetParam;
+    emit videoSurfaceChanged(m_currentVideoSurface, m_currentVideoSurfaceParam);
+}
+
+
 Win7NativeEventFilter::Win7NativeEventFilter(QObject* parent)
     : QObject(parent)
 {
diff --git a/modules/gui/qt/maininterface/compositor_win7.hpp b/modules/gui/qt/maininterface/compositor_win7.hpp
index a62650dc8b..b658dea193 100644
--- a/modules/gui/qt/maininterface/compositor_win7.hpp
+++ b/modules/gui/qt/maininterface/compositor_win7.hpp
@@ -21,10 +21,12 @@
 #include "compositor_dummy.hpp"
 #include "videosurface.hpp"
 #include "video_window_handler.hpp"
+#include "detached_video_window.hpp"
 #include <QAbstractNativeEventFilter>
 #include <memory>
 
 class WinTaskbarWidget;
+class QMainWindow;
 
 namespace vlc {
 
@@ -51,6 +53,9 @@ public:
     virtual MainInterface *makeMainInterface() override;
     virtual bool setupVoutWindow(vout_window_t*) override;
 
+    Compositor::VideoSurfaceTarget getSupportedVideoSurfaceModes() const override;
+    void setVideoSurface(VideoSurfaceTarget target, QVariant targetParam = QVariant()) override;
+
 protected:
     bool eventFilter(QObject *obj, QEvent *ev) override;
 
@@ -67,16 +72,23 @@ private slots:
     void resetVideoZOrder();
 
 private:
+    QWidget* m_videoWidget = nullptr;
+    QVBoxLayout* m_videoWidgetLayout = nullptr;
     QWidget* m_stable = nullptr;
     std::unique_ptr<QQuickView> m_qmlView;
     std::unique_ptr<VideoWindowHandler> m_videoWindowHandler;
-    std::unique_ptr<VideoSurfaceProvider> m_qmlVideoSurfaceProvider;
+    std::unique_ptr<VideoSurfaceProvider> m_videoSurfaceProvider;
     WinTaskbarWidget* m_taskbarWidget = nullptr;
     Win7NativeEventFilter* m_nativeEventFilter = nullptr;
 
     HWND m_qmlWindowHWND = nullptr;
     HWND m_videoWindowHWND = nullptr;
 
+    vout_window_t *m_voutWindow = nullptr;
+
+    std::unique_ptr<DetachedVideoWindow> m_detachedVideoWindow;;
+    VideoSurfaceTarget m_currentVideoSurface = VideoSurfaceTarget::EMBED;
+    QVariant m_currentVideoSurfaceParam;
 };
 
 }
-- 
2.25.1



More information about the vlc-devel mailing list