apply labwc/labwc#85 to add support for pointer constraints

This commit is contained in:
Dima Krasner 2021-12-22 08:31:14 +02:00
parent 3321daef98
commit 4e9b9273f1
5 changed files with 121 additions and 3 deletions

8
cage.c
View file

@ -36,6 +36,8 @@
#if CAGE_HAS_XWAYLAND
#include <wlr/types/wlr_xcursor_manager.h>
#endif
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/types/wlr_xdg_decoration_v1.h>
#include <wlr/types/wlr_xdg_output_v1.h>
#include <wlr/types/wlr_xdg_shell.h>
@ -459,6 +461,12 @@ main(int argc, char *argv[])
goto end;
}
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 = seat_create_constraint;
wl_signal_add(&server.constraints->events.new_constraint, &server.new_constraint);
#if CAGE_HAS_XWAYLAND
xwayland = wlr_xwayland_create(server.wl_display, compositor, true);
if (!xwayland) {

View file

@ -51,6 +51,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'],
]
server_protos_headers = []

98
seat.c
View file

@ -18,6 +18,7 @@
#include <wlr/types/wlr_data_device.h>
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_keyboard_group.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_primary_selection.h>
#include <wlr/types/wlr_scene.h>
#include <wlr/types/wlr_seat.h>
@ -252,7 +253,8 @@ handle_key_event(struct wlr_input_device *device, struct cg_seat *seat, void *da
bool handled = false;
uint32_t modifiers = wlr_keyboard_get_modifiers(device->keyboard);
if ((modifiers & WLR_MODIFIER_ALT) && event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
if ((modifiers & WLR_MODIFIER_ALT) && event->state == WL_KEYBOARD_KEY_STATE_PRESSED &&
!seat->current_constraint) {
/* If Alt is held down and this button was pressed, we
* attempt to process it as a compositor
* keybinding. */
@ -571,7 +573,18 @@ handle_cursor_motion_absolute(struct wl_listener *listener, void *data)
struct cg_seat *seat = wl_container_of(listener, seat, cursor_motion_absolute);
struct wlr_event_pointer_motion_absolute *event = data;
wlr_cursor_warp_absolute(seat->cursor, event->device, event->x, event->y);
double lx, ly;
wlr_cursor_absolute_to_layout_coords(seat->cursor, event->device, event->x, event->y, &lx, &ly);
double dx = lx - seat->cursor->x;
double dy = ly - seat->cursor->y;
wlr_relative_pointer_manager_v1_send_relative_motion(seat->server->relative_pointer_manager, seat->seat,
(uint64_t) event->time_msec * 1000, dx, dy, dx, dy);
if (!seat->current_constraint) {
wlr_cursor_move(seat->cursor, event->device, dx, dy);
}
process_cursor_motion(seat, event->time_msec);
wlr_idle_notify_activity(seat->server->idle, seat->seat);
}
@ -580,9 +593,15 @@ static void
handle_cursor_motion(struct wl_listener *listener, void *data)
{
struct cg_seat *seat = wl_container_of(listener, seat, cursor_motion);
struct cg_server *server = seat->server;
struct wlr_event_pointer_motion *event = data;
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) {
wlr_cursor_move(seat->cursor, event->device, event->delta_x, event->delta_y);
}
process_cursor_motion(seat, event->time_msec);
wlr_idle_notify_activity(seat->server->idle, seat->seat);
}
@ -786,6 +805,8 @@ seat_create(struct cg_server *server, struct wlr_backend *backend)
wl_list_init(&seat->pointers);
wl_list_init(&seat->touch);
wl_list_init(&seat->constraint_commit.link);
seat->new_input.notify = handle_new_input;
wl_signal_add(&backend->events.new_input, &seat->new_input);
@ -867,5 +888,76 @@ seat_set_focus(struct cg_seat *seat, struct cg_view *view)
wlr_seat_keyboard_notify_enter(wlr_seat, view->wlr_surface, NULL, 0, NULL);
}
struct wlr_pointer_constraint_v1 *constraint =
wlr_pointer_constraints_v1_constraint_for_surface(server->constraints, view->wlr_surface, wlr_seat);
seat_constrain_cursor(server, constraint);
process_cursor_motion(seat, -1);
}
static void
handle_constraint_commit(struct wl_listener *listener, void *data)
{
}
static void
destroy_constraint(struct wl_listener *listener, void *data)
{
struct cg_constraint *constraint = wl_container_of(listener, constraint, destroy);
struct wlr_pointer_constraint_v1 *wlr_constraint = data;
struct cg_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
seat_create_constraint(struct wl_listener *listener, void *data)
{
struct wlr_pointer_constraint_v1 *wlr_constraint = data;
struct cg_server *server = wl_container_of(listener, server, new_constraint);
struct cg_view *view;
struct cg_constraint *constraint = calloc(1, sizeof(struct cg_constraint));
constraint->constraint = wlr_constraint;
constraint->seat = server->seat;
constraint->destroy.notify = destroy_constraint;
wl_signal_add(&wlr_constraint->events.destroy, &constraint->destroy);
view = seat_get_focus(server->seat);
if (view->wlr_surface == wlr_constraint->surface) {
seat_constrain_cursor(server, wlr_constraint);
}
}
void
seat_constrain_cursor(struct cg_server *server, struct wlr_pointer_constraint_v1 *constraint)
{
struct cg_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);
}

11
seat.h
View file

@ -27,11 +27,13 @@ struct cg_seat {
struct wlr_cursor *cursor;
struct wlr_xcursor_manager *xcursor_manager;
struct wlr_pointer_constraint_v1 *current_constraint;
struct wl_listener cursor_motion;
struct wl_listener cursor_motion_absolute;
struct wl_listener cursor_button;
struct wl_listener cursor_axis;
struct wl_listener cursor_frame;
struct wl_listener constraint_commit;
int32_t touch_id;
double touch_lx;
@ -85,9 +87,18 @@ struct cg_drag_icon {
struct wl_listener destroy;
};
struct cg_constraint {
struct cg_seat *seat;
struct wlr_pointer_constraint_v1 *constraint;
struct wl_listener destroy;
};
struct cg_seat *seat_create(struct cg_server *server, struct wlr_backend *backend);
void seat_destroy(struct cg_seat *seat);
struct cg_view *seat_get_focus(struct cg_seat *seat);
void seat_set_focus(struct cg_seat *seat, struct cg_view *view);
void seat_create_constraint(struct wl_listener *listener, void *data);
void seat_constrain_cursor(struct cg_server *server, struct wlr_pointer_constraint_v1 *constraint);
#endif

View file

@ -7,6 +7,8 @@
#include <wlr/types/wlr_idle.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_pointer_constraints_v1.h>
#include <wlr/types/wlr_relative_pointer_v1.h>
#include <wlr/types/wlr_xdg_decoration_v1.h>
#if CAGE_HAS_XWAYLAND
#include <wlr/xwayland.h>
@ -42,6 +44,10 @@ struct cg_server {
struct wl_list outputs; // cg_output::link
struct wl_listener new_output;
struct wlr_relative_pointer_manager_v1 *relative_pointer_manager;
struct wlr_pointer_constraints_v1 *constraints;
struct wl_listener new_constraint;
struct wl_listener xdg_toplevel_decoration;
struct wl_listener new_xdg_shell_surface;
#if CAGE_HAS_XWAYLAND