mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #2820 from Emantor/fix-mouse-warping-container
Fix mouse warping container
This commit is contained in:
		
						commit
						765c80e5f7
					
				
					 8 changed files with 102 additions and 68 deletions
				
			
		| 
						 | 
					@ -48,4 +48,9 @@ void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec,
 | 
				
			||||||
void cursor_set_image(struct sway_cursor *cursor, const char *image,
 | 
					void cursor_set_image(struct sway_cursor *cursor, const char *image,
 | 
				
			||||||
	struct wl_client *client);
 | 
						struct wl_client *client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cursor_warp_to_container(struct sway_cursor *cursor,
 | 
				
			||||||
 | 
						struct sway_container *container);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void cursor_warp_to_workspace(struct sway_cursor *cursor,
 | 
				
			||||||
 | 
							struct sway_workspace *workspace);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -329,7 +329,8 @@ void view_destroy(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_begin_destroy(struct sway_view *view);
 | 
					void view_begin_destroy(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface);
 | 
					void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
 | 
				
			||||||
 | 
						bool fullscreen, bool decoration);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_unmap(struct sway_view *view);
 | 
					void view_unmap(struct sway_view *view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -406,26 +406,18 @@ static void handle_map(struct wl_listener *listener, void *data) {
 | 
				
			||||||
		view->natural_height = view->wlr_xdg_surface->surface->current.height;
 | 
							view->natural_height = view->wlr_xdg_surface->surface->current.height;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	view_map(view, view->wlr_xdg_surface->surface);
 | 
						bool csd = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!view->xdg_decoration) {
 | 
						if (!view->xdg_decoration) {
 | 
				
			||||||
		struct sway_server_decoration *deco =
 | 
							struct sway_server_decoration *deco =
 | 
				
			||||||
				decoration_from_surface(xdg_surface->surface);
 | 
									decoration_from_surface(xdg_surface->surface);
 | 
				
			||||||
		bool csd = !deco || deco->wlr_server_decoration->mode ==
 | 
							csd = !deco || deco->wlr_server_decoration->mode ==
 | 
				
			||||||
			WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
 | 
								WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
 | 
				
			||||||
		view_update_csd_from_client(view, csd);
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (xdg_surface->toplevel->client_pending.fullscreen) {
 | 
						view_map(view, view->wlr_xdg_surface->surface,
 | 
				
			||||||
		container_set_fullscreen(view->container, true);
 | 
							xdg_surface->toplevel->client_pending.fullscreen, csd);
 | 
				
			||||||
		arrange_workspace(view->container->workspace);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if (view->container->parent) {
 | 
					 | 
				
			||||||
			arrange_container(view->container->parent);
 | 
					 | 
				
			||||||
		} else if (view->container->workspace) {
 | 
					 | 
				
			||||||
			arrange_workspace(view->container->workspace);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -402,25 +402,14 @@ static void handle_map(struct wl_listener *listener, void *data) {
 | 
				
			||||||
		view->natural_width = view->wlr_xdg_surface_v6->surface->current.width;
 | 
							view->natural_width = view->wlr_xdg_surface_v6->surface->current.width;
 | 
				
			||||||
		view->natural_height = view->wlr_xdg_surface_v6->surface->current.height;
 | 
							view->natural_height = view->wlr_xdg_surface_v6->surface->current.height;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					 | 
				
			||||||
	view_map(view, view->wlr_xdg_surface_v6->surface);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct sway_server_decoration *deco =
 | 
						struct sway_server_decoration *deco =
 | 
				
			||||||
			decoration_from_surface(xdg_surface->surface);
 | 
								decoration_from_surface(xdg_surface->surface);
 | 
				
			||||||
	bool csd = !deco || deco->wlr_server_decoration->mode ==
 | 
						bool csd = !deco || deco->wlr_server_decoration->mode
 | 
				
			||||||
			WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
 | 
							== WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT;
 | 
				
			||||||
	view_update_csd_from_client(view, csd);
 | 
					
 | 
				
			||||||
 | 
						view_map(view, view->wlr_xdg_surface_v6->surface,
 | 
				
			||||||
 | 
							xdg_surface->toplevel->client_pending.fullscreen, csd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (xdg_surface->toplevel->client_pending.fullscreen) {
 | 
					 | 
				
			||||||
		container_set_fullscreen(view->container, true);
 | 
					 | 
				
			||||||
		arrange_workspace(view->container->workspace);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if (view->container->parent) {
 | 
					 | 
				
			||||||
			arrange_container(view->container->parent);
 | 
					 | 
				
			||||||
		} else if (view->container->workspace) {
 | 
					 | 
				
			||||||
			arrange_workspace(view->container->workspace);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	xdg_shell_v6_view->commit.notify = handle_commit;
 | 
						xdg_shell_v6_view->commit.notify = handle_commit;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -405,18 +405,8 @@ static void handle_map(struct wl_listener *listener, void *data) {
 | 
				
			||||||
	xwayland_view->commit.notify = handle_commit;
 | 
						xwayland_view->commit.notify = handle_commit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Put it back into the tree
 | 
						// Put it back into the tree
 | 
				
			||||||
	view_map(view, xsurface->surface);
 | 
						view_map(view, xsurface->surface, xsurface->fullscreen, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (xsurface->fullscreen) {
 | 
					 | 
				
			||||||
		container_set_fullscreen(view->container, true);
 | 
					 | 
				
			||||||
		arrange_workspace(view->container->workspace);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		if (view->container->parent) {
 | 
					 | 
				
			||||||
			arrange_container(view->container->parent);
 | 
					 | 
				
			||||||
		} else if (view->container->workspace) {
 | 
					 | 
				
			||||||
			arrange_workspace(view->container->workspace);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include <wlr/types/wlr_cursor.h>
 | 
					#include <wlr/types/wlr_cursor.h>
 | 
				
			||||||
#include <wlr/types/wlr_xcursor_manager.h>
 | 
					#include <wlr/types/wlr_xcursor_manager.h>
 | 
				
			||||||
#include <wlr/types/wlr_idle.h>
 | 
					#include <wlr/types/wlr_idle.h>
 | 
				
			||||||
 | 
					#include <wlr/types/wlr_box.h>
 | 
				
			||||||
#include "list.h"
 | 
					#include "list.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
#include "config.h"
 | 
					#include "config.h"
 | 
				
			||||||
| 
						 | 
					@ -1271,4 +1272,44 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
 | 
				
			||||||
	cursor->cursor = wlr_cursor;
 | 
						cursor->cursor = wlr_cursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return cursor;
 | 
						return cursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Warps the cursor to the middle of the container argument.
 | 
				
			||||||
 | 
					 * Does nothing if the cursor is already inside the container.
 | 
				
			||||||
 | 
					 * If container is NULL, returns without doing anything.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void cursor_warp_to_container(struct sway_cursor *cursor,
 | 
				
			||||||
 | 
							struct sway_container *container) {
 | 
				
			||||||
 | 
						if (!container) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct wlr_box box;
 | 
				
			||||||
 | 
						container_get_box(container, &box);
 | 
				
			||||||
 | 
						if (wlr_box_contains_point(&box, cursor->cursor->x, cursor->cursor->y)) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double x = container->x + container->width / 2.0;
 | 
				
			||||||
 | 
						double y = container->y + container->height / 2.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_cursor_warp(cursor->cursor, NULL, x, y);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Warps the cursor to the middle of the workspace argument.
 | 
				
			||||||
 | 
					 * If workspace is NULL, returns without doing anything.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void cursor_warp_to_workspace(struct sway_cursor *cursor,
 | 
				
			||||||
 | 
							struct sway_workspace *workspace) {
 | 
				
			||||||
 | 
						if (!workspace) {
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						double x = workspace->x + workspace->width / 2.0;
 | 
				
			||||||
 | 
						double y = workspace->y + workspace->height / 2.0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wlr_cursor_warp(cursor->cursor, NULL, x, y);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -774,27 +774,18 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node,
 | 
				
			||||||
		workspace_consider_destroy(last_workspace);
 | 
							workspace_consider_destroy(last_workspace);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (last_focus) {
 | 
						if (last_focus && warp) {
 | 
				
			||||||
		if (config->mouse_warping && warp &&
 | 
							if (container && config->mouse_warping == WARP_CONTAINER) {
 | 
				
			||||||
				(new_output != last_output ||
 | 
								cursor_warp_to_container(seat->cursor, container);
 | 
				
			||||||
				config->mouse_warping == WARP_CONTAINER)) {
 | 
					 | 
				
			||||||
			double x = 0;
 | 
					 | 
				
			||||||
			double y = 0;
 | 
					 | 
				
			||||||
			if (container) {
 | 
					 | 
				
			||||||
				x = container->x + container->width / 2.0;
 | 
					 | 
				
			||||||
				y = container->y + container->height / 2.0;
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				x = new_workspace->x + new_workspace->width / 2.0;
 | 
					 | 
				
			||||||
				y = new_workspace->y + new_workspace->height / 2.0;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (!wlr_output_layout_contains_point(root->output_layout,
 | 
					 | 
				
			||||||
					new_output->wlr_output, seat->cursor->cursor->x,
 | 
					 | 
				
			||||||
					seat->cursor->cursor->y)
 | 
					 | 
				
			||||||
					|| config->mouse_warping == WARP_CONTAINER) {
 | 
					 | 
				
			||||||
				wlr_cursor_warp(seat->cursor->cursor, NULL, x, y);
 | 
					 | 
				
			||||||
			cursor_send_pointer_motion(seat->cursor, 0, true);
 | 
								cursor_send_pointer_motion(seat->cursor, 0, true);
 | 
				
			||||||
 | 
							} else if (new_output != last_output &&
 | 
				
			||||||
 | 
									   config->mouse_warping >= WARP_OUTPUT) {
 | 
				
			||||||
 | 
								if (container) {
 | 
				
			||||||
 | 
									cursor_warp_to_container(seat->cursor, container);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									cursor_warp_to_workspace(seat->cursor, new_workspace);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								cursor_send_pointer_motion(seat->cursor, 0, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -544,7 +544,8 @@ static bool should_focus(struct sway_view *view) {
 | 
				
			||||||
	return len == 0;
 | 
						return len == 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
 | 
					void view_map(struct sway_view *view, struct wlr_surface *wlr_surface,
 | 
				
			||||||
 | 
								  bool fullscreen, bool decoration) {
 | 
				
			||||||
	if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
 | 
						if (!sway_assert(view->surface == NULL, "cannot map mapped view")) {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -595,13 +596,28 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (should_focus(view)) {
 | 
					 | 
				
			||||||
		input_manager_set_focus(input_manager, &view->container->node);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	view_update_title(view, false);
 | 
						view_update_title(view, false);
 | 
				
			||||||
	container_update_representation(view->container);
 | 
						container_update_representation(view->container);
 | 
				
			||||||
	view_execute_criteria(view);
 | 
						view_execute_criteria(view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (decoration) {
 | 
				
			||||||
 | 
							view_update_csd_from_client(view, decoration);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (fullscreen) {
 | 
				
			||||||
 | 
							container_set_fullscreen(view->container, true);
 | 
				
			||||||
 | 
							arrange_workspace(view->container->workspace);
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (view->container->parent) {
 | 
				
			||||||
 | 
								arrange_container(view->container->parent);
 | 
				
			||||||
 | 
							} else if (view->container->workspace) {
 | 
				
			||||||
 | 
								arrange_workspace(view->container->workspace);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (should_focus(view)) {
 | 
				
			||||||
 | 
							input_manager_set_focus(input_manager, &view->container->node);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void view_unmap(struct sway_view *view) {
 | 
					void view_unmap(struct sway_view *view) {
 | 
				
			||||||
| 
						 | 
					@ -630,8 +646,17 @@ void view_unmap(struct sway_view *view) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct sway_seat *seat;
 | 
						struct sway_seat *seat;
 | 
				
			||||||
	wl_list_for_each(seat, &input_manager->seats, link) {
 | 
						wl_list_for_each(seat, &input_manager->seats, link) {
 | 
				
			||||||
 | 
							if (config->mouse_warping == WARP_CONTAINER) {
 | 
				
			||||||
 | 
								struct sway_node *node = seat_get_focus(seat);
 | 
				
			||||||
 | 
								if (node && node->type == N_CONTAINER) {
 | 
				
			||||||
 | 
									cursor_warp_to_container(seat->cursor, node->sway_container);
 | 
				
			||||||
 | 
								} else if (node && node->type == N_WORKSPACE) {
 | 
				
			||||||
 | 
									cursor_warp_to_workspace(seat->cursor, node->sway_workspace);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
			cursor_send_pointer_motion(seat->cursor, 0, true);
 | 
								cursor_send_pointer_motion(seat->cursor, 0, true);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	transaction_commit_dirty();
 | 
						transaction_commit_dirty();
 | 
				
			||||||
	view->surface = NULL;
 | 
						view->surface = NULL;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue