diff --git a/src/meson.build b/src/meson.build index 4eaaaa88a..d5bd90a33 100644 --- a/src/meson.build +++ b/src/meson.build @@ -14,6 +14,7 @@ magpie_sources = [ 'surface/popup.cpp', 'surface/subsurface.cpp', 'surface/view.cpp', + 'surface/xdg_decoration.cpp', 'surface/xdg_view.cpp', 'surface/xwayland_view.cpp', budgie_keyboard_shortcuts_protocol, diff --git a/src/server.cpp b/src/server.cpp index 73b617466..dbed9646e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -6,6 +6,7 @@ #include "surface/popup.hpp" #include "surface/surface.hpp" #include "surface/view.hpp" +#include "surface/xdg_decoration.hpp" #include "types.hpp" #include "xwayland.hpp" @@ -253,6 +254,25 @@ static void new_xdg_toplevel_notify(wl_listener* listener, void* data) { server.views.emplace_back(std::make_shared(server, xdg_toplevel)); } +static void new_toplevel_decoration_notify(wl_listener* listener, void* data) { + wlr_log(WLR_DEBUG, "wlr_xdg_decoration_v1.events.new_toplevel_decoration(listener=%p, data=%p)", (void*) listener, data); + + if (data == nullptr) { + wlr_log(WLR_ERROR, "No data passed to wlr_xdg_decoration_v1.events.new_toplevel_decoration"); + return; + } + + auto& xdg_toplevel_decoration = *static_cast(data); + + auto* view = static_cast(xdg_toplevel_decoration.toplevel->base->data); + if (view == nullptr) { + wlr_log(WLR_ERROR, "xdg_toplevel_decoration_v1 created for toplevel surface without data ptr set"); + return; + } + + view->set_decoration(std::make_shared(*view, xdg_toplevel_decoration)); +} + static void new_layer_surface_notify(wl_listener* listener, void* data) { wlr_log(WLR_DEBUG, "wlr_layer_shell_v1.events.new_surface(listener=%p, data=%p)", (void*) listener, data); @@ -579,6 +599,10 @@ Server::Server() : listeners(*this) { listeners.xdg_shell_new_xdg_toplevel.notify = new_xdg_toplevel_notify; wl_signal_add(&xdg_shell->events.new_toplevel, &listeners.xdg_shell_new_xdg_toplevel); + xdg_decoration_manager = wlr_xdg_decoration_manager_v1_create(display); + listeners.xdg_decoration_new_toplevel_decoration.notify = new_toplevel_decoration_notify; + wl_signal_add(&xdg_decoration_manager->events.new_toplevel_decoration, &listeners.xdg_decoration_new_toplevel_decoration); + layer_shell = wlr_layer_shell_v1_create(display, 4); listeners.layer_shell_new_layer_surface.notify = new_layer_surface_notify; wl_signal_add(&layer_shell->events.new_surface, &listeners.layer_shell_new_layer_surface); diff --git a/src/server.hpp b/src/server.hpp index d1747305b..ed9935a2b 100644 --- a/src/server.hpp +++ b/src/server.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "wlr-wrap-end.hpp" @@ -43,6 +44,7 @@ class Server final : public std::enable_shared_from_this { struct Listeners { std::reference_wrapper parent; wl_listener xdg_shell_new_xdg_toplevel = {}; + wl_listener xdg_decoration_new_toplevel_decoration = {}; wl_listener layer_shell_new_layer_surface = {}; wl_listener activation_request_activation = {}; wl_listener backend_new_output = {}; @@ -71,6 +73,7 @@ class Server final : public std::enable_shared_from_this { std::array scene_layers = {}; wlr_xdg_shell* xdg_shell; + wlr_xdg_decoration_manager_v1* xdg_decoration_manager; wlr_xdg_activation_v1* xdg_activation; diff --git a/src/surface/view.hpp b/src/surface/view.hpp index 26de9daa7..bfc0fc76e 100644 --- a/src/surface/view.hpp +++ b/src/surface/view.hpp @@ -91,6 +91,7 @@ class XdgView final : public View { public: Server& server; wlr_xdg_toplevel& wlr; + std::shared_ptr deco = nullptr; XdgView(Server& server, wlr_xdg_toplevel& xdg_toplevel) noexcept; ~XdgView() noexcept override; @@ -106,6 +107,8 @@ class XdgView final : public View { void unmap() override; void close() override; + void set_decoration(std::shared_ptr deco); + protected: void impl_set_position(int32_t x, int32_t y) override; void impl_set_size(int32_t width, int32_t height) override; diff --git a/src/surface/xdg_decoration.cpp b/src/surface/xdg_decoration.cpp new file mode 100644 index 000000000..3fb3bb843 --- /dev/null +++ b/src/surface/xdg_decoration.cpp @@ -0,0 +1,25 @@ +#include "xdg_decoration.hpp" + +#include "view.hpp" + +#include "wlr-wrap-start.hpp" +#include +#include "wlr-wrap-end.hpp" + +static void xdg_decoration_destroy_notify(wl_listener* listener, [[maybe_unused]] void* data) { + wlr_log(WLR_DEBUG, "wlr_xdg_toplevel_decoration_v1.events.destroy(listener=%p, data=%p)", (void*) listener, data); + + XdgDecoration& deco = magpie_container_of(listener, deco, destroy); + + deco.view.set_decoration(nullptr); +} + +XdgDecoration::XdgDecoration(XdgView& view, wlr_xdg_toplevel_decoration_v1& deco) noexcept + : listeners(*this), view(view), wlr(deco) { + listeners.destroy.notify = xdg_decoration_destroy_notify; + wl_signal_add(&deco.events.destroy, &listeners.destroy); +} + +XdgDecoration::~XdgDecoration() noexcept { + wl_list_remove(&listeners.destroy.link); +} diff --git a/src/surface/xdg_decoration.hpp b/src/surface/xdg_decoration.hpp new file mode 100644 index 000000000..df1fb3e72 --- /dev/null +++ b/src/surface/xdg_decoration.hpp @@ -0,0 +1,31 @@ +#ifndef MAGPIE_XDG_DECORATION_HPP +#define MAGPIE_XDG_DECORATION_HPP + +#include "types.hpp" + +#include + +#include "wlr-wrap-start.hpp" +#include +#include "wlr-wrap-end.hpp" + +class XdgDecoration : public std::enable_shared_from_this { + public: + struct Listeners { + std::reference_wrapper parent; + wl_listener destroy = {}; + explicit Listeners(XdgDecoration& parent) noexcept : parent(parent) {} + }; + + private: + Listeners listeners; + + public: + XdgView& view; + wlr_xdg_toplevel_decoration_v1& wlr; + + XdgDecoration(XdgView& view, wlr_xdg_toplevel_decoration_v1& deco) noexcept; + ~XdgDecoration() noexcept; +}; + +#endif diff --git a/src/surface/xdg_view.cpp b/src/surface/xdg_view.cpp index 5efa45706..56c6a9b0b 100644 --- a/src/surface/xdg_view.cpp +++ b/src/surface/xdg_view.cpp @@ -193,6 +193,7 @@ XdgView::XdgView(Server& server, wlr_xdg_toplevel& xdg_toplevel) noexcept scene_node = &scene_tree->node; scene_node->data = this; + wlr.base->data = this; wlr.base->surface->data = this; toplevel_handle.emplace(*this); @@ -321,6 +322,10 @@ void XdgView::close() { wlr_xdg_toplevel_send_close(&wlr); } +void XdgView::set_decoration(std::shared_ptr new_deco) { + this->deco = std::move(new_deco); +} + void XdgView::impl_set_position(const int32_t x, const int32_t y) { (void) x; (void) y; diff --git a/src/types.hpp b/src/types.hpp index aaef110af..7fda521fd 100644 --- a/src/types.hpp +++ b/src/types.hpp @@ -13,6 +13,7 @@ class PointerConstraint; struct Surface; struct View; class XdgView; +class XdgDecoration; class XWaylandView; class Layer; class Subsurface;