From 7d1c9a9c6721606b129829134d6f614f015621e2 Mon Sep 17 00:00:00 2001 From: outfoxxed Date: Sun, 10 May 2026 23:46:39 -0700 Subject: [PATCH] wayland/toplevel: reorganize toplevel management --- src/wayland/CMakeLists.txt | 2 +- src/wayland/hyprland/ipc/connection.cpp | 7 +- src/wayland/hyprland/ipc/connection.hpp | 7 +- .../hyprland/ipc/hyprland_toplevel.cpp | 6 +- .../hyprland/ipc/hyprland_toplevel.hpp | 14 ++-- src/wayland/hyprland/ipc/toplevel_mapping.cpp | 4 +- src/wayland/hyprland/ipc/toplevel_mapping.hpp | 20 +++--- src/wayland/module.md | 2 +- .../hyprland_screencopy.cpp | 6 +- .../hyprland_screencopy.hpp | 5 +- .../hyprland_screencopy_p.hpp | 6 +- src/wayland/screencopy/manager.cpp | 4 +- .../CMakeLists.txt | 3 +- .../{toplevel_management => toplevel}/qml.cpp | 33 +++++---- .../{toplevel_management => toplevel}/qml.hpp | 24 +++---- ...oreign-toplevel-management-unstable-v1.xml | 0 .../handle.cpp => toplevel/wlr_toplevel.cpp} | 61 +++++++++++++++-- .../handle.hpp => toplevel/wlr_toplevel.hpp} | 42 +++++++++++- src/wayland/toplevel_management/manager.cpp | 68 ------------------- src/wayland/toplevel_management/manager.hpp | 48 ------------- 20 files changed, 163 insertions(+), 199 deletions(-) rename src/wayland/{toplevel_management => toplevel}/CMakeLists.txt (96%) rename src/wayland/{toplevel_management => toplevel}/qml.cpp (79%) rename src/wayland/{toplevel_management => toplevel}/qml.hpp (87%) rename src/wayland/{toplevel_management => toplevel}/wlr-foreign-toplevel-management-unstable-v1.xml (100%) rename src/wayland/{toplevel_management/handle.cpp => toplevel/wlr_toplevel.cpp} (78%) rename src/wayland/{toplevel_management/handle.hpp => toplevel/wlr_toplevel.hpp} (66%) delete mode 100644 src/wayland/toplevel_management/manager.cpp delete mode 100644 src/wayland/toplevel_management/manager.hpp diff --git a/src/wayland/CMakeLists.txt b/src/wayland/CMakeLists.txt index cf84713..509fd91 100644 --- a/src/wayland/CMakeLists.txt +++ b/src/wayland/CMakeLists.txt @@ -105,7 +105,7 @@ if (WAYLAND_SESSION_LOCK) endif() if (WAYLAND_TOPLEVEL_MANAGEMENT) - add_subdirectory(toplevel_management) + add_subdirectory(toplevel) list(APPEND WAYLAND_MODULES Quickshell.Wayland._ToplevelManagement) endif() diff --git a/src/wayland/hyprland/ipc/connection.cpp b/src/wayland/hyprland/ipc/connection.cpp index 0c98e35..627c369 100644 --- a/src/wayland/hyprland/ipc/connection.cpp +++ b/src/wayland/hyprland/ipc/connection.cpp @@ -24,7 +24,7 @@ #include "../../../core/logcat.hpp" #include "../../../core/model.hpp" #include "../../../core/qmlscreen.hpp" -#include "../../toplevel_management/handle.hpp" +#include "../../toplevel/wlr_toplevel.hpp" #include "hyprland_toplevel.hpp" #include "monitor.hpp" #include "toplevel_mapping.hpp" @@ -139,11 +139,10 @@ void HyprlandIpc::eventSocketReady() { } void HyprlandIpc::toplevelAddressed( - wayland::toplevel_management::impl::ToplevelHandle* handle, + wayland::toplevel::wlr::ToplevelHandle* handle, quint64 address ) { - auto* waylandToplevel = - wayland::toplevel_management::ToplevelManager::instance()->forImpl(handle); + auto* waylandToplevel = wayland::toplevel::ToplevelManager::instance()->forImpl(handle); if (!waylandToplevel) return; diff --git a/src/wayland/hyprland/ipc/connection.hpp b/src/wayland/hyprland/ipc/connection.hpp index c617c04..717e665 100644 --- a/src/wayland/hyprland/ipc/connection.hpp +++ b/src/wayland/hyprland/ipc/connection.hpp @@ -15,7 +15,7 @@ #include "../../../core/model.hpp" #include "../../../core/qmlscreen.hpp" #include "../../../core/streamreader.hpp" -#include "../../../wayland/toplevel_management/handle.hpp" +#include "../../../wayland/toplevel/wlr_toplevel.hpp" namespace qs::hyprland::ipc { @@ -128,10 +128,7 @@ private slots: void eventSocketStateChanged(QLocalSocket::LocalSocketState state); void eventSocketReady(); - void toplevelAddressed( - qs::wayland::toplevel_management::impl::ToplevelHandle* handle, - quint64 address - ); + void toplevelAddressed(qs::wayland::toplevel::wlr::ToplevelHandle* handle, quint64 address); void onFocusedMonitorDestroyed(); diff --git a/src/wayland/hyprland/ipc/hyprland_toplevel.cpp b/src/wayland/hyprland/ipc/hyprland_toplevel.cpp index 43b9838..e02dcdc 100644 --- a/src/wayland/hyprland/ipc/hyprland_toplevel.cpp +++ b/src/wayland/hyprland/ipc/hyprland_toplevel.cpp @@ -6,12 +6,12 @@ #include #include -#include "../../toplevel_management/qml.hpp" +#include "../../toplevel/qml.hpp" #include "connection.hpp" #include "toplevel_mapping.hpp" #include "workspace.hpp" -using namespace qs::wayland::toplevel_management; +using namespace qs::wayland::toplevel; namespace qs::hyprland::ipc { @@ -112,7 +112,7 @@ Toplevel* HyprlandToplevel::waylandHandle() { return ToplevelManager::instance()->forImpl(this->mWaylandHandle); } -void HyprlandToplevel::setWaylandHandle(impl::ToplevelHandle* handle) { +void HyprlandToplevel::setWaylandHandle(wlr::ToplevelHandle* handle) { if (this->mWaylandHandle == handle) return; if (this->mWaylandHandle) { QObject::disconnect(this->mWaylandHandle, nullptr, this, nullptr); diff --git a/src/wayland/hyprland/ipc/hyprland_toplevel.hpp b/src/wayland/hyprland/ipc/hyprland_toplevel.hpp index ebd4f84..8e6aadb 100644 --- a/src/wayland/hyprland/ipc/hyprland_toplevel.hpp +++ b/src/wayland/hyprland/ipc/hyprland_toplevel.hpp @@ -7,8 +7,8 @@ #include #include -#include "../../toplevel_management/handle.hpp" -#include "../../toplevel_management/qml.hpp" +#include "../../toplevel/qml.hpp" +#include "../../toplevel/wlr_toplevel.hpp" #include "connection.hpp" namespace qs::hyprland::ipc { @@ -30,7 +30,7 @@ class HyprlandToplevel: public QObject { /// Will be null until the address is reported Q_PROPERTY(HyprlandToplevel* handle READ hyprlandHandle NOTIFY hyprlandHandleChanged); /// The wayland toplevel handle. Will be null intil the address is reported - Q_PROPERTY(qs::wayland::toplevel_management::Toplevel* wayland READ waylandHandle NOTIFY waylandHandleChanged); + Q_PROPERTY(qs::wayland::toplevel::Toplevel* wayland READ waylandHandle NOTIFY waylandHandleChanged); /// The title of the toplevel Q_PROPERTY(QString title READ default NOTIFY titleChanged BINDABLE bindableTitle); /// Whether the toplevel is active or not @@ -53,7 +53,7 @@ public: /// When invoked from HyprlandIpc, reacting to Hyprland's IPC events. explicit HyprlandToplevel(HyprlandIpc* ipc); /// When attached from a Toplevel - explicit HyprlandToplevel(HyprlandIpc* ipc, qs::wayland::toplevel_management::Toplevel* toplevel); + explicit HyprlandToplevel(HyprlandIpc* ipc, qs::wayland::toplevel::Toplevel* toplevel); static HyprlandToplevel* qmlAttachedProperties(QObject* object); @@ -69,8 +69,8 @@ public: [[nodiscard]] HyprlandToplevel* hyprlandHandle() { return this->mHyprlandHandle; } void setHyprlandHandle(HyprlandToplevel* handle); - [[nodiscard]] wayland::toplevel_management::Toplevel* waylandHandle(); - void setWaylandHandle(wayland::toplevel_management::impl::ToplevelHandle* handle); + [[nodiscard]] wayland::toplevel::Toplevel* waylandHandle(); + void setWaylandHandle(wayland::toplevel::wlr::ToplevelHandle* handle); // clang-format on [[nodiscard]] QBindable bindableTitle() { return &this->bTitle; } @@ -105,7 +105,7 @@ private: quint64 mAddress = 0; HyprlandIpc* ipc; - qs::wayland::toplevel_management::impl::ToplevelHandle* mWaylandHandle = nullptr; + qs::wayland::toplevel::wlr::ToplevelHandle* mWaylandHandle = nullptr; HyprlandToplevel* mHyprlandHandle = nullptr; // clang-format off diff --git a/src/wayland/hyprland/ipc/toplevel_mapping.cpp b/src/wayland/hyprland/ipc/toplevel_mapping.cpp index dadd7d8..b902c63 100644 --- a/src/wayland/hyprland/ipc/toplevel_mapping.cpp +++ b/src/wayland/hyprland/ipc/toplevel_mapping.cpp @@ -6,9 +6,9 @@ #include #include -#include "../../toplevel_management/manager.hpp" +#include "../../toplevel/wlr_toplevel.hpp" -using namespace qs::wayland::toplevel_management::impl; +using namespace qs::wayland::toplevel::wlr; namespace qs::hyprland::ipc { diff --git a/src/wayland/hyprland/ipc/toplevel_mapping.hpp b/src/wayland/hyprland/ipc/toplevel_mapping.hpp index 31eeade..d8f4897 100644 --- a/src/wayland/hyprland/ipc/toplevel_mapping.hpp +++ b/src/wayland/hyprland/ipc/toplevel_mapping.hpp @@ -8,7 +8,7 @@ #include #include -#include "../../toplevel_management/handle.hpp" +#include "../../toplevel/wlr_toplevel.hpp" #include "wayland-hyprland-toplevel-mapping-v1-client-protocol.h" namespace qs::hyprland::ipc { @@ -16,7 +16,7 @@ namespace qs::hyprland::ipc { class HyprlandToplevelMappingHandle: QtWayland::hyprland_toplevel_window_mapping_handle_v1 { public: explicit HyprlandToplevelMappingHandle( - qs::wayland::toplevel_management::impl::ToplevelHandle* handle, + qs::wayland::toplevel::wlr::ToplevelHandle* handle, ::hyprland_toplevel_window_mapping_handle_v1* mapping ) : QtWayland::hyprland_toplevel_window_mapping_handle_v1(mapping) @@ -34,7 +34,7 @@ protected: void hyprland_toplevel_window_mapping_handle_v1_failed() override; private: - qs::wayland::toplevel_management::impl::ToplevelHandle* handle; + qs::wayland::toplevel::wlr::ToplevelHandle* handle; }; class HyprlandToplevelMappingManager @@ -48,22 +48,18 @@ public: static HyprlandToplevelMappingManager* instance(); [[nodiscard]] quint64 - getToplevelAddress(qs::wayland::toplevel_management::impl::ToplevelHandle* handle) const; + getToplevelAddress(qs::wayland::toplevel::wlr::ToplevelHandle* handle) const; signals: - void toplevelAddressed( - qs::wayland::toplevel_management::impl::ToplevelHandle* handle, - quint64 address - ); + void toplevelAddressed(qs::wayland::toplevel::wlr::ToplevelHandle* handle, quint64 address); private slots: - void onToplevelReady(qs::wayland::toplevel_management::impl::ToplevelHandle* handle); + void onToplevelReady(qs::wayland::toplevel::wlr::ToplevelHandle* handle); void onToplevelDestroyed(QObject* object); private: - void - assignAddress(qs::wayland::toplevel_management::impl::ToplevelHandle* handle, quint64 address); - QHash addresses; + void assignAddress(qs::wayland::toplevel::wlr::ToplevelHandle* handle, quint64 address); + QHash addresses; friend class HyprlandToplevelMappingHandle; }; diff --git a/src/wayland/module.md b/src/wayland/module.md index 964fa76..1e34988 100644 --- a/src/wayland/module.md +++ b/src/wayland/module.md @@ -3,7 +3,7 @@ description = "Wayland specific Quickshell types" headers = [ "wlr_layershell/wlr_layershell.hpp", "session_lock.hpp", - "toplevel_management/qml.hpp", + "toplevel/qml.hpp", "screencopy/view.hpp", "idle_inhibit/inhibitor.hpp", "idle_notify/monitor.hpp", diff --git a/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.cpp b/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.cpp index 6fc2955..678c000 100644 --- a/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.cpp +++ b/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.cpp @@ -9,7 +9,7 @@ #include #include "../../../core/logcat.hpp" -#include "../../toplevel_management/handle.hpp" +#include "../../toplevel/wlr_toplevel.hpp" #include "../manager.hpp" #include "hyprland_screencopy_p.hpp" @@ -29,7 +29,7 @@ HyprlandScreencopyManager* HyprlandScreencopyManager::instance() { } ScreencopyContext* HyprlandScreencopyManager::captureToplevel( - toplevel_management::impl::ToplevelHandle* handle, + toplevel::wlr::ToplevelHandle* handle, bool paintCursors ) { return new HyprlandScreencopyContext(this, handle, paintCursors); @@ -37,7 +37,7 @@ ScreencopyContext* HyprlandScreencopyManager::captureToplevel( HyprlandScreencopyContext::HyprlandScreencopyContext( HyprlandScreencopyManager* manager, - toplevel_management::impl::ToplevelHandle* handle, + toplevel::wlr::ToplevelHandle* handle, bool paintCursors ) : manager(manager) diff --git a/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.hpp b/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.hpp index fbd08c5..b9c555c 100644 --- a/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.hpp +++ b/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy.hpp @@ -3,7 +3,7 @@ #include #include -#include "../../toplevel_management/handle.hpp" +#include "../../toplevel/wlr_toplevel.hpp" #include "../manager.hpp" namespace qs::wayland::screencopy::hyprland { @@ -12,8 +12,7 @@ class HyprlandScreencopyManager : public QWaylandClientExtensionTemplate , public QtWayland::hyprland_toplevel_export_manager_v1 { public: - ScreencopyContext* - captureToplevel(toplevel_management::impl::ToplevelHandle* handle, bool paintCursors); + ScreencopyContext* captureToplevel(toplevel::wlr::ToplevelHandle* handle, bool paintCursors); static HyprlandScreencopyManager* instance(); diff --git a/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy_p.hpp b/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy_p.hpp index 199390e..b3f588e 100644 --- a/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy_p.hpp +++ b/src/wayland/screencopy/hyprland_screencopy/hyprland_screencopy_p.hpp @@ -3,7 +3,7 @@ #include #include -#include "../../toplevel_management/handle.hpp" +#include "../../toplevel/wlr_toplevel.hpp" #include "../manager.hpp" namespace qs::wayland::screencopy::hyprland { @@ -16,7 +16,7 @@ class HyprlandScreencopyContext public: explicit HyprlandScreencopyContext( HyprlandScreencopyManager* manager, - toplevel_management::impl::ToplevelHandle* handle, + toplevel::wlr::ToplevelHandle* handle, bool paintCursors ); @@ -43,7 +43,7 @@ private: buffer::WlBufferRequest request; bool copiedFirstFrame = false; - toplevel_management::impl::ToplevelHandle* handle; + toplevel::wlr::ToplevelHandle* handle; bool paintCursors; }; diff --git a/src/wayland/screencopy/manager.cpp b/src/wayland/screencopy/manager.cpp index 8345e31..37ef038 100644 --- a/src/wayland/screencopy/manager.cpp +++ b/src/wayland/screencopy/manager.cpp @@ -17,7 +17,7 @@ #endif #if SCREENCOPY_HYPRLAND_TOPLEVEL -#include "../toplevel_management/qml.hpp" +#include "../toplevel/qml.hpp" #include "hyprland_screencopy/hyprland_screencopy.hpp" #endif @@ -42,7 +42,7 @@ ScreencopyContext* ScreencopyManager::createContext(QObject* object, bool paintC } #endif #if SCREENCOPY_HYPRLAND_TOPLEVEL - } else if (auto* toplevel = qobject_cast(object)) { + } else if (auto* toplevel = qobject_cast(object)) { auto* manager = hyprland::HyprlandScreencopyManager::instance(); if (manager->isActive()) { return manager->captureToplevel(toplevel->implHandle(), paintCursors); diff --git a/src/wayland/toplevel_management/CMakeLists.txt b/src/wayland/toplevel/CMakeLists.txt similarity index 96% rename from src/wayland/toplevel_management/CMakeLists.txt rename to src/wayland/toplevel/CMakeLists.txt index 97f8c7a..0c1d555 100644 --- a/src/wayland/toplevel_management/CMakeLists.txt +++ b/src/wayland/toplevel/CMakeLists.txt @@ -1,6 +1,5 @@ qt_add_library(quickshell-wayland-toplevel-management STATIC - manager.cpp - handle.cpp + wlr_toplevel.cpp qml.cpp ) diff --git a/src/wayland/toplevel_management/qml.cpp b/src/wayland/toplevel/qml.cpp similarity index 79% rename from src/wayland/toplevel_management/qml.cpp rename to src/wayland/toplevel/qml.cpp index cb53381..ea09e09 100644 --- a/src/wayland/toplevel_management/qml.cpp +++ b/src/wayland/toplevel/qml.cpp @@ -10,23 +10,22 @@ #include "../../core/util.hpp" #include "../../window/proxywindow.hpp" #include "../output_tracking.hpp" -#include "handle.hpp" -#include "manager.hpp" +#include "wlr_toplevel.hpp" -namespace qs::wayland::toplevel_management { +namespace qs::wayland::toplevel { -Toplevel::Toplevel(impl::ToplevelHandle* handle, QObject* parent): QObject(parent), handle(handle) { +Toplevel::Toplevel(wlr::ToplevelHandle* handle, QObject* parent): QObject(parent), handle(handle) { // clang-format off - QObject::connect(handle, &impl::ToplevelHandle::closed, this, &Toplevel::onClosed); - QObject::connect(handle, &impl::ToplevelHandle::appIdChanged, this, &Toplevel::appIdChanged); - QObject::connect(handle, &impl::ToplevelHandle::titleChanged, this, &Toplevel::titleChanged); - QObject::connect(handle, &impl::ToplevelHandle::parentChanged, this, &Toplevel::parentChanged); - QObject::connect(handle, &impl::ToplevelHandle::activatedChanged, this, &Toplevel::activatedChanged); + QObject::connect(handle, &wlr::ToplevelHandle::closed, this, &Toplevel::onClosed); + QObject::connect(handle, &wlr::ToplevelHandle::appIdChanged, this, &Toplevel::appIdChanged); + QObject::connect(handle, &wlr::ToplevelHandle::titleChanged, this, &Toplevel::titleChanged); + QObject::connect(handle, &wlr::ToplevelHandle::parentChanged, this, &Toplevel::parentChanged); + QObject::connect(handle, &wlr::ToplevelHandle::activatedChanged, this, &Toplevel::activatedChanged); QObject::connect(&handle->visibleScreens, &WlOutputTracker::screenAdded, this, &Toplevel::screensChanged); QObject::connect(&handle->visibleScreens, &WlOutputTracker::screenRemoved, this, &Toplevel::screensChanged); - QObject::connect(handle, &impl::ToplevelHandle::maximizedChanged, this, &Toplevel::maximizedChanged); - QObject::connect(handle, &impl::ToplevelHandle::minimizedChanged, this, &Toplevel::minimizedChanged); - QObject::connect(handle, &impl::ToplevelHandle::fullscreenChanged, this, &Toplevel::fullscreenChanged); + QObject::connect(handle, &wlr::ToplevelHandle::maximizedChanged, this, &Toplevel::maximizedChanged); + QObject::connect(handle, &wlr::ToplevelHandle::minimizedChanged, this, &Toplevel::minimizedChanged); + QObject::connect(handle, &wlr::ToplevelHandle::fullscreenChanged, this, &Toplevel::fullscreenChanged); // clang-format on } @@ -114,11 +113,11 @@ void Toplevel::onRectangleProxyDestroyed() { } ToplevelManager::ToplevelManager() { - auto* manager = impl::ToplevelManager::instance(); + auto* manager = wlr::ToplevelManager::instance(); QObject::connect( manager, - &impl::ToplevelManager::toplevelReady, + &wlr::ToplevelManager::toplevelReady, this, &ToplevelManager::onToplevelReady ); @@ -128,7 +127,7 @@ ToplevelManager::ToplevelManager() { } } -Toplevel* ToplevelManager::forImpl(impl::ToplevelHandle* impl) const { +Toplevel* ToplevelManager::forImpl(wlr::ToplevelHandle* impl) const { if (impl == nullptr) return nullptr; for (auto* toplevel: this->mToplevels.valueList()) { @@ -140,7 +139,7 @@ Toplevel* ToplevelManager::forImpl(impl::ToplevelHandle* impl) const { ObjectModel* ToplevelManager::toplevels() { return &this->mToplevels; } -void ToplevelManager::onToplevelReady(impl::ToplevelHandle* handle) { +void ToplevelManager::onToplevelReady(wlr::ToplevelHandle* handle) { auto* toplevel = new Toplevel(handle, this); // clang-format off @@ -191,4 +190,4 @@ Toplevel* ToplevelManagerQml::activeToplevel() { return ToplevelManager::instance()->activeToplevel(); } -} // namespace qs::wayland::toplevel_management +} // namespace qs::wayland::toplevel diff --git a/src/wayland/toplevel_management/qml.hpp b/src/wayland/toplevel/qml.hpp similarity index 87% rename from src/wayland/toplevel_management/qml.hpp rename to src/wayland/toplevel/qml.hpp index 5ca189b..72ceb1a 100644 --- a/src/wayland/toplevel_management/qml.hpp +++ b/src/wayland/toplevel/qml.hpp @@ -11,12 +11,12 @@ #include "../../core/util.hpp" #include "../../window/proxywindow.hpp" -namespace qs::wayland::toplevel_management { +namespace qs::wayland::toplevel { -namespace impl { +namespace wlr { class ToplevelManager; // NOLINT class ToplevelHandle; -} // namespace impl +} // namespace wlr ///! Window from another application. /// A window/toplevel from another application, retrievable from @@ -26,7 +26,7 @@ class Toplevel: public QObject { Q_PROPERTY(QString appId READ appId NOTIFY appIdChanged); Q_PROPERTY(QString title READ title NOTIFY titleChanged); /// Parent toplevel if this toplevel is a modal/dialog, otherwise null. - Q_PROPERTY(qs::wayland::toplevel_management::Toplevel* parent READ parent NOTIFY parentChanged); + Q_PROPERTY(qs::wayland::toplevel::Toplevel* parent READ parent NOTIFY parentChanged); /// If the window is currently activated or focused. /// /// Activation can be requested with the @@activate() function. @@ -56,7 +56,7 @@ class Toplevel: public QObject { QML_UNCREATABLE("Toplevels must be acquired from the ToplevelManager."); public: - explicit Toplevel(impl::ToplevelHandle* handle, QObject* parent); + explicit Toplevel(wlr::ToplevelHandle* handle, QObject* parent); /// Request that this toplevel is activated. /// The request may be ignored by the compositor. @@ -91,7 +91,7 @@ public: [[nodiscard]] bool fullscreen() const; void setFullscreen(bool fullscreen); - [[nodiscard]] impl::ToplevelHandle* implHandle() const { return this->handle; } + [[nodiscard]] wlr::ToplevelHandle* implHandle() const { return this->handle; } signals: void closed(); @@ -110,7 +110,7 @@ private slots: void onRectangleProxyDestroyed(); private: - impl::ToplevelHandle* handle; + wlr::ToplevelHandle* handle; ProxyWindowBase* rectWindow = nullptr; QRect rectangle; @@ -121,7 +121,7 @@ class ToplevelManager: public QObject { Q_OBJECT; public: - Toplevel* forImpl(impl::ToplevelHandle* impl) const; + Toplevel* forImpl(wlr::ToplevelHandle* impl) const; [[nodiscard]] ObjectModel* toplevels(); @@ -131,7 +131,7 @@ signals: void activeToplevelChanged(); private slots: - void onToplevelReady(impl::ToplevelHandle* handle); + void onToplevelReady(wlr::ToplevelHandle* handle); void onToplevelActiveChanged(); void onToplevelClosed(); @@ -158,13 +158,13 @@ class ToplevelManagerQml: public QObject { Q_OBJECT; // clang-format off /// All toplevel windows exposed by the compositor. - QSDOC_TYPE_OVERRIDE(ObjectModel*); + QSDOC_TYPE_OVERRIDE(ObjectModel*); Q_PROPERTY(UntypedObjectModel* toplevels READ toplevels CONSTANT); /// Active toplevel or null. /// /// > [!INFO] If multiple are active, this will be the most recently activated one. /// > Usually compositors will not report more than one toplevel as active at a time. - Q_PROPERTY(qs::wayland::toplevel_management::Toplevel* activeToplevel READ activeToplevel NOTIFY activeToplevelChanged); + Q_PROPERTY(qs::wayland::toplevel::Toplevel* activeToplevel READ activeToplevel NOTIFY activeToplevelChanged); // clang-format on QML_NAMED_ELEMENT(ToplevelManager); QML_SINGLETON; @@ -179,4 +179,4 @@ signals: void activeToplevelChanged(); }; -} // namespace qs::wayland::toplevel_management +} // namespace qs::wayland::toplevel diff --git a/src/wayland/toplevel_management/wlr-foreign-toplevel-management-unstable-v1.xml b/src/wayland/toplevel/wlr-foreign-toplevel-management-unstable-v1.xml similarity index 100% rename from src/wayland/toplevel_management/wlr-foreign-toplevel-management-unstable-v1.xml rename to src/wayland/toplevel/wlr-foreign-toplevel-management-unstable-v1.xml diff --git a/src/wayland/toplevel_management/handle.cpp b/src/wayland/toplevel/wlr_toplevel.cpp similarity index 78% rename from src/wayland/toplevel_management/handle.cpp rename to src/wayland/toplevel/wlr_toplevel.cpp index 914e44e..fe6f1b3 100644 --- a/src/wayland/toplevel_management/handle.cpp +++ b/src/wayland/toplevel/wlr_toplevel.cpp @@ -1,4 +1,4 @@ -#include "handle.hpp" +#include "wlr_toplevel.hpp" #include #include @@ -13,13 +13,66 @@ #include #include #include +#include #include -#include "manager.hpp" +#include "../../core/logcat.hpp" #include "qwayland-wlr-foreign-toplevel-management-unstable-v1.h" #include "wayland-wlr-foreign-toplevel-management-unstable-v1-client-protocol.h" -namespace qs::wayland::toplevel_management::impl { +namespace qs::wayland::toplevel::wlr { + +QS_LOGGING_CATEGORY(logToplevelManagement, "quickshell.wayland.toplevelManagement", QtWarningMsg); + +ToplevelManager::ToplevelManager(): QWaylandClientExtensionTemplate(3) { this->initialize(); } + +bool ToplevelManager::available() const { return this->isActive(); } + +const QVector& ToplevelManager::readyToplevels() const { + return this->mReadyToplevels; +} + +ToplevelHandle* ToplevelManager::handleFor(::zwlr_foreign_toplevel_handle_v1* toplevel) { + if (toplevel == nullptr) return nullptr; + + for (auto* other: this->mToplevels) { + if (other->object() == toplevel) return other; + } + + return nullptr; +} + +ToplevelManager* ToplevelManager::instance() { + static auto* instance = new ToplevelManager(); // NOLINT + return instance; +} + +void ToplevelManager::zwlr_foreign_toplevel_manager_v1_toplevel( + ::zwlr_foreign_toplevel_handle_v1* toplevel +) { + auto* handle = new ToplevelHandle(); + QObject::connect(handle, &ToplevelHandle::closed, this, &ToplevelManager::onToplevelClosed); + QObject::connect(handle, &ToplevelHandle::ready, this, &ToplevelManager::onToplevelReady); + + qCDebug(logToplevelManagement) << "Toplevel handle created" << handle; + this->mToplevels.push_back(handle); + + // Not done in constructor as a close could technically be picked up immediately on init, + // making touching the handle a UAF. + handle->init(toplevel); +} + +void ToplevelManager::onToplevelReady() { + auto* handle = qobject_cast(this->sender()); + this->mReadyToplevels.push_back(handle); + emit this->toplevelReady(handle); +} + +void ToplevelManager::onToplevelClosed() { + auto* handle = qobject_cast(this->sender()); + this->mReadyToplevels.removeOne(handle); + this->mToplevels.removeOne(handle); +} QString ToplevelHandle::appId() const { return this->mAppId; } QString ToplevelHandle::title() const { return this->mTitle; } @@ -215,4 +268,4 @@ void ToplevelHandle::onParentClosed() { emit this->parentChanged(); } -} // namespace qs::wayland::toplevel_management::impl +} // namespace qs::wayland::toplevel::wlr diff --git a/src/wayland/toplevel_management/handle.hpp b/src/wayland/toplevel/wlr_toplevel.hpp similarity index 66% rename from src/wayland/toplevel_management/handle.hpp rename to src/wayland/toplevel/wlr_toplevel.hpp index 92531a5..2c69fcd 100644 --- a/src/wayland/toplevel_management/handle.hpp +++ b/src/wayland/toplevel/wlr_toplevel.hpp @@ -1,15 +1,23 @@ #pragma once +#include #include +#include #include +#include #include +#include #include +#include #include +#include "../../core/logcat.hpp" #include "../output_tracking.hpp" #include "wayland-wlr-foreign-toplevel-management-unstable-v1-client-protocol.h" -namespace qs::wayland::toplevel_management::impl { +namespace qs::wayland::toplevel::wlr { + +QS_DECLARE_LOGGING_CATEGORY(logToplevelManagement); class ToplevelHandle : public QObject @@ -73,4 +81,34 @@ private: QWindow* rectWindow = nullptr; }; -} // namespace qs::wayland::toplevel_management::impl +class ToplevelManager + : public QWaylandClientExtensionTemplate + , public QtWayland::zwlr_foreign_toplevel_manager_v1 { + Q_OBJECT; + +public: + [[nodiscard]] bool available() const; + [[nodiscard]] const QVector& readyToplevels() const; + [[nodiscard]] ToplevelHandle* handleFor(::zwlr_foreign_toplevel_handle_v1* toplevel); + + static ToplevelManager* instance(); + +signals: + void toplevelReady(ToplevelHandle* toplevel); + +protected: + explicit ToplevelManager(); + + void + zwlr_foreign_toplevel_manager_v1_toplevel(::zwlr_foreign_toplevel_handle_v1* toplevel) override; + +private slots: + void onToplevelReady(); + void onToplevelClosed(); + +private: + QVector mToplevels; + QVector mReadyToplevels; +}; + +} // namespace qs::wayland::toplevel::wlr diff --git a/src/wayland/toplevel_management/manager.cpp b/src/wayland/toplevel_management/manager.cpp deleted file mode 100644 index 471d7e2..0000000 --- a/src/wayland/toplevel_management/manager.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "manager.hpp" - -#include -#include -#include -#include -#include -#include - -#include "../../core/logcat.hpp" -#include "handle.hpp" -#include "wayland-wlr-foreign-toplevel-management-unstable-v1-client-protocol.h" - -namespace qs::wayland::toplevel_management::impl { - -QS_LOGGING_CATEGORY(logToplevelManagement, "quickshell.wayland.toplevelManagement", QtWarningMsg); - -ToplevelManager::ToplevelManager(): QWaylandClientExtensionTemplate(3) { this->initialize(); } - -bool ToplevelManager::available() const { return this->isActive(); } - -const QVector& ToplevelManager::readyToplevels() const { - return this->mReadyToplevels; -} - -ToplevelHandle* ToplevelManager::handleFor(::zwlr_foreign_toplevel_handle_v1* toplevel) { - if (toplevel == nullptr) return nullptr; - - for (auto* other: this->mToplevels) { - if (other->object() == toplevel) return other; - } - - return nullptr; -} - -ToplevelManager* ToplevelManager::instance() { - static auto* instance = new ToplevelManager(); // NOLINT - return instance; -} - -void ToplevelManager::zwlr_foreign_toplevel_manager_v1_toplevel( - ::zwlr_foreign_toplevel_handle_v1* toplevel -) { - auto* handle = new ToplevelHandle(); - QObject::connect(handle, &ToplevelHandle::closed, this, &ToplevelManager::onToplevelClosed); - QObject::connect(handle, &ToplevelHandle::ready, this, &ToplevelManager::onToplevelReady); - - qCDebug(logToplevelManagement) << "Toplevel handle created" << handle; - this->mToplevels.push_back(handle); - - // Not done in constructor as a close could technically be picked up immediately on init, - // making touching the handle a UAF. - handle->init(toplevel); -} - -void ToplevelManager::onToplevelReady() { - auto* handle = qobject_cast(this->sender()); - this->mReadyToplevels.push_back(handle); - emit this->toplevelReady(handle); -} - -void ToplevelManager::onToplevelClosed() { - auto* handle = qobject_cast(this->sender()); - this->mReadyToplevels.removeOne(handle); - this->mToplevels.removeOne(handle); -} - -} // namespace qs::wayland::toplevel_management::impl diff --git a/src/wayland/toplevel_management/manager.hpp b/src/wayland/toplevel_management/manager.hpp deleted file mode 100644 index 83e3e09..0000000 --- a/src/wayland/toplevel_management/manager.hpp +++ /dev/null @@ -1,48 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -#include "../../core/logcat.hpp" -#include "wayland-wlr-foreign-toplevel-management-unstable-v1-client-protocol.h" - -namespace qs::wayland::toplevel_management::impl { - -class ToplevelHandle; - -QS_DECLARE_LOGGING_CATEGORY(logToplevelManagement); - -class ToplevelManager - : public QWaylandClientExtensionTemplate - , public QtWayland::zwlr_foreign_toplevel_manager_v1 { - Q_OBJECT; - -public: - [[nodiscard]] bool available() const; - [[nodiscard]] const QVector& readyToplevels() const; - [[nodiscard]] ToplevelHandle* handleFor(::zwlr_foreign_toplevel_handle_v1* toplevel); - - static ToplevelManager* instance(); - -signals: - void toplevelReady(ToplevelHandle* toplevel); - -protected: - explicit ToplevelManager(); - - void - zwlr_foreign_toplevel_manager_v1_toplevel(::zwlr_foreign_toplevel_handle_v1* toplevel) override; - -private slots: - void onToplevelReady(); - void onToplevelClosed(); - -private: - QVector mToplevels; - QVector mReadyToplevels; -}; - -} // namespace qs::wayland::toplevel_management::impl