]> git.mdlowis.com Git - proto/labwc.git/commitdiff
add pointer constraints
authorARDiDo <90479315+ARDiDo@users.noreply.github.com>
Sun, 17 Oct 2021 20:54:35 +0000 (16:54 -0400)
committerJohan Malm <johanmalm@users.noreply.github.com>
Sun, 17 Oct 2021 21:32:25 +0000 (22:32 +0100)
include/labwc.h
protocols/meson.build
src/cursor.c
src/seat.c
src/server.c

index 68c5469296b8f99e93c5db8b0e5d2c0110be1373..eb00fd024a259fc17936771e11a7975eee2ec86b 100644 (file)
@@ -23,7 +23,9 @@
 #include <wlr/types/wlr_output_damage.h>
 #include <wlr/types/wlr_output_management_v1.h>
 #include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_relative_pointer_v1.h>
 #include <wlr/types/wlr_pointer.h>
+#include <wlr/types/wlr_pointer_constraints_v1.h>
 #include <wlr/types/wlr_seat.h>
 #include <wlr/types/wlr_server_decoration.h>
 #include <wlr/types/wlr_xcursor_manager.h>
@@ -72,6 +74,7 @@ struct seat {
        struct wlr_cursor *cursor;
        struct wlr_xcursor_manager *xcursor_manager;
        struct wlr_drag_icon *drag_icon;
+       struct wlr_pointer_constraint_v1 *current_constraint;
 
        /* if set, views cannot receive focus */
        struct wlr_layer_surface_v1 *focused_layer;
@@ -96,6 +99,7 @@ struct seat {
        struct wl_listener request_start_drag;
        struct wl_listener start_drag;
        struct wl_listener destroy_drag;
+       struct wl_listener constraint_commit;
 };
 
 struct server {
@@ -143,6 +147,10 @@ struct server {
 
        struct wlr_foreign_toplevel_manager_v1 *foreign_toplevel_manager;
 
+       struct wlr_relative_pointer_manager_v1 *relative_pointer_manager;
+       struct wlr_pointer_constraints_v1 *constraints;
+       struct wl_listener new_constraint;
+
        /* Set when in cycle (alt-tab) mode */
        struct view *cycle_view;
 
@@ -312,6 +320,12 @@ struct xdg_popup {
        struct wl_listener new_popup;
 };
 
+struct constraint {
+       struct seat *seat;
+       struct wlr_pointer_constraint_v1 *constraint;
+       struct wl_listener destroy;
+};
+
 void xdg_popup_create(struct view *view, struct wlr_xdg_popup *wlr_popup);
 
 void xdg_toplevel_decoration(struct wl_listener *listener, void *data);
@@ -435,4 +449,8 @@ void osd_update(struct server *server);
 bool input_inhibit_blocks_surface(struct seat *seat,
        struct wl_resource *resource);
 
+void create_constraint(struct wl_listener *listener, void *data);
+void constrain_cursor(struct server *server, struct wlr_pointer_constraint_v1
+       *constraint);
+
 #endif /* __LABWC_H */
index 6541a5fb6087e5713be5b4a5942e54d3cc71d74d..c342e0f1794ca6c6ee15429a296852d844215b04 100644 (file)
@@ -15,6 +15,7 @@ wayland_scanner_server = generator(
 
 server_protocols = [
        [wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
+       [wl_protocol_dir, 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml'],
        ['wlr-layer-shell-unstable-v1.xml'],
        ['wlr-input-inhibitor-unstable-v1.xml'],
 ]
index 774e044b8862c242d553d960b4448a0719772e16..5fc711d8b3f3c0a11911d6ae3c6dedd724fce5da 100644 (file)
@@ -236,6 +236,81 @@ start_drag(struct wl_listener *listener, void *data)
        wl_signal_add(&seat->drag_icon->events.destroy, &seat->destroy_drag);
 }
 
+void
+handle_constraint_commit(struct wl_listener *listener, void *data)
+{
+       struct seat *seat = wl_container_of(listener, seat, constraint_commit);
+       struct wlr_pointer_constraint_v1 *constraint = seat->current_constraint;
+       assert(constraint->surface = data);
+}
+
+void
+destroy_constraint(struct wl_listener *listener, void *data)
+{
+       struct constraint *constraint = wl_container_of(listener, constraint,
+               destroy);
+       struct wlr_pointer_constraint_v1 *wlr_constraint = data;
+       struct seat *seat = constraint->seat;
+
+       wl_list_remove(&constraint->destroy.link);
+       if (seat->current_constraint == wlr_constraint) {
+               if (seat->constraint_commit.link.next != NULL) {
+                       wl_list_remove(&seat->constraint_commit.link);
+               }
+               wl_list_init(&seat->constraint_commit.link);
+               seat->current_constraint = NULL;
+       }
+
+       free(constraint);
+}
+
+void
+create_constraint(struct wl_listener *listener, void *data)
+{
+       struct wlr_pointer_constraint_v1 *wlr_constraint = data;
+       struct server *server = wl_container_of(listener, server,
+               new_constraint);
+       struct view *view;
+       struct constraint *constraint = calloc(1, sizeof(struct constraint));
+
+       constraint->constraint = wlr_constraint;
+       constraint->seat = &server->seat;
+       constraint->destroy.notify = destroy_constraint;
+       wl_signal_add(&wlr_constraint->events.destroy, &constraint->destroy);
+
+       view = desktop_focused_view(server);
+       if (view->surface == wlr_constraint->surface) {
+               constrain_cursor(server, wlr_constraint);
+       }
+}
+
+void
+constrain_cursor(struct server *server, struct wlr_pointer_constraint_v1
+               *constraint)
+{
+       struct seat *seat = &server->seat;
+       if (seat->current_constraint == constraint) {
+               return;
+       }
+       wl_list_remove(&seat->constraint_commit.link);
+       if (seat->current_constraint) {
+               wlr_pointer_constraint_v1_send_deactivated(
+                       seat->current_constraint);
+       }
+
+       seat->current_constraint = constraint;
+
+       if (constraint == NULL) {
+               wl_list_init(&seat->constraint_commit.link);
+               return;
+       }
+
+       wlr_pointer_constraint_v1_send_activated(constraint);
+       seat->constraint_commit.notify = handle_constraint_commit;
+       wl_signal_add(&constraint->surface->events.commit,
+               &seat->constraint_commit);
+}
+
 static void
 cursor_motion(struct wl_listener *listener, void *data)
 {
@@ -244,17 +319,25 @@ cursor_motion(struct wl_listener *listener, void *data)
         * _relative_ pointer motion event (i.e. a delta)
         */
        struct seat *seat = wl_container_of(listener, seat, cursor_motion);
+       struct server *server = seat->server;
        struct wlr_event_pointer_motion *event = data;
 
-       /*
-        * The cursor doesn't move unless we tell it to. The cursor
-        * automatically handles constraining the motion to the output layout,
-        * as well as any special configuration applied for the specific input
-        * device which generated the event. You can pass NULL for the device
-        * if you want to move the cursor around without any input.
-        */
-       wlr_cursor_move(seat->cursor, event->device, event->delta_x,
-               event->delta_y);
+       wlr_relative_pointer_manager_v1_send_relative_motion(
+               server->relative_pointer_manager,
+               seat->seat, (uint64_t)event->time_msec * 1000,
+               event->delta_x, event->delta_y, event->unaccel_dx,
+               event->unaccel_dy);
+       if (!seat->current_constraint) {
+               /*
+                * The cursor doesn't move unless we tell it to. The cursor
+                * automatically handles constraining the motion to the output layout,
+                * as well as any special configuration applied for the specific input
+                * device which generated the event. You can pass NULL for the device
+                * if you want to move the cursor around without any input.
+                */
+               wlr_cursor_move(seat->cursor, event->device, event->delta_x,
+                       event->delta_y);
+       }
        process_cursor_motion(seat->server, event->time_msec);
 }
 
index a918978986612505c55414f8986c6f5fb85992e5..f912762b37a74e014c9961ac7d92eff518d03b7a 100644 (file)
@@ -181,6 +181,7 @@ seat_init(struct server *server)
                exit(EXIT_FAILURE);
        }
 
+       wl_list_init(&seat->constraint_commit.link);
        wl_list_init(&seat->inputs);
        seat->new_input.notify = new_input_notify;
        wl_signal_add(&server->backend->events.new_input, &seat->new_input);
@@ -242,6 +243,12 @@ seat_focus_surface(struct seat *seat, struct wlr_surface *surface)
        struct wlr_keyboard *kb = &seat->keyboard_group->keyboard;
        wlr_seat_keyboard_notify_enter(seat->seat, surface, kb->keycodes,
                kb->num_keycodes, &kb->modifiers);
+
+       struct server *server = seat->server;
+       struct wlr_pointer_constraint_v1 *constraint =
+               wlr_pointer_constraints_v1_constraint_for_surface(server->constraints,
+                       surface, seat->seat);
+       constrain_cursor(server, constraint);
 }
 
 void
index 0b944bfe68d17d2f2b9120390af55bf82d34d65f..4cbfac8fb037641963fd327de9f2cafbeb2844d3 100644 (file)
@@ -269,6 +269,15 @@ server_init(struct server *server)
        wlr_data_control_manager_v1_create(server->wl_display);
        wlr_gamma_control_manager_v1_create(server->wl_display);
 
+       server->relative_pointer_manager = wlr_relative_pointer_manager_v1_create(
+               server->wl_display);
+       server->constraints = wlr_pointer_constraints_v1_create(
+               server->wl_display);
+
+       server->new_constraint.notify = create_constraint;
+       wl_signal_add(&server->constraints->events.new_constraint,
+               &server->new_constraint);
+
        server->input_inhibit =
                wlr_input_inhibit_manager_create(server->wl_display);
        if (!server->input_inhibit) {