commit 7c349df1f9bbb84e0d947731dab5cb936d9a1ce6
parent c5f3ea929d9bb9703d3ab6872516ff243dcba133
Author: deurzen <max@deurzen.net>
Date: Thu, 2 Jun 2022 18:20:07 +0200
implements XDG decoration request handling
Diffstat:
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;
+}