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
|
@ -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
|
* 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,
|
* 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];
|
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 *workspace_output_next(
|
||||||
struct sway_workspace *current, bool create) {
|
struct sway_workspace *current, bool create) {
|
||||||
return workspace_output_prev_next_impl(current->output, 1, 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 *workspace_output_prev(
|
||||||
struct sway_workspace *current, bool create) {
|
struct sway_workspace *current, bool create) {
|
||||||
return workspace_output_prev_next_impl(current->output, -1, 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 workspace_switch(struct sway_workspace *workspace,
|
||||||
bool no_auto_back_and_forth) {
|
bool no_auto_back_and_forth) {
|
||||||
struct sway_seat *seat = input_manager_current_seat();
|
struct sway_seat *seat = input_manager_current_seat();
|
||||||
|
|
Loading…
Reference in a new issue