From b4fa2f74df099445c9a141b0b7c2b1d8c0a48296 Mon Sep 17 00:00:00 2001 From: Fatih Uzunoglu <fuzun54@outlook.com> Date: Mon, 7 Apr 2025 23:03:13 +0300 Subject: [PATCH] qt: wayland: try to use layer shell instead of xdg shell if always on top is wanted --- modules/gui/qt/Makefile.am | 1 + modules/gui/qt/maininterface/mainui.cpp | 23 +++++++++++- .../qml/MainInterfaceLayerShell.qml | 36 +++++++++++++++++++ modules/gui/qt/meson.build | 1 + 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 modules/gui/qt/maininterface/qml/MainInterfaceLayerShell.qml diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am index daabd5e5508e..4426d1abe414 100644 --- a/modules/gui/qt/Makefile.am +++ b/modules/gui/qt/Makefile.am @@ -993,6 +993,7 @@ libqml_module_maininterface_a_CPPFLAGS = $(libqt_plugin_la_CPPFLAGS) libqml_module_maininterface_a_QML = \ maininterface/qml/BannerSources.qml \ maininterface/qml/MainInterface.qml \ + maininterface/qml/MainInterfaceLayerShell.qml \ maininterface/qml/MainViewLoader.qml \ maininterface/qml/MainDisplay.qml \ maininterface/qml/MainGridView.qml \ diff --git a/modules/gui/qt/maininterface/mainui.cpp b/modules/gui/qt/maininterface/mainui.cpp index 94ec5d756cbb..680979e34299 100644 --- a/modules/gui/qt/maininterface/mainui.cpp +++ b/modules/gui/qt/maininterface/mainui.cpp @@ -115,7 +115,28 @@ bool MainUI::setup(QQmlEngine* engine) engine->addImageProvider(QStringLiteral("svgcolor"), new SVGColorImageImageProvider()); engine->addImageProvider(QStringLiteral("vlcaccess"), new VLCAccessImageProvider()); - m_component = new QQmlComponent(engine, QStringLiteral("qrc:/qt/qml/VLC/MainInterface/MainInterface.qml"), QQmlComponent::PreferSynchronous, engine); + // NOTE: Starting with Qt 6.5, `QQmlComponent` accepts `QAnyStringView`. + constexpr QLatin1String mainInterface {"qrc:/qt/qml/VLC/MainInterface/MainInterface.qml"}; + constexpr QLatin1String mainInterfaceLayerShell {"qrc:/qt/qml/VLC/MainInterface/MainInterfaceLayerShell.qml"}; + + const bool useLayerShell = [this]() { + assert(qGuiApp); + if (qGuiApp->platformName().startsWith(QLatin1String("wayland")) && + m_mainCtx->isInterfaceAlwaysOnTop() && + var_InheritBool(m_intf, "embedded-video")) + return true; + return false; + }(); + + m_component = new QQmlComponent(engine, useLayerShell ? mainInterfaceLayerShell : mainInterface, QQmlComponent::PreferSynchronous, engine); + + if (useLayerShell && m_component->isError()) + { + // fallback for missing org.kde.layershell or other errors + delete m_component; // `QQmlComponent` does not seem to allow changing the source URL. + m_component = new QQmlComponent(engine, mainInterface, QQmlComponent::PreferSynchronous, engine); + } + if (m_component->isLoading()) { msg_Warn(m_intf, "component is still loading"); diff --git a/modules/gui/qt/maininterface/qml/MainInterfaceLayerShell.qml b/modules/gui/qt/maininterface/qml/MainInterfaceLayerShell.qml new file mode 100644 index 000000000000..88ab977b8145 --- /dev/null +++ b/modules/gui/qt/maininterface/qml/MainInterfaceLayerShell.qml @@ -0,0 +1,36 @@ +/***************************************************************************** + * Copyright (C) 2025 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. + *****************************************************************************/ +import QtQuick +import QtQuick.Window + +import VLC.MainInterface + +import org.kde.layershell as LayerShell + +MainInterface { + Window.onWindowChanged: { + if (Window.window) { + console.warn("Attempting to use layer shell, most features available with xdg shell will not be available.") + Window.window.LayerShell // at this point, QML engine should create the attached layer shell + if (MainCtx.interfaceAlwaysOnTop) { + // Video always on top: + Window.window.LayerShell.Window.layer = LayerShell.Window.LayerTop + } + } + } +} diff --git a/modules/gui/qt/meson.build b/modules/gui/qt/meson.build index 6c6b3dbac48f..6f4ce7f6ba7f 100644 --- a/modules/gui/qt/meson.build +++ b/modules/gui/qt/meson.build @@ -593,6 +593,7 @@ qml_modules += { 'sources': files( 'maininterface/qml/BannerSources.qml', 'maininterface/qml/MainInterface.qml', + 'maininterface/qml/MainInterfaceLayerShell.qml', 'maininterface/qml/MainViewLoader.qml', 'maininterface/qml/MainDisplay.qml', 'maininterface/qml/MainGridView.qml', -- GitLab