diff --git a/modules/gui/qt/Makefile.am b/modules/gui/qt/Makefile.am
index daabd5e5508ec58959662bf2abce9148d22e4724..4426d1abe4149bb6e2277a0398ea9fe5dc0a1e8f 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 94ec5d756cbb1ba30a437587c6d261f04016c869..680979e34299d776a77a8270d18bae61c4ade448 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 0000000000000000000000000000000000000000..88ab977b81458e16cef9a8e2293a15b473d90f7b
--- /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 6c6b3dbac48f32607561789852faf539a3c5e59c..6f4ce7f6ba7f8ba16388cd3a17c2d1c775ff25a1 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',