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