mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	Merge pull request #233 from sce/multiple_adjacent_outputs
output: Support multiple adjacent outputs.
This commit is contained in:
		
						commit
						6850174049
					
				
					 6 changed files with 169 additions and 51 deletions
				
			
		| 
						 | 
					@ -63,7 +63,7 @@ struct sway_container {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * The coordinates that this view appear at, relative to the output they
 | 
						 * The coordinates that this view appear at, relative to the output they
 | 
				
			||||||
	 * are located on.
 | 
						 * are located on (output containers have absolute coordinates).
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	double x, y;
 | 
						double x, y;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,16 @@
 | 
				
			||||||
#include "container.h"
 | 
					#include "container.h"
 | 
				
			||||||
#include "focus.h"
 | 
					#include "focus.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *output_by_name(const char* name);
 | 
					// Position is absolute coordinates on the edge where the adjacent output
 | 
				
			||||||
swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir);
 | 
					// should be searched for.
 | 
				
			||||||
 | 
					swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos);
 | 
				
			||||||
 | 
					swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir, const struct wlc_point *abs_pos, bool pick_closest);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Place absolute coordinates for given container into given wlc_point.
 | 
				
			||||||
 | 
					void get_absolute_position(swayc_t *container, struct wlc_point *point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Place absolute coordinates for the center point of given container into
 | 
				
			||||||
 | 
					// given wlc_point.
 | 
				
			||||||
 | 
					void get_absolute_center_position(swayc_t *container, struct wlc_point *point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -377,11 +377,13 @@ static struct cmd_results *cmd_focus(int argc, char **argv) {
 | 
				
			||||||
	struct cmd_results *error = NULL;
 | 
						struct cmd_results *error = NULL;
 | 
				
			||||||
	if (argc > 0 && strcasecmp(argv[0], "output") == 0) {
 | 
						if (argc > 0 && strcasecmp(argv[0], "output") == 0) {
 | 
				
			||||||
		swayc_t *output = NULL;
 | 
							swayc_t *output = NULL;
 | 
				
			||||||
 | 
							struct wlc_point abs_pos;
 | 
				
			||||||
 | 
							get_absolute_center_position(get_focused_container(&root_container), &abs_pos);
 | 
				
			||||||
		if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 2))) {
 | 
							if ((error = checkarg(argc, "focus", EXPECTED_EQUAL_TO, 2))) {
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
		} else if (!(output = output_by_name(argv[1]))) {
 | 
							} else if (!(output = output_by_name(argv[1], &abs_pos))) {
 | 
				
			||||||
			return cmd_results_new(CMD_FAILURE, "focus output",
 | 
								return cmd_results_new(CMD_FAILURE, "focus output",
 | 
				
			||||||
				"Can't find output with name/at direction %s", argv[1]);
 | 
									"Can't find output with name/at direction '%s' @ (%i,%i)", argv[1], abs_pos.x, abs_pos.y);
 | 
				
			||||||
		} else if (!workspace_switch(swayc_active_workspace_for(output))) {
 | 
							} else if (!workspace_switch(swayc_active_workspace_for(output))) {
 | 
				
			||||||
			return cmd_results_new(CMD_FAILURE, "focus output",
 | 
								return cmd_results_new(CMD_FAILURE, "focus output",
 | 
				
			||||||
				"Switching to workspace on output '%s' was blocked", argv[1]);
 | 
									"Switching to workspace on output '%s' was blocked", argv[1]);
 | 
				
			||||||
| 
						 | 
					@ -591,11 +593,13 @@ static struct cmd_results *cmd_move(int argc, char **argv) {
 | 
				
			||||||
		} else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) {
 | 
							} else if (strcasecmp(argv[1], "to") == 0 && strcasecmp(argv[2], "output") == 0) {
 | 
				
			||||||
			// move container to output x
 | 
								// move container to output x
 | 
				
			||||||
			swayc_t *output = NULL;
 | 
								swayc_t *output = NULL;
 | 
				
			||||||
 | 
								struct wlc_point abs_pos;
 | 
				
			||||||
 | 
								get_absolute_center_position(view, &abs_pos);
 | 
				
			||||||
			if (view->type != C_CONTAINER && view->type != C_VIEW) {
 | 
								if (view->type != C_CONTAINER && view->type != C_VIEW) {
 | 
				
			||||||
				return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views.");
 | 
									return cmd_results_new(CMD_FAILURE, "move", "Can only move containers and views.");
 | 
				
			||||||
			} else if (!(output = output_by_name(argv[3]))) {
 | 
								} else if (!(output = output_by_name(argv[3], &abs_pos))) {
 | 
				
			||||||
				return cmd_results_new(CMD_FAILURE, "move",
 | 
									return cmd_results_new(CMD_FAILURE, "move",
 | 
				
			||||||
					"Can't find output with name/direction '%s'", argv[3]);
 | 
										"Can't find output with name/direction '%s' @ (%i,%i)", argv[3], abs_pos.x, abs_pos.y);
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				swayc_t *container = get_focused_container(output);
 | 
									swayc_t *container = get_focused_container(output);
 | 
				
			||||||
				if (container->is_floating) {
 | 
									if (container->is_floating) {
 | 
				
			||||||
| 
						 | 
					@ -610,13 +614,15 @@ static struct cmd_results *cmd_move(int argc, char **argv) {
 | 
				
			||||||
	} else if (strcasecmp(argv[0], "workspace") == 0) {
 | 
						} else if (strcasecmp(argv[0], "workspace") == 0) {
 | 
				
			||||||
		// move workspace (to output x)
 | 
							// move workspace (to output x)
 | 
				
			||||||
		swayc_t *output = NULL;
 | 
							swayc_t *output = NULL;
 | 
				
			||||||
 | 
							struct wlc_point abs_pos;
 | 
				
			||||||
 | 
							get_absolute_center_position(view, &abs_pos);
 | 
				
			||||||
		if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) {
 | 
							if ((error = checkarg(argc, "move workspace", EXPECTED_EQUAL_TO, 4))) {
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
		} else if (strcasecmp(argv[1], "to") != 0 || strcasecmp(argv[2], "output") != 0) {
 | 
							} else if (strcasecmp(argv[1], "to") != 0 || strcasecmp(argv[2], "output") != 0) {
 | 
				
			||||||
			return cmd_results_new(CMD_INVALID, "move", expected_syntax);
 | 
								return cmd_results_new(CMD_INVALID, "move", expected_syntax);
 | 
				
			||||||
		} else if (!(output = output_by_name(argv[3]))) {
 | 
							} else if (!(output = output_by_name(argv[3], &abs_pos))) {
 | 
				
			||||||
			return cmd_results_new(CMD_FAILURE, "move workspace",
 | 
								return cmd_results_new(CMD_FAILURE, "move workspace",
 | 
				
			||||||
				"Can't find output with name/at direction '%s'", argv[3]);
 | 
									"Can't find output with name/direction '%s' @ (%i,%i)", argv[3], abs_pos.x, abs_pos.y);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (view->type == C_WORKSPACE) {
 | 
							if (view->type == C_WORKSPACE) {
 | 
				
			||||||
			// This probably means we're moving an empty workspace, but
 | 
								// This probably means we're moving an empty workspace, but
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -305,28 +305,39 @@ static bool handle_pointer_motion(wlc_handle handle, uint32_t time, const struct
 | 
				
			||||||
			!pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) {
 | 
								!pointer_state.left.held && !pointer_state.right.held && !pointer_state.scroll.held) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		swayc_t *output = swayc_active_output(), *adjacent = NULL;
 | 
							swayc_t *output = swayc_active_output(), *adjacent = NULL;
 | 
				
			||||||
 | 
							struct wlc_point abs_pos = *origin;
 | 
				
			||||||
 | 
							abs_pos.x += output->x;
 | 
				
			||||||
 | 
							abs_pos.y += output->y;
 | 
				
			||||||
		if (origin->x == 0) { // Left edge
 | 
							if (origin->x == 0) { // Left edge
 | 
				
			||||||
			if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT))) {
 | 
								if ((adjacent = swayc_adjacent_output(output, MOVE_LEFT, &abs_pos, false))) {
 | 
				
			||||||
				if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
									if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
				
			||||||
					new_origin.x = adjacent->width;
 | 
										new_origin.x = adjacent->width;
 | 
				
			||||||
 | 
										// adjust for differently aligned outputs (well, this is
 | 
				
			||||||
 | 
										// only correct when the two outputs have the same
 | 
				
			||||||
 | 
										// resolution or the same dpi I guess, it should take
 | 
				
			||||||
 | 
										// physical attributes into account)
 | 
				
			||||||
 | 
										new_origin.y += (output->y - adjacent->y);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if ((double)origin->x == output->width) { // Right edge
 | 
							} else if ((double)origin->x == output->width) { // Right edge
 | 
				
			||||||
			if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT))) {
 | 
								if ((adjacent = swayc_adjacent_output(output, MOVE_RIGHT, &abs_pos, false))) {
 | 
				
			||||||
				if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
									if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
				
			||||||
					new_origin.x = 0;
 | 
										new_origin.x = 0;
 | 
				
			||||||
 | 
										new_origin.y += (output->y - adjacent->y);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if (origin->y == 0) { // Top edge
 | 
							} else if (origin->y == 0) { // Top edge
 | 
				
			||||||
			if ((adjacent = swayc_adjacent_output(output, MOVE_UP))) {
 | 
								if ((adjacent = swayc_adjacent_output(output, MOVE_UP, &abs_pos, false))) {
 | 
				
			||||||
				if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
									if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
				
			||||||
					new_origin.y = adjacent->height;
 | 
										new_origin.y = adjacent->height;
 | 
				
			||||||
 | 
										new_origin.x += (output->x - adjacent->x);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if ((double)origin->y == output->height) { // Bottom edge
 | 
							} else if ((double)origin->y == output->height) { // Bottom edge
 | 
				
			||||||
			if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN))) {
 | 
								if ((adjacent = swayc_adjacent_output(output, MOVE_DOWN, &abs_pos, false))) {
 | 
				
			||||||
				if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
									if (workspace_switch(swayc_active_workspace_for(adjacent))) {
 | 
				
			||||||
					new_origin.y = 0;
 | 
										new_origin.y = 0;
 | 
				
			||||||
 | 
										new_origin.x += (output->x - adjacent->x);
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -533,13 +533,17 @@ swayc_t *get_swayc_in_direction_under(swayc_t *container, enum movement_directio
 | 
				
			||||||
			return parent;
 | 
								return parent;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// If moving to an adjacent output we need a starting position (since this
 | 
				
			||||||
 | 
						// output might border to multiple outputs).
 | 
				
			||||||
 | 
						struct wlc_point abs_pos;
 | 
				
			||||||
 | 
						get_absolute_center_position(container, &abs_pos);
 | 
				
			||||||
	while (true) {
 | 
						while (true) {
 | 
				
			||||||
		// Test if we can even make a difference here
 | 
							// Test if we can even make a difference here
 | 
				
			||||||
		bool can_move = false;
 | 
							bool can_move = false;
 | 
				
			||||||
		int diff = 0;
 | 
							int diff = 0;
 | 
				
			||||||
		if (parent->type == C_ROOT) {
 | 
							if (parent->type == C_ROOT) {
 | 
				
			||||||
			sway_log(L_DEBUG, "Moving between outputs");
 | 
								sway_log(L_DEBUG, "Moving between outputs");
 | 
				
			||||||
			return swayc_adjacent_output(container, dir);
 | 
								return swayc_adjacent_output(container, dir, &abs_pos, true);
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
 | 
								if (dir == MOVE_LEFT || dir == MOVE_RIGHT) {
 | 
				
			||||||
				if (parent->layout == L_HORIZ) {
 | 
									if (parent->layout == L_HORIZ) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										162
									
								
								sway/output.c
									
										
									
									
									
								
							
							
						
						
									
										162
									
								
								sway/output.c
									
										
									
									
									
								
							| 
						 | 
					@ -2,15 +2,15 @@
 | 
				
			||||||
#include "output.h"
 | 
					#include "output.h"
 | 
				
			||||||
#include "log.h"
 | 
					#include "log.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *output_by_name(const char* name) {
 | 
					swayc_t *output_by_name(const char* name, const struct wlc_point *abs_pos) {
 | 
				
			||||||
	if (strcasecmp(name, "left") == 0) {
 | 
						if (strcasecmp(name, "left") == 0) {
 | 
				
			||||||
		return swayc_adjacent_output(NULL, MOVE_LEFT);
 | 
							return swayc_adjacent_output(NULL, MOVE_LEFT, abs_pos, true);
 | 
				
			||||||
	} else if (strcasecmp(name, "right") == 0) {
 | 
						} else if (strcasecmp(name, "right") == 0) {
 | 
				
			||||||
		return swayc_adjacent_output(NULL, MOVE_RIGHT);
 | 
							return swayc_adjacent_output(NULL, MOVE_RIGHT, abs_pos, true);
 | 
				
			||||||
	} else if (strcasecmp(name, "up") == 0) {
 | 
						} else if (strcasecmp(name, "up") == 0) {
 | 
				
			||||||
		return swayc_adjacent_output(NULL, MOVE_UP);
 | 
							return swayc_adjacent_output(NULL, MOVE_UP, abs_pos, true);
 | 
				
			||||||
	} else if (strcasecmp(name, "down") == 0) {
 | 
						} else if (strcasecmp(name, "down") == 0) {
 | 
				
			||||||
		return swayc_adjacent_output(NULL, MOVE_DOWN);
 | 
							return swayc_adjacent_output(NULL, MOVE_DOWN, abs_pos, true);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		for(int i = 0; i < root_container.children->length; ++i) {
 | 
							for(int i = 0; i < root_container.children->length; ++i) {
 | 
				
			||||||
			swayc_t *c = root_container.children->items[i];
 | 
								swayc_t *c = root_container.children->items[i];
 | 
				
			||||||
| 
						 | 
					@ -22,65 +22,125 @@ swayc_t *output_by_name(const char* name) {
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir) {
 | 
					// Position is where on the edge (as absolute position) the adjacent output should be searched for.
 | 
				
			||||||
	// TODO: This implementation is naïve: We assume all outputs are
 | 
					swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir,
 | 
				
			||||||
	// perfectly aligned (ie. only a single output per edge which covers
 | 
							const struct wlc_point *abs_pos, bool pick_closest) {
 | 
				
			||||||
	// the whole edge).
 | 
					
 | 
				
			||||||
	if (!output) {
 | 
						if (!output) {
 | 
				
			||||||
		output = swayc_active_output();
 | 
							output = swayc_active_output();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// In order to find adjacent outputs we need to test that the outputs are
 | 
				
			||||||
 | 
						// aligned on one axis (decided by the direction given) and that the given
 | 
				
			||||||
 | 
						// position is within the edge of the adjacent output. If no such output
 | 
				
			||||||
 | 
						// exists we pick the adjacent output within the edge that is closest to
 | 
				
			||||||
 | 
						// the given position, if any.
 | 
				
			||||||
	swayc_t *adjacent = NULL;
 | 
						swayc_t *adjacent = NULL;
 | 
				
			||||||
 | 
						char *dir_text = NULL;
 | 
				
			||||||
	switch(dir) {
 | 
						switch(dir) {
 | 
				
			||||||
		case MOVE_LEFT:
 | 
							case MOVE_LEFT:
 | 
				
			||||||
 | 
							case MOVE_RIGHT: ;
 | 
				
			||||||
 | 
								double delta_y = 0;
 | 
				
			||||||
			for(int i = 0; i < root_container.children->length; ++i) {
 | 
								for(int i = 0; i < root_container.children->length; ++i) {
 | 
				
			||||||
				swayc_t *c = root_container.children->items[i];
 | 
									swayc_t *c = root_container.children->items[i];
 | 
				
			||||||
				if (c == output || c->type != C_OUTPUT) {
 | 
									if (c == output || c->type != C_OUTPUT) {
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (c->y == output->y && c->x + c->width == output->x) {
 | 
									bool x_aligned = dir == MOVE_LEFT ?
 | 
				
			||||||
					sway_log(L_DEBUG, "%s is left of current output %s", c->name, output->name);
 | 
										c->x + c->width == output->x :
 | 
				
			||||||
 | 
										c->x == output->x + output->width;
 | 
				
			||||||
 | 
									if (!x_aligned) {
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (abs_pos->y >= c->y && abs_pos->y <= c->y + c->height) {
 | 
				
			||||||
 | 
										delta_y = 0;
 | 
				
			||||||
					adjacent = c;
 | 
										adjacent = c;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
 | 
									} else if (pick_closest) {
 | 
				
			||||||
 | 
										// track closest adjacent output
 | 
				
			||||||
 | 
										double top_y = c->y, bottom_y = c->y + c->height;
 | 
				
			||||||
 | 
										if (top_y >= output->y && top_y <= output->y + output->height) {
 | 
				
			||||||
 | 
											double delta = top_y - abs_pos->y;
 | 
				
			||||||
 | 
											if (delta < 0) delta = -delta;
 | 
				
			||||||
 | 
											if (delta < delta_y || !adjacent) {
 | 
				
			||||||
 | 
												delta_y = delta;
 | 
				
			||||||
 | 
												adjacent = c;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										// we check both points and pick the closest
 | 
				
			||||||
 | 
										if (bottom_y >= output->y && bottom_y <= output->y + output->height) {
 | 
				
			||||||
 | 
											double delta = bottom_y - abs_pos->y;
 | 
				
			||||||
 | 
											if (delta < 0) delta = -delta;
 | 
				
			||||||
 | 
											if (delta < delta_y || !adjacent) {
 | 
				
			||||||
 | 
												delta_y = delta;
 | 
				
			||||||
 | 
												adjacent = c;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								dir_text = dir == MOVE_LEFT ? "left of" : "right of";
 | 
				
			||||||
		case MOVE_RIGHT:
 | 
								if (adjacent && delta_y == 0) {
 | 
				
			||||||
			for(int i = 0; i < root_container.children->length; ++i) {
 | 
									sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (y-position %i)",
 | 
				
			||||||
				swayc_t *c = root_container.children->items[i];
 | 
											adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y,
 | 
				
			||||||
				if (c == output || c->type != C_OUTPUT) {
 | 
											dir_text, output->name, abs_pos->y);
 | 
				
			||||||
					continue;
 | 
								} else if (adjacent) {
 | 
				
			||||||
				}
 | 
									// so we end up picking the closest adjacent output because
 | 
				
			||||||
				if (c->y == output->y && output->x + output->width == c->x) {
 | 
									// there is no directly adjacent to the given position
 | 
				
			||||||
					sway_log(L_DEBUG, "%s is right of current output %s", c->name, output->name);
 | 
									sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (y-position %i, delta: %.0f)",
 | 
				
			||||||
					adjacent = c;
 | 
										adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y,
 | 
				
			||||||
					break;
 | 
										dir_text, output->name, abs_pos->y, delta_y);
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case MOVE_UP:
 | 
							case MOVE_UP:
 | 
				
			||||||
 | 
							case MOVE_DOWN: ;
 | 
				
			||||||
 | 
								double delta_x = 0;
 | 
				
			||||||
			for(int i = 0; i < root_container.children->length; ++i) {
 | 
								for(int i = 0; i < root_container.children->length; ++i) {
 | 
				
			||||||
				swayc_t *c = root_container.children->items[i];
 | 
									swayc_t *c = root_container.children->items[i];
 | 
				
			||||||
				if (c == output || c->type != C_OUTPUT) {
 | 
									if (c == output || c->type != C_OUTPUT) {
 | 
				
			||||||
					continue;
 | 
										continue;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (output->x == c->x && c->y + c->height == output->y) {
 | 
									bool y_aligned = dir == MOVE_UP ?
 | 
				
			||||||
					sway_log(L_DEBUG, "%s is above current output %s", c->name, output->name);
 | 
										c->y + c->height == output->y :
 | 
				
			||||||
 | 
										c->y == output->y + output->height;
 | 
				
			||||||
 | 
									if (!y_aligned) {
 | 
				
			||||||
 | 
										continue;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if (abs_pos->x >= c->x && abs_pos->x <= c->x + c->width) {
 | 
				
			||||||
 | 
										delta_x = 0;
 | 
				
			||||||
					adjacent = c;
 | 
										adjacent = c;
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
 | 
									} else if (pick_closest) {
 | 
				
			||||||
 | 
										// track closest adjacent output
 | 
				
			||||||
 | 
										double left_x = c->x, right_x = c->x + c->width;
 | 
				
			||||||
 | 
										if (left_x >= output->x && left_x <= output->x + output->width) {
 | 
				
			||||||
 | 
											double delta = left_x - abs_pos->x;
 | 
				
			||||||
 | 
											if (delta < 0) delta = -delta;
 | 
				
			||||||
 | 
											if (delta < delta_x || !adjacent) {
 | 
				
			||||||
 | 
												delta_x = delta;
 | 
				
			||||||
 | 
												adjacent = c;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										// we check both points and pick the closest
 | 
				
			||||||
 | 
										if (right_x >= output->x && right_x <= output->x + output->width) {
 | 
				
			||||||
 | 
											double delta = right_x - abs_pos->x;
 | 
				
			||||||
 | 
											if (delta < 0) delta = -delta;
 | 
				
			||||||
 | 
											if (delta < delta_x || !adjacent) {
 | 
				
			||||||
 | 
												delta_x = delta;
 | 
				
			||||||
 | 
												adjacent = c;
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								dir_text = dir == MOVE_UP ? "above" : "below";
 | 
				
			||||||
		case MOVE_DOWN:
 | 
								if (adjacent && delta_x == 0) {
 | 
				
			||||||
			for(int i = 0; i < root_container.children->length; ++i) {
 | 
									sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (x-position %i)",
 | 
				
			||||||
				swayc_t *c = root_container.children->items[i];
 | 
											adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y,
 | 
				
			||||||
				if (c == output || c->type != C_OUTPUT) {
 | 
											dir_text, output->name, abs_pos->x);
 | 
				
			||||||
					continue;
 | 
								} else if (adjacent) {
 | 
				
			||||||
				}
 | 
									// so we end up picking the closest adjacent output because
 | 
				
			||||||
				if (output->x == c->x && output->y + output->height == c->y) {
 | 
									// there is no directly adjacent to the given position
 | 
				
			||||||
					sway_log(L_DEBUG, "%s is below current output %s", c->name, output->name);
 | 
									sway_log(L_DEBUG, "%s (%.0fx%.0f+%.0f+%.0f) is %s current output %s (x-position %i, delta: %.0f)",
 | 
				
			||||||
					adjacent = c;
 | 
										adjacent->name, adjacent->width, adjacent->height, adjacent->x, adjacent->y,
 | 
				
			||||||
					break;
 | 
										dir_text, output->name, abs_pos->x, delta_x);
 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
| 
						 | 
					@ -89,3 +149,31 @@ swayc_t *swayc_adjacent_output(swayc_t *output, enum movement_direction dir) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return adjacent;
 | 
						return adjacent;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void get_absolute_position(swayc_t *container, struct wlc_point *point) {
 | 
				
			||||||
 | 
						if (!container || !point)
 | 
				
			||||||
 | 
							sway_abort("Need container and wlc_point (was %p, %p).", container, point);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (container->type == C_OUTPUT) {
 | 
				
			||||||
 | 
							// Coordinates are already absolute.
 | 
				
			||||||
 | 
							point->x = container->x;
 | 
				
			||||||
 | 
							point->y = container->y;
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							swayc_t *output = swayc_parent_by_type(container, C_OUTPUT);
 | 
				
			||||||
 | 
							if (container->type == C_WORKSPACE) {
 | 
				
			||||||
 | 
								// Workspace coordinates are actually wrong/arbitrary, but should
 | 
				
			||||||
 | 
								// be same as output.
 | 
				
			||||||
 | 
								point->x = output->x;
 | 
				
			||||||
 | 
								point->y = output->y;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								point->x = output->x + container->x;
 | 
				
			||||||
 | 
								point->y = output->y + container->y;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void get_absolute_center_position(swayc_t *container, struct wlc_point *point) {
 | 
				
			||||||
 | 
						get_absolute_position(container, point);
 | 
				
			||||||
 | 
						point->x += container->width/2;
 | 
				
			||||||
 | 
						point->y += container->height/2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue