mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Handle set_cursor requests from clients
Allow clients to set a custom cursor if they have the seat's pointer focus.
This commit is contained in:
		
							parent
							
								
									2d46050281
								
							
						
					
					
						commit
						6c9d67b105
					
				
					 2 changed files with 43 additions and 8 deletions
				
			
		| 
						 | 
					@ -9,6 +9,7 @@ struct sway_cursor {
 | 
				
			||||||
	struct wlr_xcursor_manager *xcursor_manager;
 | 
						struct wlr_xcursor_manager *xcursor_manager;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	double x, y;
 | 
						double x, y;
 | 
				
			||||||
 | 
						struct wl_client *image_client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_listener motion;
 | 
						struct wl_listener motion;
 | 
				
			||||||
	struct wl_listener motion_absolute;
 | 
						struct wl_listener motion_absolute;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,10 +25,12 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
 | 
				
			||||||
	struct wlr_surface *surface = NULL;
 | 
						struct wlr_surface *surface = NULL;
 | 
				
			||||||
	double sx, sy;
 | 
						double sx, sy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct sway_container *focus = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// check for unmanaged views first
 | 
						// check for unmanaged views first
 | 
				
			||||||
	struct sway_view *view;
 | 
						struct sway_view *view;
 | 
				
			||||||
	wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views,
 | 
						wl_list_for_each_reverse(view, &root_container.sway_root->unmanaged_views,
 | 
				
			||||||
		unmanaged_view_link) {
 | 
								unmanaged_view_link) {
 | 
				
			||||||
		if (view->type == SWAY_XWAYLAND_VIEW) {
 | 
							if (view->type == SWAY_XWAYLAND_VIEW) {
 | 
				
			||||||
			struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
 | 
								struct wlr_xwayland_surface *xsurface = view->wlr_xwayland_surface;
 | 
				
			||||||
			struct wlr_box box = {
 | 
								struct wlr_box box = {
 | 
				
			||||||
| 
						 | 
					@ -39,19 +41,34 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor,
 | 
				
			||||||
			};
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (wlr_box_contains_point(&box, cursor->x, cursor->y)) {
 | 
								if (wlr_box_contains_point(&box, cursor->x, cursor->y)) {
 | 
				
			||||||
 | 
									focus = view->swayc;
 | 
				
			||||||
				surface = xsurface->surface;
 | 
									surface = xsurface->surface;
 | 
				
			||||||
				sx = cursor->x - box.x;
 | 
									sx = cursor->x - box.x;
 | 
				
			||||||
				sy = cursor->y - box.y;
 | 
									sy = cursor->y - box.y;
 | 
				
			||||||
				wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
 | 
									break;
 | 
				
			||||||
				wlr_seat_pointer_notify_motion(seat, time, sx, sy);
 | 
					 | 
				
			||||||
				return;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_container *swayc =
 | 
						// then check for managed views
 | 
				
			||||||
		container_at(&root_container, cursor->x, cursor->y, &surface, &sx, &sy);
 | 
						if (focus == NULL) {
 | 
				
			||||||
	if (swayc) {
 | 
							focus = container_at(&root_container, cursor->x, cursor->y, &surface,
 | 
				
			||||||
 | 
								&sx, &sy);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// reset cursor if switching between clients
 | 
				
			||||||
 | 
						struct wl_client *client = NULL;
 | 
				
			||||||
 | 
						if (focus) {
 | 
				
			||||||
 | 
							client = wl_resource_get_client(surface->resource);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (client != cursor->image_client) {
 | 
				
			||||||
 | 
							wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager,
 | 
				
			||||||
 | 
								"left_ptr", cursor->cursor);
 | 
				
			||||||
 | 
							cursor->image_client = client;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// send pointer enter/leave
 | 
				
			||||||
 | 
						if (focus) {
 | 
				
			||||||
		wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
 | 
							wlr_seat_pointer_notify_enter(seat, surface, sx, sy);
 | 
				
			||||||
		wlr_seat_pointer_notify_motion(seat, time, sx, sy);
 | 
							wlr_seat_pointer_notify_motion(seat, time, sx, sy);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -145,7 +162,24 @@ static void handle_request_set_cursor(struct wl_listener *listener,
 | 
				
			||||||
	struct sway_cursor *cursor =
 | 
						struct sway_cursor *cursor =
 | 
				
			||||||
		wl_container_of(listener, cursor, request_set_cursor);
 | 
							wl_container_of(listener, cursor, request_set_cursor);
 | 
				
			||||||
	struct wlr_seat_pointer_request_set_cursor_event *event = data;
 | 
						struct wlr_seat_pointer_request_set_cursor_event *event = data;
 | 
				
			||||||
	wlr_log(L_DEBUG, "TODO: handle request set cursor event: %p", event);
 | 
					
 | 
				
			||||||
 | 
						struct wl_client *focused_client = NULL;
 | 
				
			||||||
 | 
						struct wlr_surface *focused_surface =
 | 
				
			||||||
 | 
							cursor->seat->wlr_seat->pointer_state.focused_surface;
 | 
				
			||||||
 | 
						if (focused_surface != NULL) {
 | 
				
			||||||
 | 
							focused_client = wl_resource_get_client(focused_surface->resource);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// TODO: check cursor mode
 | 
				
			||||||
 | 
						if (focused_client == NULL ||
 | 
				
			||||||
 | 
								event->seat_client->client != focused_client) {
 | 
				
			||||||
 | 
							wlr_log(L_DEBUG, "denying request to set cursor from unfocused client");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_cursor_set_surface(cursor->cursor, event->surface, event->hotspot_x,
 | 
				
			||||||
 | 
							event->hotspot_y);
 | 
				
			||||||
 | 
						cursor->image_client = focused_client;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void sway_cursor_destroy(struct sway_cursor *cursor) {
 | 
					void sway_cursor_destroy(struct sway_cursor *cursor) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue