commit e73b155aca6afe3d710bf3841a4804ece9ce5b10
parent 23eef476404d2a2b1456cb09bf45c37c8f8c2bf0
Author: deurzen <max@deurzen.net>
Date: Sat, 28 May 2022 18:46:25 +0200
provides client cursor handoff
Diffstat:
6 files changed, 364 insertions(+), 186 deletions(-)
diff --git a/include/kranewl/input/mouse.hh b/include/kranewl/input/mouse.hh
@@ -1,13 +1,91 @@
#pragma once
+#include <kranewl/geometry.hh>
+
+extern "C" {
+#include <wlr/backend.h>
+#include <xkbcommon/xkbcommon.h>
+}
+
#include <cstdint>
#include <unordered_set>
struct MouseInput {
- uint32_t mod;
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();
+
+ 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 <>
@@ -15,10 +93,10 @@ namespace std
std::size_t
operator()(MouseInput const& input) const
{
- std::size_t mod_hash = std::hash<uint32_t>()(input.mod);
+ std::size_t modifiers_hash = std::hash<uint32_t>()(input.modifiers);
std::size_t button_hash = std::hash<unsigned>()(input.button);
- return mod_hash ^ button_hash;
+ return modifiers_hash ^ button_hash;
}
};
}
diff --git a/include/kranewl/input/seat.hh b/include/kranewl/input/seat.hh
@@ -12,23 +12,11 @@ extern "C" {
typedef class Server* Server_ptr;
typedef class Model* Model_ptr;
-typedef class Keyboard* Keyboard_ptr;
-typedef class Client* Client_ptr;
+typedef struct Keyboard* Keyboard_ptr;
+typedef struct Mouse* Mouse_ptr;
typedef class Seat final {
public:
- enum class CursorMode {
- Passthrough,
- Move,
- Resize,
- };
-
- enum class CursorButton {
- Left = 272,
- Right = 273,
- Middle = 274,
- };
-
Seat(
Server_ptr,
Model_ptr,
@@ -50,14 +38,6 @@ public:
void unregister_keyboard(Keyboard_ptr);
static void handle_destroy(struct wl_listener*, void*);
- 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*);
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*);
@@ -70,37 +50,17 @@ public:
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;
+ Mouse_ptr mp_mouse;
std::vector<Keyboard_ptr> m_keyboards;
- struct {
- Client_ptr client;
- double x, y;
- Region region;
- uint32_t resize_edges;
- } m_grab_state;
-
struct wl_client* mp_exclusive_client;
struct wl_listener ml_destroy;
- 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;
struct wl_listener ml_request_set_selection;
struct wl_listener ml_request_set_primary_selection;
struct wl_listener ml_inhibit_manager_new_inhibitor;
diff --git a/src/kranewl/input/mouse.cc b/src/kranewl/input/mouse.cc
@@ -0,0 +1,256 @@
+#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 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 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;
+}
+
+static inline void
+cursor_set_focus(
+ 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_set_focus(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();
+
+}
+
+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,6 +1,7 @@
#include <trace.hh>
#include <kranewl/input/keyboard.hh>
+#include <kranewl/input/mouse.hh>
#include <kranewl/input/seat.hh>
#include <kranewl/util.hh>
@@ -30,24 +31,20 @@ Seat::Seat(
mp_model(model),
mp_wlr_seat(seat),
mp_idle(idle),
- mp_cursor(cursor),
- 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),
+ mp_mouse(new Mouse(
+ server,
+ this,
+ cursor,
+ pointer_constraints,
+ relative_pointer_manager,
+ virtual_pointer_manager
+ )),
+ m_keyboards(),
ml_destroy({ .notify = Seat::handle_destroy }),
- ml_cursor_motion({ .notify = Seat::handle_cursor_motion }),
- ml_cursor_motion_absolute({ .notify = Seat::handle_cursor_motion_absolute }),
- ml_cursor_button({ .notify = Seat::handle_cursor_button }),
- ml_cursor_axis({ .notify = Seat::handle_cursor_axis }),
- ml_cursor_frame({ .notify = Seat::handle_cursor_frame }),
- ml_request_start_drag({ .notify = Seat::handle_request_start_drag }),
- 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_inhibit_manager_new_inhibitor({ .notify = Seat::handle_inhibit_manager_new_inhibitor }),
@@ -56,17 +53,7 @@ Seat::Seat(
{
TRACE();
- wlr_xcursor_manager_load(mp_cursor_manager, 1);
-
wl_signal_add(&seat->events.destroy, &ml_destroy);
- 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(&seat->events.request_start_drag, &ml_request_start_drag);
- wl_signal_add(&seat->events.start_drag, &ml_start_drag);
- 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);
@@ -78,47 +65,11 @@ Seat::~Seat()
{
TRACE();
-}
-
-static inline void
-process_cursor_move(Seat_ptr seat, uint32_t time)
-{
-
-}
-
-static inline void
-process_cursor_resize(Seat_ptr seat, uint32_t time)
-{
-
-}
+ delete mp_mouse;
+ for (Keyboard_ptr keyboard : m_keyboards)
+ delete keyboard;
-static inline void
-process_cursor_motion(Seat_ptr seat, uint32_t time)
-{
- switch (seat->m_cursor_mode) {
- case Seat::CursorMode::Move: process_cursor_move(seat, time); return;
- case Seat::CursorMode::Resize: process_cursor_resize(seat, time); return;
- case Seat::CursorMode::Passthrough: // fallthrough
- default: break;
- }
-
- double sx, sy;
- struct wlr_surface* surface = nullptr;
- // TODO: get client under cursor
-
- if (true /* no client under cursor? */) {
- wlr_xcursor_manager_set_cursor_image(
- seat->mp_cursor_manager,
- "left_ptr",
- seat->mp_cursor
- );
- }
-
- if (surface) {
- 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_wlr_seat);
+ m_keyboards.clear();
}
Keyboard_ptr
@@ -149,76 +100,6 @@ Seat::handle_destroy(struct wl_listener*, void*)
}
void
-Seat::handle_cursor_motion(struct wl_listener* listener, void* data)
-{
- TRACE();
-
- Seat_ptr seat = wl_container_of(listener, seat, ml_cursor_motion);
- struct wlr_event_pointer_motion* event
- = reinterpret_cast<struct wlr_event_pointer_motion*>(data);
-
- wlr_cursor_move(seat->mp_cursor, event->device, event->delta_x, event->delta_y);
- process_cursor_motion(seat, event->time_msec);
-}
-
-void
-Seat::handle_cursor_motion_absolute(struct wl_listener* listener, void* data)
-{
- TRACE();
-
- Seat_ptr seat = wl_container_of(listener, seat, ml_cursor_motion_absolute);
- struct wlr_event_pointer_motion_absolute* event
- = reinterpret_cast<struct wlr_event_pointer_motion_absolute*>(data);
-
- wlr_cursor_warp_absolute(seat->mp_cursor, event->device, event->x, event->y);
- process_cursor_motion(seat, event->time_msec);
-}
-
-void
-Seat::handle_cursor_button(struct wl_listener*, void*)
-{
- TRACE();
-
-}
-
-void
-Seat::handle_cursor_axis(struct wl_listener*, void*)
-{
- TRACE();
-
-}
-
-void
-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_wlr_seat);
-}
-
-void
-Seat::handle_request_start_drag(struct wl_listener*, void*)
-{
- TRACE();
-
-}
-
-void
-Seat::handle_start_drag(struct wl_listener*, void*)
-{
- TRACE();
-
-}
-
-void
-Seat::handle_request_set_cursor(struct wl_listener*, void*)
-{
- TRACE();
-
-}
-
-void
Seat::handle_request_set_selection(struct wl_listener*, void*)
{
TRACE();
diff --git a/src/kranewl/model.cc b/src/kranewl/model.cc
@@ -224,7 +224,7 @@ Model::focus_view(View_ptr view)
Output_ptr output = view->mp_context->output();
- if (!output)
+ if (!output || mp_focus == view)
return;
if (!view->sticky()) {
@@ -232,9 +232,10 @@ Model::focus_view(View_ptr view)
mp_workspace->activate_view(view);
}
- if (mp_focus && mp_focus != view)
- unfocus_view(mp_focus);
+ if (mp_focus)
+ mp_focus->focus(Toggle::Off);
+ view->focus(Toggle::On);
view->set_urgent(false);
mp_focus = view;
diff --git a/src/kranewl/server.cc b/src/kranewl/server.cc
@@ -15,15 +15,14 @@
#include <spdlog/spdlog.h>
-#include <wayland-server-core.h>
-#include <wayland-util.h>
-
// https://github.com/swaywm/wlroots/issues/682
#include <pthread.h>
#define class class_
#define namespace namespace_
#define static
extern "C" {
+#include <wayland-server-core.h>
+#include <wayland-util.h>
#include <wlr/backend.h>
#include <wlr/backend/multi.h>
#include <wlr/render/allocator.h>
@@ -454,7 +453,10 @@ Server::handle_new_input(struct wl_listener* listener, void* data)
}
case WLR_INPUT_DEVICE_POINTER:
{
- wlr_cursor_attach_input_device(server->m_seat.mp_cursor, device);
+ wlr_cursor_attach_input_device(
+ server->m_seat.mp_mouse->mp_cursor,
+ device
+ );
break;
}
default: break;