diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h index dac694d1..90851a17 100644 --- a/include/rootston/desktop.h +++ b/include/rootston/desktop.h @@ -68,8 +68,7 @@ struct roots_desktop { struct wl_listener input_inhibit_activate; struct wl_listener input_inhibit_deactivate; struct wl_listener virtual_keyboard_new; - struct wl_listener constraint_create; - struct wl_listener constraint_destroy; + struct wl_listener pointer_constraint; #ifdef WLR_HAS_XWAYLAND struct wlr_xwayland *xwayland; diff --git a/include/rootston/output.h b/include/rootston/output.h index f78ee81d..69bc5126 100644 --- a/include/rootston/output.h +++ b/include/rootston/output.h @@ -28,6 +28,9 @@ struct roots_output { struct wl_listener damage_destroy; }; +void rotate_child_position(double *sx, double *sy, double sw, double sh, + double pw, double ph, float rotation); + void handle_new_output(struct wl_listener *listener, void *data); struct roots_view; diff --git a/include/rootston/seat.h b/include/rootston/seat.h index a3192d26..1248918a 100644 --- a/include/rootston/seat.h +++ b/include/rootston/seat.h @@ -122,6 +122,12 @@ struct roots_tablet_tool { struct wl_listener tablet_destroy; }; +struct roots_pointer_constraint { + struct wlr_pointer_constraint_v1 *constraint; + + struct wl_listener destroy; +}; + struct roots_seat *roots_seat_create(struct roots_input *input, char *name); void roots_seat_destroy(struct roots_seat *seat); diff --git a/include/wlr/types/wlr_pointer_constraints_v1.h b/include/wlr/types/wlr_pointer_constraints_v1.h index 6fdae9c4..97edf0ea 100644 --- a/include/wlr/types/wlr_pointer_constraints_v1.h +++ b/include/wlr/types/wlr_pointer_constraints_v1.h @@ -48,6 +48,10 @@ struct wlr_pointer_constraint_v1 { struct wl_list link; // wlr_pointer_constraints_v1::constraints + struct { + struct wl_signal destroy; + } events; + void *data; }; @@ -59,15 +63,9 @@ struct wlr_pointer_constraints_v1 { /** * Called when a new pointer constraint is created. * - * data: wlr_pointer_constraint_v1* + * data: struct wlr_pointer_constraint_v1 * */ - struct wl_signal constraint_create; - /** - * Called when a pointer constraint is destroyed. - * - * data: wlr_pointer_constraint_v1* - */ - struct wl_signal constraint_destroy; + struct wl_signal new_constraint; } events; struct wl_list constraints; // wlr_pointer_constraint_v1::link @@ -78,10 +76,11 @@ struct wlr_pointer_constraints_v1 { struct wlr_pointer_constraints_v1 *wlr_pointer_constraints_v1_create( struct wl_display *display); void wlr_pointer_constraints_v1_destroy( - struct wlr_pointer_constraints_v1 *wlr_pointer_constraints_v1); + struct wlr_pointer_constraints_v1 *pointer_constraints); -struct wlr_pointer_constraint_v1 *wlr_pointer_constraints_v1_constraint_for_surface( - struct wlr_pointer_constraints_v1 *wlr_pointer_constraints_v1, +struct wlr_pointer_constraint_v1 * + wlr_pointer_constraints_v1_constraint_for_surface( + struct wlr_pointer_constraints_v1 *pointer_constraints, struct wlr_surface *surface, struct wlr_seat *seat); void wlr_pointer_constraint_v1_send_activated( @@ -89,5 +88,4 @@ void wlr_pointer_constraint_v1_send_activated( void wlr_pointer_constraint_v1_send_deactivated( struct wlr_pointer_constraint_v1 *constraint); - #endif diff --git a/rootston/cursor.c b/rootston/cursor.c index 4ec600e1..08a71ec4 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -572,32 +572,45 @@ void roots_cursor_handle_constraint_commit(struct roots_cursor *cursor) { } } +static void handle_constraint_commit(struct wl_listener *listener, + void *data) { + struct roots_cursor *cursor = + wl_container_of(listener, cursor, constraint_commit); + assert(cursor->active_constraint->surface == data); + roots_cursor_handle_constraint_commit(cursor); +} + void roots_cursor_constrain(struct roots_cursor *cursor, struct wlr_pointer_constraint_v1 *constraint, double sx, double sy) { - if (cursor->active_constraint != constraint) { - wlr_log(WLR_DEBUG, "roots_cursor_constrain(%p, %p)", cursor, constraint); - wlr_log(WLR_DEBUG, "cursor->active_constraint: %p", cursor->active_constraint); - - if (cursor->active_constraint) { - wlr_pointer_constraint_v1_send_deactivated(cursor->active_constraint); - if (cursor->constraint_commit.link.next) { - wl_list_remove(&cursor->constraint_commit.link); - } - } + if (cursor->active_constraint == constraint) { + return; + } - cursor->active_constraint = constraint; + wlr_log(WLR_DEBUG, "roots_cursor_constrain(%p, %p)", + cursor, constraint); + wlr_log(WLR_DEBUG, "cursor->active_constraint: %p", + cursor->active_constraint); - if (!constraint) { - return; - } + wl_list_remove(&cursor->constraint_commit.link); + wl_list_init(&cursor->constraint_commit.link); + if (cursor->active_constraint) { + wlr_pointer_constraint_v1_send_deactivated( + cursor->active_constraint); + } - wlr_pointer_constraint_v1_send_activated(constraint); - wl_signal_add(&constraint->surface->events.commit, - &cursor->constraint_commit); - } else if (constraint == NULL) { + cursor->active_constraint = constraint; + + if (constraint == NULL) { return; } + wlr_pointer_constraint_v1_send_activated(constraint); + + wl_list_remove(&cursor->constraint_commit.link); + wl_signal_add(&constraint->surface->events.commit, + &cursor->constraint_commit); + cursor->constraint_commit.notify = handle_constraint_commit; + pixman_region32_clear(&cursor->confine); pixman_region32_t *region = &constraint->region; @@ -612,20 +625,11 @@ void roots_cursor_constrain(struct roots_cursor *cursor, double sx = (boxes[0].x1 + boxes[0].x2) / 2.; double sy = (boxes[0].y1 + boxes[0].y2) / 2.; - double lx, ly; - if (view->rotation == 0.0) { - lx = sx + view->x; - ly = sy + view->y; - } else { - double c = cos(view->rotation); - double s = sin(view->rotation); - - double center_x = view->width / 2.; - double center_y = view->height / 2.; + rotate_child_position(&sx, &sy, 0, 0, view->width, view->height, + view->rotation); - lx = c * (sx - center_x) - s * (sy - center_y) + center_x + view->x; - ly = s * (sx - center_x) + c * (sy - center_y) + center_y + view->y; - } + double lx = view->x + sx; + double ly = view->y + sy; wlr_cursor_warp_closest(cursor->cursor, NULL, lx, ly); } diff --git a/rootston/desktop.c b/rootston/desktop.c index a1e61738..c180c839 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -777,52 +777,59 @@ static void input_inhibit_deactivate(struct wl_listener *listener, void *data) { } } -static void handle_constraint_create( - struct wl_listener *listener, - struct wlr_pointer_constraint_v1 *constraint) { - struct roots_seat* seat = constraint->seat->data; +static void handle_constraint_destroy(struct wl_listener *listener, + void *data) { + struct roots_pointer_constraint *constraint = + wl_container_of(listener, constraint, destroy); + struct wlr_pointer_constraint_v1 *wlr_constraint = data; + struct roots_seat *seat = wlr_constraint->seat->data; - double sx, sy; - struct wlr_surface *surface = desktop_surface_at(seat->input->server->desktop, - seat->cursor->cursor->x, seat->cursor->cursor->y, &sx, &sy, NULL); + wl_list_remove(&constraint->destroy.link); - if (surface == constraint->surface) { - assert(!seat->cursor->active_constraint); - roots_cursor_constrain(seat->cursor, constraint, sx, sy); - } -} + if (seat->cursor->active_constraint == wlr_constraint) { + wl_list_remove(&seat->cursor->constraint_commit.link); + wl_list_init(&seat->cursor->constraint_commit.link); + seat->cursor->active_constraint = NULL; -static void handle_constraint_destroy( - struct wl_listener *listener, - struct wlr_pointer_constraint_v1 *constraint) { - struct roots_seat* seat = constraint->seat->data; - if (seat->cursor->active_constraint == constraint) { - roots_cursor_constrain(seat->cursor, NULL, NAN, NAN); - if (constraint->current.committed & + if (wlr_constraint->current.committed & WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT && seat->cursor->pointer_view) { - double sx = constraint->current.cursor_hint.x; - double sy = constraint->current.cursor_hint.y; + double sx = wlr_constraint->current.cursor_hint.x; + double sy = wlr_constraint->current.cursor_hint.y; struct roots_view *view = seat->cursor->pointer_view->view; + rotate_child_position(&sx, &sy, 0, 0, view->width, view->height, + view->rotation); + double lx = view->x + sx; + double ly = view->y + sy; - double lx, ly; - if (view->rotation == 0.0) { - lx = sx + view->x; - ly = sy + view->y; - } else { - double c = cos(view->rotation); - double s = sin(view->rotation); + wlr_cursor_warp(seat->cursor->cursor, NULL, lx, ly); + } + } - double center_x = view->width / 2.; - double center_y = view->height / 2.; + free(constraint); +} - lx = c * (sx - center_x) - s * (sy - center_y) + center_x + view->x; - ly = s * (sx - center_x) + c * (sy - center_y) + center_y + view->y; - } +static void handle_pointer_constraint(struct wl_listener *listener, + void *data) { + struct wlr_pointer_constraint_v1 *wlr_constraint = data; + struct roots_seat *seat = wlr_constraint->seat->data; - wlr_cursor_warp(seat->cursor->cursor, NULL, lx, ly); - } + struct roots_pointer_constraint *constraint = + calloc(1, sizeof(struct roots_pointer_constraint)); + constraint->constraint = wlr_constraint; + + constraint->destroy.notify = handle_constraint_destroy; + wl_signal_add(&wlr_constraint->events.destroy, &constraint->destroy); + + double sx, sy; + struct wlr_surface *surface = desktop_surface_at( + seat->input->server->desktop, + seat->cursor->cursor->x, seat->cursor->cursor->y, &sx, &sy, NULL); + + if (surface == wlr_constraint->surface) { + assert(!seat->cursor->active_constraint); + roots_cursor_constrain(seat->cursor, wlr_constraint, sx, sy); } } @@ -956,13 +963,11 @@ struct roots_desktop *desktop_create(struct roots_server *server, &desktop->xdg_toplevel_decoration); desktop->xdg_toplevel_decoration.notify = handle_xdg_toplevel_decoration; - desktop->pointer_constraints = wlr_pointer_constraints_v1_create(server->wl_display); - desktop->constraint_destroy.notify = (wl_notify_func_t)handle_constraint_destroy; - wl_signal_add(&desktop->pointer_constraints->events.constraint_destroy, - &desktop->constraint_destroy); - desktop->constraint_create.notify = (wl_notify_func_t)handle_constraint_create; - wl_signal_add(&desktop->pointer_constraints->events.constraint_create, - &desktop->constraint_create); + desktop->pointer_constraints = + wlr_pointer_constraints_v1_create(server->wl_display); + desktop->pointer_constraint.notify = handle_pointer_constraint; + wl_signal_add(&desktop->pointer_constraints->events.new_constraint, + &desktop->pointer_constraint); return desktop; } diff --git a/rootston/output.c b/rootston/output.c index 4207f0d0..e85612fa 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -22,7 +22,7 @@ * Rotate a child's position relative to a parent. The parent size is (pw, ph), * the child position is (*sx, *sy) and its size is (sw, sh). */ -static void rotate_child_position(double *sx, double *sy, double sw, double sh, +void rotate_child_position(double *sx, double *sy, double sw, double sh, double pw, double ph, float rotation) { if (rotation != 0.0) { // Coordinates relative to the center of the subsurface diff --git a/rootston/seat.c b/rootston/seat.c index 466f1429..e3336fde 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -307,14 +307,6 @@ static void handle_pointer_focus_change(struct wl_listener *listener, roots_cursor_handle_focus_change(cursor, event); } -static void handle_constraint_commit(struct wl_listener *listener, - void *data) { - struct roots_cursor *cursor = - wl_container_of(listener, cursor, constraint_commit); - assert(cursor->active_constraint->surface == data); - roots_cursor_handle_constraint_commit(cursor); -} - static void seat_reset_device_mappings(struct roots_seat *seat, struct wlr_input_device *device) { struct wlr_cursor *cursor = seat->cursor->cursor; @@ -456,7 +448,6 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { seat->cursor->focus_change.notify = handle_pointer_focus_change; wl_list_init(&seat->cursor->constraint_commit.link); - seat->cursor->constraint_commit.notify = handle_constraint_commit; } static void roots_drag_icon_handle_surface_commit(struct wl_listener *listener, diff --git a/types/wlr_pointer_constraints_v1.c b/types/wlr_pointer_constraints_v1.c index e281277f..ce69a856 100644 --- a/types/wlr_pointer_constraints_v1.c +++ b/types/wlr_pointer_constraints_v1.c @@ -1,14 +1,13 @@ #include #include +#include #include #include -#include #include #include #include #include #include - #include "util/signal.h" static const struct zwp_locked_pointer_v1_interface locked_pointer_impl; @@ -47,16 +46,13 @@ static void pointer_constraint_destroy(struct wlr_pointer_constraint_v1 *constra wlr_log(WLR_DEBUG, "destroying constraint %p", constraint); + wlr_signal_emit_safe(&constraint->events.destroy, constraint); + wl_resource_set_user_data(constraint->resource, NULL); wl_list_remove(&constraint->link); wl_list_remove(&constraint->surface_commit.link); wl_list_remove(&constraint->surface_destroy.link); wl_list_remove(&constraint->seat_destroy.link); - - wlr_signal_emit_safe( - &constraint->pointer_constraints->events.constraint_destroy, - constraint); - pixman_region32_fini(&constraint->current.region); pixman_region32_fini(&constraint->pending.region); pixman_region32_fini(&constraint->region); @@ -87,6 +83,9 @@ static void pointer_constraint_handle_set_region(struct wl_client *client, struct wl_resource *resource, struct wl_resource *region_resource) { struct wlr_pointer_constraint_v1 *constraint = pointer_constraint_from_resource(resource); + if (constraint == NULL) { + return; + } pointer_constraint_set_region(constraint, region_resource); } @@ -95,13 +94,16 @@ static void pointer_constraint_set_cursor_position_hint(struct wl_client *client struct wl_resource *resource, wl_fixed_t x, wl_fixed_t y) { struct wlr_pointer_constraint_v1 *constraint = pointer_constraint_from_resource(resource); + if (constraint == NULL) { + return; + } constraint->pending.cursor_hint.x = wl_fixed_to_double(x); constraint->pending.cursor_hint.y = wl_fixed_to_double(y); constraint->pending.committed |= WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT; } -static void pointer_constraint_handle_commit( +static void pointer_constraint_commit( struct wlr_pointer_constraint_v1 *constraint) { if (constraint->pending.committed & WLR_POINTER_CONSTRAINT_V1_STATE_REGION) { @@ -130,7 +132,7 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) { struct wlr_pointer_constraint_v1 *constraint = wl_container_of(listener, constraint, surface_commit); - pointer_constraint_handle_commit(constraint); + pointer_constraint_commit(constraint); } static void handle_surface_destroy(struct wl_listener *listener, void *data) { @@ -188,7 +190,6 @@ static void pointer_constraint_create(struct wl_client *client, struct wl_resource *resource = locked_pointer ? wl_resource_create(client, &zwp_locked_pointer_v1_interface, version, id) : wl_resource_create(client, &zwp_confined_pointer_v1_interface, version, id); - if (resource == NULL) { wl_client_post_no_memory(client); return; @@ -196,6 +197,7 @@ static void pointer_constraint_create(struct wl_client *client, struct wlr_pointer_constraint_v1 *constraint = calloc(1, sizeof(*constraint)); if (constraint == NULL) { + wl_resource_destroy(resource); wl_client_post_no_memory(client); return; } @@ -207,13 +209,15 @@ static void pointer_constraint_create(struct wl_client *client, constraint->type = type; constraint->pointer_constraints = pointer_constraints; + wl_signal_init(&constraint->events.destroy); + pixman_region32_init(&constraint->region); pixman_region32_init(&constraint->pending.region); pixman_region32_init(&constraint->current.region); pointer_constraint_set_region(constraint, region_resource); - pointer_constraint_handle_commit(constraint); + pointer_constraint_commit(constraint); constraint->surface_commit.notify = handle_surface_commit; wl_signal_add(&surface->events.commit, &constraint->surface_commit); @@ -224,16 +228,18 @@ static void pointer_constraint_create(struct wl_client *client, constraint->seat_destroy.notify = handle_seat_destroy; wl_signal_add(&seat->events.destroy, &constraint->seat_destroy); - wl_resource_set_implementation(constraint->resource, - locked_pointer ? (void*)&locked_pointer_impl : (void*)&confined_pointer_impl, - constraint, pointer_constraint_destroy_resource); + void *impl = locked_pointer ? + (void *)&locked_pointer_impl : (void *)&confined_pointer_impl; + wl_resource_set_implementation(constraint->resource, impl, constraint, + pointer_constraint_destroy_resource); wlr_log(WLR_DEBUG, "new %s_pointer %p (res %p)", - locked_pointer ? "locked" : "confined", constraint, constraint->resource); + locked_pointer ? "locked" : "confined", + constraint, constraint->resource); wl_list_insert(&pointer_constraints->constraints, &constraint->link); - wlr_signal_emit_safe(&pointer_constraints->events.constraint_create, + wlr_signal_emit_safe(&pointer_constraints->events.new_constraint, constraint); } @@ -303,8 +309,7 @@ struct wlr_pointer_constraints_v1 *wlr_pointer_constraints_v1_create( wl_list_init(&pointer_constraints->resources); wl_list_init(&pointer_constraints->constraints); - wl_signal_init(&pointer_constraints->events.constraint_create); - wl_signal_init(&pointer_constraints->events.constraint_destroy); + wl_signal_init(&pointer_constraints->events.new_constraint); return pointer_constraints; }