correctly sort numbered workspaces (+testcase)
Numbered workspaces (workspaces with a name containing only digits) will be inserted in the correct order now. Named workspaces are always sorted after numbered workspaces and in the order of creation.
This commit is contained in:
parent
fab8b84db7
commit
1de97a1f1f
@ -281,6 +281,10 @@ struct Con {
|
||||
|
||||
char *name;
|
||||
|
||||
/** the workspace number, if this Con is of type CT_WORKSPACE and the
|
||||
* workspace is not a named workspace (for named workspaces, num == -1) */
|
||||
int num;
|
||||
|
||||
/* a sticky-group is an identifier which bundles several containers to a
|
||||
* group. The contents are shared between all of them, that is they are
|
||||
* displayed on whichever of the containers is currently visible */
|
||||
|
34
src/con.c
34
src/con.c
@ -72,6 +72,35 @@ void con_attach(Con *con, Con *parent) {
|
||||
con->parent = parent;
|
||||
Con *loop;
|
||||
Con *current = NULL;
|
||||
struct nodes_head *nodes_head = &(parent->nodes_head);
|
||||
|
||||
/* Workspaces are handled differently: they need to be inserted at the
|
||||
* right position. */
|
||||
if (con->type == CT_WORKSPACE) {
|
||||
DLOG("it's a workspace. num = %d\n", con->num);
|
||||
if (con->num == -1 || TAILQ_EMPTY(nodes_head)) {
|
||||
TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
||||
} else {
|
||||
current = TAILQ_FIRST(nodes_head);
|
||||
if (con->num < current->num) {
|
||||
/* we need to insert the container at the beginning */
|
||||
TAILQ_INSERT_HEAD(nodes_head, con, nodes);
|
||||
return;
|
||||
}
|
||||
while (current->num != -1 && con->num > current->num) {
|
||||
current = TAILQ_NEXT(current, nodes);
|
||||
if (current == TAILQ_END(nodes_head)) {
|
||||
current = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* we need to insert con after current, if current is not NULL */
|
||||
if (current)
|
||||
TAILQ_INSERT_BEFORE(current, con, nodes);
|
||||
else TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
||||
}
|
||||
goto add_to_focus_head;
|
||||
}
|
||||
|
||||
/* Get the first tiling container in focus stack */
|
||||
TAILQ_FOREACH(loop, &(parent->focus_head), focused) {
|
||||
@ -85,9 +114,10 @@ void con_attach(Con *con, Con *parent) {
|
||||
if (current) {
|
||||
DLOG("Inserting con = %p after last focused tiling con %p\n",
|
||||
con, current);
|
||||
TAILQ_INSERT_AFTER(&(parent->nodes_head), current, con, nodes);
|
||||
} else TAILQ_INSERT_TAIL(&(parent->nodes_head), con, nodes);
|
||||
TAILQ_INSERT_AFTER(nodes_head, current, con, nodes);
|
||||
} else TAILQ_INSERT_TAIL(nodes_head, con, nodes);
|
||||
|
||||
add_to_focus_head:
|
||||
/* We insert to the TAIL because con_focus() will correct this.
|
||||
* This way, we have the option to insert Cons without having
|
||||
* to focus them. */
|
||||
|
@ -269,7 +269,9 @@ IPC_HANDLER(get_workspaces) {
|
||||
y(map_open);
|
||||
|
||||
ystr("num");
|
||||
y(integer, con_num_children(ws));
|
||||
if (ws->num == -1)
|
||||
y(null);
|
||||
else y(integer, ws->num);
|
||||
|
||||
ystr("name");
|
||||
ystr(ws->name);
|
||||
|
@ -77,10 +77,12 @@ void tree_init() {
|
||||
free(name);
|
||||
|
||||
/* add a workspace to this output */
|
||||
ws = con_new(oc);
|
||||
ws = con_new(NULL);
|
||||
ws->type = CT_WORKSPACE;
|
||||
ws->num = c;
|
||||
asprintf(&(ws->name), "%d", c);
|
||||
c++;
|
||||
con_attach(ws, oc);
|
||||
|
||||
asprintf(&name, "[i3 con] workspace %s", ws->name);
|
||||
x_set_name(ws, name);
|
||||
|
@ -38,14 +38,28 @@ Con *workspace_get(const char *num) {
|
||||
LOG("need to create this one\n");
|
||||
output = con_get_output(focused);
|
||||
LOG("got output %p\n", output);
|
||||
workspace = con_new(output);
|
||||
/* We need to attach this container after setting its type. con_attach
|
||||
* will handle CT_WORKSPACEs differently */
|
||||
workspace = con_new(NULL);
|
||||
char *name;
|
||||
asprintf(&name, "[i3 con] workspace %s", num);
|
||||
x_set_name(workspace, name);
|
||||
free(name);
|
||||
workspace->type = CT_WORKSPACE;
|
||||
workspace->name = strdup(num);
|
||||
/* We set ->num to the number if this workspace’s name consists only of
|
||||
* a positive number. Otherwise it’s a named ws and num will be -1. */
|
||||
char *end;
|
||||
long parsed_num = strtol(num, &end, 10);
|
||||
if (parsed_num == LONG_MIN ||
|
||||
parsed_num == LONG_MAX ||
|
||||
parsed_num < 0 ||
|
||||
(end && *end != '\0'))
|
||||
workspace->num = -1;
|
||||
else workspace->num = parsed_num;
|
||||
LOG("num = %d\n", workspace->num);
|
||||
workspace->orientation = HORIZ;
|
||||
con_attach(workspace, output);
|
||||
|
||||
ipc_send_event("workspace", I3_IPC_EVENT_WORKSPACE, "{\"change\":\"init\"}");
|
||||
}
|
||||
|
59
testcases/t/39-ws-numbers.t
Normal file
59
testcases/t/39-ws-numbers.t
Normal file
@ -0,0 +1,59 @@
|
||||
#!perl
|
||||
# vim:ts=4:sw=4:expandtab
|
||||
# Check if numbered workspaces and named workspaces are sorted in the right way
|
||||
# in get_workspaces IPC output (necessary for i3bar etc.).
|
||||
use i3test tests => 9;
|
||||
use X11::XCB qw(:all);
|
||||
use Time::HiRes qw(sleep);
|
||||
|
||||
BEGIN {
|
||||
use_ok('X11::XCB::Window');
|
||||
}
|
||||
|
||||
my $i3 = i3("/tmp/nestedcons");
|
||||
my $x = X11::XCB::Connection->new;
|
||||
|
||||
sub check_order {
|
||||
my ($msg) = @_;
|
||||
|
||||
my @ws = @{$i3->get_workspaces->recv};
|
||||
my @nums = map { $_->{num} } grep { defined($_->{num}) } @ws;
|
||||
my @sorted = sort @nums;
|
||||
|
||||
cmp_deeply(\@nums, \@sorted, $msg);
|
||||
}
|
||||
|
||||
check_order('workspace order alright before testing');
|
||||
|
||||
#############################################################################
|
||||
# open a window to keep this ws open
|
||||
#############################################################################
|
||||
|
||||
$i3->command("workspace 93")->recv;
|
||||
|
||||
open_standard_window($x);
|
||||
|
||||
my @ws = @{$i3->get_workspaces->recv};
|
||||
my @f = grep { defined($_->{num}) && $_->{num} == 93 } @ws;
|
||||
is(@f, 1, 'ws 93 found by num');
|
||||
check_order('workspace order alright after opening 93');
|
||||
|
||||
$i3->command("workspace 92")->recv;
|
||||
open_standard_window($x);
|
||||
check_order('workspace order alright after opening 92');
|
||||
|
||||
$i3->command("workspace 94")->recv;
|
||||
open_standard_window($x);
|
||||
check_order('workspace order alright after opening 94');
|
||||
|
||||
$i3->command("workspace 96")->recv;
|
||||
open_standard_window($x);
|
||||
check_order('workspace order alright after opening 96');
|
||||
|
||||
$i3->command("workspace foo")->recv;
|
||||
open_standard_window($x);
|
||||
check_order('workspace order alright after opening foo');
|
||||
|
||||
$i3->command("workspace 91")->recv;
|
||||
open_standard_window($x);
|
||||
check_order('workspace order alright after opening 91');
|
@ -10,7 +10,7 @@ use List::Util qw(first);
|
||||
use v5.10;
|
||||
|
||||
use Exporter ();
|
||||
our @EXPORT = qw(get_workspace_names get_unused_workspace get_ws_content get_ws get_focused open_empty_con);
|
||||
our @EXPORT = qw(get_workspace_names get_unused_workspace get_ws_content get_ws get_focused open_empty_con open_standard_window);
|
||||
|
||||
BEGIN {
|
||||
my $window_count = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user