From 5bd1c6561cc461eb0e9bda901ae8130b8fe4f401 Mon Sep 17 00:00:00 2001 From: AstralZX <208268648+AstralZX@users.noreply.github.com> Date: Sat, 29 Aug 2026 10:01:39 +0200 Subject: [PATCH] add xdg decoration, scene/tree factories, geometry + seat focus more wrapper soup. xdg decoration manager, scene/tree node factories so callers stop touching raw wlr_scene_*_create, a box geometry helper, and seat pointer/keyboard focus clearing. dragging myself through it. --- include/wlr/box.hpp | 40 +++++++++++++++++++++++ include/wlr/color.hpp | 41 +++++++++++++++++++++++ include/wlr/node.hpp | 30 ++++++++++------- include/wlr/output.hpp | 14 ++++++++ include/wlr/scene.hpp | 42 ++++++------------------ include/wlr/seat.hpp | 10 ++++++ include/wlr/wlr.hpp | 2 ++ include/wlr/xdg_decoration.hpp | 59 ++++++++++++++++++++++++++++++++++ src/wlrootspp.cpp | 2 ++ 9 files changed, 197 insertions(+), 43 deletions(-) create mode 100644 include/wlr/box.hpp create mode 100644 include/wlr/color.hpp create mode 100644 include/wlr/xdg_decoration.hpp diff --git a/include/wlr/box.hpp b/include/wlr/box.hpp new file mode 100644 index 0000000..07c974b --- /dev/null +++ b/include/wlr/box.hpp @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: AGPL-3.0-only +#pragma once + +#include + +#include "wlr/wlr.hpp" + +namespace wlr { + +class Geometry { +public: + Geometry() = default; + Geometry(int x, int y, int w, int h) : m_box{x, y, w, h} {} + explicit Geometry(const struct wlr_box& b) : m_box(b) {} + + struct wlr_box* raw() { return &m_box; } + const struct wlr_box* raw() const { return &m_box; } + + int x() const { return m_box.x; } + int y() const { return m_box.y; } + int width() const { return m_box.width; } + int height() const { return m_box.height; } + + void set(int x, int y, int w, int h) { + m_box.x = x; m_box.y = y; m_box.width = w; m_box.height = h; + } + + bool contains(double px, double py) const { + return wlr_box_contains_point(&m_box, px, py); + } + bool intersects(const Geometry& o) const { + struct wlr_box dest; + return wlr_box_intersection(&dest, &m_box, &o.m_box); + } + +private: + struct wlr_box m_box{}; +}; + +} diff --git a/include/wlr/color.hpp b/include/wlr/color.hpp new file mode 100644 index 0000000..de1f142 --- /dev/null +++ b/include/wlr/color.hpp @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: AGPL-3.0-only +#pragma once + +#include + +#include "wlr/wlr.hpp" + +namespace wlr { + +struct Box { + int x = 0, y = 0, width = 0, height = 0; + pixman_box32 to_box() const { return {x, y, x + width, y + height}; } + static Box from_box(pixman_box32 b) { + return {b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1}; + } +}; + +struct Color { + float r = 1.0f, g = 1.0f, b = 1.0f, a = 1.0f; + void apply(float out[4]) const { + out[0] = r; out[1] = g; out[2] = b; out[3] = a; + } +}; + +struct CornerRadii { + uint16_t top_left = 0, top_right = 0, bottom_right = 0, bottom_left = 0; + + CornerRadii() = default; + CornerRadii(uint16_t all) : top_left(all), top_right(all), bottom_right(all), bottom_left(all) {} + CornerRadii(uint16_t tl, uint16_t tr, uint16_t br, uint16_t bl) + : top_left(tl), top_right(tr), bottom_right(br), bottom_left(bl) {} + + fx_corner_radii raw() const { + return fx_corner_radii{top_left, top_right, bottom_right, bottom_left}; + } + static CornerRadii from_radii(fx_corner_radii r) { + return {r.top_left, r.top_right, r.bottom_right, r.bottom_left}; + } +}; + +} diff --git a/include/wlr/node.hpp b/include/wlr/node.hpp index 5f68d99..431748c 100644 --- a/include/wlr/node.hpp +++ b/include/wlr/node.hpp @@ -4,7 +4,7 @@ #include #include "wlr/wlr.hpp" -#include "wlr/scene.hpp" +#include "wlr/color.hpp" namespace wlr { @@ -36,16 +36,6 @@ protected: struct wlr_scene_node* m_node; }; -class Tree : public Node { -public: - Tree(struct wlr_scene_tree* tree) : Node(&tree->node), m_tree(tree) {} - struct wlr_scene_tree* raw() const { return m_tree; } - void reparent(Node& n) { wlr_scene_node_reparent(n.raw(), m_tree); } - -private: - struct wlr_scene_tree* m_tree; -}; - class Rect : public Node { public: Rect(struct wlr_scene_rect* rect) : Node(&rect->node), m_rect(rect) {} @@ -127,4 +117,22 @@ private: struct wlr_scene_surface* m_surface; }; +class Tree : public Node { +public: + Tree(struct wlr_scene_tree* tree) : Node(&tree->node), m_tree(tree) {} + struct wlr_scene_tree* raw() const { return m_tree; } + void reparent(Node& n) { wlr_scene_node_reparent(n.raw(), m_tree); } + + Tree add_tree() { return Tree{wlr_scene_tree_create(m_tree)}; } + Rect add_rect(int w, int h, const Color& c) { + float col[4]; c.apply(col); + return Rect{wlr_scene_rect_create(m_tree, w, h, col)}; + } + Buffer add_buffer() { return Buffer{wlr_scene_buffer_create(m_tree, nullptr)}; } + Surface add_surface(struct wlr_surface* s) { return Surface{wlr_scene_surface_create(m_tree, s)}; } + +private: + struct wlr_scene_tree* m_tree; +}; + } diff --git a/include/wlr/output.hpp b/include/wlr/output.hpp index 13d9bab..ca8a1e1 100644 --- a/include/wlr/output.hpp +++ b/include/wlr/output.hpp @@ -19,6 +19,11 @@ public: const char* make() const { return m_output->make; } const char* model() const { return m_output->model; } + int width() const { return m_output->width; } + int height() const { return m_output->height; } + enum wl_output_transform transform() const { return m_output->transform; } + struct wlr_output_mode* current_mode() const { return m_output->current_mode; } + struct wlr_output_mode* preferred_mode() const { return wlr_output_preferred_mode(m_output); } @@ -32,6 +37,15 @@ public: wlr_output_state_finish(&state); return ok; } + bool set_mode(struct wlr_output_mode* mode) { + if (!mode) return false; + struct wlr_output_state state; + wlr_output_state_init(&state); + wlr_output_state_set_mode(&state, mode); + bool ok = wlr_output_commit_state(m_output, &state); + wlr_output_state_finish(&state); + return ok; + } private: struct wlr_output* m_output; diff --git a/include/wlr/scene.hpp b/include/wlr/scene.hpp index c5af9ae..27b4bbb 100644 --- a/include/wlr/scene.hpp +++ b/include/wlr/scene.hpp @@ -1,10 +1,11 @@ // SPDX-License-Identifier: AGPL-3.0-only #pragma once -#include #include #include "wlr/wlr.hpp" +#include "wlr/color.hpp" +#include "wlr/node.hpp" namespace wlr { @@ -36,39 +37,16 @@ public: void set_blur_saturation(float saturation) { wlr_scene_set_blur_saturation(m_scene, saturation); } struct wlr_scene_tree* root() { return &m_scene->tree; } + Tree add_tree() { return Tree{wlr_scene_tree_create(&m_scene->tree)}; } + Rect add_rect(int w, int h, const Color& c) { + float col[4]; c.apply(col); + return Rect{wlr_scene_rect_create(&m_scene->tree, w, h, col)}; + } + Buffer add_buffer() { return Buffer{wlr_scene_buffer_create(&m_scene->tree, nullptr)}; } + Surface add_surface(struct wlr_surface* s) { return Surface{wlr_scene_surface_create(&m_scene->tree, s)}; } + private: struct wlr_scene* m_scene; }; -struct Box { - int x = 0, y = 0, width = 0, height = 0; - pixman_box32 to_box() const { return {x, y, x + width, y + height}; } - static Box from_box(pixman_box32 b) { - return {b.x1, b.y1, b.x2 - b.x1, b.y2 - b.y1}; - } -}; - -struct Color { - float r = 1.0f, g = 1.0f, b = 1.0f, a = 1.0f; - void apply(float out[4]) const { - out[0] = r; out[1] = g; out[2] = b; out[3] = a; - } -}; - -struct CornerRadii { - uint16_t top_left = 0, top_right = 0, bottom_right = 0, bottom_left = 0; - - CornerRadii() = default; - CornerRadii(uint16_t all) : top_left(all), top_right(all), bottom_right(all), bottom_left(all) {} - CornerRadii(uint16_t tl, uint16_t tr, uint16_t br, uint16_t bl) - : top_left(tl), top_right(tr), bottom_right(br), bottom_left(bl) {} - - fx_corner_radii raw() const { - return fx_corner_radii{top_left, top_right, bottom_right, bottom_left}; - } - static CornerRadii from_radii(fx_corner_radii r) { - return {r.top_left, r.top_right, r.bottom_right, r.bottom_left}; - } -}; - } diff --git a/include/wlr/seat.hpp b/include/wlr/seat.hpp index 4628b31..eecb1a7 100644 --- a/include/wlr/seat.hpp +++ b/include/wlr/seat.hpp @@ -71,6 +71,16 @@ public: void keyboard_notify_key(uint32_t time, uint32_t keycode, enum wl_keyboard_key_state state) { wlr_seat_keyboard_notify_key(m_seat, time, keycode, state); } + void keyboard_notify_enter(struct wlr_surface* surface, + uint32_t* keycodes = nullptr, size_t num_keycodes = 0, + struct wlr_keyboard_modifiers* modifiers = nullptr) { + wlr_seat_keyboard_notify_enter(m_seat, surface, keycodes, num_keycodes, modifiers); + } + void keyboard_clear_focus() { wlr_seat_keyboard_clear_focus(m_seat); } + void pointer_notify_enter(struct wlr_surface* surface, double sx, double sy) { + wlr_seat_pointer_notify_enter(m_seat, surface, sx, sy); + } + void pointer_clear_focus() { wlr_seat_pointer_clear_focus(m_seat); } void pointer_notify_motion(uint32_t time, double sx, double sy) { wlr_seat_pointer_notify_motion(m_seat, time, sx, sy); } diff --git a/include/wlr/wlr.hpp b/include/wlr/wlr.hpp index f8d8ebb..aba0644 100644 --- a/include/wlr/wlr.hpp +++ b/include/wlr/wlr.hpp @@ -20,7 +20,9 @@ extern "C" { #include #include #include +#include #include +#include #include #include #include diff --git a/include/wlr/xdg_decoration.hpp b/include/wlr/xdg_decoration.hpp new file mode 100644 index 0000000..2e6729b --- /dev/null +++ b/include/wlr/xdg_decoration.hpp @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: AGPL-3.0-only +#pragma once + +#include + +#include "wlr/wlr.hpp" +#include "wlr/display.hpp" +#include "wlr/signals.hpp" +#include "wlr/xdg_shell.hpp" + +namespace wlr { + +class XdgToplevelDecoration { +public: + enum Mode { None = 0, ClientSide = 1, ServerSide = 2 }; + + XdgToplevelDecoration(struct wlr_xdg_toplevel_decoration_v1* d) : m_dec(d) {} + struct wlr_xdg_toplevel_decoration_v1* raw() const { return m_dec; } + explicit operator bool() const { return m_dec != nullptr; } + + Mode current_mode() const { return static_cast(m_dec->current.mode); } + Mode requested_mode() const { return static_cast(m_dec->requested_mode); } + void set_mode(Mode m) { + wlr_xdg_toplevel_decoration_v1_set_mode(m_dec, + static_cast(m)); + } + + Toplevel toplevel() const { return Toplevel{m_dec->toplevel}; } + + void on_request_mode(std::function cb) { + m_request.connect(&m_dec->events.request_mode, std::move(cb)); + } + void on_destroy(std::function cb) { + m_destroy.connect(&m_dec->events.destroy, std::move(cb)); + } + +private: + struct wlr_xdg_toplevel_decoration_v1* m_dec; + SignalSink m_request; + SignalSink m_destroy; +}; + +class XdgDecorationManager { +public: + XdgDecorationManager(Display& d) + : m_mgr(wlr_xdg_decoration_manager_v1_create(d.raw())) {} + struct wlr_xdg_decoration_manager_v1* raw() const { return m_mgr; } + explicit operator bool() const { return m_mgr != nullptr; } + + void on_new_toplevel_decoration(std::function cb) { + m_new.connect(&m_mgr->events.new_toplevel_decoration, std::move(cb)); + } + +private: + struct wlr_xdg_decoration_manager_v1* m_mgr; + SignalSink m_new; +}; + +} diff --git a/src/wlrootspp.cpp b/src/wlrootspp.cpp index 4605d00..37ae8b8 100644 --- a/src/wlrootspp.cpp +++ b/src/wlrootspp.cpp @@ -1,5 +1,7 @@ // SPDX-License-Identifier: AGPL-3.0-only #include "wlr/node.hpp" +#include "wlr/box.hpp" +#include "wlr/xdg_decoration.hpp" #include #include