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:
		
							parent
							
								
									6089967e07
								
							
						
					
					
						commit
						57c18c38bb
					
				|  | @ -9,6 +9,11 @@ struct wlr_output_layout_state; | |||
| struct wlr_output_layout { | ||||
| 	struct wl_list outputs; | ||||
| 	struct wlr_output_layout_state *state; | ||||
| 
 | ||||
| 	struct { | ||||
| 		struct wl_signal change; | ||||
| 		struct wl_signal destroy; | ||||
| 	} events; | ||||
| }; | ||||
| 
 | ||||
| struct wlr_output_layout_output_state; | ||||
|  |  | |||
|  | @ -34,11 +34,15 @@ struct wlr_cursor_device { | |||
| }; | ||||
| 
 | ||||
| struct wlr_cursor_state { | ||||
| 	struct wlr_cursor *cursor; | ||||
| 	struct wl_list devices; | ||||
| 	struct wlr_output_layout *layout; | ||||
| 	struct wlr_xcursor *xcursor; | ||||
| 	struct wlr_output *mapped_output; | ||||
| 	struct wlr_box *mapped_box; | ||||
| 
 | ||||
| 	struct wl_listener layout_change; | ||||
| 	struct wl_listener layout_destroy; | ||||
| }; | ||||
| 
 | ||||
| struct wlr_cursor *wlr_cursor_create() { | ||||
|  | @ -55,6 +59,7 @@ struct wlr_cursor *wlr_cursor_create() { | |||
| 		return NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	cur->state->cursor = cur; | ||||
| 	cur->state->mapped_output = NULL; | ||||
| 
 | ||||
| 	wl_list_init(&cur->state->devices); | ||||
|  | @ -83,7 +88,20 @@ struct wlr_cursor *wlr_cursor_create() { | |||
| 	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) { | ||||
| 	wlr_cursor_detach_output_layout(cur); | ||||
| 
 | ||||
| 	struct wlr_cursor_device *device, *device_tmp = NULL; | ||||
| 	wl_list_for_each_safe(device, device_tmp, &cur->state->devices, 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, | ||||
| 		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; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,6 +28,10 @@ struct wlr_output_layout *wlr_output_layout_init() { | |||
| 	layout->state = calloc(1, sizeof(struct wlr_output_layout_state)); | ||||
| 	layout->state->_box = calloc(1, sizeof(struct wlr_box)); | ||||
| 	wl_list_init(&layout->outputs); | ||||
| 
 | ||||
| 	wl_signal_init(&layout->events.change); | ||||
| 	wl_signal_init(&layout->events.destroy); | ||||
| 
 | ||||
| 	return layout; | ||||
| } | ||||
| 
 | ||||
|  | @ -46,6 +50,8 @@ void wlr_output_layout_destroy(struct wlr_output_layout *layout) { | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	wl_signal_emit(&layout->events.destroy, layout); | ||||
| 
 | ||||
| 	struct wlr_output_layout_output *_output, *temp = NULL; | ||||
| 	wl_list_for_each_safe(_output, temp, &layout->outputs, link) { | ||||
| 		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 | ||||
|  * configured outputs. | ||||
|  * configured outputs and emit the `changed` event. | ||||
|  * | ||||
|  * Auto configured outputs are placed to the right of the north east corner of | ||||
|  * 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; | ||||
| 		max_x += box->width; | ||||
| 	} | ||||
| 
 | ||||
| 	wl_signal_emit(&layout->events.change, layout); | ||||
| } | ||||
| 
 | ||||
| static void handle_output_resolution(struct wl_listener *listener, void *data) { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue