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 cf8ac9d10ca9745668f752825c5618555d209b84
parent 378bbc4e4b832ef15a20d0da5a057eb503c71745
Author: deurzen <max@deurzen.net>
Date:   Sun, 29 May 2022 08:07:49 +0200

adds cursor input processing, cursor bindings

Diffstat:
Minclude/kranewl/conf/config.hh | 2+-
Minclude/kranewl/input/bindings.hh | 8++++----
Ainclude/kranewl/input/cursor-bindings.hh | 162+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/kranewl/input/cursor.hh | 121+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ainclude/kranewl/input/key-bindings.hh | 313+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dinclude/kranewl/input/keybindings.hh | 313-------------------------------------------------------------------------------
Dinclude/kranewl/input/mouse.hh | 104-------------------------------------------------------------------------------
Dinclude/kranewl/input/mousebindings.hh | 3---
Minclude/kranewl/input/seat.hh | 6++----
Ainclude/kranewl/layer.hh | 14++++++++++++++
Dinclude/kranewl/layers.hh | 13-------------
Minclude/kranewl/model.hh | 6+++---
Minclude/kranewl/server.hh | 19++++++-------------
Dinclude/kranewl/tree/client.hh | 185-------------------------------------------------------------------------------
Minclude/kranewl/tree/output.hh | 4----
Minclude/kranewl/tree/view.hh | 8+++++---
Asrc/kranewl/input/cursor.cc | 420+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/kranewl/input/mouse.cc | 300-------------------------------------------------------------------------------
Msrc/kranewl/input/seat.cc | 6+++---
Msrc/kranewl/layout.cc | 4++--
Msrc/kranewl/model.cc | 22+++++++++++-----------
Msrc/kranewl/server.cc | 12+++---------
Dsrc/kranewl/tree/client.cc | 210-------------------------------------------------------------------------------
Msrc/kranewl/tree/output.cc | 2+-
Msrc/kranewl/tree/view.cc | 18++++++++++++++++--
Msrc/kranewl/tree/xdg_view.cc | 2+-
26 files changed, 1088 insertions(+), 1189 deletions(-)

diff --git a/include/kranewl/conf/config.hh b/include/kranewl/conf/config.hh @@ -13,7 +13,7 @@ extern "C" { struct Config final { KeyBindings key_bindings; - MouseBindings mouse_bindings; + CursorBindings cursor_bindings; }; class ConfigParser final { diff --git a/include/kranewl/input/bindings.hh b/include/kranewl/input/bindings.hh @@ -1,7 +1,7 @@ #pragma once #include <kranewl/input/keyboard.hh> -#include <kranewl/input/mouse.hh> +#include <kranewl/input/cursor.hh> #include <cstdint> #include <functional> @@ -16,12 +16,12 @@ typedef typedef std::function<bool(Model&, View_ptr)> - MouseAction; + CursorAction; typedef std::unordered_map<KeyboardInput, KeyboardAction> KeyBindings; typedef - std::unordered_map<MouseInput, MouseAction> - MouseBindings; + std::unordered_map<CursorInput, CursorAction> + CursorBindings; diff --git a/include/kranewl/input/cursor-bindings.hh b/include/kranewl/input/cursor-bindings.hh @@ -0,0 +1,162 @@ +#pragma once + +#include <kranewl/input/bindings.hh> +#include <kranewl/input/cursor.hh> +#include <kranewl/layout.hh> +#include <kranewl/model.hh> + +extern "C" { +#include <linux/input-event-codes.h> +#include <wlr/types/wlr_keyboard.h> +} + +#ifdef NDEBUG +#define MODKEY WLR_MODIFIER_LOGO +#define SECKEY WLR_MODIFIER_ALT +#else +#define MODKEY WLR_MODIFIER_ALT +#define SECKEY WLR_MODIFIER_LOGO +#endif +#define SHIFT WLR_MODIFIER_SHIFT +#define CAPS WLR_MODIFIER_CAPS +#define CTRL WLR_MODIFIER_CTRL +#define ALT WLR_MODIFIER_ALT +#define MOD2 WLR_MODIFIER_MOD2 +#define MOD3 WLR_MODIFIER_MOD3 +#define LOGO WLR_MODIFIER_LOGO +#define MOD5 WLR_MODIFIER_MOD5 +#define GLOBAL CursorInput::Target::Global +#define ROOT CursorInput::Target::Root +#define VIEW CursorInput::Target::View +#define LEFT CursorInput::Button::Left +#define RIGHT CursorInput::Button::Right +#define MIDDLE CursorInput::Button::Middle +#define SCROLLUP CursorInput::Button::ScrollUp +#define SCROLLDOWN CursorInput::Button::ScrollDown +#define SCROLLLEFT CursorInput::Button::ScrollLeft +#define SCROLLRIGHT CursorInput::Button::ScrollRight +#define FORWARD CursorInput::Button::Forward +#define BACKWARD CursorInput::Button::Backward +#define CALL_FOCUS(args) [](Model& model, View_ptr view) {{args} return true;} +#define CALL_NOFOCUS(args) [](Model& model, View_ptr view) {{args} return false;} +#define CALL_EXTERNAL(command) CALL(spawn_external(#command)) + +namespace Bindings { + +static const CursorBindings cursor_bindings = { +{ { VIEW, RIGHT, MODKEY | CTRL }, + CALL_FOCUS({ + if (view) + model.set_floating_view(Toggle::Reverse, view); + }) +}, +{ { VIEW, MIDDLE, MODKEY | CTRL | SHIFT }, + CALL_FOCUS({ + if (view) + model.set_fullscreen_view(Toggle::Reverse, view); + }) +}, +{ { VIEW, MIDDLE, MODKEY }, + CALL_FOCUS({ + if (view) + model.center_view(view); + }) +}, +{ { VIEW, SCROLLDOWN, MODKEY | CTRL | SHIFT }, + CALL_FOCUS({ + if (view) + model.inflate_view(-16, view); + }) +}, +{ { VIEW, SCROLLUP, MODKEY | CTRL | SHIFT }, + CALL_FOCUS({ + if (view) + model.inflate_view(16, view); + }) +}, +{ { VIEW, LEFT, MODKEY }, + CALL_FOCUS({ + /* if (view) */ + /* model.start_moving(view); */ + }) +}, +{ { VIEW, RIGHT, MODKEY }, + CALL_FOCUS({ + /* if (view) */ + /* model.start_resizing(view); */ + }) +}, +{ { GLOBAL, SCROLLDOWN, MODKEY }, + CALL_NOFOCUS({ + model.cycle_focus(Direction::Forward); + }) +}, +{ { GLOBAL, SCROLLUP, MODKEY }, + CALL_NOFOCUS({ + model.cycle_focus(Direction::Backward); + }) +}, +{ { GLOBAL, SCROLLDOWN, MODKEY | SHIFT }, + CALL_NOFOCUS({ + /* model.activate_next_workspace(Direction::Forward); */ + }) +}, +{ { GLOBAL, SCROLLUP, MODKEY | SHIFT }, + CALL_NOFOCUS({ + /* model.activate_next_workspace(Direction::Backward); */ + }) +}, +{ { VIEW, FORWARD, MODKEY }, + CALL_NOFOCUS({ + /* if (view) */ + /* model.move_view_to_next_workspace(Direction::Forward, view); */ + }) +}, +{ { VIEW, BACKWARD, MODKEY }, + CALL_NOFOCUS({ + /* if (view) */ + /* model.move_view_to_next_workspace(Direction::Backward, view); */ + }) +}, +{ { VIEW, RIGHT, MODKEY | CTRL | SHIFT }, + CALL_NOFOCUS({ + if (view) + model.kill_view(view); + }) +}, +{ { GLOBAL, LEFT, MODKEY | SECKEY | CTRL }, + CALL_NOFOCUS({ + model.spawn_external("alacritty --class kranewl:cf,Alacritty"); + }) +}, +}; + +} + +#undef CALL_EXTERNAL +#undef CALL_NOFOCUS +#undef CALL_FOCUS +#undef BACKWARD +#undef FORWARD +#undef SCROLLRIGHT +#undef SCROLLLEFT +#undef SCROLLDOWN +#undef SCROLLUP +#undef MIDDLE +#undef RIGHT +#undef LEFT +#undef VIEW +#undef ROOT +#undef GLOBAL +#undef MOD5 +#undef LOGO +#undef MOD3 +#undef MOD2 +#undef ALT +#undef CTRL +#undef CAPS +#undef SHIFT +#undef SECKEY +#undef MODKEY +#undef SECKEY +#undef MODKEY diff --git a/include/kranewl/input/cursor.hh b/include/kranewl/input/cursor.hh @@ -0,0 +1,121 @@ +#pragma once + +#include <kranewl/geometry.hh> + +extern "C" { +#include <linux/input-event-codes.h> +#include <wlr/backend.h> +#include <xkbcommon/xkbcommon.h> +} + +#include <cstdint> +#include <unordered_set> + +struct CursorInput { + enum class Target + { + Global, + Root, + View + }; + + enum Button : uint32_t { + Left = BTN_LEFT, + Right = BTN_RIGHT, + Middle = BTN_MIDDLE, + Forward = BTN_SIDE, + Backward = BTN_EXTRA, + ScrollUp = KEY_MAX + 1, + ScrollDown = KEY_MAX + 2, + ScrollLeft = KEY_MAX + 3, + ScrollRight = KEY_MAX + 4, + }; + + Target target; + Button button; + uint32_t modifiers; +}; + +typedef class Server* Server_ptr; +typedef class Seat* Seat_ptr; +typedef struct View* View_ptr; + +typedef struct Cursor { + enum class CursorMode { + Passthrough, + Move, + Resize, + }; + + Cursor( + Server_ptr, + Seat_ptr, + struct wlr_cursor*, + struct wlr_pointer_constraints_v1*, + struct wlr_relative_pointer_manager_v1*, + struct wlr_virtual_pointer_manager_v1* + ); + ~Cursor(); + + View_ptr view_under_cursor() const; + + static void handle_cursor_motion(struct wl_listener*, void*); + static void handle_cursor_motion_absolute(struct wl_listener*, void*); + static void handle_cursor_button(struct wl_listener*, void*); + static void handle_cursor_axis(struct wl_listener*, void*); + static void handle_cursor_frame(struct wl_listener*, void*); + static void handle_request_start_drag(struct wl_listener*, void*); + static void handle_start_drag(struct wl_listener*, void*); + static void handle_request_set_cursor(struct wl_listener*, void*); + + Server_ptr mp_server; + Seat_ptr mp_seat; + + CursorMode m_cursor_mode; + struct wlr_cursor* mp_wlr_cursor; + struct wlr_xcursor_manager* mp_cursor_manager; + struct wlr_pointer_constraints_v1* mp_pointer_constraints; + struct wlr_relative_pointer_manager_v1* mp_relative_pointer_manager; + struct wlr_virtual_pointer_manager_v1* mp_virtual_pointer_manager; + + struct { + View_ptr view; + double x, y; + Region region; + uint32_t resize_edges; + } m_grab_state; + + struct wl_listener ml_cursor_motion; + struct wl_listener ml_cursor_motion_absolute; + struct wl_listener ml_cursor_button; + struct wl_listener ml_cursor_axis; + struct wl_listener ml_cursor_frame; + struct wl_listener ml_request_start_drag; + struct wl_listener ml_start_drag; + struct wl_listener ml_request_set_cursor; + +}* Cursor_ptr; + +inline bool +operator==(CursorInput const& lhs, CursorInput const& rhs) +{ + return lhs.target == rhs.target + && lhs.button == rhs.button + && lhs.modifiers == rhs.modifiers; +} + +namespace std +{ + template <> + struct hash<CursorInput> { + std::size_t + operator()(CursorInput const& input) const + { + std::size_t target_hash = std::hash<CursorInput::Target>()(input.target); + std::size_t modifiers_hash = std::hash<uint32_t>()(input.modifiers); + std::size_t button_hash = std::hash<uint32_t>()(input.button); + + return target_hash ^ modifiers_hash ^ button_hash; + } + }; +} diff --git a/include/kranewl/input/key-bindings.hh b/include/kranewl/input/key-bindings.hh @@ -0,0 +1,313 @@ +#pragma once + +#include <kranewl/input/bindings.hh> +#include <kranewl/layout.hh> +#include <kranewl/model.hh> + +extern "C" { +#include <wlr/types/wlr_keyboard.h> +} + +#ifdef NDEBUG +#define MODKEY WLR_MODIFIER_LOGO +#define SECKEY WLR_MODIFIER_ALT +#else +#define MODKEY WLR_MODIFIER_ALT +#define SECKEY WLR_MODIFIER_LOGO +#endif +#define SHIFT WLR_MODIFIER_SHIFT +#define CAPS WLR_MODIFIER_CAPS +#define CTRL WLR_MODIFIER_CTRL +#define ALT WLR_MODIFIER_ALT +#define MOD2 WLR_MODIFIER_MOD2 +#define MOD3 WLR_MODIFIER_MOD3 +#define LOGO WLR_MODIFIER_LOGO +#define MOD5 WLR_MODIFIER_MOD5 +#define CALL(args) [](Model& model) {model.args;} +#define CALL_EXTERNAL(command) CALL(spawn_external(#command)) + +namespace Bindings { + +static const KeyBindings key_bindings = { +{ { XKB_KEY_Q, MODKEY | CTRL | SHIFT }, + CALL(exit()) +}, + +// view state modifiers +{ { XKB_KEY_c, MODKEY }, + CALL(kill_focus()) +}, +{ { XKB_KEY_space, MODKEY | SHIFT }, + CALL(set_floating_focus(Toggle::Reverse)) +}, +{ { XKB_KEY_f, MODKEY }, + CALL(set_fullscreen_focus(Toggle::Reverse)) +}, +{ { XKB_KEY_x, MODKEY }, + CALL(set_sticky_focus(Toggle::Reverse)) +}, +{ { XKB_KEY_f, MODKEY | SECKEY | CTRL }, + CALL(set_contained_focus(Toggle::Reverse)) +}, +{ { XKB_KEY_i, MODKEY | SECKEY | CTRL }, + CALL(set_invincible_focus(Toggle::Reverse)) +}, +{ { XKB_KEY_y, MODKEY }, + CALL(set_iconify_focus(Toggle::Reverse)) +}, +{ { XKB_KEY_u, MODKEY }, + CALL(pop_deiconify()) +}, +{ { XKB_KEY_u, MODKEY | SECKEY }, + CALL(deiconify_all()) +}, + +// view arrangers +{ { XKB_KEY_space, MODKEY | CTRL }, + CALL(center_focus()) +}, +{ { XKB_KEY_h, MODKEY | CTRL }, + [](Model& model) { + View_ptr focus = model.focused_view(); + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Left, 15); + else + model.shuffle_main(Direction::Backward); + } +}, +{ { XKB_KEY_j, MODKEY | CTRL }, + [](Model& model) { + View_ptr focus = model.focused_view(); + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Bottom, 15); + else + model.shuffle_stack(Direction::Forward); + } +}, +{ { XKB_KEY_k, MODKEY | CTRL }, + [](Model& model) { + View_ptr focus = model.focused_view(); + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Top, 15); + else + model.shuffle_stack(Direction::Backward); + } +}, +{ { XKB_KEY_l, MODKEY | CTRL }, + [](Model& model) { + View_ptr focus = model.focused_view(); + + if (focus && model.is_free(focus)) + model.nudge_focus(Edge::Right, 15); + else + model.shuffle_main(Direction::Forward); + } +}, +{ { XKB_KEY_H, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Left, 15)) +}, +{ { XKB_KEY_J, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Bottom, 15)) +}, +{ { XKB_KEY_K, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Top, 15)) +}, +{ { XKB_KEY_L, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Right, 15)) +}, +{ { XKB_KEY_Y, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Left, -15)) +}, +{ { XKB_KEY_U, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Bottom, -15)) +}, +{ { XKB_KEY_I, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Top, -15)) +}, +{ { XKB_KEY_O, MODKEY | CTRL | SHIFT }, + CALL(stretch_focus(Edge::Right, -15)) +}, +{ { XKB_KEY_leftarrow, MODKEY | CTRL }, + CALL(snap_focus(Edge::Left)) +}, +{ { XKB_KEY_downarrow, MODKEY | CTRL }, + CALL(snap_focus(Edge::Bottom)) +}, +{ { XKB_KEY_uparrow, MODKEY | CTRL }, + CALL(snap_focus(Edge::Top)) +}, +{ { XKB_KEY_rightarrow, MODKEY | CTRL }, + CALL(snap_focus(Edge::Right)) +}, +{ { XKB_KEY_j, MODKEY }, + CALL(cycle_focus(Direction::Forward)) +}, +{ { XKB_KEY_k, MODKEY }, + CALL(cycle_focus(Direction::Backward)) +}, +{ { XKB_KEY_J, MODKEY | SHIFT }, + CALL(drag_focus(Direction::Forward)) +}, +{ { XKB_KEY_K, MODKEY | SHIFT }, + CALL(drag_focus(Direction::Backward)) +}, +{ { XKB_KEY_r, MODKEY }, + CALL(reverse_views()) +}, +{ { XKB_KEY_semicolon, MODKEY | SHIFT }, + CALL(rotate_views(Direction::Forward)) +}, +{ { XKB_KEY_comma, MODKEY | SHIFT }, + CALL(rotate_views(Direction::Backward)) +}, + +// workspace layout modifiers +{ { XKB_KEY_F, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::Float)) +}, +{ { XKB_KEY_L, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::FramelessFloat)) +}, +{ { XKB_KEY_z, MODKEY }, + CALL(set_layout(LayoutHandler::LayoutKind::SingleFloat)) +}, +{ { XKB_KEY_Z, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::FramelessSingleFloat)) +}, +{ { XKB_KEY_m, MODKEY }, + CALL(set_layout(LayoutHandler::LayoutKind::Monocle)) +}, +{ { XKB_KEY_d, MODKEY | CTRL }, + CALL(set_layout(LayoutHandler::LayoutKind::MainDeck)) +}, +{ { XKB_KEY_D, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::StackDeck)) +}, +{ { XKB_KEY_D, MODKEY | CTRL | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::DoubleDeck)) +}, +{ { XKB_KEY_g, MODKEY }, + CALL(set_layout(LayoutHandler::LayoutKind::Center)) +}, +{ { XKB_KEY_t, MODKEY }, + CALL(set_layout(LayoutHandler::LayoutKind::DoubleStack)) +}, +{ { XKB_KEY_T, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::CompactDoubleStack)) +}, +{ { XKB_KEY_P, MODKEY | CTRL | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::Paper)) +}, +{ { XKB_KEY_P, MODKEY | SECKEY | CTRL | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::CompactPaper)) +}, +{ { XKB_KEY_Y, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::HorizontalStack)) +}, +{ { XKB_KEY_y, MODKEY | CTRL }, + CALL(set_layout(LayoutHandler::LayoutKind::CompactHorizontalStack)) +}, +{ { XKB_KEY_V, MODKEY | SHIFT }, + CALL(set_layout(LayoutHandler::LayoutKind::VerticalStack)) +}, +{ { XKB_KEY_V, MODKEY | CTRL }, + CALL(set_layout(LayoutHandler::LayoutKind::CompactVerticalStack)) +}, +{ { XKB_KEY_F, MODKEY | CTRL | SHIFT }, + CALL(set_layout_retain_region(LayoutHandler::LayoutKind::Float)) +}, +{ { XKB_KEY_space, MODKEY }, + CALL(toggle_layout()) +}, +{ { XKB_KEY_Return, MODKEY }, + CALL_EXTERNAL(alacritty) +}, + +// workspace layout data modifiers +{ { XKB_KEY_equal, MODKEY }, + CALL(change_gap_size(2)) +}, +{ { XKB_KEY_minus, MODKEY }, + CALL(change_gap_size(-2)) +}, +{ { XKB_KEY_equal, MODKEY | SHIFT }, + CALL(reset_gap_size()) +}, +{ { XKB_KEY_i, MODKEY }, + CALL(change_main_count(1)) +}, +{ { XKB_KEY_d, MODKEY }, + CALL(change_main_count(-1)) +}, +{ { XKB_KEY_l, MODKEY }, + CALL(change_main_factor(.05f)) +}, +{ { XKB_KEY_h, MODKEY }, + CALL(change_main_factor(-.05f)) +}, +{ { XKB_KEY_Page_Up, MODKEY | SHIFT }, + CALL(change_margin(5)) +}, +{ { XKB_KEY_Page_Down, MODKEY | SHIFT }, + CALL(change_margin(-5)) +}, +{ { XKB_KEY_Left, MODKEY | SHIFT }, + CALL(change_margin(Edge::Left, 5)) +}, +{ { XKB_KEY_Left, MODKEY | CTRL | SHIFT }, + CALL(change_margin(Edge::Left, -5)) +}, +{ { XKB_KEY_Up, MODKEY | SHIFT }, + CALL(change_margin(Edge::Top, 5)) +}, +{ { XKB_KEY_Up, MODKEY | CTRL | SHIFT }, + CALL(change_margin(Edge::Top, -5)) +}, +{ { XKB_KEY_Right, MODKEY | SHIFT }, + CALL(change_margin(Edge::Right, 5)) +}, +{ { XKB_KEY_Right, MODKEY | CTRL | SHIFT }, + CALL(change_margin(Edge::Right, -5)) +}, +{ { XKB_KEY_Down, MODKEY | SHIFT }, + CALL(change_margin(Edge::Bottom, 5)) +}, +{ { XKB_KEY_Down, MODKEY | CTRL | SHIFT }, + CALL(change_margin(Edge::Bottom, -5)) +}, +{ { XKB_KEY_comma, MODKEY | CTRL | SHIFT }, + CALL(cycle_layout_data(Direction::Backward)) +}, +{ { XKB_KEY_period, MODKEY | CTRL | SHIFT }, + CALL(cycle_layout_data(Direction::Forward)) +}, +{ { XKB_KEY_slash, MODKEY | CTRL | SHIFT }, + CALL(toggle_layout_data()) +}, +{ { XKB_KEY_Delete, MODKEY | CTRL | SHIFT }, + CALL(copy_data_from_prev_layout()) +}, +{ { XKB_KEY_equal, MODKEY | CTRL | SHIFT }, + CALL(reset_margin()) +}, +{ { XKB_KEY_equal, MODKEY | SECKEY | CTRL | SHIFT }, + CALL(reset_layout_data()) +}, +}; + +} +#undef CALL_EXTERNAL +#undef CALL +#undef MOD5 +#undef LOGO +#undef MOD3 +#undef MOD2 +#undef ALT +#undef CTRL +#undef CAPS +#undef SHIFT +#undef SECKEY +#undef MODKEY diff --git a/include/kranewl/input/keybindings.hh b/include/kranewl/input/keybindings.hh @@ -1,313 +0,0 @@ -#pragma once - -#include <kranewl/input/bindings.hh> -#include <kranewl/model.hh> -#include <kranewl/layout.hh> - -extern "C" { -#include <wlr/types/wlr_keyboard.h> -} - -#ifdef NDEBUG -#define MODKEY WLR_MODIFIER_LOGO -#define SECKEY WLR_MODIFIER_ALT -#else -#define MODKEY WLR_MODIFIER_ALT -#define SECKEY WLR_MODIFIER_LOGO -#endif -#define SHIFT WLR_MODIFIER_SHIFT -#define CAPS WLR_MODIFIER_CAPS -#define CTRL WLR_MODIFIER_CTRL -#define ALT WLR_MODIFIER_ALT -#define MOD2 WLR_MODIFIER_MOD2 -#define MOD3 WLR_MODIFIER_MOD3 -#define LOGO WLR_MODIFIER_LOGO -#define MOD5 WLR_MODIFIER_MOD5 -#define CALL(args) [](Model& model) {model.args;} -#define CALL_EXTERNAL(command) CALL(spawn_external(#command)) - -namespace Bindings { - -static const KeyBindings key_bindings = { -{ { XKB_KEY_Q, MODKEY | CTRL | SHIFT }, - CALL(exit()) -}, - -// view state modifiers -{ { XKB_KEY_c, MODKEY }, - CALL(kill_focus()) -}, -{ { XKB_KEY_space, MODKEY | SHIFT }, - CALL(set_floating_focus(Toggle::Reverse)) -}, -{ { XKB_KEY_f, MODKEY }, - CALL(set_fullscreen_focus(Toggle::Reverse)) -}, -{ { XKB_KEY_x, MODKEY }, - CALL(set_sticky_focus(Toggle::Reverse)) -}, -{ { XKB_KEY_f, MODKEY | SECKEY | CTRL }, - CALL(set_contained_focus(Toggle::Reverse)) -}, -{ { XKB_KEY_i, MODKEY | SECKEY | CTRL }, - CALL(set_invincible_focus(Toggle::Reverse)) -}, -{ { XKB_KEY_y, MODKEY }, - CALL(set_iconify_focus(Toggle::Reverse)) -}, -{ { XKB_KEY_u, MODKEY }, - CALL(pop_deiconify()) -}, -{ { XKB_KEY_u, MODKEY | SECKEY }, - CALL(deiconify_all()) -}, - -// view arrangers -{ { XKB_KEY_space, MODKEY | CTRL }, - CALL(center_focus()) -}, -{ { XKB_KEY_h, MODKEY | CTRL }, - [](Model& model) { - View_ptr focus = model.focused_view(); - - if (focus && model.is_free(focus)) - model.nudge_focus(Edge::Left, 15); - else - model.shuffle_main(Direction::Backward); - } -}, -{ { XKB_KEY_j, MODKEY | CTRL }, - [](Model& model) { - View_ptr focus = model.focused_view(); - - if (focus && model.is_free(focus)) - model.nudge_focus(Edge::Bottom, 15); - else - model.shuffle_stack(Direction::Forward); - } -}, -{ { XKB_KEY_k, MODKEY | CTRL }, - [](Model& model) { - View_ptr focus = model.focused_view(); - - if (focus && model.is_free(focus)) - model.nudge_focus(Edge::Top, 15); - else - model.shuffle_stack(Direction::Backward); - } -}, -{ { XKB_KEY_l, MODKEY | CTRL }, - [](Model& model) { - View_ptr focus = model.focused_view(); - - if (focus && model.is_free(focus)) - model.nudge_focus(Edge::Right, 15); - else - model.shuffle_main(Direction::Forward); - } -}, -{ { XKB_KEY_H, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Left, 15)) -}, -{ { XKB_KEY_J, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Bottom, 15)) -}, -{ { XKB_KEY_K, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Top, 15)) -}, -{ { XKB_KEY_L, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Right, 15)) -}, -{ { XKB_KEY_Y, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Left, -15)) -}, -{ { XKB_KEY_U, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Bottom, -15)) -}, -{ { XKB_KEY_I, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Top, -15)) -}, -{ { XKB_KEY_O, MODKEY | CTRL | SHIFT }, - CALL(stretch_focus(Edge::Right, -15)) -}, -{ { XKB_KEY_leftarrow, MODKEY | CTRL }, - CALL(snap_focus(Edge::Left)) -}, -{ { XKB_KEY_downarrow, MODKEY | CTRL }, - CALL(snap_focus(Edge::Bottom)) -}, -{ { XKB_KEY_uparrow, MODKEY | CTRL }, - CALL(snap_focus(Edge::Top)) -}, -{ { XKB_KEY_rightarrow, MODKEY | CTRL }, - CALL(snap_focus(Edge::Right)) -}, -{ { XKB_KEY_j, MODKEY }, - CALL(cycle_focus(Direction::Forward)) -}, -{ { XKB_KEY_k, MODKEY }, - CALL(cycle_focus(Direction::Backward)) -}, -{ { XKB_KEY_J, MODKEY | SHIFT }, - CALL(drag_focus(Direction::Forward)) -}, -{ { XKB_KEY_K, MODKEY | SHIFT }, - CALL(drag_focus(Direction::Backward)) -}, -{ { XKB_KEY_r, MODKEY }, - CALL(reverse_views()) -}, -{ { XKB_KEY_semicolon, MODKEY | SHIFT }, - CALL(rotate_views(Direction::Forward)) -}, -{ { XKB_KEY_comma, MODKEY | SHIFT }, - CALL(rotate_views(Direction::Backward)) -}, - -// workspace layout modifiers -{ { XKB_KEY_F, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::Float)) -}, -{ { XKB_KEY_L, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::FramelessFloat)) -}, -{ { XKB_KEY_z, MODKEY }, - CALL(set_layout(LayoutHandler::LayoutKind::SingleFloat)) -}, -{ { XKB_KEY_Z, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::FramelessSingleFloat)) -}, -{ { XKB_KEY_m, MODKEY }, - CALL(set_layout(LayoutHandler::LayoutKind::Monocle)) -}, -{ { XKB_KEY_d, MODKEY | CTRL }, - CALL(set_layout(LayoutHandler::LayoutKind::MainDeck)) -}, -{ { XKB_KEY_D, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::StackDeck)) -}, -{ { XKB_KEY_D, MODKEY | CTRL | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::DoubleDeck)) -}, -{ { XKB_KEY_g, MODKEY }, - CALL(set_layout(LayoutHandler::LayoutKind::Center)) -}, -{ { XKB_KEY_t, MODKEY }, - CALL(set_layout(LayoutHandler::LayoutKind::DoubleStack)) -}, -{ { XKB_KEY_T, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::CompactDoubleStack)) -}, -{ { XKB_KEY_P, MODKEY | CTRL | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::Paper)) -}, -{ { XKB_KEY_P, MODKEY | SECKEY | CTRL | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::CompactPaper)) -}, -{ { XKB_KEY_Y, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::HorizontalStack)) -}, -{ { XKB_KEY_y, MODKEY | CTRL }, - CALL(set_layout(LayoutHandler::LayoutKind::CompactHorizontalStack)) -}, -{ { XKB_KEY_V, MODKEY | SHIFT }, - CALL(set_layout(LayoutHandler::LayoutKind::VerticalStack)) -}, -{ { XKB_KEY_V, MODKEY | CTRL }, - CALL(set_layout(LayoutHandler::LayoutKind::CompactVerticalStack)) -}, -{ { XKB_KEY_F, MODKEY | CTRL | SHIFT }, - CALL(set_layout_retain_region(LayoutHandler::LayoutKind::Float)) -}, -{ { XKB_KEY_space, MODKEY }, - CALL(toggle_layout()) -}, -{ { XKB_KEY_Return, MODKEY }, - CALL_EXTERNAL(alacritty) -}, - -// workspace layout data modifiers -{ { XKB_KEY_equal, MODKEY }, - CALL(change_gap_size(2)) -}, -{ { XKB_KEY_minus, MODKEY }, - CALL(change_gap_size(-2)) -}, -{ { XKB_KEY_equal, MODKEY | SHIFT }, - CALL(reset_gap_size()) -}, -{ { XKB_KEY_i, MODKEY }, - CALL(change_main_count(1)) -}, -{ { XKB_KEY_d, MODKEY }, - CALL(change_main_count(-1)) -}, -{ { XKB_KEY_l, MODKEY }, - CALL(change_main_factor(.05f)) -}, -{ { XKB_KEY_h, MODKEY }, - CALL(change_main_factor(-.05f)) -}, -{ { XKB_KEY_Page_Up, MODKEY | SHIFT }, - CALL(change_margin(5)) -}, -{ { XKB_KEY_Page_Down, MODKEY | SHIFT }, - CALL(change_margin(-5)) -}, -{ { XKB_KEY_Left, MODKEY | SHIFT }, - CALL(change_margin(Edge::Left, 5)) -}, -{ { XKB_KEY_Left, MODKEY | CTRL | SHIFT }, - CALL(change_margin(Edge::Left, -5)) -}, -{ { XKB_KEY_Up, MODKEY | SHIFT }, - CALL(change_margin(Edge::Top, 5)) -}, -{ { XKB_KEY_Up, MODKEY | CTRL | SHIFT }, - CALL(change_margin(Edge::Top, -5)) -}, -{ { XKB_KEY_Right, MODKEY | SHIFT }, - CALL(change_margin(Edge::Right, 5)) -}, -{ { XKB_KEY_Right, MODKEY | CTRL | SHIFT }, - CALL(change_margin(Edge::Right, -5)) -}, -{ { XKB_KEY_Down, MODKEY | SHIFT }, - CALL(change_margin(Edge::Bottom, 5)) -}, -{ { XKB_KEY_Down, MODKEY | CTRL | SHIFT }, - CALL(change_margin(Edge::Bottom, -5)) -}, -{ { XKB_KEY_comma, MODKEY | CTRL | SHIFT }, - CALL(cycle_layout_data(Direction::Backward)) -}, -{ { XKB_KEY_period, MODKEY | CTRL | SHIFT }, - CALL(cycle_layout_data(Direction::Forward)) -}, -{ { XKB_KEY_slash, MODKEY | CTRL | SHIFT }, - CALL(toggle_layout_data()) -}, -{ { XKB_KEY_Delete, MODKEY | CTRL | SHIFT }, - CALL(copy_data_from_prev_layout()) -}, -{ { XKB_KEY_equal, MODKEY | CTRL | SHIFT }, - CALL(reset_margin()) -}, -{ { XKB_KEY_equal, MODKEY | SECKEY | CTRL | SHIFT }, - CALL(reset_layout_data()) -}, -}; - -} -#undef CALL_EXTERNAL -#undef CALL -#undef MOD5 -#undef LOGO -#undef MOD3 -#undef MOD2 -#undef ALT -#undef CTRL -#undef CAPS -#undef SHIFT -#undef SECKEY -#undef MODKEY diff --git a/include/kranewl/input/mouse.hh b/include/kranewl/input/mouse.hh @@ -1,104 +0,0 @@ -#pragma once - -#include <kranewl/geometry.hh> - -extern "C" { -#include <wlr/backend.h> -#include <xkbcommon/xkbcommon.h> -} - -#include <cstdint> -#include <unordered_set> - -struct MouseInput { - unsigned button; - uint32_t modifiers; -}; - -typedef class Server* Server_ptr; -typedef class Seat* Seat_ptr; -typedef struct View* View_ptr; - -typedef struct Mouse { - enum class CursorMode { - Passthrough, - Move, - Resize, - }; - - enum class CursorButton { - Left = 272, - Right = 273, - Middle = 274, - }; - - Mouse( - Server_ptr, - Seat_ptr, - struct wlr_cursor*, - struct wlr_pointer_constraints_v1*, - struct wlr_relative_pointer_manager_v1*, - struct wlr_virtual_pointer_manager_v1* - ); - ~Mouse(); - - View_ptr view_under_cursor() const; - - static void handle_cursor_motion(struct wl_listener*, void*); - static void handle_cursor_motion_absolute(struct wl_listener*, void*); - static void handle_cursor_button(struct wl_listener*, void*); - static void handle_cursor_axis(struct wl_listener*, void*); - static void handle_cursor_frame(struct wl_listener*, void*); - static void handle_request_start_drag(struct wl_listener*, void*); - static void handle_start_drag(struct wl_listener*, void*); - static void handle_request_set_cursor(struct wl_listener*, void*); - - Server_ptr mp_server; - Seat_ptr mp_seat; - - CursorMode m_cursor_mode; - struct wlr_cursor* mp_cursor; - struct wlr_xcursor_manager* mp_cursor_manager; - struct wlr_pointer_constraints_v1* mp_pointer_constraints; - struct wlr_relative_pointer_manager_v1* mp_relative_pointer_manager; - struct wlr_virtual_pointer_manager_v1* mp_virtual_pointer_manager; - - struct { - View_ptr client; - double x, y; - Region region; - uint32_t resize_edges; - } m_grab_state; - - struct wl_listener ml_cursor_motion; - struct wl_listener ml_cursor_motion_absolute; - struct wl_listener ml_cursor_button; - struct wl_listener ml_cursor_axis; - struct wl_listener ml_cursor_frame; - struct wl_listener ml_request_start_drag; - struct wl_listener ml_start_drag; - struct wl_listener ml_request_set_cursor; - -}* Mouse_ptr; - -inline bool -operator==(MouseInput const& lhs, MouseInput const& rhs) -{ - return lhs.button == rhs.button - && lhs.modifiers == rhs.modifiers; -} - -namespace std -{ - template <> - struct hash<MouseInput> { - std::size_t - operator()(MouseInput const& input) const - { - std::size_t modifiers_hash = std::hash<uint32_t>()(input.modifiers); - std::size_t button_hash = std::hash<unsigned>()(input.button); - - return modifiers_hash ^ button_hash; - } - }; -} diff --git a/include/kranewl/input/mousebindings.hh b/include/kranewl/input/mousebindings.hh @@ -1,3 +0,0 @@ -#pragma once - - diff --git a/include/kranewl/input/seat.hh b/include/kranewl/input/seat.hh @@ -13,7 +13,7 @@ extern "C" { typedef class Server* Server_ptr; typedef class Model* Model_ptr; typedef struct Keyboard* Keyboard_ptr; -typedef struct Mouse* Mouse_ptr; +typedef struct Cursor* Cursor_ptr; typedef class Seat final { public: @@ -55,11 +55,9 @@ public: struct wlr_virtual_keyboard_manager_v1* mp_virtual_keyboard_manager; struct wlr_keyboard_shortcuts_inhibit_manager_v1* mp_keyboard_shortcuts_inhibit_manager; - Mouse_ptr mp_mouse; + Cursor_ptr mp_cursor; std::vector<Keyboard_ptr> m_keyboards; - struct wl_client* mp_exclusive_client; - struct wl_listener ml_destroy; struct wl_listener ml_request_set_selection; struct wl_listener ml_request_set_primary_selection; diff --git a/include/kranewl/layer.hh b/include/kranewl/layer.hh @@ -0,0 +1,14 @@ +#pragma once + +#include <cstdlib> + +enum Layer : short { + None = -1, + Background = 0, + Bottom = 1, + Tile = 2, + Free = 3, + Top = 4, + Overlay = 5, + NoFocus = 6, +}; diff --git a/include/kranewl/layers.hh b/include/kranewl/layers.hh @@ -1,13 +0,0 @@ -#pragma once - -struct Layer { - typedef short type; - static constexpr short None = -1; - static constexpr short Background = 0; - static constexpr short Bottom = 1; - static constexpr short Tile = 2; - static constexpr short Free = 3; - static constexpr short Top = 4; - static constexpr short Overlay = 5; - static constexpr short NoFocus = 6; -}; diff --git a/include/kranewl/model.hh b/include/kranewl/model.hh @@ -37,9 +37,10 @@ public: void register_server(Server_ptr); void exit(); - const View_ptr focused_view() const; + View_ptr focused_view() const; KeyBindings const& key_bindings() const; + CursorBindings const& cursor_bindings() const; Output_ptr create_output(struct wlr_output*, struct wlr_scene_output*, Region const&&); void register_output(Output_ptr); @@ -60,7 +61,6 @@ public: void disown_view(View_ptr); void reclaim_view(View_ptr); void focus_view(View_ptr); - void unfocus_view(View_ptr); void place_view(Placement&); void sync_focus(); @@ -174,6 +174,6 @@ private: View_ptr mp_focus; const KeyBindings m_key_bindings; - const MouseBindings m_mouse_bindings; + const CursorBindings m_cursor_bindings; }; 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/layer.hh> extern "C" { #include <wlr/backend.h> @@ -9,6 +10,7 @@ extern "C" { #include <xkbcommon/xkbcommon.h> } +#include <array> #include <cstdint> #include <string> @@ -17,12 +19,6 @@ typedef class Server* Server_ptr; typedef struct View* View_ptr; typedef class Server final { - enum class CursorMode { - Passthrough, - Move, - Resize, - }; - public: Server(Model_ptr); ~Server(); @@ -47,7 +43,6 @@ private: static void handle_xdg_toplevel_destroy(struct wl_listener*, void*); static void handle_xdg_toplevel_request_move(struct wl_listener*, void*); static void handle_xdg_toplevel_request_resize(struct wl_listener*, void*); - static void handle_xdg_toplevel_handle_moveresize(View_ptr, CursorMode, uint32_t); #ifdef XWAYLAND static void handle_xwayland_ready(struct wl_listener*, void*); static void handle_new_xwayland_surface(struct wl_listener*, void*); @@ -66,17 +61,15 @@ public: struct wlr_renderer* mp_renderer; struct wlr_allocator* mp_allocator; struct wlr_compositor* mp_compositor; - struct wlr_data_device_manager* mp_data_device_manager; - struct wlr_output_layout* mp_output_layout; - struct wlr_scene* mp_scene; - struct wlr_scene_node* m_layers[7]; #ifdef XWAYLAND struct wlr_xwayland* mp_xwayland; #endif - + struct wlr_data_device_manager* mp_data_device_manager; + struct wlr_output_layout* mp_output_layout; + struct wlr_scene* mp_scene; + std::array<struct wlr_scene_node*, 7> m_layers; Seat m_seat; - private: struct wlr_xdg_shell* mp_xdg_shell; struct wlr_layer_shell_v1* mp_layer_shell; diff --git a/include/kranewl/tree/client.hh b/include/kranewl/tree/client.hh @@ -1,185 +0,0 @@ -#pragma once - -#include <kranewl/common.hh> -#include <kranewl/decoration.hh> -#include <kranewl/geometry.hh> -#include <kranewl/tree/surface.hh> - -extern "C" { -#include <wlr/backend.h> -} - -#include <chrono> -#include <cstdint> -#include <optional> -#include <string> -#include <vector> - -typedef class Server* Server_ptr; -typedef class Output* Output_ptr; -typedef class Context* Context_ptr; -typedef class Workspace* Workspace_ptr; -typedef struct Client* Client_ptr; - -typedef struct Client final { - static constexpr Dim MIN_CLIENT_DIM = Dim{25, 10}; - static constexpr Dim PREFERRED_INIT_CLIENT_DIM = Dim{480, 260}; - - enum class OutsideState { - Focused, - FocusedDisowned, - FocusedSticky, - Unfocused, - UnfocusedDisowned, - UnfocusedSticky, - Urgent - }; - - static bool - is_free(Client_ptr client) - { - return (client->m_floating && (!client->m_fullscreen || client->m_contained)) - || !client->m_managed - || client->m_disowned; - } - - Client( - Server_ptr server, - Surface surface, - Output_ptr output, - Context_ptr context, - Workspace_ptr workspace - ); - - ~Client(); - - Client(Client const&) = default; - Client& operator=(Client const&) = default; - - OutsideState get_outside_state() const noexcept; - - struct wlr_surface* get_surface() noexcept; - - void focus() noexcept; - void unfocus() noexcept; - - void stick() noexcept; - void unstick() noexcept; - - void disown() noexcept; - void reclaim() noexcept; - - void set_urgent() noexcept; - void unset_urgent() noexcept; - - void expect_unmap() noexcept; - bool consume_unmap_if_expecting() noexcept; - - void set_tile_region(Region&) noexcept; - void set_free_region(Region&) noexcept; - - void set_tile_decoration(Decoration const&) noexcept; - void set_free_decoration(Decoration const&) noexcept; - - Server_ptr mp_server; - - Uid m_uid; - Surface m_surface; - - struct wlr_scene_node* mp_scene; - struct wlr_scene_node* mp_scene_surface; - struct wlr_scene_rect* m_protrusions[4]; // top, bottom, left, right - - std::string m_title; - - Output_ptr mp_output; - Context_ptr mp_context; - Workspace_ptr mp_workspace; - - Region m_free_region; - Region m_tile_region; - Region m_active_region; - Region m_previous_region; - Region m_inner_region; - - Decoration m_tile_decoration; - Decoration m_free_decoration; - Decoration m_active_decoration; - - bool m_focused; - bool m_mapped; - bool m_managed; - bool m_urgent; - bool m_floating; - bool m_fullscreen; - bool m_contained; - bool m_invincible; - bool m_sticky; - bool m_iconifyable; - bool m_iconified; - bool m_disowned; - bool m_producing; - bool m_attaching; - - std::chrono::time_point<std::chrono::steady_clock> m_last_focused; - std::chrono::time_point<std::chrono::steady_clock> m_last_touched; - std::chrono::time_point<std::chrono::steady_clock> m_managed_since; - - struct wl_listener ml_commit; - struct wl_listener ml_map; - struct wl_listener ml_unmap; - struct wl_listener ml_destroy; - struct wl_listener ml_set_title; - struct wl_listener ml_fullscreen; - struct wl_listener ml_request_move; - struct wl_listener ml_request_resize; -#ifdef XWAYLAND - struct wl_listener ml_request_activate; - struct wl_listener ml_request_configure; - struct wl_listener ml_set_hints; -#else - struct wl_listener ml_new_xdg_popup; -#endif - -private: - OutsideState m_outside_state; - - void set_inner_region(Region&) noexcept; - void set_active_region(Region&) noexcept; - -}* Client_ptr; - -inline bool -operator==(Client const& lhs, Client const& rhs) -{ - if (lhs.m_surface.type != rhs.m_surface.type) - return false; - - switch (lhs.m_surface.type) { - case SurfaceType::XDGShell: // fallthrough - case SurfaceType::LayerShell: return lhs.m_surface.xdg == rhs.m_surface.xdg; - case SurfaceType::X11Managed: // fallthrough - case SurfaceType::X11Unmanaged: return lhs.m_surface.xwayland == rhs.m_surface.xwayland; - } -} - -namespace std -{ - template <> - struct hash<Client> { - - std::size_t - operator()(Client const& client) const - { - switch (client.m_surface.type) { - case SurfaceType::XDGShell: // fallthrough - case SurfaceType::LayerShell: - return std::hash<wlr_xdg_surface*>{}(client.m_surface.xdg); - case SurfaceType::X11Managed: // fallthrough - case SurfaceType::X11Unmanaged: - return std::hash<wlr_xwayland_surface*>{}(client.m_surface.xwayland); - } - } - - }; -} diff --git a/include/kranewl/tree/output.hh b/include/kranewl/tree/output.hh @@ -52,10 +52,6 @@ public: struct wlr_output* mp_wlr_output; struct wlr_scene_output* mp_wlr_scene_output; - struct wlr_output_damage* mp_damage; - struct wlr_output_mode* mp_current_mode; - enum wl_output_subpixel m_subpixel; - struct wl_listener ml_frame; struct wl_listener ml_commit; struct wl_listener ml_present; diff --git a/include/kranewl/tree/view.hh b/include/kranewl/tree/view.hh @@ -3,7 +3,7 @@ #include <kranewl/common.hh> #include <kranewl/decoration.hh> #include <kranewl/geometry.hh> -#include <kranewl/layers.hh> +#include <kranewl/layer.hh> #include <kranewl/model.hh> #include <kranewl/tree/surface.hh> @@ -88,7 +88,7 @@ typedef struct View { void map(); void unmap(); void tile(Toggle); - void relayer(Layer::type); + void relayer(Layer); void raise() const; void lower() const; @@ -129,6 +129,7 @@ typedef struct View { Region const& tile_region() const { return m_tile_region; } Region const& active_region() const { return m_active_region; } void set_free_region(Region const&); + void set_free_pos(Pos const&); void set_tile_region(Region const&); Dim const& minimum_dim() const { return m_minimum_dim; } Dim const& preferred_dim() const { return m_preferred_dim; } @@ -216,12 +217,13 @@ private: bool m_iconified; bool m_disowned; - Layer::type m_layer; + Layer m_layer; OutsideState m_outside_state; void set_inner_region(Region const&); void set_active_region(Region const&); + void set_active_pos(Pos const&); }* View_ptr; diff --git a/src/kranewl/input/cursor.cc b/src/kranewl/input/cursor.cc @@ -0,0 +1,420 @@ +#include <trace.hh> + +#include <kranewl/input/cursor.hh> + +#include <kranewl/input/seat.hh> +#include <kranewl/layer.hh> +#include <kranewl/server.hh> +#include <kranewl/tree/view.hh> +#include <kranewl/util.hh> + +// https://github.com/swaywm/wlroots/issues/682 +#include <pthread.h> +#define class class_ +#define namespace namespace_ +#define static +extern "C" { +#include <wlr/types/wlr_cursor.h> +#include <wlr/types/wlr_data_device.h> +#include <wlr/types/wlr_idle.h> +#include <wlr/types/wlr_scene.h> +#include <wlr/types/wlr_seat.h> +#include <wlr/types/wlr_xcursor_manager.h> +} +#undef static +#undef class +#undef namespace + +Cursor::Cursor( + Server_ptr server, + Seat_ptr seat, + struct wlr_cursor* cursor, + struct wlr_pointer_constraints_v1* pointer_constraints, + struct wlr_relative_pointer_manager_v1* relative_pointer_manager, + struct wlr_virtual_pointer_manager_v1* virtual_pointer_manager +) + : mp_server(server), + mp_seat(seat), + mp_wlr_cursor(cursor), + mp_cursor_manager(wlr_xcursor_manager_create(nullptr, 24)), + mp_pointer_constraints(pointer_constraints), + mp_relative_pointer_manager(relative_pointer_manager), + mp_virtual_pointer_manager(virtual_pointer_manager), + ml_cursor_motion({ .notify = Cursor::handle_cursor_motion }), + ml_cursor_motion_absolute({ .notify = Cursor::handle_cursor_motion_absolute }), + ml_cursor_button({ .notify = Cursor::handle_cursor_button }), + ml_cursor_axis({ .notify = Cursor::handle_cursor_axis }), + ml_cursor_frame({ .notify = Cursor::handle_cursor_frame }), + ml_request_start_drag({ .notify = Cursor::handle_request_start_drag }), + ml_start_drag({ .notify = Cursor::handle_start_drag }), + ml_request_set_cursor({ .notify = Cursor::handle_request_set_cursor }) +{ + TRACE(); + + wlr_xcursor_manager_load(mp_cursor_manager, 1); + + wl_signal_add(&cursor->events.motion, &ml_cursor_motion); + wl_signal_add(&cursor->events.motion_absolute, &ml_cursor_motion_absolute); + wl_signal_add(&cursor->events.button, &ml_cursor_button); + wl_signal_add(&cursor->events.axis, &ml_cursor_axis); + wl_signal_add(&cursor->events.frame, &ml_cursor_frame); + wl_signal_add(&mp_seat->mp_wlr_seat->events.request_start_drag, &ml_request_start_drag); + wl_signal_add(&mp_seat->mp_wlr_seat->events.start_drag, &ml_start_drag); + wl_signal_add(&mp_seat->mp_wlr_seat->events.request_set_cursor, &ml_request_set_cursor); +} + +Cursor::~Cursor() +{ + TRACE(); + +} + +static inline View_ptr +view_at( + Server_ptr server, + double lx, double ly, + struct wlr_surface** surface, + double* sx, double* sy +) +{ + static std::vector<Layer> focus_order = { + Layer::Overlay, + Layer::Top, + Layer::Free, + Layer::Tile, + Layer::Bottom, + }; + + struct wlr_scene_node* node; + for (auto const& layer : focus_order) { + if ((node = wlr_scene_node_at(server->m_layers[layer], lx, ly, sx, sy))) { + if (node->type != WLR_SCENE_NODE_SURFACE) + return nullptr; + + *surface = wlr_scene_surface_from_node(node)->surface; + + while (node && !node->data) + node = node->parent; + + return reinterpret_cast<View_ptr>(node->data); + } + } + + return nullptr; +} + +View_ptr +Cursor::view_under_cursor() const +{ + double sx, sy; + struct wlr_surface* surface = nullptr; + + View_ptr view = view_at( + mp_server, + mp_wlr_cursor->x, + mp_wlr_cursor->y, + &surface, + &sx, &sy + ); + + return view; +} + +static inline void +process_cursor_move(Cursor_ptr cursor, uint32_t time) +{ + TRACE(); + + View_ptr view = cursor->m_grab_state.view; + view->set_free_pos(Pos{ + .x = cursor->mp_wlr_cursor->x - cursor->m_grab_state.x, + .y = cursor->mp_wlr_cursor->y - cursor->m_grab_state.y + }); + + view->configure( + view->free_region(), + view->free_decoration().extents(), + true + ); +} + +static inline void +process_cursor_resize(Cursor_ptr cursor, uint32_t time) +{ + TRACE(); + +} + +static inline void +cursor_motion_to_client( + Cursor_ptr cursor, + View_ptr view, + struct wlr_surface* surface, + double sx, double sy, + uint32_t time +) +{ + if (true /* TODO: focus_follows_cursor */ && time && view && view->managed()) + cursor->mp_seat->mp_model->focus_view(view); + + if (!surface) { + wlr_seat_pointer_notify_clear_focus(cursor->mp_seat->mp_wlr_seat); + return; + } + + if (!time) { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + time = now.tv_sec * 1000 + now.tv_nsec / 1000000; + } + + wlr_seat_pointer_notify_enter(cursor->mp_seat->mp_wlr_seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(cursor->mp_seat->mp_wlr_seat, time, sx, sy); +} + +static inline void +process_cursor_motion(Cursor_ptr cursor, uint32_t time) +{ + TRACE(); + + struct wlr_drag_icon* icon; + if (cursor->mp_seat->mp_wlr_seat->drag && (icon = cursor->mp_seat->mp_wlr_seat->drag->icon)) + wlr_scene_node_set_position( + reinterpret_cast<struct wlr_scene_node*>(icon->data), + cursor->mp_wlr_cursor->x + icon->surface->sx, + cursor->mp_wlr_cursor->y + icon->surface->sy + ); + + switch (cursor->m_cursor_mode) { + case Cursor::CursorMode::Move: process_cursor_move(cursor, time); return; + case Cursor::CursorMode::Resize: process_cursor_resize(cursor, time); return; + case Cursor::CursorMode::Passthrough: // fallthrough + default: break; + } + + double sx, sy; + struct wlr_surface* surface = nullptr; + + View_ptr view = view_at( + cursor->mp_server, + cursor->mp_wlr_cursor->x, + cursor->mp_wlr_cursor->y, + &surface, + &sx, &sy + ); + + if (!view && time) { + wlr_xcursor_manager_set_cursor_image( + cursor->mp_cursor_manager, + "left_ptr", + cursor->mp_wlr_cursor + ); + } + + cursor_motion_to_client(cursor, view, surface, sx, sy, time); +} + +void +Cursor::handle_cursor_motion(struct wl_listener* listener, void* data) +{ + TRACE(); + + Cursor_ptr cursor = wl_container_of(listener, cursor, ml_cursor_motion); + struct wlr_event_pointer_motion* event + = reinterpret_cast<struct wlr_event_pointer_motion*>(data); + + wlr_cursor_move(cursor->mp_wlr_cursor, event->device, event->delta_x, event->delta_y); + process_cursor_motion(cursor, event->time_msec); +} + +void +Cursor::handle_cursor_motion_absolute(struct wl_listener* listener, void* data) +{ + TRACE(); + + Cursor_ptr cursor = wl_container_of(listener, cursor, ml_cursor_motion_absolute); + struct wlr_event_pointer_motion_absolute* event + = reinterpret_cast<struct wlr_event_pointer_motion_absolute*>(data); + + wlr_cursor_warp_absolute(cursor->mp_wlr_cursor, event->device, event->x, event->y); + process_cursor_motion(cursor, event->time_msec); +} + +bool +process_cursorbinding(Cursor_ptr cursor, uint32_t button, uint32_t modifiers) +{ + TRACE(); + + if (!button || !modifiers) + return false; + + CursorInput input = CursorInput{ + .target = CursorInput::Target::Global, + .button = static_cast<CursorInput::Button>(button), + .modifiers = modifiers & ~WLR_MODIFIER_CAPS + }; + + View_ptr view = cursor->view_under_cursor(); + Model_ptr model = cursor->mp_seat->mp_model; + View_ptr focused_view = model->focused_view(); + +#define CALL_AND_HANDLE_FOCUS(binding) \ + do { \ + if (((*binding)(*model, view) && view && view != focused_view && view->managed())) \ + model->focus_view(view); \ + } while (false) + + { // global binding + auto binding = Util::const_retrieve(model->cursor_bindings(), input); + + if (binding) { + CALL_AND_HANDLE_FOCUS(binding); + return true; + } + } + + if (!view) { // root binding + input.target = CursorInput::Target::Root; + auto binding = Util::const_retrieve(model->cursor_bindings(), input); + + if (binding) { + CALL_AND_HANDLE_FOCUS(binding); + return true; + } + } else { // view binding + input.target = CursorInput::Target::View; + auto binding = Util::const_retrieve(model->cursor_bindings(), input); + + if (binding) { + CALL_AND_HANDLE_FOCUS(binding); + return true; + } + } +#undef CALL_AND_HANDLE_FOCUS + + return false; +} + +void +Cursor::handle_cursor_button(struct wl_listener* listener, void* data) +{ + TRACE(); + + Cursor_ptr cursor = wl_container_of(listener, cursor, ml_cursor_button); + struct wlr_event_pointer_button* event + = reinterpret_cast<struct wlr_event_pointer_button*>(data); + + wlr_idle_notify_activity( + cursor->mp_seat->mp_idle, + cursor->mp_seat->mp_wlr_seat + ); + + switch (event->state) { + case WLR_BUTTON_PRESSED: + { + struct wlr_keyboard* keyboard + = wlr_seat_get_keyboard(cursor->mp_seat->mp_wlr_seat); + + uint32_t button = event->button; + uint32_t modifiers = keyboard + ? wlr_keyboard_get_modifiers(keyboard) + : 0; + + if (!process_cursorbinding(cursor, button, modifiers) && false /* TODO: !focus_follows_cursor */) { + View_ptr view = cursor->view_under_cursor(); + + if (view && !view->focused() && view->managed()) { + cursor->mp_seat->mp_model->focus_view(view); + return; + } + } + + break; + } + case WLR_BUTTON_RELEASED: + { + if (cursor->m_cursor_mode != CursorMode::Passthrough) { + cursor->m_cursor_mode = CursorMode::Passthrough; + + wlr_xcursor_manager_set_cursor_image( + cursor->mp_cursor_manager, + "left_ptr", + cursor->mp_wlr_cursor + ); + } + + break; + } + default: break; + } + + wlr_seat_pointer_notify_button( + cursor->mp_seat->mp_wlr_seat, + event->time_msec, + event->button, + event->state + ); +} + +void +Cursor::handle_cursor_axis(struct wl_listener* listener, void* data) +{ + TRACE(); + + Cursor_ptr cursor = wl_container_of(listener, cursor, ml_cursor_axis); + struct wlr_event_pointer_axis* event + = reinterpret_cast<struct wlr_event_pointer_axis*>(data); + + wlr_seat_pointer_notify_axis( + cursor->mp_seat->mp_wlr_seat, + event->time_msec, + event->orientation, + event->delta, + event->delta_discrete, + event->source + ); +} + +void +Cursor::handle_cursor_frame(struct wl_listener* listener, void*) +{ + TRACE(); + + Cursor_ptr cursor = wl_container_of(listener, cursor, ml_cursor_frame); + wlr_seat_pointer_notify_frame(cursor->mp_seat->mp_wlr_seat); +} + +void +Cursor::handle_request_start_drag(struct wl_listener* listener, void* data) +{ + TRACE(); + + Cursor_ptr cursor = wl_container_of(listener, cursor, ml_request_set_cursor); + struct wlr_seat_pointer_request_set_cursor_event* event + = reinterpret_cast<struct wlr_seat_pointer_request_set_cursor_event*>(data); + + struct wlr_seat_client* focused_client + = cursor->mp_seat->mp_wlr_seat->pointer_state.focused_client; + + if (focused_client == event->seat_client) + wlr_cursor_set_surface( + cursor->mp_wlr_cursor, + event->surface, + event->hotspot_x, + event->hotspot_y + ); +} + +void +Cursor::handle_start_drag(struct wl_listener*, void*) +{ + TRACE(); + +} + +void +Cursor::handle_request_set_cursor(struct wl_listener*, void*) +{ + TRACE(); + +} diff --git a/src/kranewl/input/mouse.cc b/src/kranewl/input/mouse.cc @@ -1,300 +0,0 @@ -#include <trace.hh> - -#include <kranewl/input/mouse.hh> - -#include <kranewl/input/seat.hh> -#include <kranewl/layers.hh> -#include <kranewl/server.hh> -#include <kranewl/tree/view.hh> - -// https://github.com/swaywm/wlroots/issues/682 -#include <pthread.h> -#define class class_ -#define namespace namespace_ -#define static -extern "C" { -#include <wlr/types/wlr_cursor.h> -#include <wlr/types/wlr_data_device.h> -#include <wlr/types/wlr_scene.h> -#include <wlr/types/wlr_seat.h> -#include <wlr/types/wlr_xcursor_manager.h> -} -#undef static -#undef class -#undef namespace - -Mouse::Mouse( - Server_ptr server, - Seat_ptr seat, - struct wlr_cursor* cursor, - struct wlr_pointer_constraints_v1* pointer_constraints, - struct wlr_relative_pointer_manager_v1* relative_pointer_manager, - struct wlr_virtual_pointer_manager_v1* virtual_pointer_manager -) - : mp_server(server), - mp_seat(seat), - mp_cursor(cursor), - mp_cursor_manager(wlr_xcursor_manager_create(nullptr, 24)), - mp_pointer_constraints(pointer_constraints), - mp_relative_pointer_manager(relative_pointer_manager), - mp_virtual_pointer_manager(virtual_pointer_manager), - ml_cursor_motion({ .notify = Mouse::handle_cursor_motion }), - ml_cursor_motion_absolute({ .notify = Mouse::handle_cursor_motion_absolute }), - ml_cursor_button({ .notify = Mouse::handle_cursor_button }), - ml_cursor_axis({ .notify = Mouse::handle_cursor_axis }), - ml_cursor_frame({ .notify = Mouse::handle_cursor_frame }), - ml_request_start_drag({ .notify = Mouse::handle_request_start_drag }), - ml_start_drag({ .notify = Mouse::handle_start_drag }), - ml_request_set_cursor({ .notify = Mouse::handle_request_set_cursor }) -{ - TRACE(); - - wlr_xcursor_manager_load(mp_cursor_manager, 1); - - wl_signal_add(&cursor->events.motion, &ml_cursor_motion); - wl_signal_add(&cursor->events.motion_absolute, &ml_cursor_motion_absolute); - wl_signal_add(&cursor->events.button, &ml_cursor_button); - wl_signal_add(&cursor->events.axis, &ml_cursor_axis); - wl_signal_add(&cursor->events.frame, &ml_cursor_frame); - wl_signal_add(&mp_seat->mp_wlr_seat->events.request_start_drag, &ml_request_start_drag); - wl_signal_add(&mp_seat->mp_wlr_seat->events.start_drag, &ml_start_drag); - wl_signal_add(&mp_seat->mp_wlr_seat->events.request_set_cursor, &ml_request_set_cursor); -} - -Mouse::~Mouse() -{ - TRACE(); - -} - -static inline View_ptr -view_at( - Server_ptr server, - double lx, double ly, - struct wlr_surface** surface, - double* sx, double* sy -) -{ - static std::vector<Layer::type> focus_order = { - Layer::Overlay, - Layer::Top, - Layer::Free, - Layer::Tile, - Layer::Bottom, - }; - - struct wlr_scene_node** layers = server->m_layers; - struct wlr_scene_node* node; - - for (auto const& layer : focus_order) { - if ((node = wlr_scene_node_at(layers[layer], lx, ly, sx, sy))) { - if (node->type != WLR_SCENE_NODE_SURFACE) - return nullptr; - - *surface = wlr_scene_surface_from_node(node)->surface; - - while (node && !node->data) - node = node->parent; - - return reinterpret_cast<View_ptr>(node->data); - } - } - - return nullptr; -} - -View_ptr -Mouse::view_under_cursor() const -{ - double sx, sy; - struct wlr_surface* surface = nullptr; - - View_ptr view = view_at( - mp_server, - mp_cursor->x, - mp_cursor->y, - &surface, - &sx, &sy - ); - - return view; -} - -static inline void -process_cursor_move(Mouse_ptr mouse, uint32_t time) -{ - TRACE(); - -} - -static inline void -process_cursor_resize(Mouse_ptr mouse, uint32_t time) -{ - TRACE(); - -} - -static inline void -cursor_motion_to_client( - Mouse_ptr mouse, - View_ptr view, - struct wlr_surface* surface, - double sx, double sy, - uint32_t time -) -{ - if (true /* TODO: focus_follows_mouse */ && time && view && view->managed()) - mouse->mp_seat->mp_model->focus_view(view); - - if (!surface) { - wlr_seat_pointer_notify_clear_focus(mouse->mp_seat->mp_wlr_seat); - return; - } - - if (!time) { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - time = now.tv_sec * 1000 + now.tv_nsec / 1000000; - } - - wlr_seat_pointer_notify_enter(mouse->mp_seat->mp_wlr_seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(mouse->mp_seat->mp_wlr_seat, time, sx, sy); -} - -static inline void -process_cursor_motion(Mouse_ptr mouse, uint32_t time) -{ - TRACE(); - - struct wlr_drag_icon* icon; - if (mouse->mp_seat->mp_wlr_seat->drag && (icon = mouse->mp_seat->mp_wlr_seat->drag->icon)) - wlr_scene_node_set_position( - reinterpret_cast<struct wlr_scene_node*>(icon->data), - mouse->mp_cursor->x + icon->surface->sx, - mouse->mp_cursor->y + icon->surface->sy - ); - - switch (mouse->m_cursor_mode) { - case Mouse::CursorMode::Move: process_cursor_move(mouse, time); return; - case Mouse::CursorMode::Resize: process_cursor_resize(mouse, time); return; - case Mouse::CursorMode::Passthrough: // fallthrough - default: break; - } - - double sx, sy; - struct wlr_surface* surface = nullptr; - - View_ptr view = view_at( - mouse->mp_server, - mouse->mp_cursor->x, - mouse->mp_cursor->y, - &surface, - &sx, &sy - ); - - if (!view && time) { - wlr_xcursor_manager_set_cursor_image( - mouse->mp_cursor_manager, - "left_ptr", - mouse->mp_cursor - ); - } - - cursor_motion_to_client(mouse, view, surface, sx, sy, time); -} - -void -Mouse::handle_cursor_motion(struct wl_listener* listener, void* data) -{ - TRACE(); - - Mouse_ptr mouse = wl_container_of(listener, mouse, ml_cursor_motion); - struct wlr_event_pointer_motion* event - = reinterpret_cast<struct wlr_event_pointer_motion*>(data); - - wlr_cursor_move(mouse->mp_cursor, event->device, event->delta_x, event->delta_y); - process_cursor_motion(mouse, event->time_msec); -} - -void -Mouse::handle_cursor_motion_absolute(struct wl_listener* listener, void* data) -{ - TRACE(); - - Mouse_ptr mouse = wl_container_of(listener, mouse, ml_cursor_motion_absolute); - struct wlr_event_pointer_motion_absolute* event - = reinterpret_cast<struct wlr_event_pointer_motion_absolute*>(data); - - wlr_cursor_warp_absolute(mouse->mp_cursor, event->device, event->x, event->y); - process_cursor_motion(mouse, event->time_msec); -} - -void -Mouse::handle_cursor_button(struct wl_listener* listener, void* data) -{ - TRACE(); - - Mouse_ptr mouse = wl_container_of(listener, mouse, ml_cursor_button); - struct wlr_event_pointer_button* event - = reinterpret_cast<struct wlr_event_pointer_button*>(data); - - wlr_seat_pointer_notify_button( - mouse->mp_seat->mp_wlr_seat, - event->time_msec, - event->button, - event->state - ); - - double sx, sy; - struct wlr_surface* surface = nullptr; - - View_ptr view = view_at( - mouse->mp_server, - mouse->mp_cursor->x, - mouse->mp_cursor->y, - &surface, - &sx, &sy - ); - - if (event->state == WLR_BUTTON_RELEASED) - mouse->m_cursor_mode = CursorMode::Passthrough; - else if (false /* TODO: !focus_follows_mouse */) - mouse->mp_seat->mp_model->focus_view(view); -} - -void -Mouse::handle_cursor_axis(struct wl_listener*, void*) -{ - TRACE(); - -} - -void -Mouse::handle_cursor_frame(struct wl_listener* listener, void*) -{ - TRACE(); - - Mouse_ptr mouse = wl_container_of(listener, mouse, ml_cursor_frame); - wlr_seat_pointer_notify_frame(mouse->mp_seat->mp_wlr_seat); -} - -void -Mouse::handle_request_start_drag(struct wl_listener*, void*) -{ - TRACE(); - -} - -void -Mouse::handle_start_drag(struct wl_listener*, void*) -{ - TRACE(); - -} - -void -Mouse::handle_request_set_cursor(struct wl_listener*, void*) -{ - TRACE(); - -} diff --git a/src/kranewl/input/seat.cc b/src/kranewl/input/seat.cc @@ -1,7 +1,7 @@ #include <trace.hh> #include <kranewl/input/keyboard.hh> -#include <kranewl/input/mouse.hh> +#include <kranewl/input/cursor.hh> #include <kranewl/input/seat.hh> #include <kranewl/util.hh> @@ -35,7 +35,7 @@ Seat::Seat( mp_idle_inhibit_manager(idle_inhibit_manager), mp_virtual_keyboard_manager(virtual_keyboard_manager), mp_keyboard_shortcuts_inhibit_manager(keyboard_shortcuts_inhibit_manager), - mp_mouse(new Mouse( + mp_cursor(new Cursor( server, this, cursor, @@ -65,7 +65,7 @@ Seat::~Seat() { TRACE(); - delete mp_mouse; + delete mp_cursor; for (Keyboard_ptr keyboard : m_keyboards) delete keyboard; diff --git a/src/kranewl/layout.cc b/src/kranewl/layout.cc @@ -1536,7 +1536,7 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) } default: { - spdlog::critical("no associated configuration defined"); + spdlog::critical("No associated configuration defined"); std::exit(EXIT_FAILURE); } } @@ -1583,7 +1583,7 @@ LayoutHandler::Layout::kind_to_default_data(LayoutKind kind) } default: { - spdlog::critical("no associated default data defined"); + spdlog::critical("No associated default data defined"); std::exit(EXIT_FAILURE); } } diff --git a/src/kranewl/model.cc b/src/kranewl/model.cc @@ -7,8 +7,9 @@ #include <kranewl/context.hh> #include <kranewl/cycle.t.hh> #include <kranewl/exec.hh> -#include <kranewl/input/mouse.hh> -#include <kranewl/input/keybindings.hh> +#include <kranewl/input/cursor-bindings.hh> +#include <kranewl/input/cursor.hh> +#include <kranewl/input/key-bindings.hh> #include <kranewl/server.hh> #include <kranewl/tree/output.hh> #include <kranewl/tree/view.hh> @@ -56,7 +57,7 @@ Model::Model( m_unmanaged_views{}, mp_focus(nullptr), m_key_bindings(Bindings::key_bindings), - m_mouse_bindings{} + m_cursor_bindings(Bindings::cursor_bindings) { TRACE(); @@ -119,7 +120,7 @@ Model::exit() mp_server->terminate(); } -const View_ptr +View_ptr Model::focused_view() const { return mp_focus; @@ -131,6 +132,12 @@ Model::key_bindings() const return m_key_bindings; } +CursorBindings const& +Model::cursor_bindings() const +{ + return m_cursor_bindings; +} + Output_ptr Model::create_output( struct wlr_output* wlr_output, @@ -244,13 +251,6 @@ Model::focus_view(View_ptr view) } void -Model::unfocus_view(View_ptr view) -{ - TRACE(); - -} - -void Model::place_view(Placement& placement) { TRACE(); diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc @@ -5,7 +5,6 @@ #include <kranewl/exec.hh> #include <kranewl/input/keyboard.hh> #include <kranewl/model.hh> -#include <kranewl/tree/client.hh> #include <kranewl/tree/output.hh> #include <kranewl/tree/view.hh> #include <kranewl/tree/xdg_view.hh> @@ -61,7 +60,9 @@ extern "C" { #include <wlr/types/wlr_xdg_shell.h> #include <wlr/util/box.h> #ifdef XWAYLAND +#define Cursor Cursor_ #include <X11/Xlib.h> +#undef Cursor #include <wlr/xwayland.h> #endif } @@ -454,7 +455,7 @@ Server::handle_new_input(struct wl_listener* listener, void* data) case WLR_INPUT_DEVICE_POINTER: { wlr_cursor_attach_input_device( - server->m_seat.mp_mouse->mp_cursor, + server->m_seat.mp_cursor->mp_wlr_cursor, device ); break; @@ -518,13 +519,6 @@ Server::handle_xdg_toplevel_request_resize(struct wl_listener*, void*) } -void -Server::handle_xdg_toplevel_handle_moveresize(View_ptr, CursorMode, uint32_t) -{ - TRACE(); - -} - #ifdef XWAYLAND void Server::handle_xwayland_ready(struct wl_listener*, void*) diff --git a/src/kranewl/tree/client.cc b/src/kranewl/tree/client.cc @@ -1,210 +0,0 @@ -#include <kranewl/tree/client.hh> - -// https://github.com/swaywm/wlroots/issues/682 -#include <pthread.h> -#define class class_ -#define namespace namespace_ -#define static -extern "C" { -#include <wlr/types/wlr_xdg_shell.h> -#ifdef XWAYLAND -#include <wlr/xwayland.h> -#endif -} -#undef static -#undef class -#undef namespace - -Client::Client( - Server_ptr server, - Surface surface, - Output_ptr output, - Context_ptr context, - Workspace_ptr workspace -) - : m_uid{surface.uid()}, - mp_server{server}, - m_surface{surface}, - mp_output{output}, - mp_context{context}, - mp_workspace{workspace}, - m_free_region({}), - m_tile_region({}), - m_active_region({}), - m_previous_region({}), - m_inner_region({}), - m_tile_decoration({}, DEFAULT_COLOR_SCHEME), - m_free_decoration({}, DEFAULT_COLOR_SCHEME), - m_active_decoration({}, DEFAULT_COLOR_SCHEME), - m_focused(false), - m_mapped(false), - m_managed(true), - m_urgent(false), - m_floating(false), - m_fullscreen(false), - m_contained(false), - m_invincible(false), - m_sticky(false), - m_iconifyable(true), - m_iconified(false), - m_disowned(false), - m_producing(true), - m_attaching(false), - m_last_focused(std::chrono::steady_clock::now()), - m_last_touched(std::chrono::steady_clock::now()), - m_managed_since(std::chrono::steady_clock::now()), - m_outside_state{OutsideState::Unfocused} -{} - -Client::~Client() -{} - -Client::OutsideState -Client::get_outside_state() const noexcept -{ - if (m_urgent) - return Client::OutsideState::Urgent; - - return m_outside_state; -} - -struct wlr_surface* -Client::get_surface() noexcept -{ - switch (m_surface.type) { - case SurfaceType::XDGShell: //fallthrough - case SurfaceType::LayerShell: return m_surface.xdg->surface; - case SurfaceType::X11Managed: //fallthrough - case SurfaceType::X11Unmanaged: return m_surface.xwayland->surface; - } - - return nullptr; -} - -void -Client::focus() noexcept -{ - m_focused = true; - m_last_focused = std::chrono::steady_clock::now(); - - switch (m_outside_state) { - case OutsideState::Unfocused: m_outside_state = OutsideState::Focused; return; - case OutsideState::UnfocusedDisowned: m_outside_state = OutsideState::FocusedDisowned; return; - case OutsideState::UnfocusedSticky: m_outside_state = OutsideState::FocusedSticky; return; - default: return; - } -} - -void -Client::unfocus() noexcept -{ - m_focused = false; - - switch (m_outside_state) { - case OutsideState::Focused: m_outside_state = OutsideState::Unfocused; return; - case OutsideState::FocusedDisowned: m_outside_state = OutsideState::UnfocusedDisowned; return; - case OutsideState::FocusedSticky: m_outside_state = OutsideState::UnfocusedSticky; return; - default: return; - } -} - -void -Client::stick() noexcept -{ - m_sticky = true; - - switch (m_outside_state) { - case OutsideState::Focused: m_outside_state = OutsideState::FocusedSticky; return; - case OutsideState::Unfocused: m_outside_state = OutsideState::UnfocusedSticky; return; - default: return; - } -} - -void -Client::unstick() noexcept -{ - m_sticky = false; - - switch (m_outside_state) { - case OutsideState::FocusedSticky: m_outside_state = OutsideState::Focused; return; - case OutsideState::UnfocusedSticky: m_outside_state = OutsideState::Unfocused; return; - default: return; - } -} - -void -Client::disown() noexcept -{ - m_disowned = true; - - switch (m_outside_state) { - case OutsideState::Focused: m_outside_state = OutsideState::FocusedDisowned; return; - case OutsideState::Unfocused: m_outside_state = OutsideState::UnfocusedDisowned; return; - default: return; - } -} - -void -Client::reclaim() noexcept -{ - m_disowned = false; - - switch (m_outside_state) { - case OutsideState::FocusedDisowned: m_outside_state = OutsideState::Focused; return; - case OutsideState::UnfocusedDisowned: m_outside_state = OutsideState::Unfocused; return; - default: return; - } -} - -void -Client::set_tile_region(Region& region) noexcept -{ - m_tile_region = region; - set_active_region(region); -} - -void -Client::set_free_region(Region& region) noexcept -{ - m_free_region = region; - set_active_region(region); -} - -void -Client::set_active_region(Region& region) noexcept -{ - m_previous_region = m_active_region; - set_inner_region(region); - m_active_region = region; -} - -void -Client::set_tile_decoration(Decoration const& decoration) noexcept -{ - m_tile_decoration = decoration; - m_active_decoration = decoration; -} - -void -Client::set_free_decoration(Decoration const& decoration) noexcept -{ - m_free_decoration = decoration; - m_active_decoration = decoration; -} - -void -Client::set_inner_region(Region& region) noexcept -{ - if (m_active_decoration.frame) { - Frame const& frame = *m_active_decoration.frame; - - m_inner_region.pos.x = frame.extents.left; - m_inner_region.pos.y = frame.extents.top; - m_inner_region.dim.w = region.dim.w - frame.extents.left - frame.extents.right; - m_inner_region.dim.h = region.dim.h - frame.extents.top - frame.extents.bottom; - } else { - m_inner_region.pos.x = 0; - m_inner_region.pos.y = 0; - m_inner_region.dim = region.dim; - } -} diff --git a/src/kranewl/tree/output.cc b/src/kranewl/tree/output.cc @@ -118,7 +118,7 @@ Output::set_context(Context_ptr context) TRACE(); if (!context) - spdlog::error("output must contain a valid context"); + spdlog::error("Output must contain a valid context"); if (mp_context) mp_context->set_output(nullptr); diff --git a/src/kranewl/tree/view.cc b/src/kranewl/tree/view.cc @@ -1,6 +1,6 @@ #include <trace.hh> -#include <kranewl/layers.hh> +#include <kranewl/layer.hh> #include <kranewl/server.hh> #include <kranewl/model.hh> #include <kranewl/tree/view.hh> @@ -324,7 +324,7 @@ View::tile(Toggle toggle) } void -View::relayer(Layer::type layer) +View::relayer(Layer layer) { if (layer == m_layer) return; @@ -458,6 +458,13 @@ View::set_free_region(Region const& region) } void +View::set_free_pos(Pos const& pos) +{ + m_free_region.pos = pos; + set_active_pos(pos); +} + +void View::set_tile_region(Region const& region) { m_tile_region = region; @@ -496,6 +503,13 @@ View::set_active_region(Region const& region) } void +View::set_active_pos(Pos const& pos) +{ + m_previous_region = m_active_region; + m_active_region.pos = pos; +} + +void View::set_inner_region(Region const& region) { if (m_active_decoration.frame) { diff --git a/src/kranewl/tree/xdg_view.cc b/src/kranewl/tree/xdg_view.cc @@ -1,7 +1,7 @@ #include <trace.hh> #include <kranewl/context.hh> -#include <kranewl/layers.hh> +#include <kranewl/layer.hh> #include <kranewl/model.hh> #include <kranewl/server.hh> #include <kranewl/tree/output.hh>