mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Give keyboard focus to unmanaged xwayland surfaces
This fixes dmenu
This commit is contained in:
		
							parent
							
								
									a5d06b6e2b
								
							
						
					
					
						commit
						2b357af7ee
					
				
					 4 changed files with 58 additions and 36 deletions
				
			
		| 
						 | 
				
			
			@ -64,6 +64,9 @@ void seat_set_focus(struct sway_seat *seat, struct sway_container *container);
 | 
			
		|||
void seat_set_focus_warp(struct sway_seat *seat,
 | 
			
		||||
		struct sway_container *container, bool warp);
 | 
			
		||||
 | 
			
		||||
void seat_set_focus_surface(struct sway_seat *seat,
 | 
			
		||||
		struct wlr_surface *surface);
 | 
			
		||||
 | 
			
		||||
void seat_set_focus_layer(struct sway_seat *seat,
 | 
			
		||||
		struct wlr_layer_surface *layer);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,6 +59,13 @@ static void unmanaged_handle_map(struct wl_listener *listener, void *data) {
 | 
			
		|||
	surface->ly = xsurface->y;
 | 
			
		||||
	desktop_damage_surface(xsurface->surface, surface->lx, surface->ly, true);
 | 
			
		||||
 | 
			
		||||
	if (!wlr_xwayland_surface_is_unmanaged(xsurface)) {
 | 
			
		||||
		struct sway_seat *seat = input_manager_current_seat(input_manager);
 | 
			
		||||
		struct wlr_xwayland *xwayland = seat->input->server->xwayland;
 | 
			
		||||
		wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
 | 
			
		||||
		seat_set_focus_surface(seat, xsurface->surface);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// TODO: we don't send surface enter/leave events to xwayland unmanaged
 | 
			
		||||
	// surfaces, but xwayland doesn't support HiDPI anyway
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -333,7 +333,7 @@ bool input_manager_has_focus(struct sway_input_manager *input,
 | 
			
		|||
 | 
			
		||||
void input_manager_set_focus(struct sway_input_manager *input,
 | 
			
		||||
		struct sway_container *container) {
 | 
			
		||||
	struct sway_seat *seat ;
 | 
			
		||||
	struct sway_seat *seat;
 | 
			
		||||
	wl_list_for_each(seat, &input->seats, link) {
 | 
			
		||||
		seat_set_focus(seat, container);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,7 +84,6 @@ static void seat_send_focus(struct sway_seat *seat,
 | 
			
		|||
		wlr_seat_keyboard_notify_enter(
 | 
			
		||||
				seat->wlr_seat, view->surface, NULL, 0, NULL);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void handle_seat_container_destroy(struct wl_listener *listener,
 | 
			
		||||
| 
						 | 
				
			
			@ -405,23 +404,29 @@ void seat_set_focus_warp(struct sway_seat *seat,
 | 
			
		|||
				container_destroy(last_ws);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		struct sway_container *last_output = last_focus;
 | 
			
		||||
		if (last_output && last_output->type != C_OUTPUT) {
 | 
			
		||||
			last_output = container_parent(last_output, C_OUTPUT);
 | 
			
		||||
		}
 | 
			
		||||
		struct sway_container *new_output = container;
 | 
			
		||||
		if (new_output && new_output->type != C_OUTPUT) {
 | 
			
		||||
			new_output = container_parent(new_output, C_OUTPUT);
 | 
			
		||||
		}
 | 
			
		||||
		if (new_output && last_output && new_output != last_output
 | 
			
		||||
				&& config->mouse_warping && warp) {
 | 
			
		||||
			struct wlr_output *output = new_output->sway_output->wlr_output;
 | 
			
		||||
			double x = container->x + output->lx + container->width / 2.0;
 | 
			
		||||
			double y = container->y + output->ly + container->height / 2.0;
 | 
			
		||||
			if (!wlr_output_layout_contains_point(
 | 
			
		||||
					root_container.sway_root->output_layout,
 | 
			
		||||
					output, seat->cursor->cursor->x, seat->cursor->cursor->y)) {
 | 
			
		||||
				wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
 | 
			
		||||
 | 
			
		||||
		if (config->mouse_warping && warp) {
 | 
			
		||||
			struct sway_container *last_output = last_focus;
 | 
			
		||||
			if (last_output && last_output->type != C_OUTPUT) {
 | 
			
		||||
				last_output = container_parent(last_output, C_OUTPUT);
 | 
			
		||||
			}
 | 
			
		||||
			struct sway_container *new_output = container;
 | 
			
		||||
			if (new_output && new_output->type != C_OUTPUT) {
 | 
			
		||||
				new_output = container_parent(new_output, C_OUTPUT);
 | 
			
		||||
			}
 | 
			
		||||
			if (new_output && last_output && new_output != last_output) {
 | 
			
		||||
				double x = new_output->x + container->x +
 | 
			
		||||
					container->width / 2.0;
 | 
			
		||||
				double y = new_output->y + container->y +
 | 
			
		||||
					container->height / 2.0;
 | 
			
		||||
				struct wlr_output *wlr_output =
 | 
			
		||||
					new_output->sway_output->wlr_output;
 | 
			
		||||
				if (!wlr_output_layout_contains_point(
 | 
			
		||||
						root_container.sway_root->output_layout,
 | 
			
		||||
						wlr_output, seat->cursor->cursor->x,
 | 
			
		||||
						seat->cursor->cursor->y)) {
 | 
			
		||||
					wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -442,6 +447,29 @@ void seat_set_focus(struct sway_seat *seat,
 | 
			
		|||
	seat_set_focus_warp(seat, container, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void seat_set_focus_surface(struct sway_seat *seat,
 | 
			
		||||
		struct wlr_surface *surface) {
 | 
			
		||||
	if (seat->focused_layer != NULL) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (seat->has_focus) {
 | 
			
		||||
		struct sway_container *focus = seat_get_focus(seat);
 | 
			
		||||
		if (focus->type == C_VIEW) {
 | 
			
		||||
			wlr_seat_keyboard_clear_focus(seat->wlr_seat);
 | 
			
		||||
			view_set_activated(focus->sway_view, false);
 | 
			
		||||
		}
 | 
			
		||||
		seat->has_focus = false;
 | 
			
		||||
	}
 | 
			
		||||
	struct wlr_keyboard *keyboard =
 | 
			
		||||
		wlr_seat_get_keyboard(seat->wlr_seat);
 | 
			
		||||
	if (keyboard) {
 | 
			
		||||
		wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface,
 | 
			
		||||
			keyboard->keycodes, keyboard->num_keycodes, &keyboard->modifiers);
 | 
			
		||||
	} else {
 | 
			
		||||
		wlr_seat_keyboard_notify_enter(seat->wlr_seat, surface, NULL, 0, NULL);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void seat_set_focus_layer(struct sway_seat *seat,
 | 
			
		||||
		struct wlr_layer_surface *layer) {
 | 
			
		||||
	if (!layer && seat->focused_layer) {
 | 
			
		||||
| 
						 | 
				
			
			@ -458,26 +486,10 @@ void seat_set_focus_layer(struct sway_seat *seat,
 | 
			
		|||
	} else if (!layer || seat->focused_layer == layer) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (seat->has_focus) {
 | 
			
		||||
		struct sway_container *focus = seat_get_focus(seat);
 | 
			
		||||
		if (focus->type == C_VIEW) {
 | 
			
		||||
			wlr_seat_keyboard_clear_focus(seat->wlr_seat);
 | 
			
		||||
			view_set_activated(focus->sway_view, false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	seat_set_focus_surface(seat, layer->surface);
 | 
			
		||||
	if (layer->layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) {
 | 
			
		||||
		seat->focused_layer = layer;
 | 
			
		||||
	}
 | 
			
		||||
	struct wlr_keyboard *keyboard =
 | 
			
		||||
		wlr_seat_get_keyboard(seat->wlr_seat);
 | 
			
		||||
	if (keyboard) {
 | 
			
		||||
		wlr_seat_keyboard_notify_enter(seat->wlr_seat,
 | 
			
		||||
				layer->surface, keyboard->keycodes,
 | 
			
		||||
				keyboard->num_keycodes, &keyboard->modifiers);
 | 
			
		||||
	} else {
 | 
			
		||||
		wlr_seat_keyboard_notify_enter(seat->wlr_seat,
 | 
			
		||||
				layer->surface, NULL, 0, NULL);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void seat_set_exclusive_client(struct sway_seat *seat,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue