[vlc-devel] [PATCH 3/7] qt: provide a detached window to render video in detached or fullscreen mode
Pierre Lamot
pierre at videolabs.io
Fri Aug 14 18:49:01 CEST 2020
This allows to render video in a separate window from the main interface or
fullscreen on a specific screen.
---
modules/gui/qt/Makefile.am | 3 +
.../maininterface/detached_video_window.cpp | 247 ++++++++++++++++++
.../maininterface/detached_video_window.hpp | 75 ++++++
3 files changed, 325 insertions(+)
create mode 100644 modules/gui/qt/maininterface/detached_video_window.cpp
create mode 100644 modules/gui/qt/maininterface/detached_video_window.hpp
diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index 86add9398b..dbb43476b8 100644
--- a/modules/gui/qt/Makefile.am
+++ b/modules/gui/qt/Makefile.am
@@ -118,6 +118,8 @@ libqt_plugin_la_SOURCES = \
gui/qt/maininterface/compositor.cpp \
gui/qt/maininterface/compositor_dummy.hpp \
gui/qt/maininterface/compositor_dummy.cpp \
+ gui/qt/maininterface/detached_video_window.cpp \
+ gui/qt/maininterface/detached_video_window.hpp \
gui/qt/maininterface/interface_window_handler.cpp \
gui/qt/maininterface/interface_window_handler.hpp \
gui/qt/maininterface/main_interface.cpp \
@@ -293,6 +295,7 @@ nodist_libqt_plugin_la_SOURCES = \
gui/qt/dialogs/toolbar/toolbareditor.moc.cpp \
gui/qt/maininterface/compositor.moc.cpp \
gui/qt/maininterface/compositor_dummy.moc.cpp \
+ gui/qt/maininterface/detached_video_window.moc.cpp \
gui/qt/maininterface/interface_window_handler.moc.cpp \
gui/qt/maininterface/main_interface.moc.cpp \
gui/qt/maininterface/mainui.moc.cpp \
diff --git a/modules/gui/qt/maininterface/detached_video_window.cpp b/modules/gui/qt/maininterface/detached_video_window.cpp
new file mode 100644
index 0000000000..cbc9c3b1e9
--- /dev/null
+++ b/modules/gui/qt/maininterface/detached_video_window.cpp
@@ -0,0 +1,247 @@
+/*****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#include "detached_video_window.hpp"
+#include "widgets/native/customwidgets.hpp" // qtEventToVLCKey, QVLCStackedWidget
+
+#if defined (QT5_HAS_X11)
+# include <X11/Xlib.h>
+# include <QX11Info>
+# if defined(QT5_HAS_XCB)
+# include <xcb/xproto.h>
+# endif
+#endif
+#ifdef QT5_HAS_WAYLAND
+# include QPNI_HEADER
+#endif
+
+#include <QWindow>
+#include <QScreen>
+
+#if defined(_WIN32)
+#include <qpa/qplatformnativeinterface.h>
+#endif
+
+#include <vlc_vout_window.h>
+#include "compositor.hpp"
+
+DetachedVideoWindow::DetachedVideoWindow(intf_thread_t *p_intf,
+ vout_window_t *p_wnd,
+ QWidget *parent)
+ : QWidget(parent)
+ , m_intf(p_intf)
+ , m_voutWindow(p_wnd)
+{
+ m_cursorTimer = new QTimer( this );
+ m_cursorTimer->setSingleShot( true );
+ connect( m_cursorTimer, &QTimer::timeout, this, &DetachedVideoWindow::hideCursor);
+ m_cursorTimeout = var_InheritInteger( m_intf, "mouse-hide-timeout" );
+}
+
+QSize DetachedVideoWindow::physicalSize() const
+{
+#ifdef QT5_HAS_X11
+ if ( QX11Info::isPlatformX11() )
+ {
+ Display *p_x_display = QX11Info::display();
+ Window x_window = this->winId();
+ XWindowAttributes x_attributes;
+
+ XGetWindowAttributes( p_x_display, x_window, &x_attributes );
+
+ return QSize( x_attributes.width, x_attributes.height );
+ }
+#endif
+#if defined(_WIN32)
+ HWND hwnd;
+ RECT rect;
+
+ QWindow *window = windowHandle();
+ hwnd = static_cast<HWND>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", window));
+
+ GetClientRect(hwnd, &rect);
+
+ return QSize( rect.right, rect.bottom );
+#endif
+
+ QSize current_size = size();
+ current_size *= devicePixelRatioF();
+ return current_size;
+}
+
+void DetachedVideoWindow::showFSOnScreen(QString screenName, QWindow* interfaceWindow)
+{
+ auto screenList = QGuiApplication::screens();
+ auto it = std::find_if(screenList.begin(), screenList.end(), [&screenName](QScreen* screen) {
+ return screen->name() == screenName;
+ });
+ if (it == screenList.end())
+ {
+ //target screen not found, show it fullscreen anyway
+ showFullScreen();
+ return;
+ }
+
+ QWindow* window = windowHandle();
+ assert(window);
+ window->setScreen(*it);
+
+ showFullScreen();
+
+ //move the interface if it is on the destination screen
+ if (!interfaceWindow)
+ return;
+
+ QScreen* currentInterfaceScreen = interfaceWindow->screen();
+ if (screenList.count() > 1 && currentInterfaceScreen == *it)
+ {
+ auto availableScreenIt = std::find_if(screenList.begin(), screenList.end(), [currentInterfaceScreen](QScreen* screen) {
+ return screen != currentInterfaceScreen;
+ });
+ if (availableScreenIt != screenList.end())
+ {
+ QScreen* newInterfaceScreen = *availableScreenIt;
+ interfaceWindow->setScreen(newInterfaceScreen);
+ interfaceWindow->setFramePosition(newInterfaceScreen->geometry().topLeft());
+ interfaceWindow->resize(qMin(interfaceWindow->width(), newInterfaceScreen->size().width()),
+ qMin(interfaceWindow->height(), newInterfaceScreen->size().height()));
+ }
+ }
+
+}
+
+void DetachedVideoWindow::reportSize()
+{
+ if( !m_voutWindow )
+ {
+ msg_Info(m_intf, "no size report, no m_voutWindow");
+ return;
+ }
+ msg_Info(m_intf, "report size");
+
+ QSize size = physicalSize();
+ vout_window_ReportSize( m_voutWindow, size.width(), size.height() );
+}
+
+void DetachedVideoWindow::resizeEvent( QResizeEvent *event )
+{
+ QWidget::resizeEvent( event );
+ QMetaObject::invokeMethod(this, &DetachedVideoWindow::reportSize, Qt::QueuedConnection);
+}
+
+void DetachedVideoWindow::hideCursor()
+{
+ setCursor( Qt::BlankCursor );
+}
+
+void DetachedVideoWindow::showCursor()
+{
+ setCursor( Qt::ArrowCursor );
+ m_cursorTimer->start( m_cursorTimeout );
+}
+
+int DetachedVideoWindow::qtMouseButton2VLC( Qt::MouseButton qtButton )
+{
+ if( m_voutWindow == NULL )
+ return -1;
+ switch( qtButton )
+ {
+ case Qt::LeftButton:
+ return 0;
+ case Qt::RightButton:
+ return 2;
+ case Qt::MiddleButton:
+ return 1;
+ default:
+ return -1;
+ }
+}
+
+void DetachedVideoWindow::mouseReleaseEvent( QMouseEvent *event )
+{
+ int vlc_button = qtMouseButton2VLC( event->button() );
+ if( vlc_button >= 0 )
+ {
+ vout_window_ReportMouseReleased( m_voutWindow, vlc_button );
+ showCursor();
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+void DetachedVideoWindow::mousePressEvent( QMouseEvent* event )
+{
+ int vlc_button = qtMouseButton2VLC( event->button() );
+ if( vlc_button >= 0 )
+ {
+ vout_window_ReportMousePressed( m_voutWindow, vlc_button );
+ showCursor();
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+void DetachedVideoWindow::mouseMoveEvent( QMouseEvent *event )
+{
+ if( m_voutWindow != NULL )
+ {
+ QPointF current_pos = event->localPos();
+
+ current_pos *= devicePixelRatioF();
+
+ vout_window_ReportMouseMoved( m_voutWindow, current_pos.x(), current_pos.y() );
+ showCursor();
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+void DetachedVideoWindow::mouseDoubleClickEvent( QMouseEvent *event )
+{
+ int vlc_button = qtMouseButton2VLC( event->button() );
+ if( vlc_button >= 0 )
+ {
+ vout_window_ReportMouseDoubleClick( m_voutWindow, vlc_button );
+ showCursor();
+ event->accept();
+ }
+ else
+ event->ignore();
+}
+
+void DetachedVideoWindow::keyPressEvent(QKeyEvent* e)
+{
+ int vlck = qtEventToVLCKey( e );
+ if( vlck > 0 )
+ {
+ var_SetInteger(vlc_object_instance(m_intf), "key-pressed", vlck);
+ e->accept();
+ }
+ else
+ e->ignore();
+
+}
+
+void DetachedVideoWindow::closeEvent(QCloseEvent* e)
+{
+ emit windowClosed();
+ e->ignore();
+}
diff --git a/modules/gui/qt/maininterface/detached_video_window.hpp b/modules/gui/qt/maininterface/detached_video_window.hpp
new file mode 100644
index 0000000000..0646e14b7c
--- /dev/null
+++ b/modules/gui/qt/maininterface/detached_video_window.hpp
@@ -0,0 +1,75 @@
+/*****************************************************************************
+ * Copyright (C) 2020 VLC authors and VideoLAN
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#ifndef DETACHEDVIDEOWINDOW_H
+#define DETACHEDVIDEOWINDOW_H
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "maininterface/main_interface.hpp" /* Interface integration */
+#include <QWidget>
+#include <QTimer>
+
+class DetachedVideoWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit DetachedVideoWindow(intf_thread_t *p_intf, vout_window_t* p_wnd, QWidget *parent = nullptr);
+
+
+ virtual void resizeEvent( QResizeEvent *event ) override;
+ virtual void mousePressEvent(QMouseEvent *) override;
+ virtual void mouseMoveEvent(QMouseEvent *) override;
+ virtual void mouseReleaseEvent(QMouseEvent *) override;
+ virtual void mouseDoubleClickEvent(QMouseEvent *) override;
+ virtual void keyPressEvent(QKeyEvent *) override;
+ virtual void closeEvent(QCloseEvent *) override;
+
+ virtual QSize physicalSize() const;
+
+ /**
+ * @brief showFSOnScreen show fullscreen on screen named @a screenName,
+ * if @a interfaceWindow window is on target screen it will be moved
+ * to another window
+ * @param screenName
+ * @param interfaceWindow
+ */
+ void showFSOnScreen( QString screenName, QWindow* interfaceWindow );
+
+signals:
+ void windowClosed();
+
+public slots:
+ void hideCursor();
+ void showCursor();
+
+private:
+ int qtMouseButton2VLC( Qt::MouseButton qtButton );
+ void reportSize();
+
+ intf_thread_t* m_intf = nullptr;
+ vout_window_t* m_voutWindow = nullptr;
+
+ QTimer* m_cursorTimer = nullptr;
+ int m_cursorTimeout;
+};
+
+#endif // DETACHEDVIDEOWINDOW_H
--
2.25.1
More information about the vlc-devel
mailing list