aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ronan Pigott <rpigott@berkeley.edu>2020-12-04 19:56:51 -0700
committerLibravatar Tudor Brindus <me@tbrindus.ca>2020-12-20 00:58:42 -0500
commit5f1fe33d369b88539c9fb434703c1c00cd26c903 (patch)
treec59850f93654d8916226c9402409efdd0871af61
parentcommands/move: reset geometry of promoted containers (diff)
downloadsway-5f1fe33d369b88539c9fb434703c1c00cd26c903.tar.gz
sway-5f1fe33d369b88539c9fb434703c1c00cd26c903.tar.zst
sway-5f1fe33d369b88539c9fb434703c1c00cd26c903.zip
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
-rw-r--r--sway/tree/workspace.c176
1 files changed, 142 insertions, 34 deletions
diff --git a/sway/tree/workspace.c b/sway/tree/workspace.c
index 62549434..921b7d19 100644
--- a/sway/tree/workspace.c
+++ b/sway/tree/workspace.c
@@ -382,6 +382,148 @@ struct sway_workspace *workspace_by_name(const char *name) {
382 } 382 }
383} 383}
384 384
385static int workspace_get_number(struct sway_workspace *workspace) {
386 char *endptr = NULL;
387 errno = 0;
388 long long n = strtoll(workspace->name, &endptr, 10);
389 if (errno != 0 || n > INT32_MAX || n < 0 || endptr == workspace->name) {
390 n = -1;
391 }
392 return n;
393}
394
395struct sway_workspace *workspace_prev(struct sway_workspace *workspace) {
396 int n = workspace_get_number(workspace);
397 struct sway_workspace *prev = NULL, *last = NULL, *other = NULL;
398 bool found = false;
399 if (n < 0) {
400 // Find the prev named workspace
401 int othern = -1;
402 for (int i = root->outputs->length - 1; i >= 0; i--) {
403 struct sway_output *output = root->outputs->items[i];
404 for (int j = output->workspaces->length - 1; j >= 0; j--) {
405 struct sway_workspace *ws = output->workspaces->items[j];
406 int wsn = workspace_get_number(ws);
407 if (!last) {
408 // The first workspace in reverse order
409 last = ws;
410 }
411 if (!other || (wsn >= 0 && wsn > othern)) {
412 // The last (greatest) numbered workspace.
413 other = ws;
414 othern = workspace_get_number(other);
415 }
416 if (ws == workspace) {
417 found = true;
418 } else if (wsn < 0 && found) {
419 // Found a non-numbered workspace before current
420 return ws;
421 }
422 }
423 }
424 } else {
425 // Find the prev numbered workspace
426 int prevn = -1, lastn = -1;
427 for (int i = root->outputs->length - 1; i >= 0; i--) {
428 struct sway_output *output = root->outputs->items[i];
429 for (int j = output->workspaces->length - 1; j >= 0; j--) {
430 struct sway_workspace *ws = output->workspaces->items[j];
431 int wsn = workspace_get_number(ws);
432 if (!last || (wsn >= 0 && wsn > lastn)) {
433 // The greatest numbered (or last) workspace
434 last = ws;
435 lastn = workspace_get_number(last);
436 }
437 if (!other && wsn < 0) {
438 // The last named workspace
439 other = ws;
440 }
441 if (wsn < 0) {
442 // Haven't reached the numbered workspaces
443 continue;
444 }
445 if (wsn < n && (!prev || wsn > prevn)) {
446 // The closest workspace before the current
447 prev = ws;
448 prevn = workspace_get_number(prev);
449 }
450 }
451 }
452 }
453
454 if (!prev) {
455 prev = other ? other : last;
456 }
457 return prev;
458}
459
460struct sway_workspace *workspace_next(struct sway_workspace *workspace) {
461 int n = workspace_get_number(workspace);
462 struct sway_workspace *next = NULL, *first = NULL, *other = NULL;
463 bool found = false;
464 if (n < 0) {
465 // Find the next named workspace
466 int othern = -1;
467 for (int i = 0; i < root->outputs->length; i++) {
468 struct sway_output *output = root->outputs->items[i];
469 for (int j = 0; j < output->workspaces->length; j++) {
470 struct sway_workspace *ws = output->workspaces->items[j];
471 int wsn = workspace_get_number(ws);
472 if (!first) {
473 // The first named workspace
474 first = ws;
475 }
476 if (!other || (wsn >= 0 && wsn < othern)) {
477 // The first (least) numbered workspace
478 other = ws;
479 othern = workspace_get_number(other);
480 }
481 if (ws == workspace) {
482 found = true;
483 } else if (wsn < 0 && found) {
484 // The first non-numbered workspace after the current
485 return ws;
486 }
487 }
488 }
489 } else {
490 // Find the next numbered workspace
491 int nextn = -1, firstn = -1;
492 for (int i = 0; i < root->outputs->length; i++) {
493 struct sway_output *output = root->outputs->items[i];
494 for (int j = 0; j < output->workspaces->length; j++) {
495 struct sway_workspace *ws = output->workspaces->items[j];
496 int wsn = workspace_get_number(ws);
497 if (!first || (wsn >= 0 && wsn < firstn)) {
498 // The first (or least numbered) workspace
499 first = ws;
500 firstn = workspace_get_number(first);
501 }
502 if (!other && wsn < 0) {
503 // The first non-numbered workspace
504 other = ws;
505 }
506 if (wsn < 0) {
507 // Checked all the numbered workspaces
508 break;
509 }
510 if (n < wsn && (!next || wsn < nextn)) {
511 // The first workspace numerically after the current
512 next = ws;
513 nextn = workspace_get_number(next);
514 }
515 }
516 }
517 }
518
519 if (!next) {
520 // If there is no next workspace from the same category, return the
521 // first from this category.
522 next = other ? other : first;
523 }
524 return next;
525}
526
385/** 527/**
386 * Get the previous or next workspace on the specified output. Wraps around at 528 * Get the previous or next workspace on the specified output. Wraps around at
387 * the end and beginning. If next is false, the previous workspace is returned, 529 * 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(
409 return output->workspaces->items[new_index]; 551 return output->workspaces->items[new_index];
410} 552}
411 553
412/**
413 * Get the previous or next workspace. If the first/last workspace on an output
414 * is active, proceed to the previous/next output's previous/next workspace.
415 */
416static struct sway_workspace *workspace_prev_next_impl(
417 struct sway_workspace *workspace, int dir) {
418 struct sway_output *output = workspace->output;
419 int index = list_find(output->workspaces, workspace);
420 int new_index = index + dir;
421
422 if (new_index >= 0 && new_index < output->workspaces->length) {
423 return output->workspaces->items[new_index];
424 }
425
426 // Look on a different output
427 int output_index = list_find(root->outputs, output);
428 new_index = wrap(output_index + dir, root->outputs->length);
429 output = root->outputs->items[new_index];
430
431 if (dir == 1) {
432 return output->workspaces->items[0];
433 } else {
434 return output->workspaces->items[output->workspaces->length - 1];
435 }
436}
437
438struct sway_workspace *workspace_output_next( 554struct sway_workspace *workspace_output_next(
439 struct sway_workspace *current, bool create) { 555 struct sway_workspace *current, bool create) {
440 return workspace_output_prev_next_impl(current->output, 1, create); 556 return workspace_output_prev_next_impl(current->output, 1, create);
441} 557}
442 558
443struct sway_workspace *workspace_next(struct sway_workspace *current) {
444 return workspace_prev_next_impl(current, 1);
445}
446
447struct sway_workspace *workspace_output_prev( 559struct sway_workspace *workspace_output_prev(
448 struct sway_workspace *current, bool create) { 560 struct sway_workspace *current, bool create) {
449 return workspace_output_prev_next_impl(current->output, -1, create); 561 return workspace_output_prev_next_impl(current->output, -1, create);
450} 562}
451 563
452struct sway_workspace *workspace_prev(struct sway_workspace *current) {
453 return workspace_prev_next_impl(current, -1);
454}
455
456bool workspace_switch(struct sway_workspace *workspace, 564bool workspace_switch(struct sway_workspace *workspace,
457 bool no_auto_back_and_forth) { 565 bool no_auto_back_and_forth) {
458 struct sway_seat *seat = input_manager_current_seat(); 566 struct sway_seat *seat = input_manager_current_seat();