commit c91f6b5a1f70ac0af6d961aa47ab23d0c6a6439b
parent 4dce3ea6ad7396af946be8fe6baf9967c5372953
Author: deurzen <max@deurzen.net>
Date: Wed, 1 Jun 2022 05:44:34 +0200
adds client-initiated drag capabilities
Diffstat:
2 files changed, 67 insertions(+), 16 deletions(-)
diff --git a/include/kranewl/input/cursor.hh b/include/kranewl/input/cursor.hh
@@ -33,8 +33,8 @@ struct CursorInput {
};
Target target;
- Button button;
- uint32_t modifiers;
+ Button button;
+ uint32_t modifiers;
};
typedef class Server* Server_ptr;
@@ -78,11 +78,12 @@ typedef struct Cursor {
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_destroy_drag(struct wl_listener*, void*);
static void handle_request_set_cursor(struct wl_listener*, void*);
Server_ptr mp_server;
Model_ptr mp_model;
- Seat_ptr mp_seat;
+ Seat_ptr mp_seat;
struct wlr_cursor* mp_wlr_cursor;
struct wlr_xcursor_manager* mp_cursor_manager;
@@ -105,6 +106,7 @@ typedef struct Cursor {
struct wl_listener ml_cursor_frame;
struct wl_listener ml_request_start_drag;
struct wl_listener ml_start_drag;
+ struct wl_listener ml_destroy_drag;
struct wl_listener ml_request_set_cursor;
}* Cursor_ptr;
diff --git a/src/kranewl/input/cursor.cc b/src/kranewl/input/cursor.cc
@@ -53,6 +53,7 @@ Cursor::Cursor(
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_destroy_drag({ .notify = Cursor::handle_destroy_drag }),
ml_request_set_cursor({ .notify = Cursor::handle_request_set_cursor })
{
TRACE();
@@ -621,32 +622,80 @@ 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);
+ Cursor_ptr cursor = wl_container_of(listener, cursor, ml_request_start_drag);
+ struct wlr_seat_request_start_drag_event* event
+ = reinterpret_cast<struct wlr_seat_request_start_drag_event*>(data);
- struct wlr_seat_client* focused_client
- = cursor->mp_seat->mp_wlr_seat->pointer_state.focused_client;
+ if (wlr_seat_validate_pointer_grab_serial(
+ cursor->mp_seat->mp_wlr_seat, event->origin, event->serial))
+ {
+ wlr_seat_start_pointer_drag(
+ cursor->mp_seat->mp_wlr_seat,
+ event->drag,
+ event->serial
+ );
+ } else
+ wlr_data_source_destroy(event->drag->source);
+}
- 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* listener, void* data)
+{
+ TRACE();
+
+ Cursor_ptr cursor = wl_container_of(listener, cursor, ml_start_drag);
+ struct wlr_drag* drag = reinterpret_cast<struct wlr_drag*>(data);
+
+ if (drag->icon)
+ drag->icon->data = wlr_scene_subsurface_tree_create(
+ cursor->mp_server->m_scene_layers[SceneLayer::SCENE_LAYER_NOFOCUS],
+ drag->icon->surface
);
+
+ cursor->mp_seat->mp_cursor->process_cursor_motion(0);
+
+ View_ptr view = cursor->view_under_cursor();
+ if (view && cursor->m_cursor_mode == Mode::Passthrough)
+ view->mp_model->cursor_interactive(Cursor::Mode::Move, view);
+
+ wl_signal_add(&drag->events.destroy, &cursor->ml_destroy_drag);
}
void
-Cursor::handle_start_drag(struct wl_listener*, void*)
+Cursor::handle_destroy_drag(struct wl_listener* listener, void* data)
{
TRACE();
+ Cursor_ptr cursor = wl_container_of(listener, cursor, ml_destroy_drag);
+ struct wlr_drag* drag = reinterpret_cast<struct wlr_drag*>(data);
+
+ if (drag->icon)
+ wlr_scene_node_destroy(reinterpret_cast<wlr_scene_node*>(drag->icon->data));
+
+ cursor->mp_model->refocus();
+ cursor->mp_seat->mp_cursor->process_cursor_motion(0);
}
void
-Cursor::handle_request_set_cursor(struct wl_listener*, void*)
+Cursor::handle_request_set_cursor(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);
+
+ if (cursor->m_cursor_mode != Mode::Passthrough)
+ return;
+
+ struct wlr_seat_client* focused_client
+ = cursor->mp_seat->mp_wlr_seat->pointer_state.focused_client;
+
+ if (event->seat_client == focused_client)
+ wlr_cursor_set_surface(
+ cursor->mp_wlr_cursor,
+ event->surface,
+ event->hotspot_x,
+ event->hotspot_y
+ );
}