Merge pull request #257 from emersion/fix-client-cursors
[WIP] Fix client cursors
This commit is contained in:
		
						commit
						62371a9974
					
				| 
						 | 
				
			
			@ -470,7 +470,7 @@ static void wlr_drm_connector_transform(struct wlr_output *output,
 | 
			
		|||
 | 
			
		||||
static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
 | 
			
		||||
		const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height,
 | 
			
		||||
		int32_t hotspot_x, int32_t hotspot_y) {
 | 
			
		||||
		int32_t hotspot_x, int32_t hotspot_y, bool update_pixels) {
 | 
			
		||||
	struct wlr_drm_connector *conn = (struct wlr_drm_connector *)output;
 | 
			
		||||
	struct wlr_drm_backend *drm = conn->drm;
 | 
			
		||||
	struct wlr_drm_renderer *renderer = &drm->renderer;
 | 
			
		||||
| 
						 | 
				
			
			@ -478,7 +478,8 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
 | 
			
		|||
	struct wlr_drm_crtc *crtc = conn->crtc;
 | 
			
		||||
	struct wlr_drm_plane *plane = crtc->cursor;
 | 
			
		||||
 | 
			
		||||
	if (!buf) {
 | 
			
		||||
	if (!buf && update_pixels) {
 | 
			
		||||
		// Hide the cursor
 | 
			
		||||
		return drm->iface->crtc_set_cursor(drm, crtc, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -566,6 +567,11 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
 | 
			
		|||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!update_pixels) {
 | 
			
		||||
		// Only update the cursor hotspot
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct gbm_bo *bo = plane->cursor_bo;
 | 
			
		||||
	uint32_t bo_width = gbm_bo_get_width(bo);
 | 
			
		||||
	uint32_t bo_height = gbm_bo_get_height(bo);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,13 +54,24 @@ static void wlr_wl_output_transform(struct wlr_output *_output,
 | 
			
		|||
 | 
			
		||||
static bool wlr_wl_output_set_cursor(struct wlr_output *_output,
 | 
			
		||||
		const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height,
 | 
			
		||||
		int32_t hotspot_x, int32_t hotspot_y) {
 | 
			
		||||
		int32_t hotspot_x, int32_t hotspot_y, bool update_pixels) {
 | 
			
		||||
	struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output;
 | 
			
		||||
	struct wlr_wl_backend *backend = output->backend;
 | 
			
		||||
 | 
			
		||||
	if (!update_pixels) {
 | 
			
		||||
		// Update hotspot without changing cursor image
 | 
			
		||||
		wlr_wl_output_update_cursor(output, output->enter_serial, hotspot_x,
 | 
			
		||||
			hotspot_y);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	if (!buf) {
 | 
			
		||||
		wl_pointer_set_cursor(output->backend->pointer, output->enter_serial,
 | 
			
		||||
			NULL, 0, 0);
 | 
			
		||||
		// Hide cursor
 | 
			
		||||
		wl_surface_destroy(output->cursor_surface);
 | 
			
		||||
		munmap(output->cursor_data, output->cursor_buf_size);
 | 
			
		||||
		output->cursor_surface = NULL;
 | 
			
		||||
		output->cursor_buf_size = 0;
 | 
			
		||||
		wlr_wl_output_update_cursor(output, output->enter_serial, hotspot_x,
 | 
			
		||||
			hotspot_y);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +164,7 @@ static void wlr_wl_output_destroy(struct wlr_output *_output) {
 | 
			
		|||
 | 
			
		||||
void wlr_wl_output_update_cursor(struct wlr_wl_backend_output *output,
 | 
			
		||||
			uint32_t serial, int32_t hotspot_x, int32_t hotspot_y) {
 | 
			
		||||
	if (output->cursor_surface && output->backend->pointer && serial) {
 | 
			
		||||
	if (output->backend->pointer && serial) {
 | 
			
		||||
		wl_pointer_set_cursor(output->backend->pointer, serial,
 | 
			
		||||
			output->cursor_surface, hotspot_x, hotspot_y);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ struct roots_input {
 | 
			
		|||
	struct wlr_xcursor_theme *theme;
 | 
			
		||||
	struct wlr_xcursor *xcursor;
 | 
			
		||||
	struct wlr_seat *wl_seat;
 | 
			
		||||
	struct roots_view *client_cursor_view;
 | 
			
		||||
	struct wl_client *cursor_client;
 | 
			
		||||
 | 
			
		||||
	enum roots_cursor_mode mode;
 | 
			
		||||
	struct roots_view *active_view, *last_active_view;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,16 +8,16 @@ struct wlr_output_impl {
 | 
			
		|||
	void (*enable)(struct wlr_output *output, bool enable);
 | 
			
		||||
	bool (*set_mode)(struct wlr_output *output, struct wlr_output_mode *mode);
 | 
			
		||||
	void (*transform)(struct wlr_output *output,
 | 
			
		||||
			enum wl_output_transform transform);
 | 
			
		||||
		enum wl_output_transform transform);
 | 
			
		||||
	bool (*set_cursor)(struct wlr_output *output, const uint8_t *buf,
 | 
			
		||||
			int32_t stride, uint32_t width, uint32_t height,
 | 
			
		||||
			int32_t hotspot_x, int32_t hotspot_y);
 | 
			
		||||
		int32_t stride, uint32_t width, uint32_t height,
 | 
			
		||||
		int32_t hotspot_x, int32_t hotspot_y, bool update_pixels);
 | 
			
		||||
	bool (*move_cursor)(struct wlr_output *output, int x, int y);
 | 
			
		||||
	void (*destroy)(struct wlr_output *output);
 | 
			
		||||
	void (*make_current)(struct wlr_output *output);
 | 
			
		||||
	void (*swap_buffers)(struct wlr_output *output);
 | 
			
		||||
	void (*set_gamma)(struct wlr_output *output,
 | 
			
		||||
			uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
 | 
			
		||||
		uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b);
 | 
			
		||||
	uint16_t (*get_gamma_size)(struct wlr_output *output);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,6 @@ void wlr_output_init(struct wlr_output *output, const struct wlr_output_impl *im
 | 
			
		|||
void wlr_output_free(struct wlr_output *output);
 | 
			
		||||
void wlr_output_update_matrix(struct wlr_output *output);
 | 
			
		||||
struct wl_global *wlr_output_create_global(
 | 
			
		||||
		struct wlr_output *wlr_output, struct wl_display *display);
 | 
			
		||||
	struct wlr_output *wlr_output, struct wl_display *display);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,10 +83,16 @@ void cursor_update_position(struct roots_input *input, uint32_t time) {
 | 
			
		|||
	case ROOTS_CURSOR_PASSTHROUGH:
 | 
			
		||||
		view = view_at(desktop, input->cursor->x, input->cursor->y, &surface,
 | 
			
		||||
			&sx, &sy);
 | 
			
		||||
		if (view != input->client_cursor_view) {
 | 
			
		||||
		bool set_compositor_cursor = !view && input->cursor_client;
 | 
			
		||||
		if (view) {
 | 
			
		||||
			struct wl_client *view_client =
 | 
			
		||||
				wl_resource_get_client(view->wlr_surface->resource);
 | 
			
		||||
			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]);
 | 
			
		||||
			input->client_cursor_view = NULL;
 | 
			
		||||
			input->cursor_client = NULL;
 | 
			
		||||
		}
 | 
			
		||||
		if (view) {
 | 
			
		||||
			wlr_seat_pointer_notify_enter(input->wl_seat, surface, sx, sy);
 | 
			
		||||
| 
						 | 
				
			
			@ -301,18 +307,16 @@ static void handle_request_set_cursor(struct wl_listener *listener,
 | 
			
		|||
		request_set_cursor);
 | 
			
		||||
	struct wlr_seat_pointer_request_set_cursor_event *event = data;
 | 
			
		||||
 | 
			
		||||
	struct wlr_surface *focused_surface = NULL;
 | 
			
		||||
	double sx, sy;
 | 
			
		||||
	struct roots_view *focused_view = view_at(input->server->desktop,
 | 
			
		||||
		input->cursor->x, input->cursor->y, &focused_surface, &sx, &sy);
 | 
			
		||||
	bool ok = focused_surface != NULL;
 | 
			
		||||
	if (focused_surface != NULL) {
 | 
			
		||||
	struct wlr_surface *focused_surface =
 | 
			
		||||
		event->seat_handle->wlr_seat->pointer_state.focused_surface;
 | 
			
		||||
	bool ok = focused_surface != NULL && focused_surface->resource != NULL;
 | 
			
		||||
	if (ok) {
 | 
			
		||||
		struct wl_client *focused_client =
 | 
			
		||||
			wl_resource_get_client(focused_surface->resource);
 | 
			
		||||
		ok = event->client == focused_client;
 | 
			
		||||
	}
 | 
			
		||||
	if (!ok) {
 | 
			
		||||
		wlr_log(L_DEBUG, "Denying request to set cursor outside view");
 | 
			
		||||
		wlr_log(L_DEBUG, "Denying request to set cursor from unfocused client");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -324,7 +328,7 @@ static void handle_request_set_cursor(struct wl_listener *listener,
 | 
			
		|||
			event->hotspot_x, event->hotspot_y);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	input->client_cursor_view = focused_view;
 | 
			
		||||
	input->cursor_client = event->client;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cursor_initialize(struct roots_input *input) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,7 +127,7 @@ static bool set_cursor(struct wlr_output *output, const uint8_t *buf,
 | 
			
		|||
		int32_t hotspot_y) {
 | 
			
		||||
	if (output->impl->set_cursor
 | 
			
		||||
			&& output->impl->set_cursor(output, buf, stride, width, height,
 | 
			
		||||
				hotspot_x, hotspot_y)) {
 | 
			
		||||
				hotspot_x, hotspot_y, true)) {
 | 
			
		||||
		output->cursor.is_sw = false;
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +179,10 @@ static inline int64_t timespec_to_msec(const struct timespec *a) {
 | 
			
		|||
 | 
			
		||||
static void commit_cursor_surface(struct wlr_output *output,
 | 
			
		||||
		struct wlr_surface *surface) {
 | 
			
		||||
	if (output->cursor.is_sw) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer);
 | 
			
		||||
	if (buffer == NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
| 
						 | 
				
			
			@ -231,14 +235,19 @@ static void handle_cursor_surface_destroy(struct wl_listener *listener,
 | 
			
		|||
 | 
			
		||||
void wlr_output_set_cursor_surface(struct wlr_output *output,
 | 
			
		||||
		struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) {
 | 
			
		||||
	if (surface && strcmp(surface->role, "cursor") != 0) {
 | 
			
		||||
	if (surface && strcmp(surface->role, "wl_pointer-cursor") != 0) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	output->cursor.hotspot_x = hotspot_x;
 | 
			
		||||
	output->cursor.hotspot_y = hotspot_y;
 | 
			
		||||
 | 
			
		||||
	if (surface && output->cursor.surface == surface) {
 | 
			
		||||
	if (surface && surface == output->cursor.surface) {
 | 
			
		||||
		if (output->impl->set_cursor && !output->cursor.is_sw) {
 | 
			
		||||
			// Only update the hotspot
 | 
			
		||||
			output->impl->set_cursor(output, NULL, 0, 0, 0, hotspot_x,
 | 
			
		||||
				hotspot_y, false);
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -248,11 +257,22 @@ void wlr_output_set_cursor_surface(struct wlr_output *output,
 | 
			
		|||
		output->cursor.surface = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Disable hardware cursor
 | 
			
		||||
	// TODO: support hardware cursors
 | 
			
		||||
	output->cursor.is_sw = true;
 | 
			
		||||
	if (output->impl->set_cursor) {
 | 
			
		||||
		output->impl->set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y,
 | 
			
		||||
			true);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//output->cursor.is_sw = output->impl->set_cursor == NULL;
 | 
			
		||||
	output->cursor.surface = surface;
 | 
			
		||||
 | 
			
		||||
	if (surface != NULL) {
 | 
			
		||||
		wl_signal_add(&surface->events.commit, &output->cursor.surface_commit);
 | 
			
		||||
		wl_signal_add(&surface->events.destroy, &output->cursor.surface_destroy);
 | 
			
		||||
		wl_signal_add(&surface->events.destroy,
 | 
			
		||||
			&output->cursor.surface_destroy);
 | 
			
		||||
		commit_cursor_surface(output, surface);
 | 
			
		||||
	} else {
 | 
			
		||||
		set_cursor(output, NULL, 0, 0, 0, hotspot_x, hotspot_y);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -333,10 +353,20 @@ void wlr_output_swap_buffers(struct wlr_output *output) {
 | 
			
		|||
		glViewport(0, 0, output->width, output->height);
 | 
			
		||||
		glEnable(GL_BLEND);
 | 
			
		||||
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
		float matrix[16];
 | 
			
		||||
		wlr_texture_get_matrix(output->cursor.texture, &matrix, &output->transform_matrix,
 | 
			
		||||
			output->cursor.x, output->cursor.y);
 | 
			
		||||
		wlr_render_with_matrix(output->cursor.renderer, output->cursor.texture, &matrix);
 | 
			
		||||
 | 
			
		||||
		struct wlr_texture *texture = output->cursor.texture;
 | 
			
		||||
		struct wlr_renderer *renderer = output->cursor.renderer;
 | 
			
		||||
		if (output->cursor.surface) {
 | 
			
		||||
			texture = output->cursor.surface->texture;
 | 
			
		||||
			renderer = output->cursor.surface->renderer;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (texture && renderer) {
 | 
			
		||||
			float matrix[16];
 | 
			
		||||
			wlr_texture_get_matrix(texture, &matrix, &output->transform_matrix,
 | 
			
		||||
				output->cursor.x, output->cursor.y);
 | 
			
		||||
			wlr_render_with_matrix(renderer, texture, &matrix);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	wl_signal_emit(&output->events.swap_buffers, &output);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ static void wl_pointer_set_cursor(struct wl_client *client,
 | 
			
		|||
	if (surface_resource != NULL) {
 | 
			
		||||
		surface = wl_resource_get_user_data(surface_resource);
 | 
			
		||||
 | 
			
		||||
		if (wlr_surface_set_role(surface, "cursor", resource,
 | 
			
		||||
		if (wlr_surface_set_role(surface, "wl_pointer-cursor", resource,
 | 
			
		||||
				WL_POINTER_ERROR_ROLE) < 0) {
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue