kranewl

A wlroots-based dynamic Wayland compositor, written in C++, configurable with Lua
git clone git://git.deurzen.net/kranewl
Log | Files | Refs | LICENSE

commit 7c349df1f9bbb84e0d947731dab5cb936d9a1ce6
parent c5f3ea929d9bb9703d3ab6872516ff243dcba133
Author: deurzen <max@deurzen.net>
Date:   Thu,  2 Jun 2022 18:20:07 +0200

implements XDG decoration request handling

Diffstat:
Minclude/kranewl/server.hh | 9+++++++--
Minclude/kranewl/tree/xdg-view.hh | 3+++
Ainclude/kranewl/xdg-decoration.hh | 42++++++++++++++++++++++++++++++++++++++++++
Msrc/kranewl/server.cc | 24++++++++++++++++--------
Msrc/kranewl/tree/xdg-view.cc | 5+++++
Asrc/kranewl/xdg-decoration.cc | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 140 insertions(+), 10 deletions(-)

diff --git a/include/kranewl/server.hh b/include/kranewl/server.hh @@ -2,6 +2,7 @@ #include <kranewl/geometry.hh> #include <kranewl/input/seat.hh> +#include <kranewl/xdg-decoration.hh> #include <kranewl/xwayland.hh> extern "C" { @@ -13,10 +14,12 @@ extern "C" { #include <array> #include <cstdint> #include <string> +#include <unordered_map> typedef class Model* Model_ptr; typedef class Server* Server_ptr; typedef struct View* View_ptr; +typedef struct XDGDecoration* XDGDecoration_ptr; typedef class Server final { public: @@ -38,7 +41,7 @@ private: static void handle_new_xdg_surface(struct wl_listener*, void*); static void handle_new_layer_shell_surface(struct wl_listener*, void*); static void handle_new_input(struct wl_listener*, void*); - static void handle_xdg_new_toplevel_decoration(struct wl_listener*, void*); + static void handle_new_xdg_toplevel_decoration(struct wl_listener*, void*); static void handle_xdg_request_activate(struct wl_listener*, void*); static void handle_new_virtual_keyboard(struct wl_listener*, void*); static void handle_drm_lease_request(struct wl_listener*, void*); @@ -67,6 +70,8 @@ public: struct wlr_output_manager_v1* mp_output_manager; struct wlr_drm_lease_v1_manager* mp_drm_lease_manager; + std::unordered_map<Uid, XDGDecoration_ptr> m_decorations; + private: struct wlr_xdg_shell* mp_xdg_shell; struct wlr_layer_shell_v1* mp_layer_shell; @@ -84,7 +89,7 @@ private: struct wl_listener ml_new_xdg_surface; struct wl_listener ml_new_layer_shell_surface; struct wl_listener ml_new_input; - struct wl_listener ml_xdg_new_toplevel_decoration; + struct wl_listener ml_new_xdg_toplevel_decoration; struct wl_listener ml_xdg_request_activate; struct wl_listener ml_new_virtual_keyboard; struct wl_listener ml_drm_lease_request; diff --git a/include/kranewl/tree/xdg-view.hh b/include/kranewl/tree/xdg-view.hh @@ -11,6 +11,7 @@ typedef class Seat* Seat_ptr; typedef class Output* Output_ptr; typedef class Context* Context_ptr; typedef class Workspace* Workspace_ptr; +typedef struct XDGDecoration* XDGDecoration_ptr; typedef struct XDGView final : public View { XDGView( @@ -48,6 +49,8 @@ typedef struct XDGView final : public View { struct wlr_xdg_surface* mp_wlr_xdg_surface; struct wlr_xdg_toplevel* mp_wlr_xdg_toplevel; + XDGDecoration_ptr mp_decoration; + struct wl_listener ml_commit; struct wl_listener ml_request_move; struct wl_listener ml_request_resize; diff --git a/include/kranewl/xdg-decoration.hh b/include/kranewl/xdg-decoration.hh @@ -0,0 +1,42 @@ +#pragma once + +#include <kranewl/common.hh> + +extern "C" { +#include <wayland-server-core.h> +} + +#include <unordered_map> +#include <vector> + +typedef class Server* Server_ptr; +typedef class Model* Model_ptr; +typedef struct XDGView* XDGView_ptr; + +typedef struct XDGDecoration final { +public: + XDGDecoration( + Server_ptr, + Model_ptr, + XDGView_ptr, + struct wlr_xdg_toplevel_decoration_v1* + ); + + ~XDGDecoration(); + + static void handle_request_mode(struct wl_listener*, void*); + static void handle_destroy(struct wl_listener*, void*); + +public: + Uid m_uid; + + Server_ptr mp_server; + Model_ptr mp_model; + XDGView_ptr mp_view; + + struct wlr_xdg_toplevel_decoration_v1* mp_wlr_xdg_decoration; + + struct wl_listener ml_request_mode; + struct wl_listener ml_destroy; + +}* XDGDecoration_ptr; diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc @@ -8,6 +8,7 @@ #include <kranewl/tree/output.hh> #include <kranewl/tree/view.hh> #include <kranewl/tree/xdg-view.hh> +#include <kranewl/xdg-decoration.hh> #ifdef XWAYLAND #include <kranewl/tree/xwayland-view.hh> #include <kranewl/xwayland.hh> @@ -110,7 +111,7 @@ Server::Server(Model_ptr model) ml_new_xdg_surface({ .notify = Server::handle_new_xdg_surface }), ml_new_layer_shell_surface({ .notify = Server::handle_new_layer_shell_surface }), ml_new_input({ .notify = Server::handle_new_input }), - ml_xdg_new_toplevel_decoration({ .notify = Server::handle_xdg_new_toplevel_decoration }), + ml_new_xdg_toplevel_decoration({ .notify = Server::handle_new_xdg_toplevel_decoration }), ml_xdg_request_activate({ .notify = Server::handle_xdg_request_activate }), ml_new_virtual_keyboard({ .notify = Server::handle_new_virtual_keyboard }), ml_drm_lease_request({ .notify = Server::handle_drm_lease_request }) @@ -270,7 +271,7 @@ Server::start() wl_signal_add(&mp_output_layout->events.change, &ml_output_layout_change); wl_signal_add(&mp_layer_shell->events.new_surface, &ml_new_layer_shell_surface); wl_signal_add(&mp_xdg_shell->events.new_surface, &ml_new_xdg_surface); - wl_signal_add(&mp_xdg_decoration_manager->events.new_toplevel_decoration, &ml_xdg_new_toplevel_decoration); + wl_signal_add(&mp_xdg_decoration_manager->events.new_toplevel_decoration, &ml_new_xdg_toplevel_decoration); wl_signal_add(&mp_xdg_activation->events.request_activate, &ml_xdg_request_activate); wl_signal_add(&mp_backend->events.new_input, &ml_new_input); wl_signal_add(&mp_output_manager->events.apply, &ml_output_manager_apply); @@ -613,17 +614,24 @@ Server::handle_new_input(struct wl_listener* listener, void* data) } void -Server::handle_xdg_new_toplevel_decoration(struct wl_listener*, void* data) +Server::handle_new_xdg_toplevel_decoration(struct wl_listener* listener, void* data) { TRACE(); - struct wlr_xdg_toplevel_decoration_v1* decoration + Server_ptr server = wl_container_of(listener, server, ml_new_xdg_toplevel_decoration); + struct wlr_xdg_toplevel_decoration_v1* xdg_decoration = reinterpret_cast<struct wlr_xdg_toplevel_decoration_v1*>(data); + XDGView_ptr view = reinterpret_cast<XDGView_ptr>(xdg_decoration->surface->data); - wlr_xdg_toplevel_decoration_v1_set_mode( - decoration, - WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE - ); + XDGDecoration_ptr decoration + = new XDGDecoration(server, server->mp_model, view, xdg_decoration); + view->mp_decoration = decoration; + server->m_decorations[decoration->m_uid] = decoration; + + wl_signal_add(&xdg_decoration->events.destroy, &decoration->ml_destroy); + wl_signal_add(&xdg_decoration->events.request_mode, &decoration->ml_request_mode); + + XDGDecoration::handle_request_mode(&decoration->ml_request_mode, xdg_decoration); } void diff --git a/src/kranewl/tree/xdg-view.cc b/src/kranewl/tree/xdg-view.cc @@ -19,6 +19,7 @@ extern "C" { #include <wlr/types/wlr_idle_inhibit_v1.h> #include <wlr/types/wlr_layer_shell_v1.h> #include <wlr/types/wlr_scene.h> +#include <wlr/types/wlr_xdg_decoration_v1.h> #include <wlr/types/wlr_xdg_shell.h> } #undef static @@ -41,6 +42,7 @@ XDGView::XDGView( ), mp_wlr_xdg_surface(wlr_xdg_surface), mp_wlr_xdg_toplevel(wlr_xdg_surface->toplevel), + mp_decoration(nullptr), ml_commit({ .notify = XDGView::handle_commit }), ml_request_move({ .notify = XDGView::handle_request_move }), ml_request_resize({ .notify = XDGView::handle_request_resize }), @@ -456,6 +458,9 @@ XDGView::handle_destroy(struct wl_listener* listener, void* data) wl_list_remove(&view->ml_destroy.link); wl_list_remove(&view->m_events.unmap.listener_list); + if (view->mp_decoration) + view->mp_decoration->mp_view = nullptr; + view->mp_wlr_xdg_toplevel = nullptr; view->mp_wlr_xdg_surface = nullptr; view->mp_model->destroy_view(view); diff --git a/src/kranewl/xdg-decoration.cc b/src/kranewl/xdg-decoration.cc @@ -0,0 +1,67 @@ +#include <trace.hh> + +#include <kranewl/server.hh> +#include <kranewl/tree/xdg-view.hh> +#include <kranewl/xdg-decoration.hh> + +extern "C" { +#include <wlr/types/wlr_xdg_decoration_v1.h> +} + +XDGDecoration::XDGDecoration( + Server_ptr server, + Model_ptr model, + XDGView_ptr view, + struct wlr_xdg_toplevel_decoration_v1* wlr_xdg_decoration +) + : m_uid(reinterpret_cast<std::uintptr_t>(wlr_xdg_decoration->surface)), + mp_server(server), + mp_model(model), + mp_view(view), + mp_wlr_xdg_decoration(wlr_xdg_decoration), + ml_request_mode({ .notify = XDGDecoration::handle_request_mode }), + ml_destroy({ .notify = XDGDecoration::handle_destroy }) +{} + +XDGDecoration::~XDGDecoration() +{} + +void +XDGDecoration::handle_request_mode(struct wl_listener* listener, void*) +{ + TRACE(); + + XDGDecoration_ptr decoration + = wl_container_of(listener, decoration, ml_request_mode); + XDGView_ptr view = decoration->mp_view; + + enum wlr_xdg_toplevel_decoration_v1_mode mode + = WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE; + enum wlr_xdg_toplevel_decoration_v1_mode client_mode + = decoration->mp_wlr_xdg_decoration->requested_mode; + + // TODO: allow client_mode if floating + + wlr_xdg_toplevel_decoration_v1_set_mode( + decoration->mp_wlr_xdg_decoration, + mode + ); +} + +void +XDGDecoration::handle_destroy(struct wl_listener* listener, void*) +{ + TRACE(); + + XDGDecoration_ptr decoration + = wl_container_of(listener, decoration, ml_destroy); + if (decoration->mp_view) { + decoration->mp_view->mp_decoration = nullptr; + } + + wl_list_remove(&decoration->ml_destroy.link); + wl_list_remove(&decoration->ml_request_mode.link); + + decoration->mp_server->m_decorations.erase(decoration->m_uid); + delete decoration; +}