wlr_cursor: handle layout changes

Add the layout `destroy` and `change` events.

When a layout is destroyed, detach is from the wlr_cursor.

When a layout is changed, warp the cursor to the closest layout boundary.
This commit is contained in:
Tony Crisci 2017-09-05 07:48:28 -04:00
parent 6089967e07
commit 57c18c38bb
3 changed files with 66 additions and 1 deletions

View file

@ -9,6 +9,11 @@ struct wlr_output_layout_state;
struct wlr_output_layout { struct wlr_output_layout {
struct wl_list outputs; struct wl_list outputs;
struct wlr_output_layout_state *state; struct wlr_output_layout_state *state;
struct {
struct wl_signal change;
struct wl_signal destroy;
} events;
}; };
struct wlr_output_layout_output_state; struct wlr_output_layout_output_state;

View file

@ -34,11 +34,15 @@ struct wlr_cursor_device {
}; };
struct wlr_cursor_state { struct wlr_cursor_state {
struct wlr_cursor *cursor;
struct wl_list devices; struct wl_list devices;
struct wlr_output_layout *layout; struct wlr_output_layout *layout;
struct wlr_xcursor *xcursor; struct wlr_xcursor *xcursor;
struct wlr_output *mapped_output; struct wlr_output *mapped_output;
struct wlr_box *mapped_box; struct wlr_box *mapped_box;
struct wl_listener layout_change;
struct wl_listener layout_destroy;
}; };
struct wlr_cursor *wlr_cursor_create() { struct wlr_cursor *wlr_cursor_create() {
@ -55,6 +59,7 @@ struct wlr_cursor *wlr_cursor_create() {
return NULL; return NULL;
} }
cur->state->cursor = cur;
cur->state->mapped_output = NULL; cur->state->mapped_output = NULL;
wl_list_init(&cur->state->devices); wl_list_init(&cur->state->devices);
@ -83,7 +88,20 @@ struct wlr_cursor *wlr_cursor_create() {
return cur; return cur;
} }
static void wlr_cursor_detach_output_layout(struct wlr_cursor *cur) {
if (!cur->state->layout) {
return;
}
wl_list_remove(&cur->state->layout_destroy.link);
wl_list_remove(&cur->state->layout_change.link);
cur->state->layout = NULL;
}
void wlr_cursor_destroy(struct wlr_cursor *cur) { void wlr_cursor_destroy(struct wlr_cursor *cur) {
wlr_cursor_detach_output_layout(cur);
struct wlr_cursor_device *device, *device_tmp = NULL; struct wlr_cursor_device *device, *device_tmp = NULL;
wl_list_for_each_safe(device, device_tmp, &cur->state->devices, link) { wl_list_for_each_safe(device, device_tmp, &cur->state->devices, link) {
wl_list_remove(&device->link); wl_list_remove(&device->link);
@ -430,8 +448,42 @@ void wlr_cursor_detach_input_device(struct wlr_cursor *cur,
} }
} }
static void handle_layout_destroy(struct wl_listener *listener, void *data) {
struct wlr_cursor_state *state =
wl_container_of(listener, state, layout_change);
wlr_cursor_detach_output_layout(state->cursor);
}
static void handle_layout_change(struct wl_listener *listener, void *data) {
struct wlr_cursor_state *state =
wl_container_of(listener, state, layout_change);
struct wlr_output_layout *layout = data;
if (!wlr_output_layout_contains_point(layout, NULL, state->cursor->x,
state->cursor->y)) {
// the output we were on has gone away so go to the closest boundary
// point
double x, y;
wlr_output_layout_closest_point(layout, NULL, state->cursor->x,
state->cursor->y, &x, &y);
wlr_cursor_warp_unchecked(state->cursor, x, y);
}
}
void wlr_cursor_attach_output_layout(struct wlr_cursor *cur, void wlr_cursor_attach_output_layout(struct wlr_cursor *cur,
struct wlr_output_layout *l) { struct wlr_output_layout *l) {
wlr_cursor_detach_output_layout(cur);
if (l == NULL) {
return;
}
wl_signal_add(&l->events.change, &cur->state->layout_change);
cur->state->layout_change.notify = handle_layout_change;
wl_signal_add(&l->events.destroy, &cur->state->layout_destroy);
cur->state->layout_destroy.notify = handle_layout_destroy;
cur->state->layout = l; cur->state->layout = l;
} }

View file

@ -28,6 +28,10 @@ struct wlr_output_layout *wlr_output_layout_init() {
layout->state = calloc(1, sizeof(struct wlr_output_layout_state)); layout->state = calloc(1, sizeof(struct wlr_output_layout_state));
layout->state->_box = calloc(1, sizeof(struct wlr_box)); layout->state->_box = calloc(1, sizeof(struct wlr_box));
wl_list_init(&layout->outputs); wl_list_init(&layout->outputs);
wl_signal_init(&layout->events.change);
wl_signal_init(&layout->events.destroy);
return layout; return layout;
} }
@ -46,6 +50,8 @@ void wlr_output_layout_destroy(struct wlr_output_layout *layout) {
return; return;
} }
wl_signal_emit(&layout->events.destroy, layout);
struct wlr_output_layout_output *_output, *temp = NULL; struct wlr_output_layout_output *_output, *temp = NULL;
wl_list_for_each_safe(_output, temp, &layout->outputs, link) { wl_list_for_each_safe(_output, temp, &layout->outputs, link) {
wlr_output_layout_output_destroy(_output); wlr_output_layout_output_destroy(_output);
@ -69,7 +75,7 @@ static struct wlr_box *wlr_output_layout_output_get_box(
/** /**
* This must be called whenever the layout changes to reconfigure the auto * This must be called whenever the layout changes to reconfigure the auto
* configured outputs. * configured outputs and emit the `changed` event.
* *
* Auto configured outputs are placed to the right of the north east corner of * Auto configured outputs are placed to the right of the north east corner of
* the rightmost output in the layout in a horizontal line. * the rightmost output in the layout in a horizontal line.
@ -108,6 +114,8 @@ static void wlr_output_layout_reconfigure(struct wlr_output_layout *layout) {
l_output->y = max_x_y; l_output->y = max_x_y;
max_x += box->width; max_x += box->width;
} }
wl_signal_emit(&layout->events.change, layout);
} }
static void handle_output_resolution(struct wl_listener *listener, void *data) { static void handle_output_resolution(struct wl_listener *listener, void *data) {