mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	text_input: Move popup placement to own function
(cherry picked from commit 1537c9dae5)
			
			
This commit is contained in:
		
							parent
							
								
									5a920c48d1
								
							
						
					
					
						commit
						af782c17bb
					
				
					 2 changed files with 84 additions and 69 deletions
				
			
		| 
						 | 
					@ -9,6 +9,7 @@ struct sway_input_popup {
 | 
				
			||||||
	struct wlr_scene_tree *scene_tree;
 | 
						struct wlr_scene_tree *scene_tree;
 | 
				
			||||||
	struct sway_popup_desc desc;
 | 
						struct sway_popup_desc desc;
 | 
				
			||||||
	struct wlr_input_popup_surface_v2 *popup_surface;
 | 
						struct wlr_input_popup_surface_v2 *popup_surface;
 | 
				
			||||||
 | 
						struct wlr_output *fixed_output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wl_list link;
 | 
						struct wl_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -128,6 +128,80 @@ static void handle_im_destroy(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void constrain_popup(struct sway_input_popup *popup) {
 | 
				
			||||||
 | 
						struct sway_text_input *text_input =
 | 
				
			||||||
 | 
							relay_get_focused_text_input(popup->relay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_box parent = {0};
 | 
				
			||||||
 | 
						wlr_scene_node_coords(&popup->desc.relative->parent->node, &parent.x, &parent.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_box geo = {0};
 | 
				
			||||||
 | 
						struct wlr_output *output;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (popup->desc.view) {
 | 
				
			||||||
 | 
							struct sway_view *view = popup->desc.view;
 | 
				
			||||||
 | 
							output = wlr_output_layout_output_at(root->output_layout,
 | 
				
			||||||
 | 
								view->container->pending.content_x + view->geometry.x,
 | 
				
			||||||
 | 
								view->container->pending.content_y + view->geometry.y);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							parent.width = view->geometry.width;
 | 
				
			||||||
 | 
							parent.height = view->geometry.height;
 | 
				
			||||||
 | 
							geo = view->geometry;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							output = popup->fixed_output;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_box output_box;
 | 
				
			||||||
 | 
						wlr_output_layout_get_box(root->output_layout, output, &output_box);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bool cursor_rect = text_input->input->current.features &
 | 
				
			||||||
 | 
							WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE;
 | 
				
			||||||
 | 
						struct wlr_box cursor_area;
 | 
				
			||||||
 | 
						if (cursor_rect) {
 | 
				
			||||||
 | 
							cursor_area = text_input->input->current.cursor_rectangle;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							cursor_area = (struct wlr_box) {
 | 
				
			||||||
 | 
								.width = parent.width,
 | 
				
			||||||
 | 
								.height = parent.height,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int popup_width = popup->popup_surface->surface->current.width;
 | 
				
			||||||
 | 
						int popup_height = popup->popup_surface->surface->current.height;
 | 
				
			||||||
 | 
						int x1 = parent.x + cursor_area.x;
 | 
				
			||||||
 | 
						int x2 = parent.x + cursor_area.x + cursor_area.width;
 | 
				
			||||||
 | 
						int y1 = parent.y + cursor_area.y;
 | 
				
			||||||
 | 
						int y2 = parent.y + cursor_area.y + cursor_area.height;
 | 
				
			||||||
 | 
						int x = x1;
 | 
				
			||||||
 | 
						int y = y2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int available_right = output_box.x + output_box.width - x1;
 | 
				
			||||||
 | 
						int available_left = x2 - output_box.x;
 | 
				
			||||||
 | 
						if (available_right < popup_width && available_left > available_right) {
 | 
				
			||||||
 | 
							x = x2 - popup_width;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int available_down = output_box.y + output_box.height - y2;
 | 
				
			||||||
 | 
						int available_up = y1 - output_box.y;
 | 
				
			||||||
 | 
						if (available_down < popup_height && available_up > available_down) {
 | 
				
			||||||
 | 
							y = y1 - popup_height;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_scene_node_set_position(popup->desc.relative, x - parent.x - geo.x, y - parent.y - geo.y);
 | 
				
			||||||
 | 
						if (cursor_rect) {
 | 
				
			||||||
 | 
							struct wlr_box box = {
 | 
				
			||||||
 | 
								.x = x1 - x,
 | 
				
			||||||
 | 
								.y = y1 - y,
 | 
				
			||||||
 | 
								.width = cursor_area.width,
 | 
				
			||||||
 | 
								.height = cursor_area.height,
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
							wlr_input_popup_surface_v2_send_text_input_rectangle(
 | 
				
			||||||
 | 
								popup->popup_surface, &box);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						wlr_scene_node_set_position(&popup->scene_tree->node, x - geo.x, y - geo.y);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void relay_send_im_state(struct sway_input_method_relay *relay,
 | 
					static void relay_send_im_state(struct sway_input_method_relay *relay,
 | 
				
			||||||
		struct wlr_text_input_v3 *input) {
 | 
							struct wlr_text_input_v3 *input) {
 | 
				
			||||||
	struct wlr_input_method_v2 *input_method = relay->input_method;
 | 
						struct wlr_input_method_v2 *input_method = relay->input_method;
 | 
				
			||||||
| 
						 | 
					@ -150,8 +224,7 @@ static void relay_send_im_state(struct sway_input_method_relay *relay,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	struct sway_input_popup *popup;
 | 
						struct sway_input_popup *popup;
 | 
				
			||||||
	wl_list_for_each(popup, &relay->input_popups, link) {
 | 
						wl_list_for_each(popup, &relay->input_popups, link) {
 | 
				
			||||||
		// send_text_input_rectangle is called in this function
 | 
							constrain_popup(popup);
 | 
				
			||||||
		input_popup_update(popup);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	wlr_input_method_v2_send_done(input_method);
 | 
						wlr_input_method_v2_send_done(input_method);
 | 
				
			||||||
	// TODO: pass intent, display popup size
 | 
						// TODO: pass intent, display popup size
 | 
				
			||||||
| 
						 | 
					@ -297,50 +370,30 @@ static void input_popup_update(struct sway_input_popup *popup) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool cursor_rect = text_input->input->current.features
 | 
					 | 
				
			||||||
		& WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE;
 | 
					 | 
				
			||||||
	struct wlr_surface *focused_surface = text_input->input->focused_surface;
 | 
						struct wlr_surface *focused_surface = text_input->input->focused_surface;
 | 
				
			||||||
	struct wlr_box cursor_area = text_input->input->current.cursor_rectangle;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_box output_box;
 | 
					 | 
				
			||||||
	struct wlr_box parent = {0};
 | 
					 | 
				
			||||||
	struct wlr_layer_surface_v1 *layer_surface =
 | 
						struct wlr_layer_surface_v1 *layer_surface =
 | 
				
			||||||
		wlr_layer_surface_v1_try_from_wlr_surface(focused_surface);
 | 
							wlr_layer_surface_v1_try_from_wlr_surface(focused_surface);
 | 
				
			||||||
	struct wlr_scene_tree *relative_parent;
 | 
						struct wlr_scene_tree *relative_parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct wlr_box geo = {0};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	popup->scene_tree = wlr_scene_subsurface_tree_create(root->layers.popup, popup->popup_surface->surface);
 | 
						popup->scene_tree = wlr_scene_subsurface_tree_create(root->layers.popup, popup->popup_surface->surface);
 | 
				
			||||||
	if (layer_surface != NULL) {
 | 
						if (layer_surface != NULL) {
 | 
				
			||||||
		struct sway_layer_surface *layer =
 | 
							struct sway_layer_surface *layer = layer_surface->data;
 | 
				
			||||||
			layer_surface->data;
 | 
					 | 
				
			||||||
		if (layer == NULL) {
 | 
							if (layer == NULL) {
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		relative_parent = layer->scene->tree;
 | 
							relative_parent = layer->scene->tree;
 | 
				
			||||||
		struct wlr_output *output = layer->layer_surface->output;
 | 
					 | 
				
			||||||
		wlr_output_layout_get_box(root->output_layout, output, &output_box);
 | 
					 | 
				
			||||||
		int lx, ly;
 | 
					 | 
				
			||||||
		wlr_scene_node_coords(&layer->tree->node, &lx, &ly);
 | 
					 | 
				
			||||||
		parent.x = lx;
 | 
					 | 
				
			||||||
		parent.y = ly;
 | 
					 | 
				
			||||||
		popup->desc.view = NULL;
 | 
							popup->desc.view = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// we don't need to add an event here to NULL out this field because
 | 
				
			||||||
 | 
							// this field will only be initialized if the popup is part of a layer
 | 
				
			||||||
 | 
							// surface. Layer surfaces get destroyed as part of the output being
 | 
				
			||||||
 | 
							// destroyed, thus also trickling down to popups.
 | 
				
			||||||
 | 
							popup->fixed_output = layer->layer_surface->output;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		struct sway_view *view = view_from_wlr_surface(focused_surface);
 | 
							struct sway_view *view = view_from_wlr_surface(focused_surface);
 | 
				
			||||||
		relative_parent = view->scene_tree;
 | 
							relative_parent = view->scene_tree;
 | 
				
			||||||
		geo = view->geometry;
 | 
					 | 
				
			||||||
		int lx, ly;
 | 
					 | 
				
			||||||
		wlr_scene_node_coords(&view->scene_tree->node, &lx, &ly);
 | 
					 | 
				
			||||||
		struct wlr_output *output = wlr_output_layout_output_at(root->output_layout,
 | 
					 | 
				
			||||||
			view->container->pending.content_x + view->geometry.x,
 | 
					 | 
				
			||||||
			view->container->pending.content_y + view->geometry.y);
 | 
					 | 
				
			||||||
		wlr_output_layout_get_box(root->output_layout, output, &output_box);
 | 
					 | 
				
			||||||
		parent.x = lx;
 | 
					 | 
				
			||||||
		parent.y = ly;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		parent.width = view->geometry.width;
 | 
					 | 
				
			||||||
		parent.height = view->geometry.height;
 | 
					 | 
				
			||||||
		popup->desc.view = view;
 | 
							popup->desc.view = view;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -354,46 +407,7 @@ static void input_popup_update(struct sway_input_popup *popup) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!cursor_rect) {
 | 
						constrain_popup(popup);
 | 
				
			||||||
		cursor_area.x = 0;
 | 
					 | 
				
			||||||
		cursor_area.y = 0;
 | 
					 | 
				
			||||||
		cursor_area.width = parent.width;
 | 
					 | 
				
			||||||
		cursor_area.height = parent.height;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int popup_width = popup->popup_surface->surface->current.width;
 | 
					 | 
				
			||||||
	int popup_height = popup->popup_surface->surface->current.height;
 | 
					 | 
				
			||||||
	int x1 = parent.x + cursor_area.x;
 | 
					 | 
				
			||||||
	int x2 = parent.x + cursor_area.x + cursor_area.width;
 | 
					 | 
				
			||||||
	int y1 = parent.y + cursor_area.y;
 | 
					 | 
				
			||||||
	int y2 = parent.y + cursor_area.y + cursor_area.height;
 | 
					 | 
				
			||||||
	int x = x1;
 | 
					 | 
				
			||||||
	int y = y2;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int available_right = output_box.x + output_box.width - x1;
 | 
					 | 
				
			||||||
	int available_left = x2 - output_box.x;
 | 
					 | 
				
			||||||
	if (available_right < popup_width && available_left > available_right) {
 | 
					 | 
				
			||||||
		x = x2 - popup_width;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	int available_down = output_box.y + output_box.height - y2;
 | 
					 | 
				
			||||||
	int available_up = y1 - output_box.y;
 | 
					 | 
				
			||||||
	if (available_down < popup_height && available_up > available_down) {
 | 
					 | 
				
			||||||
		y = y1 - popup_height;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	wlr_scene_node_set_position(&relative->node, x - parent.x - geo.x, y - parent.y - geo.y);
 | 
					 | 
				
			||||||
	if (cursor_rect) {
 | 
					 | 
				
			||||||
		struct wlr_box box = {
 | 
					 | 
				
			||||||
			.x = x1 - x,
 | 
					 | 
				
			||||||
			.y = y1 - y,
 | 
					 | 
				
			||||||
			.width = cursor_area.width,
 | 
					 | 
				
			||||||
			.height = cursor_area.height,
 | 
					 | 
				
			||||||
		};
 | 
					 | 
				
			||||||
		wlr_input_popup_surface_v2_send_text_input_rectangle(
 | 
					 | 
				
			||||||
			popup->popup_surface, &box);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	wlr_scene_node_set_position(&popup->scene_tree->node, x - geo.x, y - geo.y);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void input_popup_set_focus(struct sway_input_popup *popup,
 | 
					static void input_popup_set_focus(struct sway_input_popup *popup,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue