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 7f4990d42d43000be4cfc478d01b1974055dced3
parent 8752e09d79575a20a1a6c413fff9f6e77f7109cf
Author: deurzen <max@deurzen.net>
Date:   Fri, 27 May 2022 05:47:38 +0200

implements initial layout application routines

Diffstat:
Dinclude/kranewl/bindings.hh | 27---------------------------
Minclude/kranewl/conf/config.hh | 2+-
Minclude/kranewl/decoration.hh | 39++++++++++++++++++++-------------------
Ainclude/kranewl/input/bindings.hh | 27+++++++++++++++++++++++++++
Ainclude/kranewl/input/keybindings.hh | 109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/kranewl/input/keyboard.hh | 19+++++++++++++------
Ainclude/kranewl/input/mousebindings.hh | 3+++
Minclude/kranewl/input/seat.hh | 31+++++++++++++++++++++++++++++--
Minclude/kranewl/model.hh | 26++++++++++++++++++++++----
Minclude/kranewl/server.hh | 21+++------------------
Minclude/kranewl/tree/view.hh | 7+++++--
Minclude/kranewl/tree/xdg_view.hh | 3+++
Minclude/kranewl/tree/xwayland_view.hh | 3+++
Minclude/kranewl/util.hh | 14+++++++-------
Msrc/kranewl/exec.cc | 2+-
Msrc/kranewl/input/keyboard.cc | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/kranewl/input/seat.cc | 63++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Msrc/kranewl/layout.cc | 66+++++++++++++++++++++++++++++++++---------------------------------
Msrc/kranewl/main.cc | 2+-
Msrc/kranewl/model.cc | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/kranewl/server.cc | 123++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/kranewl/tree/client.cc | 44++++++++++++++++++++++----------------------
Msrc/kranewl/tree/output.cc | 5++---
Msrc/kranewl/tree/view.cc | 66+++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/kranewl/tree/xdg_view.cc | 113++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Msrc/kranewl/tree/xwayland_view.cc | 11+++++++++++
26 files changed, 841 insertions(+), 257 deletions(-)

diff --git a/include/kranewl/bindings.hh b/include/kranewl/bindings.hh @@ -1,27 +0,0 @@ -#pragma once - -#include <kranewl/input/keyboard.hh> -#include <kranewl/input/mouse.hh> - -#include <functional> -#include <optional> -#include <cstdint> - -class Model; -typedef class Client* Client_ptr; - -typedef - std::function<void(Model&)> - KeyboardAction; - -typedef - std::function<bool(Model&, Client_ptr)> - MouseAction; - -typedef - std::unordered_map<KeyboardInput, KeyboardAction> - KeyBindings; - -typedef - std::unordered_map<MouseInput, MouseAction> - MouseBindings; diff --git a/include/kranewl/conf/config.hh b/include/kranewl/conf/config.hh @@ -1,6 +1,6 @@ #pragma once -#include <kranewl/bindings.hh> +#include <kranewl/input/bindings.hh> #include <string> #include <memory> diff --git a/include/kranewl/decoration.hh b/include/kranewl/decoration.hh @@ -8,17 +8,17 @@ struct RGBA final { RGBA(unsigned hex_) : hex(hex_) { - values[0] = static_cast<float>(hex & 0xff) / 255.f; - values[1] = static_cast<float>((hex >> 8) & 0xff) / 255.f; - values[2] = static_cast<float>((hex >> 16) & 0xff) / 255.f; - values[3] = static_cast<float>((hex >> 24) & 0xff) / 255.f; + values[3] = static_cast<float>(hex & 0xff) / 255.f; + values[2] = static_cast<float>((hex >> 8) & 0xff) / 255.f; + values[1] = static_cast<float>((hex >> 16) & 0xff) / 255.f; + values[0] = static_cast<float>((hex >> 24) & 0xff) / 255.f; } RGBA(const float values_[4]) - : hex(((static_cast<unsigned>(values_[3] * 255.f) & 0xff) << 24) + - ((static_cast<unsigned>(values_[2] * 255.f) & 0xff) << 16) + - ((static_cast<unsigned>(values_[1] * 255.f) & 0xff) << 8) + - ((static_cast<unsigned>(values_[0] * 255.f) & 0xff))) + : hex(((static_cast<unsigned>(values_[0] * 255.f) & 0xff) << 24) + + ((static_cast<unsigned>(values_[1] * 255.f) & 0xff) << 16) + + ((static_cast<unsigned>(values_[2] * 255.f) & 0xff) << 8) + + ((static_cast<unsigned>(values_[3] * 255.f) & 0xff))) { values[0] = values_[0]; values[1] = values_[1]; @@ -41,22 +41,22 @@ struct ColorScheme final { }; const static ColorScheme DEFAULT_COLOR_SCHEME = ColorScheme{ - .focused = {0x8181A6FF}, - .fdisowned = {0xc1c1c1FF}, - .fsticky = {0x5F8787FF}, - .unfocused = {0x333333FF}, - .udisowned = {0x999999FF}, - .usticky = {0x444444FF}, - .urgent = {0x87875FFF}, + .focused = RGBA{0x8181A6FF}, + .fdisowned = RGBA{0xc1c1c1FF}, + .fsticky = RGBA{0x5F8787FF}, + .unfocused = RGBA{0x333333FF}, + .udisowned = RGBA{0x999999FF}, + .usticky = RGBA{0x444444FF}, + .urgent = RGBA{0x87875FFF}, }; struct Frame final { Extents extents; - ColorScheme colorscheme; }; struct Decoration final { std::optional<Frame> frame; + ColorScheme colorscheme; Extents const& extents() const { @@ -70,11 +70,12 @@ struct Decoration final { const Decoration NO_DECORATION = Decoration{ std::nullopt, + DEFAULT_COLOR_SCHEME }; const Decoration FREE_DECORATION = Decoration{ Frame{ - Extents{3, 1, 1, 1}, - DEFAULT_COLOR_SCHEME - } + Extents{3, 1, 1, 1} + }, + DEFAULT_COLOR_SCHEME }; diff --git a/include/kranewl/input/bindings.hh b/include/kranewl/input/bindings.hh @@ -0,0 +1,27 @@ +#pragma once + +#include <kranewl/input/keyboard.hh> +#include <kranewl/input/mouse.hh> + +#include <cstdint> +#include <functional> +#include <optional> + +class Model; +typedef struct View* View_ptr; + +typedef + std::function<void(Model&)> + KeyboardAction; + +typedef + std::function<bool(Model&, View_ptr)> + MouseAction; + +typedef + std::unordered_map<KeyboardInput, KeyboardAction> + KeyBindings; + +typedef + std::unordered_map<MouseInput, MouseAction> + MouseBindings; diff --git a/include/kranewl/input/keybindings.hh b/include/kranewl/input/keybindings.hh @@ -0,0 +1,109 @@ +#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()) +}, +{ { 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) +}, +}; + +} +#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/keyboard.hh b/include/kranewl/input/keyboard.hh @@ -8,6 +8,11 @@ extern "C" { #include <cstdint> #include <unordered_set> +struct KeyboardInput { + xkb_keysym_t keysym; + uint32_t modifiers; +}; + typedef class Server* Server_ptr; typedef class Seat* Seat_ptr; @@ -30,10 +35,12 @@ typedef struct Keyboard { }* Keyboard_ptr; -struct KeyboardInput { - uint32_t mod; - xkb_keysym_t keysym; -}; +inline bool +operator==(KeyboardInput const& lhs, KeyboardInput const& rhs) +{ + return lhs.keysym == rhs.keysym + && lhs.modifiers == rhs.modifiers; +} namespace std { @@ -42,10 +49,10 @@ namespace std std::size_t operator()(KeyboardInput const& input) const { - std::size_t mod_hash = std::hash<uint32_t>()(input.mod); std::size_t key_hash = std::hash<xkb_keysym_t>()(input.keysym); + std::size_t modifiers_hash = std::hash<uint32_t>()(input.modifiers); - return mod_hash ^ key_hash; + return modifiers_hash ^ key_hash; } }; } diff --git a/include/kranewl/input/mousebindings.hh b/include/kranewl/input/mousebindings.hh @@ -0,0 +1,3 @@ +#pragma once + + diff --git a/include/kranewl/input/seat.hh b/include/kranewl/input/seat.hh @@ -29,7 +29,20 @@ public: Middle = 274, }; - Seat(Server_ptr, Model_ptr, struct wlr_seat*, struct wlr_cursor*); + Seat( + Server_ptr, + Model_ptr, + struct wlr_seat*, + struct wlr_idle*, + struct wlr_cursor*, + struct wlr_input_inhibit_manager*, + struct wlr_idle_inhibit_manager_v1*, + struct wlr_pointer_constraints_v1*, + struct wlr_relative_pointer_manager_v1*, + struct wlr_virtual_pointer_manager_v1*, + struct wlr_virtual_keyboard_manager_v1*, + struct wlr_keyboard_shortcuts_inhibit_manager_v1* + ); ~Seat(); Keyboard_ptr create_keyboard(struct wlr_input_device*); @@ -47,14 +60,25 @@ public: static void handle_request_set_cursor(struct wl_listener*, void*); static void handle_request_set_selection(struct wl_listener*, void*); static void handle_request_set_primary_selection(struct wl_listener*, void*); + static void handle_inhibit_manager_new_inhibitor(struct wl_listener*, void*); + static void handle_inhibit_manager_inhibit_activate(struct wl_listener*, void*); + static void handle_inhibit_manager_inhibit_deactivate(struct wl_listener*, void*); public: Server_ptr mp_server; Model_ptr mp_model; - struct wlr_seat* mp_seat; + struct wlr_seat* mp_wlr_seat; + struct wlr_idle* mp_idle; struct wlr_cursor* mp_cursor; struct wlr_xcursor_manager* mp_cursor_manager; + struct wlr_input_inhibit_manager* mp_input_inhibit_manager; + struct wlr_idle_inhibit_manager_v1* mp_idle_inhibit_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 wlr_virtual_keyboard_manager_v1* mp_virtual_keyboard_manager; + struct wlr_keyboard_shortcuts_inhibit_manager_v1* mp_keyboard_shortcuts_inhibit_manager; CursorMode m_cursor_mode; std::vector<Keyboard_ptr> m_keyboards; @@ -79,5 +103,8 @@ public: struct wl_listener ml_request_set_cursor; struct wl_listener ml_request_set_selection; struct wl_listener ml_request_set_primary_selection; + struct wl_listener ml_inhibit_manager_new_inhibitor; + struct wl_listener ml_inhibit_manager_inhibit_activate; + struct wl_listener ml_inhibit_manager_inhibit_deactivate; }* Seat_ptr; diff --git a/include/kranewl/model.hh b/include/kranewl/model.hh @@ -1,9 +1,10 @@ #pragma once -#include <kranewl/bindings.hh> #include <kranewl/common.hh> #include <kranewl/cycle.hh> #include <kranewl/geometry.hh> +#include <kranewl/input/bindings.hh> +#include <kranewl/layout.hh> #include <kranewl/placement.hh> #include <kranewl/tree/view.hh> @@ -36,6 +37,8 @@ public: void register_server(Server_ptr); void exit(); + KeyBindings const& key_bindings() const; + Output_ptr create_output(struct wlr_output*, struct wlr_scene_output*, Region const&&); void register_output(Output_ptr); void unregister_output(Output_ptr); @@ -54,20 +57,35 @@ 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(); + void move_view_to_workspace(View_ptr, Index); void move_view_to_workspace(View_ptr, Workspace_ptr); void move_view_to_context(View_ptr, Index); void move_view_to_context(View_ptr, Context_ptr); void move_view_to_output(View_ptr, Index); void move_view_to_output(View_ptr, Output_ptr); - void move_view_to_focused_output(View_ptr); + void activate_workspace(Index); + void activate_workspace(Workspace_ptr); + void activate_context(Index); + void activate_context(Context_ptr); + void activate_output(Index); + void activate_output(Output_ptr); + + void toggle_layout(); + void set_layout(LayoutHandler::LayoutKind); + void set_layout_retain_region(LayoutHandler::LayoutKind); + void apply_layout(Index); void apply_layout(Workspace_ptr); + bool is_free(View_ptr) const; + void spawn_external(std::string&&) const; private: @@ -98,7 +116,7 @@ private: View_ptr mp_focus; - KeyBindings m_key_bindings; - MouseBindings m_mouse_bindings; + const KeyBindings m_key_bindings; + const MouseBindings m_mouse_bindings; }; diff --git a/include/kranewl/server.hh b/include/kranewl/server.hh @@ -13,8 +13,8 @@ extern "C" { #include <string> typedef class Model* Model_ptr; -typedef class View* View_ptr; typedef class Server* Server_ptr; +typedef struct View* View_ptr; typedef class Server final { enum class CursorMode { @@ -28,8 +28,9 @@ public: ~Server(); void run() noexcept; + void terminate() noexcept; - void moveresize_view(View_ptr, Region const&, Extents const&, bool); + void relinquish_focus(); private: static void handle_new_output(struct wl_listener*, void*); @@ -40,10 +41,6 @@ private: static void handle_new_layer_shell_surface(struct wl_listener*, void*); static void handle_xdg_activation(struct wl_listener*, void*); static void handle_new_input(struct wl_listener*, void*); - static void handle_inhibit_activate(struct wl_listener*, void*); - static void handle_inhibit_deactivate(struct wl_listener*, void*); - static void handle_idle_inhibitor_create(struct wl_listener*, void*); - static void handle_idle_inhibitor_destroy(struct wl_listener*, void*); static void handle_xdg_new_toplevel_decoration(struct wl_listener*, void*); static void handle_xdg_toplevel_map(struct wl_listener*, void*); static void handle_xdg_toplevel_unmap(struct wl_listener*, void*); @@ -86,16 +83,8 @@ private: struct wlr_xdg_activation_v1* mp_xdg_activation; struct wlr_output_manager_v1* mp_output_manager; struct wlr_presentation* mp_presentation; - struct wlr_idle* mp_idle; struct wlr_server_decoration_manager* mp_server_decoration_manager; struct wlr_xdg_decoration_manager_v1* mp_xdg_decoration_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 wlr_virtual_keyboard_manager_v1* mp_virtual_keyboard_manager; - struct wlr_input_inhibit_manager* mp_input_inhibit_manager; - struct wlr_idle_inhibit_manager_v1* mp_idle_inhibit_manager; - struct wlr_keyboard_shortcuts_inhibit_manager_v1* mp_keyboard_shortcuts_inhibit_manager; struct wl_listener ml_new_output; struct wl_listener ml_output_layout_change; @@ -105,10 +94,6 @@ private: struct wl_listener ml_new_layer_shell_surface; struct wl_listener ml_xdg_activation; struct wl_listener ml_new_input; - struct wl_listener ml_inhibit_activate; - struct wl_listener ml_inhibit_deactivate; - struct wl_listener ml_idle_inhibitor_create; - struct wl_listener ml_idle_inhibitor_destroy; struct wl_listener ml_xdg_new_toplevel_decoration; #ifdef XWAYLAND struct wl_listener ml_xwayland_ready; diff --git a/include/kranewl/tree/view.hh b/include/kranewl/tree/view.hh @@ -68,8 +68,11 @@ typedef struct View { virtual ~View(); - static void map_view(View_ptr, struct wlr_surface*, bool, struct wlr_output*, bool); - static void unmap_view(View_ptr); + void map(struct wlr_surface*, bool, struct wlr_output*, bool); + void unmap(); + + virtual void focus(bool) = 0; + virtual void moveresize(Region const&, Extents const&, bool) = 0; static bool is_free(View_ptr view) diff --git a/include/kranewl/tree/xdg_view.hh b/include/kranewl/tree/xdg_view.hh @@ -22,6 +22,9 @@ typedef struct XDGView final : public View { ~XDGView(); + void focus(bool) override; + void moveresize(Region const&, Extents const&, bool) override; + static void handle_foreign_activate_request(struct wl_listener*, void*); static void handle_foreign_fullscreen_request(struct wl_listener*, void*); static void handle_foreign_close_request(struct wl_listener*, void*); diff --git a/include/kranewl/tree/xwayland_view.hh b/include/kranewl/tree/xwayland_view.hh @@ -21,6 +21,9 @@ typedef struct XWaylandView final : public View { ~XWaylandView(); + void focus(bool) override; + void moveresize(Region const&, Extents const&, bool) override; + static void handle_foreign_activate_request(struct wl_listener*, void*); static void handle_foreign_fullscreen_request(struct wl_listener*, void*); static void handle_foreign_close_request(struct wl_listener*, void*); diff --git a/include/kranewl/util.hh b/include/kranewl/util.hh @@ -96,13 +96,6 @@ namespace Util } template <typename K, typename V> - V& - at(std::unordered_map<K, V>& c, K& key) - { - return c.at(key); - } - - template <typename K, typename V> std::optional<const V> const_retrieve(std::unordered_map<K, V> const& c, K const& key) { @@ -114,6 +107,13 @@ namespace Util return iter->second; } + template <typename K, typename V> + V& + at(std::unordered_map<K, V>& c, K& key) + { + return c.at(key); + } + template <typename Container> typename std::enable_if<is_iterable<Container>::value, const std::optional<const std::size_t>>::type index_of(Container const& c, typename Container::value_type const& t) diff --git a/src/kranewl/exec.cc b/src/kranewl/exec.cc @@ -8,7 +8,7 @@ void exec_external(std::string& command) { if (!fork()) { setsid(); - execl("/bin/sh", "/bin/sh", "-c", ("exec " + command).c_str(), NULL); + execl("/bin/sh", "/bin/sh", "-c", ("exec " + command).c_str(), nullptr); std::exit(EXIT_SUCCESS); } } diff --git a/src/kranewl/input/keyboard.cc b/src/kranewl/input/keyboard.cc @@ -1,6 +1,18 @@ #include <trace.hh> #include <kranewl/input/keyboard.hh> +#include <kranewl/input/seat.hh> +#include <kranewl/model.hh> +#include <kranewl/server.hh> +#include <kranewl/util.hh> + +extern "C" { +#include <wlr/types/wlr_idle.h> +#include <wlr/types/wlr_input_device.h> +#include <wlr/types/wlr_input_inhibitor.h> +#include <wlr/types/wlr_keyboard.h> +#include <xkbcommon/xkbcommon.h> +} Keyboard::Keyboard(Server_ptr server, Seat_ptr seat, struct wlr_input_device* device) : mp_server(server), @@ -10,6 +22,9 @@ Keyboard::Keyboard(Server_ptr server, Seat_ptr seat, struct wlr_input_device* de ml_modifiers({ .notify = handle_modifiers }), ml_key({ .notify = handle_key }) { + wl_signal_add(&mp_device->keyboard->events.modifiers, &ml_modifiers); + wl_signal_add(&mp_device->keyboard->events.key, &ml_key); + wl_signal_add(&mp_device->events.destroy, &ml_destroy); } Keyboard::~Keyboard() @@ -23,15 +38,83 @@ Keyboard::handle_destroy(struct wl_listener*, void*) } void -Keyboard::handle_modifiers(struct wl_listener*, void*) +Keyboard::handle_modifiers(struct wl_listener* listener, void*) { TRACE(); + Keyboard_ptr keyboard = wl_container_of(listener, keyboard, ml_modifiers); + Seat_ptr seat = keyboard->mp_seat; + + wlr_seat_set_keyboard(seat->mp_wlr_seat, keyboard->mp_device); + wlr_seat_keyboard_notify_modifiers( + seat->mp_wlr_seat, + &keyboard->mp_device->keyboard->modifiers + ); +} + +static bool +process_keybinding(Model_ptr model, KeyboardInput input) +{ + TRACE(); + + auto binding = Util::const_retrieve(model->key_bindings(), input); + + if (binding) { + (*binding)(*model); + return true; + } + + return false; } void -Keyboard::handle_key(struct wl_listener*, void*) +Keyboard::handle_key(struct wl_listener* listener, void* data) { TRACE(); + Keyboard_ptr keyboard = wl_container_of(listener, keyboard, ml_key); + Seat_ptr seat = keyboard->mp_seat; + + struct wlr_event_keyboard_key* event + = reinterpret_cast<struct wlr_event_keyboard_key*>(data); + + uint32_t keycode = event->keycode + 8; + uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->mp_device->keyboard); + + const xkb_keysym_t* keysyms; + int symcount = xkb_state_key_get_syms( + keyboard->mp_device->keyboard->xkb_state, + keycode, + &keysyms + ); + + wlr_idle_notify_activity( + seat->mp_idle, + seat->mp_wlr_seat + ); + + bool key_press_handled = false; + + if (!seat->mp_input_inhibit_manager->active_inhibitor + && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) + { + for (int i = 0; i < symcount; ++i) + key_press_handled |= process_keybinding( + seat->mp_model, + KeyboardInput{ + keysyms[i], + modifiers & ~WLR_MODIFIER_CAPS + } + ); + } + + if (!key_press_handled) { + wlr_seat_set_keyboard(seat->mp_wlr_seat, keyboard->mp_device); + wlr_seat_keyboard_notify_key( + seat->mp_wlr_seat, + event->time_msec, + event->keycode, + event->state + ); + } } diff --git a/src/kranewl/input/seat.cc b/src/kranewl/input/seat.cc @@ -8,19 +8,37 @@ extern "C" { #include <wlr/types/wlr_cursor.h> #include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_xcursor_manager.h> +#include <wlr/types/wlr_idle_inhibit_v1.h> +#include <wlr/types/wlr_input_inhibitor.h> } Seat::Seat( Server_ptr server, Model_ptr model, struct wlr_seat* seat, - struct wlr_cursor* cursor + struct wlr_idle* idle, + struct wlr_cursor* cursor, + struct wlr_input_inhibit_manager* input_inhibit_manager, + struct wlr_idle_inhibit_manager_v1* idle_inhibit_manager, + 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, + struct wlr_virtual_keyboard_manager_v1* virtual_keyboard_manager, + struct wlr_keyboard_shortcuts_inhibit_manager_v1* keyboard_shortcuts_inhibit_manager ) : mp_server(server), mp_model(model), - mp_seat(seat), + mp_wlr_seat(seat), + mp_idle(idle), mp_cursor(cursor), - mp_cursor_manager(wlr_xcursor_manager_create(NULL, 24)), + mp_cursor_manager(wlr_xcursor_manager_create(nullptr, 24)), + mp_input_inhibit_manager(input_inhibit_manager), + mp_idle_inhibit_manager(idle_inhibit_manager), + mp_pointer_constraints(pointer_constraints), + mp_relative_pointer_manager(relative_pointer_manager), + mp_virtual_pointer_manager(virtual_pointer_manager), + mp_virtual_keyboard_manager(virtual_keyboard_manager), + mp_keyboard_shortcuts_inhibit_manager(keyboard_shortcuts_inhibit_manager), ml_destroy({ .notify = Seat::handle_destroy }), ml_cursor_motion({ .notify = Seat::handle_cursor_motion }), ml_cursor_motion_absolute({ .notify = Seat::handle_cursor_motion_absolute }), @@ -31,7 +49,10 @@ Seat::Seat( ml_start_drag({ .notify = Seat::handle_start_drag }), ml_request_set_cursor({ .notify = Seat::handle_request_set_cursor }), ml_request_set_selection({ .notify = Seat::handle_request_set_selection }), - ml_request_set_primary_selection({ .notify = Seat::handle_request_set_primary_selection }) + ml_request_set_primary_selection({ .notify = Seat::handle_request_set_primary_selection }), + ml_inhibit_manager_new_inhibitor({ .notify = Seat::handle_inhibit_manager_new_inhibitor }), + ml_inhibit_manager_inhibit_activate({ .notify = Seat::handle_inhibit_manager_inhibit_activate }), + ml_inhibit_manager_inhibit_deactivate({ .notify = Seat::handle_inhibit_manager_inhibit_deactivate }) { TRACE(); @@ -48,6 +69,9 @@ Seat::Seat( wl_signal_add(&seat->events.request_set_cursor, &ml_request_set_cursor); wl_signal_add(&seat->events.request_set_selection, &ml_request_set_selection); wl_signal_add(&seat->events.request_set_primary_selection, &ml_request_set_primary_selection); + wl_signal_add(&mp_idle_inhibit_manager->events.new_inhibitor, &ml_inhibit_manager_new_inhibitor); + wl_signal_add(&mp_input_inhibit_manager->events.activate, &ml_inhibit_manager_inhibit_activate); + wl_signal_add(&mp_input_inhibit_manager->events.deactivate, &ml_inhibit_manager_inhibit_deactivate); } Seat::~Seat() @@ -79,7 +103,7 @@ process_cursor_motion(Seat_ptr seat, uint32_t time) } double sx, sy; - struct wlr_surface* surface = NULL; + struct wlr_surface* surface = nullptr; // TODO: get client under cursor if (true /* no client under cursor? */) { @@ -91,10 +115,10 @@ process_cursor_motion(Seat_ptr seat, uint32_t time) } if (surface) { - wlr_seat_pointer_notify_enter(seat->mp_seat, surface, sx, sy); - wlr_seat_pointer_notify_motion(seat->mp_seat, time, sx, sy); + wlr_seat_pointer_notify_enter(seat->mp_wlr_seat, surface, sx, sy); + wlr_seat_pointer_notify_motion(seat->mp_wlr_seat, time, sx, sy); } else - wlr_seat_pointer_clear_focus(seat->mp_seat); + wlr_seat_pointer_clear_focus(seat->mp_wlr_seat); } Keyboard_ptr @@ -170,7 +194,7 @@ Seat::handle_cursor_frame(struct wl_listener* listener, void*) TRACE(); Seat_ptr seat = wl_container_of(listener, seat, ml_cursor_frame); - wlr_seat_pointer_notify_frame(seat->mp_seat); + wlr_seat_pointer_notify_frame(seat->mp_wlr_seat); } void @@ -207,3 +231,24 @@ Seat::handle_request_set_primary_selection(struct wl_listener*, void*) TRACE(); } + +void +Seat::handle_inhibit_manager_new_inhibitor(struct wl_listener*, void*) +{ + TRACE(); + +} + +void +Seat::handle_inhibit_manager_inhibit_activate(struct wl_listener*, void*) +{ + TRACE(); + +} + +void +Seat::handle_inhibit_manager_inhibit_deactivate(struct wl_listener*, void*) +{ + TRACE(); + +} diff --git a/src/kranewl/layout.cc b/src/kranewl/layout.cc @@ -1353,9 +1353,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1370,9 +1370,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1387,9 +1387,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1404,9 +1404,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{1, 1, 0, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{1, 1, 0, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1421,9 +1421,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{1, 1, 0, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{1, 1, 0, 0} + }, + DEFAULT_COLOR_SCHEME }, true, false, @@ -1438,9 +1438,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1455,9 +1455,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, false, @@ -1472,9 +1472,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1489,9 +1489,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{0, 0, 3, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{0, 0, 3, 0} + }, + DEFAULT_COLOR_SCHEME }, true, false, @@ -1506,9 +1506,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{3, 0, 0, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{3, 0, 0, 0} + }, + DEFAULT_COLOR_SCHEME }, true, true, @@ -1523,9 +1523,9 @@ LayoutHandler::Layout::kind_to_config(LayoutKind kind) Placement::PlacementMethod::Tile, Decoration{ Frame{ - Extents{3, 0, 0, 0}, - DEFAULT_COLOR_SCHEME - } + Extents{3, 0, 0, 0} + }, + DEFAULT_COLOR_SCHEME }, true, false, diff --git a/src/kranewl/main.cc b/src/kranewl/main.cc @@ -19,7 +19,7 @@ int main(int argc, char** argv) { #ifndef NDEBUG - /* wlr_log_init(WLR_DEBUG, NULL); */ + /* wlr_log_init(WLR_DEBUG, nullptr); */ #ifdef TRACING_ENABLED spdlog::set_level(spdlog::level::trace); #else diff --git a/src/kranewl/model.cc b/src/kranewl/model.cc @@ -8,6 +8,7 @@ #include <kranewl/cycle.t.hh> #include <kranewl/exec.hh> #include <kranewl/input/mouse.hh> +#include <kranewl/input/keybindings.hh> #include <kranewl/server.hh> #include <kranewl/tree/output.hh> #include <kranewl/tree/view.hh> @@ -54,7 +55,7 @@ Model::Model( m_sticky_views{}, m_unmanaged_views{}, mp_focus(nullptr), - m_key_bindings{}, + m_key_bindings(Bindings::key_bindings), m_mouse_bindings{} { TRACE(); @@ -109,6 +110,21 @@ Model::register_server(Server_ptr server) mp_server = server; } +void +Model::exit() +{ + TRACE(); + + m_running = false; + mp_server->terminate(); +} + +KeyBindings const& +Model::key_bindings() const +{ + return m_key_bindings; +} + Output_ptr Model::create_output( struct wlr_output* wlr_output, @@ -208,9 +224,35 @@ Model::reclaim_view(View_ptr) } void -Model::focus_view(View_ptr) +Model::focus_view(View_ptr view) { TRACE(); + + Output_ptr output = view->mp_context->output(); + + if (!output) + return; + + if (!view->m_sticky) { + activate_workspace(view->mp_workspace); + mp_workspace->activate_view(view); + } + + if (mp_focus && mp_focus != view) + unfocus_view(mp_focus); + + view->m_urgent = false; + mp_focus = view; + + if (mp_workspace->layout_is_persistent() || mp_workspace->layout_is_single()) + apply_layout(mp_workspace); +} + +void +Model::unfocus_view(View_ptr view) +{ + TRACE(); + } void @@ -258,8 +300,7 @@ Model::place_view(Placement& placement) spdlog::info("Placing view {} at {}", view->m_uid, std::to_string(view->m_active_region)); map_view(view); - mp_server->moveresize_view( - view, + view->moveresize( view->m_active_region, view->m_active_decoration.extents(), false @@ -267,6 +308,19 @@ Model::place_view(Placement& placement) } void +Model::sync_focus() +{ + View_ptr active = mp_workspace->active(); + + if (active && active != mp_focus) + active->focus(true); + else if (mp_workspace->empty()) { + mp_server->relinquish_focus(); + mp_focus = nullptr; + } +} + +void Model::move_view_to_workspace(View_ptr view, Index index) { TRACE(); @@ -307,6 +361,8 @@ Model::move_view_to_workspace(View_ptr view, Workspace_ptr workspace_to) unmap_view(view); else map_view(view); + + sync_focus(); } void @@ -349,6 +405,8 @@ Model::move_view_to_context(View_ptr view, Context_ptr context_to) unmap_view(view); else map_view(view); + + sync_focus(); } void @@ -397,6 +455,8 @@ Model::move_view_to_output(View_ptr view, Output_ptr output_to) map_view(view); } else unmap_view(view); + + sync_focus(); } void @@ -407,6 +467,99 @@ Model::move_view_to_focused_output(View_ptr view) } void +Model::activate_workspace(Index) +{ + TRACE(); + +} + +void +Model::activate_workspace(Workspace_ptr) +{ + TRACE(); + +} + +void +Model::activate_context(Index) +{ + TRACE(); + +} + +void +Model::activate_context(Context_ptr) +{ + TRACE(); + +} + +void +Model::activate_output(Index) +{ + TRACE(); + +} + +void +Model::activate_output(Output_ptr) +{ + TRACE(); + +} + +void +Model::toggle_layout() +{ + TRACE(); + + mp_workspace->toggle_layout(); + apply_layout(mp_workspace); +} + +void +Model::set_layout(LayoutHandler::LayoutKind layout) +{ + TRACE(); + + mp_workspace->set_layout(layout); + apply_layout(mp_workspace); +} + +void +Model::set_layout_retain_region(LayoutHandler::LayoutKind layout) +{ + Cycle<View_ptr> const& views = mp_workspace->views(); + std::vector<Region> regions; + + bool was_tiled = !mp_workspace->layout_is_free(); + + if (was_tiled) { + regions.reserve(views.size()); + + std::transform( + views.begin(), + views.end(), + std::back_inserter(regions), + [=,this](View_ptr view) -> Region { + if (is_free(view)) + return view->m_free_region; + else + return view->m_tile_region; + } + ); + } + + mp_workspace->set_layout(layout); + + if (was_tiled && mp_workspace->layout_is_free()) + for (std::size_t i = 0; i < views.size(); ++i) + views[i]->set_free_region(regions[i]); + + apply_layout(mp_workspace); +} + +void Model::apply_layout(Index index) { TRACE(); @@ -490,8 +643,32 @@ Model::unregister_view(View_ptr view) std::stringstream uid_stream; uid_stream << std::hex << view->m_uid; + if (view->mp_workspace) + view->mp_workspace->remove_view(view); + m_view_map.erase(view->m_uid); delete view; spdlog::info("Unegistered view 0x{}", uid_stream.str()); + sync_focus(); +} + +bool +Model::is_free(View_ptr view) const +{ + return View::is_free(view) + || ((!view->m_fullscreen || view->m_contained) + && (view->m_sticky + ? mp_workspace + : view->mp_workspace + )->layout_is_free()); +} + +void +Model::spawn_external(std::string&& command) const +{ + TRACE(); + + spdlog::info("Calling external command: {}", command); + exec_external(command); } diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc @@ -114,7 +114,20 @@ Server::Server(Model_ptr model) m_seat([this]() { struct wlr_cursor* cursor = wlr_cursor_create(); wlr_cursor_attach_output_layout(cursor, mp_output_layout); - return Seat{this, mp_model, wlr_seat_create(mp_display, "seat0"), cursor}; + return Seat{ + this, + mp_model, + wlr_seat_create(mp_display, "seat0"), + wlr_idle_create(mp_display), + cursor, + wlr_input_inhibit_manager_create(mp_display), + wlr_idle_inhibit_v1_create(mp_display), + wlr_pointer_constraints_v1_create(mp_display), + wlr_relative_pointer_manager_v1_create(mp_display), + wlr_virtual_pointer_manager_v1_create(mp_display), + wlr_virtual_keyboard_manager_v1_create(mp_display), + wlr_keyboard_shortcuts_inhibit_v1_create(mp_display) + }; }()), #ifdef XWAYLAND mp_xwayland(wlr_xwayland_create(mp_display, mp_compositor, 1)), @@ -122,17 +135,9 @@ Server::Server(Model_ptr model) mp_layer_shell(wlr_layer_shell_v1_create(mp_display)), mp_xdg_shell(wlr_xdg_shell_create(mp_display)), mp_presentation(wlr_presentation_create(mp_display, mp_backend)), - mp_idle(wlr_idle_create(mp_display)), - mp_idle_inhibit_manager(wlr_idle_inhibit_v1_create(mp_display)), mp_server_decoration_manager(wlr_server_decoration_manager_create(mp_display)), mp_xdg_decoration_manager(wlr_xdg_decoration_manager_v1_create(mp_display)), mp_output_manager(wlr_output_manager_v1_create(mp_display)), - mp_input_inhibit_manager(wlr_input_inhibit_manager_create(mp_display)), - mp_keyboard_shortcuts_inhibit_manager(wlr_keyboard_shortcuts_inhibit_v1_create(mp_display)), - mp_pointer_constraints(wlr_pointer_constraints_v1_create(mp_display)), - mp_relative_pointer_manager(wlr_relative_pointer_manager_v1_create(mp_display)), - mp_virtual_pointer_manager(wlr_virtual_pointer_manager_v1_create(mp_display)), - mp_virtual_keyboard_manager(wlr_virtual_keyboard_manager_v1_create(mp_display)), ml_new_output({ .notify = Server::handle_new_output }), ml_output_layout_change({ .notify = Server::handle_output_layout_change }), ml_output_manager_apply({ .notify = Server::handle_output_manager_apply }), @@ -141,10 +146,6 @@ Server::Server(Model_ptr model) ml_new_layer_shell_surface({ .notify = Server::handle_new_layer_shell_surface }), ml_xdg_activation({ .notify = Server::handle_xdg_activation }), ml_new_input({ .notify = Server::handle_new_input }), - ml_inhibit_activate({ .notify = Server::handle_inhibit_activate }), - ml_inhibit_deactivate({ .notify = Server::handle_inhibit_deactivate }), - ml_idle_inhibitor_create({ .notify = Server::handle_idle_inhibitor_create }), - ml_idle_inhibitor_destroy({ .notify = Server::handle_idle_inhibitor_destroy }), ml_xdg_new_toplevel_decoration({ .notify = Server::handle_xdg_new_toplevel_decoration }), #ifdef XWAYLAND ml_xwayland_ready({ .notify = Server::handle_xwayland_ready }), @@ -177,13 +178,10 @@ Server::Server(Model_ptr model) 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_idle_inhibit_manager->events.new_inhibitor, &ml_idle_inhibitor_create); wl_signal_add(&mp_xdg_decoration_manager->events.new_toplevel_decoration, &ml_xdg_new_toplevel_decoration); wl_signal_add(&mp_backend->events.new_input, &ml_new_input); wl_signal_add(&mp_output_manager->events.apply, &ml_output_manager_apply); wl_signal_add(&mp_output_manager->events.test, &ml_output_manager_test); - wl_signal_add(&mp_input_inhibit_manager->events.activate, &ml_inhibit_activate); - wl_signal_add(&mp_input_inhibit_manager->events.deactivate, &ml_inhibit_deactivate); // TODO: mp_keyboard_shortcuts_inhibit_manager signals // TODO: mp_pointer_constraints signals @@ -233,20 +231,45 @@ Server::run() noexcept } void -Server::moveresize_view(View_ptr view, Region const& region, Extents const& extents, bool interactive) +Server::terminate() noexcept { TRACE(); - wlr_scene_node_set_position(view->mp_scene, region.pos.x, region.pos.y); - wlr_scene_node_set_position(view->mp_scene_surface, extents.left, extents.top); - wlr_scene_rect_set_size(view->m_protrusions[0], region.dim.w, extents.top); - wlr_scene_rect_set_size(view->m_protrusions[1], region.dim.w, extents.bottom); - wlr_scene_rect_set_size(view->m_protrusions[2], extents.left, region.dim.h - extents.top - extents.bottom); - wlr_scene_rect_set_size(view->m_protrusions[3], extents.right, region.dim.h - extents.top - extents.bottom); - wlr_scene_node_set_position(&view->m_protrusions[0]->node, 0, 0); - wlr_scene_node_set_position(&view->m_protrusions[1]->node, 0, region.dim.h - extents.bottom); - wlr_scene_node_set_position(&view->m_protrusions[2]->node, 0, extents.top); - wlr_scene_node_set_position(&view->m_protrusions[3]->node, region.dim.w - extents.right, extents.top); + wl_display_terminate(mp_display); +} + +void +Server::relinquish_focus() +{ + struct wlr_surface* focused_surface + = m_seat.mp_wlr_seat->keyboard_state.focused_surface; + + if (focused_surface) { + if (wlr_surface_is_layer_surface(focused_surface)) { + struct wlr_layer_surface_v1* wlr_layer_surface + = wlr_layer_surface_v1_from_wlr_surface(focused_surface); + + if (wlr_layer_surface->mapped && ( + wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP || + wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY)) + { + return; + } + } else { + struct wlr_scene_node* node + = reinterpret_cast<struct wlr_scene_node*>(focused_surface->data); + + struct wlr_xdg_surface* wlr_xdg_surface; + if (wlr_surface_is_xdg_surface(focused_surface) + && (wlr_xdg_surface = wlr_xdg_surface_from_wlr_surface(focused_surface)) + && wlr_xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) + { + wlr_xdg_toplevel_set_activated(wlr_xdg_surface, false); + } + } + } + + wlr_seat_keyboard_notify_clear_focus(m_seat.mp_wlr_seat); } void @@ -379,13 +402,13 @@ Server::handle_new_xdg_surface(struct wl_listener* listener, void* data) &server->m_seat ); - view->mp_scene = wlr_scene_xdg_surface_create( - &server->mp_scene->node, - xdg_surface - ); + /* view->mp_scene = wlr_scene_xdg_surface_create( */ + /* &server->mp_scene->node, */ + /* xdg_surface */ + /* ); */ - view->mp_scene->data = view; - xdg_surface->data = view->mp_scene; + /* view->mp_scene->data = view; */ + /* xdg_surface->data = view->mp_scene; */ } void @@ -418,13 +441,13 @@ Server::handle_new_input(struct wl_listener* listener, void* data) struct xkb_context* context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); struct xkb_keymap* keymap - = xkb_keymap_new_from_names(context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); + = xkb_keymap_new_from_names(context, nullptr, XKB_KEYMAP_COMPILE_NO_FLAGS); wlr_keyboard_set_keymap(device->keyboard, keymap); xkb_keymap_unref(keymap); xkb_context_unref(context); wlr_keyboard_set_repeat_info(device->keyboard, 200, 100); - wlr_seat_set_keyboard(server->m_seat.mp_seat, device); + wlr_seat_set_keyboard(server->m_seat.mp_wlr_seat, device); break; } @@ -440,35 +463,7 @@ Server::handle_new_input(struct wl_listener* listener, void* data) if (!server->m_seat.m_keyboards.empty()) caps |= WL_SEAT_CAPABILITY_KEYBOARD; - wlr_seat_set_capabilities(server->m_seat.mp_seat, caps); -} - -void -Server::handle_inhibit_activate(struct wl_listener*, void*) -{ - TRACE(); - -} - -void -Server::handle_inhibit_deactivate(struct wl_listener*, void*) -{ - TRACE(); - -} - -void -Server::handle_idle_inhibitor_create(struct wl_listener*, void*) -{ - TRACE(); - -} - -void -Server::handle_idle_inhibitor_destroy(struct wl_listener*, void*) -{ - TRACE(); - + wlr_seat_set_capabilities(server->m_seat.mp_wlr_seat, caps); } void diff --git a/src/kranewl/tree/client.cc b/src/kranewl/tree/client.cc @@ -28,28 +28,28 @@ Client::Client( 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{{}}, - m_free_decoration{{}}, - m_active_decoration{{}}, - 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_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_managed_since{std::chrono::steady_clock::now()}, m_outside_state{OutsideState::Unfocused} diff --git a/src/kranewl/tree/output.cc b/src/kranewl/tree/output.cc @@ -62,12 +62,11 @@ Output::handle_frame(struct wl_listener* listener, void*) Output_ptr output = wl_container_of(listener, output, ml_frame); - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - if (!wlr_scene_output_commit(output->mp_wlr_scene_output)) return; + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); wlr_scene_output_send_frame_done(output->mp_wlr_scene_output, &now); } diff --git a/src/kranewl/tree/view.cc b/src/kranewl/tree/view.cc @@ -45,9 +45,9 @@ View::View( mp_workspace(nullptr), mp_wlr_surface(wlr_surface), m_alpha(1.f), - m_tile_decoration(FREE_DECORATION), - m_free_decoration(FREE_DECORATION), - m_active_decoration(FREE_DECORATION), + m_tile_decoration{FREE_DECORATION}, + m_free_decoration{FREE_DECORATION}, + m_active_decoration{FREE_DECORATION}, m_minimum_dim({}), m_preferred_dim({}), m_free_region({}), @@ -99,6 +99,9 @@ View::View( mp_model(model), mp_seat(seat), mp_wlr_surface(wlr_surface), + m_tile_decoration({}, DEFAULT_COLOR_SCHEME), + m_free_decoration({}, DEFAULT_COLOR_SCHEME), + m_active_decoration({}, DEFAULT_COLOR_SCHEME), ml_foreign_activate_request({ .notify = handle_foreign_activate_request }), ml_foreign_fullscreen_request({ .notify = handle_foreign_fullscreen_request }), ml_foreign_close_request({ .notify = handle_foreign_close_request }), @@ -120,7 +123,7 @@ set_view_pid(View_ptr view) struct wl_client* client = wl_resource_get_client(view->mp_wlr_surface->resource); - wl_client_get_credentials(client, &pid, NULL, NULL); + wl_client_get_credentials(client, &pid, nullptr, nullptr); view->m_pid = pid; break; @@ -140,8 +143,7 @@ set_view_pid(View_ptr view) } void -View::map_view( - View_ptr view, +View::map( struct wlr_surface* wlr_surface, bool fullscreen, struct wlr_output* fullscreen_output, @@ -150,50 +152,56 @@ View::map_view( { TRACE(); - Server_ptr server = view->mp_server; - Model_ptr model = view->mp_model; + Server_ptr server = mp_server; + Model_ptr model = mp_model; - view->mp_wlr_surface = wlr_surface; - set_view_pid(view); + mp_wlr_surface = wlr_surface; + set_view_pid(this); - view->mp_scene = &wlr_scene_tree_create(view->mp_server->m_layers[Layer::Tile])->node; - view->mp_wlr_surface->data = view->mp_scene_surface = view->m_type == View::Type::XDGShell + mp_scene = &wlr_scene_tree_create(mp_server->m_layers[Layer::Tile])->node; + mp_wlr_surface->data = mp_scene_surface = m_type == View::Type::XDGShell ? wlr_scene_xdg_surface_create( - view->mp_scene, - reinterpret_cast<XDGView_ptr>(view)->mp_wlr_xdg_surface + mp_scene, + reinterpret_cast<XDGView_ptr>(this)->mp_wlr_xdg_surface ) - : wlr_scene_subsurface_tree_create(view->mp_scene, view->mp_wlr_surface); - view->mp_scene_surface->data = view; + : wlr_scene_subsurface_tree_create(mp_scene, mp_wlr_surface); + mp_scene_surface->data = this; wlr_scene_node_reparent( - view->mp_scene, - server->m_layers[view->m_floating ? Layer::Free : Layer::Tile] + mp_scene, + server->m_layers[m_floating ? Layer::Free : Layer::Tile] ); - // TODO: globalize - static const float border_rgba[4] = {0.5, 0.5, 0.5, 1.0}; - for (std::size_t i = 0; i < 4; ++i) { - view->m_protrusions[i] = wlr_scene_rect_create(view->mp_scene, 0, 0, border_rgba); - view->m_protrusions[i]->node.data = view; - wlr_scene_rect_set_color(view->m_protrusions[i], border_rgba); - wlr_scene_node_lower_to_bottom(&view->m_protrusions[i]->node); + m_protrusions[i] = wlr_scene_rect_create( + mp_scene, + 0, + 0, + m_active_decoration.colorscheme.unfocused.values + ); + m_protrusions[i]->node.data = this; + wlr_scene_rect_set_color( + m_protrusions[i], + m_active_decoration.colorscheme.unfocused.values + ); + wlr_scene_node_lower_to_bottom(&m_protrusions[i]->node); } if (fullscreen_output && fullscreen_output->data) { Output_ptr output = reinterpret_cast<Output_ptr>(fullscreen_output->data); } - model->move_view_to_focused_output(view); + model->move_view_to_focused_output(this); + focus(true); } - void -View::unmap_view(View_ptr view) +View::unmap() { TRACE(); - wlr_scene_node_destroy(view->mp_scene); + wlr_scene_node_destroy(mp_scene_surface); + wlr_scene_node_destroy(mp_scene); } static uint32_t diff --git a/src/kranewl/tree/xdg_view.cc b/src/kranewl/tree/xdg_view.cc @@ -11,6 +11,9 @@ #define namespace namespace_ #define static extern "C" { +#include <wlr/types/wlr_idle.h> +#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_shell.h> } @@ -59,6 +62,110 @@ XDGView::~XDGView() {} void +XDGView::focus(bool raise) +{ + TRACE(); + + struct wlr_surface* focused_surface + = mp_seat->mp_wlr_seat->keyboard_state.focused_surface; + + if (raise) + wlr_scene_node_raise_to_top(mp_scene); + + if (focused_surface == mp_wlr_surface) + return; + + mp_model->focus_view(this); + + for (std::size_t i = 0; i < 4; ++i) + wlr_scene_rect_set_color( + m_protrusions[i], + m_active_decoration.colorscheme.focused.values + ); + + if (focused_surface && focused_surface != mp_wlr_surface) { + if (wlr_surface_is_layer_surface(focused_surface)) { + struct wlr_layer_surface_v1* wlr_layer_surface + = wlr_layer_surface_v1_from_wlr_surface(focused_surface); + + if (wlr_layer_surface->mapped && ( + wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_TOP || + wlr_layer_surface->current.layer == ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY)) + { + return; + } + } else { + struct wlr_scene_node* node + = reinterpret_cast<struct wlr_scene_node*>(focused_surface->data); + + if (focused_surface->role_data && node->data) + for (std::size_t i = 0; i < 4; ++i) + wlr_scene_rect_set_color( + m_protrusions[i], + m_active_decoration.colorscheme.unfocused.values + ); + + struct wlr_xdg_surface* wlr_xdg_surface; + if (wlr_surface_is_xdg_surface(focused_surface) + && (wlr_xdg_surface = wlr_xdg_surface_from_wlr_surface(focused_surface)) + && wlr_xdg_surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) + { + wlr_xdg_toplevel_set_activated(wlr_xdg_surface, false); + } + } + } + + wlr_idle_set_enabled( + mp_seat->mp_idle, + mp_seat->mp_wlr_seat, + wl_list_empty(&mp_seat->mp_idle_inhibit_manager->inhibitors) + ); + + struct wlr_keyboard* keyboard = wlr_seat_get_keyboard(mp_seat->mp_wlr_seat); + if (keyboard) + wlr_seat_keyboard_notify_enter( + mp_seat->mp_wlr_seat, + mp_wlr_surface, + keyboard->keycodes, + keyboard->num_keycodes, + &keyboard->modifiers + ); + else + wlr_seat_keyboard_notify_enter( + mp_seat->mp_wlr_seat, + mp_wlr_surface, + nullptr, + 0, + nullptr + ); + + wlr_xdg_toplevel_set_activated(mp_wlr_xdg_surface, true); +} + +void +XDGView::moveresize(Region const& region, Extents const& extents, bool interactive) +{ + TRACE(); + + wlr_scene_node_set_position(mp_scene, region.pos.x, region.pos.y); + wlr_scene_node_set_position(mp_scene_surface, extents.left, extents.top); + wlr_scene_rect_set_size(m_protrusions[0], region.dim.w, extents.top); + wlr_scene_rect_set_size(m_protrusions[1], region.dim.w, extents.bottom); + wlr_scene_rect_set_size(m_protrusions[2], extents.left, region.dim.h - extents.top - extents.bottom); + wlr_scene_rect_set_size(m_protrusions[3], extents.right, region.dim.h - extents.top - extents.bottom); + wlr_scene_node_set_position(&m_protrusions[0]->node, 0, 0); + wlr_scene_node_set_position(&m_protrusions[1]->node, 0, region.dim.h - extents.bottom); + wlr_scene_node_set_position(&m_protrusions[2]->node, 0, extents.top); + wlr_scene_node_set_position(&m_protrusions[3]->node, region.dim.w - extents.right, extents.top); + + m_resize = wlr_xdg_toplevel_set_size( + mp_wlr_xdg_surface, + region.dim.w - extents.left - extents.right, + region.dim.h - extents.top - extents.bottom + ); +} + +void XDGView::handle_foreign_activate_request(struct wl_listener* listener, void* data) { TRACE(); @@ -196,8 +303,7 @@ XDGView::handle_map(struct wl_listener* listener, void* data) .h = state.min_height }; - View::map_view( - view, + view->map( wlr_xdg_toplevel->base->surface, wlr_xdg_toplevel->requested.fullscreen, wlr_xdg_toplevel->requested.fullscreen_output, @@ -226,7 +332,8 @@ XDGView::handle_unmap(struct wl_listener* listener, void* data) XDGView_ptr view = wl_container_of(listener, view, ml_unmap); - View::unmap_view(view); + view->unmap(); + view->mp_model->unmap_view(view); } void diff --git a/src/kranewl/tree/xwayland_view.cc b/src/kranewl/tree/xwayland_view.cc @@ -59,6 +59,17 @@ XWaylandView::XWaylandView( XWaylandView::~XWaylandView() {} +void +XWaylandView::focus(bool raise) +{} + +void +XWaylandView::moveresize(Region const& region, Extents const& extents, bool interactive) +{ + TRACE(); + +} + XWaylandUnmanaged::XWaylandUnmanaged(struct wlr_xwayland_surface* wlr_xwayland_surface) : mp_wlr_xwayland_surface(wlr_xwayland_surface) {}