mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	workspace: rework workspace prev|next like i3
Changes workspace prev|next commands to visit each numbered or named workspace first before considering workspace from the other category
This commit is contained in:
		
							parent
							
								
									89ffeaae49
								
							
						
					
					
						commit
						5f1fe33d36
					
				
					 1 changed files with 142 additions and 34 deletions
				
			
		| 
						 | 
				
			
			@ -382,6 +382,148 @@ struct sway_workspace *workspace_by_name(const char *name) {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int workspace_get_number(struct sway_workspace *workspace) {
 | 
			
		||||
	char *endptr = NULL;
 | 
			
		||||
	errno = 0;
 | 
			
		||||
	long long n = strtoll(workspace->name, &endptr, 10);
 | 
			
		||||
	if (errno != 0 || n > INT32_MAX || n < 0 || endptr == workspace->name) {
 | 
			
		||||
		n = -1;
 | 
			
		||||
	}
 | 
			
		||||
	return n;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sway_workspace *workspace_prev(struct sway_workspace *workspace) {
 | 
			
		||||
	int n = workspace_get_number(workspace);
 | 
			
		||||
	struct sway_workspace *prev = NULL, *last = NULL, *other = NULL;
 | 
			
		||||
	bool found = false;
 | 
			
		||||
	if (n < 0) {
 | 
			
		||||
		// Find the prev named workspace
 | 
			
		||||
		int othern = -1;
 | 
			
		||||
		for (int i = root->outputs->length - 1; i >= 0; i--) {
 | 
			
		||||
			struct sway_output *output = root->outputs->items[i];
 | 
			
		||||
			for (int j = output->workspaces->length - 1; j >= 0; j--) {
 | 
			
		||||
				struct sway_workspace *ws = output->workspaces->items[j];
 | 
			
		||||
				int wsn = workspace_get_number(ws);
 | 
			
		||||
				if (!last) {
 | 
			
		||||
					// The first workspace in reverse order
 | 
			
		||||
					last = ws;
 | 
			
		||||
				}
 | 
			
		||||
				if (!other || (wsn >= 0 && wsn > othern)) {
 | 
			
		||||
					// The last (greatest) numbered workspace.
 | 
			
		||||
					other = ws;
 | 
			
		||||
					othern = workspace_get_number(other);
 | 
			
		||||
				}
 | 
			
		||||
				if (ws == workspace) {
 | 
			
		||||
					found = true;
 | 
			
		||||
				} else if (wsn < 0 && found) {
 | 
			
		||||
					// Found a non-numbered workspace before current
 | 
			
		||||
					return ws;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// Find the prev numbered workspace
 | 
			
		||||
		int prevn = -1, lastn = -1;
 | 
			
		||||
		for (int i = root->outputs->length - 1; i >= 0; i--) {
 | 
			
		||||
			struct sway_output *output = root->outputs->items[i];
 | 
			
		||||
			for (int j = output->workspaces->length - 1; j >= 0; j--) {
 | 
			
		||||
				struct sway_workspace *ws = output->workspaces->items[j];
 | 
			
		||||
				int wsn = workspace_get_number(ws);
 | 
			
		||||
				if (!last || (wsn >= 0 && wsn > lastn)) {
 | 
			
		||||
					// The greatest numbered (or last) workspace
 | 
			
		||||
					last = ws;
 | 
			
		||||
					lastn = workspace_get_number(last);
 | 
			
		||||
				}
 | 
			
		||||
				if (!other && wsn < 0) {
 | 
			
		||||
					// The last named workspace
 | 
			
		||||
					other = ws;
 | 
			
		||||
				}
 | 
			
		||||
				if (wsn < 0) {
 | 
			
		||||
					// Haven't reached the numbered workspaces
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				if (wsn < n && (!prev || wsn > prevn)) {
 | 
			
		||||
					// The closest workspace before the current
 | 
			
		||||
					prev = ws;
 | 
			
		||||
					prevn = workspace_get_number(prev);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!prev) {
 | 
			
		||||
		prev = other ? other : last;
 | 
			
		||||
	}
 | 
			
		||||
	return prev;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sway_workspace *workspace_next(struct sway_workspace *workspace) {
 | 
			
		||||
	int n = workspace_get_number(workspace);
 | 
			
		||||
	struct sway_workspace *next = NULL, *first = NULL, *other = NULL;
 | 
			
		||||
	bool found = false;
 | 
			
		||||
	if (n < 0) {
 | 
			
		||||
		// Find the next named workspace
 | 
			
		||||
		int othern = -1;
 | 
			
		||||
		for (int i = 0; i < root->outputs->length; i++) {
 | 
			
		||||
			struct sway_output *output = root->outputs->items[i];
 | 
			
		||||
			for (int j = 0; j < output->workspaces->length; j++) {
 | 
			
		||||
				struct sway_workspace *ws = output->workspaces->items[j];
 | 
			
		||||
				int wsn = workspace_get_number(ws);
 | 
			
		||||
				if (!first) {
 | 
			
		||||
					// The first named workspace
 | 
			
		||||
					first = ws;
 | 
			
		||||
				}
 | 
			
		||||
				if (!other || (wsn >= 0 && wsn < othern)) {
 | 
			
		||||
					// The first (least) numbered workspace
 | 
			
		||||
					other = ws;
 | 
			
		||||
					othern = workspace_get_number(other);
 | 
			
		||||
				}
 | 
			
		||||
				if (ws == workspace) {
 | 
			
		||||
					found = true;
 | 
			
		||||
				} else if (wsn < 0 && found) {
 | 
			
		||||
					// The first non-numbered workspace after the current
 | 
			
		||||
					return ws;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		// Find the next numbered workspace
 | 
			
		||||
		int nextn = -1, firstn = -1;
 | 
			
		||||
		for (int i = 0; i < root->outputs->length; i++) {
 | 
			
		||||
			struct sway_output *output = root->outputs->items[i];
 | 
			
		||||
			for (int j = 0; j < output->workspaces->length; j++) {
 | 
			
		||||
				struct sway_workspace *ws = output->workspaces->items[j];
 | 
			
		||||
				int wsn = workspace_get_number(ws);
 | 
			
		||||
				if (!first || (wsn >= 0 && wsn < firstn)) {
 | 
			
		||||
					// The first (or least numbered) workspace
 | 
			
		||||
					first = ws;
 | 
			
		||||
					firstn = workspace_get_number(first);
 | 
			
		||||
				}
 | 
			
		||||
				if (!other && wsn < 0) {
 | 
			
		||||
					// The first non-numbered workspace
 | 
			
		||||
					other = ws;
 | 
			
		||||
				}
 | 
			
		||||
				if (wsn < 0) {
 | 
			
		||||
					// Checked all the numbered workspaces
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				if (n < wsn && (!next || wsn < nextn)) {
 | 
			
		||||
					// The first workspace numerically after the current
 | 
			
		||||
					next = ws;
 | 
			
		||||
					nextn = workspace_get_number(next);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!next) {
 | 
			
		||||
		// If there is no next workspace from the same category, return the
 | 
			
		||||
		// first from this category.
 | 
			
		||||
		next = other ? other : first;
 | 
			
		||||
	}
 | 
			
		||||
	return next;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the previous or next workspace on the specified output. Wraps around at
 | 
			
		||||
 * the end and beginning.  If next is false, the previous workspace is returned,
 | 
			
		||||
| 
						 | 
				
			
			@ -409,50 +551,16 @@ static struct sway_workspace *workspace_output_prev_next_impl(
 | 
			
		|||
	return output->workspaces->items[new_index];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get the previous or next workspace. If the first/last workspace on an output
 | 
			
		||||
 * is active, proceed to the previous/next output's previous/next workspace.
 | 
			
		||||
 */
 | 
			
		||||
static struct sway_workspace *workspace_prev_next_impl(
 | 
			
		||||
		struct sway_workspace *workspace, int dir) {
 | 
			
		||||
	struct sway_output *output = workspace->output;
 | 
			
		||||
	int index = list_find(output->workspaces, workspace);
 | 
			
		||||
	int new_index = index + dir;
 | 
			
		||||
 | 
			
		||||
	if (new_index >= 0 && new_index < output->workspaces->length) {
 | 
			
		||||
		return output->workspaces->items[new_index];
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Look on a different output
 | 
			
		||||
	int output_index = list_find(root->outputs, output);
 | 
			
		||||
	new_index = wrap(output_index + dir, root->outputs->length);
 | 
			
		||||
	output = root->outputs->items[new_index];
 | 
			
		||||
 | 
			
		||||
	if (dir == 1) {
 | 
			
		||||
		return output->workspaces->items[0];
 | 
			
		||||
	} else {
 | 
			
		||||
		return output->workspaces->items[output->workspaces->length - 1];
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sway_workspace *workspace_output_next(
 | 
			
		||||
		struct sway_workspace *current, bool create) {
 | 
			
		||||
	return workspace_output_prev_next_impl(current->output, 1, create);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sway_workspace *workspace_next(struct sway_workspace *current) {
 | 
			
		||||
	return workspace_prev_next_impl(current, 1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sway_workspace *workspace_output_prev(
 | 
			
		||||
		struct sway_workspace *current, bool create) {
 | 
			
		||||
	return workspace_output_prev_next_impl(current->output, -1, create);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sway_workspace *workspace_prev(struct sway_workspace *current) {
 | 
			
		||||
	return workspace_prev_next_impl(current, -1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool workspace_switch(struct sway_workspace *workspace,
 | 
			
		||||
		bool no_auto_back_and_forth) {
 | 
			
		||||
	struct sway_seat *seat = input_manager_current_seat();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue