diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am index 445588de8a..680e782f51 100644 --- a/modules/gui/qt/Makefile.am +++ b/modules/gui/qt/Makefile.am @@ -164,6 +164,8 @@ libqt_plugin_la_SOURCES = \ gui/qt/dialogs/playlists/playlists.cpp gui/qt/dialogs/playlists/playlists.hpp \ gui/qt/maininterface/compositor.hpp \ gui/qt/maininterface/compositor.cpp \ + gui/qt/maininterface/compositor_common.hpp \ + gui/qt/maininterface/compositor_common.cpp \ gui/qt/maininterface/compositor_dummy.hpp \ gui/qt/maininterface/compositor_dummy.cpp \ gui/qt/maininterface/interface_window_handler.cpp \ @@ -440,6 +442,7 @@ nodist_libqt_plugin_la_SOURCES = \ gui/qt/dialogs/toolbar/controlbar_profile_model.moc.cpp \ gui/qt/dialogs/playlists/playlists.moc.cpp \ gui/qt/maininterface/compositor.moc.cpp \ + gui/qt/maininterface/compositor_common.moc.cpp \ gui/qt/maininterface/compositor_dummy.moc.cpp \ gui/qt/maininterface/interface_window_handler.moc.cpp \ gui/qt/maininterface/mainctx.moc.cpp \ diff --git a/modules/gui/qt/maininterface/compositor_common.cpp b/modules/gui/qt/maininterface/compositor_common.cpp new file mode 100644 index 0000000000..7c6b8f55c5 --- /dev/null +++ b/modules/gui/qt/maininterface/compositor_common.cpp @@ -0,0 +1,172 @@ +/***************************************************************************** + * Copyright (C) 2023 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 "compositor_common.hpp" + +#include +#ifndef QT_NO_ACCESSIBILITY +#include +#endif + +#ifdef QT5_DECLARATIVE_PRIVATE +#include +#endif + +using namespace vlc; + +DummyRenderWindow::DummyRenderWindow(QWindow* parent) + : QWindow(parent) +{ + setSurfaceType(RasterSurface); + QSurfaceFormat fmt = format(); + fmt.setAlphaBufferSize(8); + setFormat(fmt); +} + +QAccessibleInterface* DummyRenderWindow::accessibleRoot() const +{ +#ifndef QT_NO_ACCESSIBILITY + QAccessibleInterface* iface = QAccessible::queryAccessibleInterface( + const_cast(this)); + return iface; +#else + return nullptr; +#endif +} + +bool DummyRenderWindow::event(QEvent* event) +{ + switch (event->type() ) + { + case QEvent::UpdateRequest: + render(); + return true; + case QEvent::Expose: + if (isExposed()) + requestUpdate(); + return true; + default: + break; + } + + return QWindow::event(event); +} + +void DummyRenderWindow::resizeEvent(QResizeEvent* resizeEvent) +{ + if (!m_backingStore) + return; + if (!m_initialized) + init(); + m_backingStore->resize(resizeEvent->size()); +} + +void DummyRenderWindow::init() +{ + if (m_initialized) + return; + m_initialized = true; + m_backingStore = new QBackingStore(this); +} + +void DummyRenderWindow::render() +{ + if (!m_initialized) + init(); + if (!isExposed()) + return; + QRect rect(0, 0, width(), height()); + if (m_backingStore->size() != size()) + { + m_backingStore->resize(size()); + } + + //note that we don't need to actually use our backing store + //drawing anything would just lead to flickering + m_backingStore->flush(QRect(0, 0, 1, 1)); + return; +} + +#ifdef QT5_DECLARATIVE_PRIVATE + +class OffscreenWindowPrivate: public QQuickWindowPrivate +{ +public: + void setVisible(bool newVisible) override { + Q_Q(QWindow); + if (visible != newVisible) + { + visible = newVisible; + q->visibleChanged(newVisible); + // this stays always invisible + visibility = newVisible ? QWindow::Windowed : QWindow::Hidden; + q->visibilityChanged(visibility); // workaround for QTBUG-49054 + } + } +}; + +CompositorOffscreenWindow::CompositorOffscreenWindow(QQuickRenderControl* renderControl) + : QQuickWindow(* (new OffscreenWindowPrivate()), renderControl) +{ +} + +static Qt::WindowState resolveWindowState(Qt::WindowStates states) +{ + // No more than one of these 3 can be set + if (states & Qt::WindowMinimized) + return Qt::WindowMinimized; + if (states & Qt::WindowMaximized) + return Qt::WindowMaximized; + if (states & Qt::WindowFullScreen) + return Qt::WindowFullScreen; + // No state means "windowed" - we ignore Qt::WindowActive + return Qt::WindowNoState; +} + +void CompositorOffscreenWindow::setWindowStateExt(Qt::WindowState state) +{ + QWindow::setWindowState(resolveWindowState(state)); +} + +void CompositorOffscreenWindow::setPseudoVisible(bool visible) +{ + setVisible(visible); +} + +#else + +CompositorOffscreenWindow::CompositorOffscreenWindow(QQuickRenderControl* renderControl) +: QQuickWindow(renderControl) +{ +} + +void CompositorOffscreenWindow::setWindowStateExt(Qt::WindowState state) +{ + QWindow::setWindowState(state); +} + +//don't set the window visible, this would create the window, and show make it actually visible +void CompositorOffscreenWindow::setPseudoVisible(bool) +{ +} + +#endif + + + diff --git a/modules/gui/qt/maininterface/compositor_common.hpp b/modules/gui/qt/maininterface/compositor_common.hpp new file mode 100644 index 0000000000..f0acd71a5d --- /dev/null +++ b/modules/gui/qt/maininterface/compositor_common.hpp @@ -0,0 +1,74 @@ +/***************************************************************************** + * Copyright (C) 2023 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 COMPOSITOR_COMMON_HPP +#define COMPOSITOR_COMMON_HPP + +#include +#include + +namespace vlc { + +/** + * a minimal window with no content + * this may be useful on linux platform to provide a + * window which can be drawn into, using a bare QWindow + * usually freeze on resize + */ +class DummyRenderWindow : public QWindow +{ + Q_OBJECT +public: + explicit DummyRenderWindow(QWindow* parent = nullptr); + + virtual QAccessibleInterface *accessibleRoot() const override; + +protected: + bool event(QEvent *event) override; + + void resizeEvent(QResizeEvent *resizeEvent) override; + +private: + void init(); + void render(); + + QBackingStore* m_backingStore = nullptr; + bool m_initialized = false;; +}; + + +/** + * @brief The CompositorOffscreenWindow class allows to fake the visiblilty + * of the the QQuickWindow, note that this feature will only work if QT5_DECLARATIVE_PRIVATE + * are available + */ +class CompositorOffscreenWindow : public QQuickWindow +{ + Q_OBJECT +public: + explicit CompositorOffscreenWindow(QQuickRenderControl* renderControl); + + void setWindowStateExt(Qt::WindowState); + + void setPseudoVisible(bool visible); +}; + + +} + +#endif /* COMPOSITOR_COMMON_HPP */ diff --git a/modules/gui/qt/meson.build b/modules/gui/qt/meson.build index 37f10968b0..d14b862aac 100644 --- a/modules/gui/qt/meson.build +++ b/modules/gui/qt/meson.build @@ -65,6 +65,7 @@ moc_headers = files( 'dialogs/playlists/playlists.hpp', 'dialogs/vlm/vlm.hpp', 'maininterface/compositor.hpp', + 'maininterface/compositor_common.hpp', 'maininterface/compositor_dummy.hpp', 'maininterface/interface_window_handler.hpp', 'maininterface/mainctx.hpp', @@ -272,6 +273,8 @@ some_sources = files( 'dialogs/playlists/playlists.hpp', 'maininterface/compositor.hpp', 'maininterface/compositor.cpp', + 'maininterface/compositor_common.hpp', + 'maininterface/compositor_common.cpp', 'maininterface/compositor_dummy.hpp', 'maininterface/compositor_dummy.cpp', 'maininterface/interface_window_handler.cpp',