Merge pull request #344 from emersion/compositor-action-cursors
Set compositor cursor for move, resize and rotate
This commit is contained in:
		
						commit
						9f1ed70b81
					
				|  | @ -88,8 +88,7 @@ struct roots_input { | |||
| 
 | ||||
| 	// TODO: multiseat, multicursor
 | ||||
| 	struct wlr_cursor *cursor; | ||||
| 	struct wlr_xcursor_theme *theme; | ||||
| 	struct wlr_xcursor *xcursor; | ||||
| 	struct wlr_xcursor_theme *xcursor_theme; | ||||
| 	struct wlr_seat *wl_seat; | ||||
| 	struct wl_list drag_icons; | ||||
| 	struct wl_client *cursor_client; | ||||
|  | @ -158,6 +157,12 @@ void view_begin_move(struct roots_input *input, struct wlr_cursor *cursor, | |||
| void view_begin_resize(struct roots_input *input, struct wlr_cursor *cursor, | ||||
| 		struct roots_view *view, uint32_t edges); | ||||
| 
 | ||||
| struct wlr_xcursor *get_default_xcursor(struct wlr_xcursor_theme *theme); | ||||
| struct wlr_xcursor *get_move_xcursor(struct wlr_xcursor_theme *theme); | ||||
| struct wlr_xcursor *get_resize_xcursor(struct wlr_xcursor_theme *theme, | ||||
| 	uint32_t edges); | ||||
| struct wlr_xcursor *get_rotate_xcursor(struct wlr_xcursor_theme *theme); | ||||
| 
 | ||||
| void set_view_focus(struct roots_input *input, struct roots_desktop *desktop, | ||||
| 	struct roots_view *view); | ||||
| 
 | ||||
|  |  | |||
|  | @ -31,6 +31,28 @@ const struct roots_input_event *get_input_event(struct roots_input *input, | |||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static void cursor_set_xcursor_image(struct roots_input *input, | ||||
| 		struct wlr_xcursor_image *image) { | ||||
| 	struct roots_output *output; | ||||
| 	wl_list_for_each(output, &input->server->desktop->outputs, link) { | ||||
| 		if (!wlr_output_set_cursor(output->wlr_output, image->buffer, | ||||
| 				image->width, image->width, image->height, | ||||
| 				image->hotspot_x, image->hotspot_y)) { | ||||
| 			wlr_log(L_DEBUG, "Failed to set hardware cursor"); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void cursor_set_surface(struct roots_input *input, | ||||
| 		struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) { | ||||
| 	struct roots_output *output; | ||||
| 	wl_list_for_each(output, &input->server->desktop->outputs, link) { | ||||
| 		wlr_output_set_cursor_surface(output->wlr_output, surface, | ||||
| 			hotspot_x, hotspot_y); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void view_begin_move(struct roots_input *input, struct wlr_cursor *cursor, | ||||
| 		struct roots_view *view) { | ||||
| 	input->mode = ROOTS_CURSOR_MOVE; | ||||
|  | @ -39,6 +61,11 @@ void view_begin_move(struct roots_input *input, struct wlr_cursor *cursor, | |||
| 	input->view_x = view->x; | ||||
| 	input->view_y = view->y; | ||||
| 	wlr_seat_pointer_clear_focus(input->wl_seat); | ||||
| 
 | ||||
| 	struct wlr_xcursor *xcursor = get_move_xcursor(input->xcursor_theme); | ||||
| 	if (xcursor != NULL) { | ||||
| 		cursor_set_xcursor_image(input, xcursor->images[0]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void view_begin_resize(struct roots_input *input, struct wlr_cursor *cursor, | ||||
|  | @ -54,6 +81,11 @@ void view_begin_resize(struct roots_input *input, struct wlr_cursor *cursor, | |||
| 	input->view_height = size.height; | ||||
| 	input->resize_edges = edges; | ||||
| 	wlr_seat_pointer_clear_focus(input->wl_seat); | ||||
| 
 | ||||
| 	struct wlr_xcursor *xcursor = get_resize_xcursor(input->xcursor_theme, edges); | ||||
| 	if (xcursor != NULL) { | ||||
| 		cursor_set_xcursor_image(input, xcursor->images[0]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void view_begin_rotate(struct roots_input *input, struct wlr_cursor *cursor, | ||||
|  | @ -63,18 +95,10 @@ void view_begin_rotate(struct roots_input *input, struct wlr_cursor *cursor, | |||
| 	input->offs_y = cursor->y; | ||||
| 	input->view_rotation = view->rotation; | ||||
| 	wlr_seat_pointer_clear_focus(input->wl_seat); | ||||
| } | ||||
| 
 | ||||
| static void cursor_set_xcursor_image(struct roots_input *input, | ||||
| 		struct wlr_xcursor_image *image) { | ||||
| 	struct roots_output *output; | ||||
| 	wl_list_for_each(output, &input->server->desktop->outputs, link) { | ||||
| 		if (!wlr_output_set_cursor(output->wlr_output, image->buffer, | ||||
| 				image->width, image->width, image->height, | ||||
| 				image->hotspot_x, image->hotspot_y)) { | ||||
| 			wlr_log(L_DEBUG, "Failed to set hardware cursor"); | ||||
| 			return; | ||||
| 		} | ||||
| 	struct wlr_xcursor *xcursor = get_rotate_xcursor(input->xcursor_theme); | ||||
| 	if (xcursor != NULL) { | ||||
| 		cursor_set_xcursor_image(input, xcursor->images[0]); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -94,8 +118,8 @@ void cursor_update_position(struct roots_input *input, uint32_t time) { | |||
| 			set_compositor_cursor = view_client != input->cursor_client; | ||||
| 		} | ||||
| 		if (set_compositor_cursor) { | ||||
| 			wlr_log(L_DEBUG, "Switching to compositor cursor"); | ||||
| 			cursor_set_xcursor_image(input, input->xcursor->images[0]); | ||||
| 			struct wlr_xcursor *xcursor = get_default_xcursor(input->xcursor_theme); | ||||
| 			cursor_set_xcursor_image(input, xcursor->images[0]); | ||||
| 			input->cursor_client = NULL; | ||||
| 		} | ||||
| 		if (view) { | ||||
|  | @ -273,6 +297,7 @@ static void do_cursor_button_press(struct roots_input *input, | |||
| 	switch (state) { | ||||
| 	case WLR_BUTTON_RELEASED: | ||||
| 		set_view_focus(input, desktop, NULL); | ||||
| 		cursor_update_position(input, time); | ||||
| 		break; | ||||
| 	case WLR_BUTTON_PRESSED: | ||||
| 		i = input->input_events_idx; | ||||
|  | @ -436,19 +461,13 @@ static void handle_request_set_cursor(struct wl_listener *listener, | |||
| 			wl_resource_get_client(focused_surface->resource); | ||||
| 		ok = event->client == focused_client; | ||||
| 	} | ||||
| 	if (!ok) { | ||||
| 	if (!ok || input->mode != ROOTS_CURSOR_PASSTHROUGH) { | ||||
| 		wlr_log(L_DEBUG, "Denying request to set cursor from unfocused client"); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_log(L_DEBUG, "Setting client cursor"); | ||||
| 
 | ||||
| 	struct roots_output *output; | ||||
| 	wl_list_for_each(output, &input->server->desktop->outputs, link) { | ||||
| 		wlr_output_set_cursor_surface(output->wlr_output, event->surface, | ||||
| 			event->hotspot_x, event->hotspot_y); | ||||
| 	} | ||||
| 
 | ||||
| 	cursor_set_surface(input, event->surface, event->hotspot_x, event->hotspot_y); | ||||
| 	input->cursor_client = event->client; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -81,16 +81,17 @@ struct roots_input *input_create(struct roots_server *server, | |||
| 	input->config = config; | ||||
| 	input->server = server; | ||||
| 
 | ||||
| 	input->theme = wlr_xcursor_theme_load("default", 16); | ||||
| 	if (input->theme == NULL) { | ||||
| 	input->xcursor_theme = wlr_xcursor_theme_load("default", 16); | ||||
| 	if (input->xcursor_theme == NULL) { | ||||
| 		wlr_log(L_ERROR, "Cannot load xcursor theme"); | ||||
| 		free(input); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	input->xcursor = wlr_xcursor_theme_get_cursor(input->theme, "left_ptr"); | ||||
| 	if (input->xcursor == NULL) { | ||||
| 
 | ||||
| 	struct wlr_xcursor *xcursor = get_default_xcursor(input->xcursor_theme); | ||||
| 	if (xcursor == NULL) { | ||||
| 		wlr_log(L_ERROR, "Cannot load xcursor from theme"); | ||||
| 		wlr_xcursor_theme_destroy(input->theme); | ||||
| 		wlr_xcursor_theme_destroy(input->xcursor_theme); | ||||
| 		free(input); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | @ -98,7 +99,7 @@ struct roots_input *input_create(struct roots_server *server, | |||
| 	input->wl_seat = wlr_seat_create(server->wl_display, "seat0"); | ||||
| 	if (input->wl_seat == NULL) { | ||||
| 		wlr_log(L_ERROR, "Cannot create seat"); | ||||
| 		wlr_xcursor_theme_destroy(input->theme); | ||||
| 		wlr_xcursor_theme_destroy(input->xcursor_theme); | ||||
| 		free(input); | ||||
| 		return NULL; | ||||
| 	} | ||||
|  | @ -117,7 +118,7 @@ struct roots_input *input_create(struct roots_server *server, | |||
| 
 | ||||
| 	input->cursor = wlr_cursor_create(); | ||||
| 	cursor_initialize(input); | ||||
| 	wlr_cursor_set_xcursor(input->cursor, input->xcursor); | ||||
| 	wlr_cursor_set_xcursor(input->cursor, xcursor); | ||||
| 
 | ||||
| 	wlr_cursor_attach_output_layout(input->cursor, server->desktop->layout); | ||||
| 	wlr_cursor_map_to_region(input->cursor, config->cursor.mapped_box); | ||||
|  |  | |||
|  | @ -10,6 +10,7 @@ sources = [ | |||
| 	'pointer.c', | ||||
| 	'tablet_tool.c', | ||||
| 	'touch.c', | ||||
| 	'xcursor.c', | ||||
| 	'xdg_shell_v6.c', | ||||
| 	'wl_shell.c', | ||||
| ] | ||||
|  |  | |||
|  | @ -200,7 +200,8 @@ void output_add_notify(struct wl_listener *listener, void *data) { | |||
| 
 | ||||
| 	cursor_load_config(config, input->cursor, input, desktop); | ||||
| 
 | ||||
| 	struct wlr_xcursor_image *image = input->xcursor->images[0]; | ||||
| 	struct wlr_xcursor *xcursor = get_default_xcursor(input->xcursor_theme); | ||||
| 	struct wlr_xcursor_image *image = xcursor->images[0]; | ||||
| 	// TODO the cursor must be set depending on which surface it is displayed
 | ||||
| 	// over which should happen in the compositor.
 | ||||
| 	if (!wlr_output_set_cursor(wlr_output, image->buffer, | ||||
|  |  | |||
|  | @ -0,0 +1,42 @@ | |||
| #include <wlr/types/wlr_cursor.h> | ||||
| #include "rootston/input.h" | ||||
| 
 | ||||
| struct wlr_xcursor *get_default_xcursor(struct wlr_xcursor_theme *theme) { | ||||
| 	return wlr_xcursor_theme_get_cursor(theme, "left_ptr"); | ||||
| } | ||||
| 
 | ||||
| struct wlr_xcursor *get_move_xcursor(struct wlr_xcursor_theme *theme) { | ||||
| 	return wlr_xcursor_theme_get_cursor(theme, "grabbing"); | ||||
| } | ||||
| 
 | ||||
| static const char *get_resize_xcursor_name(uint32_t edges) { | ||||
| 	if (edges & ROOTS_CURSOR_RESIZE_EDGE_TOP) { | ||||
| 		if (edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { | ||||
| 			return "ne-resize"; | ||||
| 		} else if (edges & ROOTS_CURSOR_RESIZE_EDGE_LEFT) { | ||||
| 			return "nw-resize"; | ||||
| 		} | ||||
| 		return "n-resize"; | ||||
| 	} else if (edges & ROOTS_CURSOR_RESIZE_EDGE_BOTTOM) { | ||||
| 		if (edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { | ||||
| 			return "se-resize"; | ||||
| 		} else if (edges & ROOTS_CURSOR_RESIZE_EDGE_LEFT) { | ||||
| 			return "sw-resize"; | ||||
| 		} | ||||
| 		return "s-resize"; | ||||
| 	} else if (edges & ROOTS_CURSOR_RESIZE_EDGE_RIGHT) { | ||||
| 		return "e-resize"; | ||||
| 	} else if (edges & ROOTS_CURSOR_RESIZE_EDGE_LEFT) { | ||||
| 		return "w-resize"; | ||||
| 	} | ||||
| 	return "se-resize"; // fallback
 | ||||
| } | ||||
| 
 | ||||
| struct wlr_xcursor *get_resize_xcursor(struct wlr_xcursor_theme *theme, | ||||
| 	uint32_t edges) { | ||||
| 	return wlr_xcursor_theme_get_cursor(theme, get_resize_xcursor_name(edges)); | ||||
| } | ||||
| 
 | ||||
| struct wlr_xcursor *get_rotate_xcursor(struct wlr_xcursor_theme *theme) { | ||||
| 	return wlr_xcursor_theme_get_cursor(theme, "grabbing"); | ||||
| } | ||||
		Loading…
	
		Reference in New Issue