From 6800524f2e1b0205972cf28bb08d5bfcf6f67dfc Mon Sep 17 00:00:00 2001 From: Michael Stapelberg Date: Sat, 14 Dec 2013 14:50:44 +0100 Subject: [PATCH] GET_TREE: serialize container type into a string So far, this was blessed for internal use only (by virtue of not being in the documentation), but we want to expose it for the stored layouts. --- docs/ipc | 11 +++++++--- src/ipc.c | 25 +++++++++++++++++++++- src/load_layout.c | 18 ++++++++++++++++ testcases/lib/i3test.pm | 14 ++++++------ testcases/t/100-fullscreen.t | 2 +- testcases/t/116-nestedcons.t | 8 +++---- testcases/t/117-workspace.t | 3 +-- testcases/t/122-split.t | 2 +- testcases/t/185-scratchpad.t | 2 +- testcases/t/504-move-workspace-to-output.t | 4 ++-- testcases/t/513-move-workspace.t | 4 ++-- 11 files changed, 69 insertions(+), 24 deletions(-) diff --git a/docs/ipc b/docs/ipc index 85e5e77e..e4f1e80c 100644 --- a/docs/ipc +++ b/docs/ipc @@ -277,7 +277,12 @@ name (string):: The internal name of this container. For all containers which are part of the tree structure down to the workspace contents, this is set to a nice human-readable name of the container. + For containers that have an X11 window, the content is the title + (_NET_WM_NAME property) of that window. For all other containers, the content is not defined (yet). +type (string):: + Type of this container. Can be one of "root", "output", "con", + "floating_con", "workspace" or "dockarea". border (string):: Can be either "normal", "none" or "1pixel", dependending on the container’s border style. @@ -670,12 +675,12 @@ but will still be present in the "old" property. "change": "focus", "current": { "id": 28489712, - "type":4, + "type": "workspace", ... } "old": { "id": 28489715, - "type": 4, + "type": "workspace", ... } } @@ -722,7 +727,7 @@ window title as "urxvt"). "change": "new", "container": { "id": 35569536, - "type": 2, + "type": "con", ... } } diff --git a/src/ipc.c b/src/ipc.c index a928dba9..b5d17ba4 100644 --- a/src/ipc.c +++ b/src/ipc.c @@ -153,7 +153,30 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) { y(integer, (long int)con); ystr("type"); - y(integer, con->type); + switch (con->type) { + case CT_ROOT: + ystr("root"); + break; + case CT_OUTPUT: + ystr("output"); + break; + case CT_CON: + ystr("con"); + break; + case CT_FLOATING_CON: + ystr("floating_con"); + break; + case CT_WORKSPACE: + ystr("workspace"); + break; + case CT_DOCKAREA: + ystr("dockarea"); + break; + default: + DLOG("About to dump unknown container type=%d. This is a bug.\n", con->type); + assert(false); + break; + } /* provided for backwards compatibility only. */ ystr("orientation"); diff --git a/src/load_layout.c b/src/load_layout.c index d0c5a3b1..d31c230a 100644 --- a/src/load_layout.c +++ b/src/load_layout.c @@ -203,6 +203,23 @@ static int json_string(void *ctx, const unsigned char *val, unsigned int len) { json_node->border_style = BS_NORMAL; else LOG("Unhandled \"border\": %s\n", buf); free(buf); + } else if (strcasecmp(last_key, "type") == 0) { + char *buf = NULL; + sasprintf(&buf, "%.*s", (int)len, val); + if (strcasecmp(buf, "root") == 0) + json_node->type = CT_ROOT; + else if (strcasecmp(buf, "output") == 0) + json_node->type = CT_OUTPUT; + else if (strcasecmp(buf, "con") == 0) + json_node->type = CT_CON; + else if (strcasecmp(buf, "floating_con") == 0) + json_node->type = CT_FLOATING_CON; + else if (strcasecmp(buf, "workspace") == 0) + json_node->type = CT_WORKSPACE; + else if (strcasecmp(buf, "dockarea") == 0) + json_node->type = CT_DOCKAREA; + else LOG("Unhandled \"type\": %s\n", buf); + free(buf); } else if (strcasecmp(last_key, "layout") == 0) { char *buf = NULL; sasprintf(&buf, "%.*s", (int)len, val); @@ -281,6 +298,7 @@ static int json_int(void *ctx, long long val) { static int json_int(void *ctx, long val) { LOG("int %ld for key %s\n", val, last_key); #endif + /* For backwards compatibility with i3 < 4.8 */ if (strcasecmp(last_key, "type") == 0) json_node->type = val; diff --git a/testcases/lib/i3test.pm b/testcases/lib/i3test.pm index 414362ae..d71a6e86 100644 --- a/testcases/lib/i3test.pm +++ b/testcases/lib/i3test.pm @@ -391,7 +391,7 @@ sub get_workspace_names { for my $output (@outputs) { next if $output->{name} eq '__i3'; # get the first CT_CON of each output - my $content = first { $_->{type} == 2 } @{$output->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$output->{nodes}}; @cons = (@cons, @{$content->{nodes}}); } [ map { $_->{name} } @cons ] @@ -434,7 +434,7 @@ sub fresh_workspace { @{$tree->{nodes}}; die "BUG: Could not find output $args{output}" unless defined($output); # Get the focused workspace on that output and switch to it. - my $content = first { $_->{type} == 2 } @{$output->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$output->{nodes}}; my $focused = $content->{focus}->[0]; my $workspace = first { $_->{id} == $focused } @{$content->{nodes}}; $workspace = $workspace->{name}; @@ -479,7 +479,7 @@ sub get_ws { my @workspaces; for my $output (@outputs) { # get the first CT_CON of each output - my $content = first { $_->{type} == 2 } @{$output->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$output->{nodes}}; @workspaces = (@workspaces, @{$content->{nodes}}); } @@ -589,13 +589,13 @@ sub get_dock_clients { for my $output (@outputs) { if (!defined($which)) { @docked = (@docked, map { @{$_->{nodes}} } - grep { $_->{type} == 5 } + grep { $_->{type} eq 'dockarea' } @{$output->{nodes}}); } elsif ($which eq 'top') { - my $first = first { $_->{type} == 5 } @{$output->{nodes}}; + my $first = first { $_->{type} eq 'dockarea' } @{$output->{nodes}}; @docked = (@docked, @{$first->{nodes}}) if defined($first); } elsif ($which eq 'bottom') { - my @matching = grep { $_->{type} == 5 } @{$output->{nodes}}; + my @matching = grep { $_->{type} eq 'dockarea' } @{$output->{nodes}}; my $last = $matching[-1]; @docked = (@docked, @{$last->{nodes}}) if defined($last); } @@ -645,7 +645,7 @@ sub focused_ws { my $tree = $i3->get_tree->recv; my $focused = $tree->{focus}->[0]; my $output = first { $_->{id} == $focused } @{$tree->{nodes}}; - my $content = first { $_->{type} == 2 } @{$output->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$output->{nodes}}; my $first = first { $_->{fullscreen_mode} == 1 } @{$content->{nodes}}; return $first->{name} } diff --git a/testcases/t/100-fullscreen.t b/testcases/t/100-fullscreen.t index 54b29c9d..206116ee 100644 --- a/testcases/t/100-fullscreen.t +++ b/testcases/t/100-fullscreen.t @@ -34,7 +34,7 @@ my @outputs = @{$tree->{nodes}}; my $output; for my $o (@outputs) { # get the first CT_CON of each output - my $content = first { $_->{type} == 2 } @{$o->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$o->{nodes}}; if (defined(first { $_->{name} eq $tmp } @{$content->{nodes}})) { $output = $o; last; diff --git a/testcases/t/116-nestedcons.t b/testcases/t/116-nestedcons.t index 84e86879..eb2fe144 100644 --- a/testcases/t/116-nestedcons.t +++ b/testcases/t/116-nestedcons.t @@ -51,7 +51,7 @@ my $expected = { window => undef, name => 'root', orientation => $ignore, - type => 0, + type => 'root', id => $ignore, rect => $ignore, window_rect => $ignore, @@ -90,16 +90,16 @@ my @nodes = @{$tree->{nodes}}; ok(@nodes > 0, 'root node has at least one leaf'); -ok((all { $_->{type} == 1 } @nodes), 'all nodes are of type CT_OUTPUT'); +ok((all { $_->{type} eq 'output' } @nodes), 'all nodes are of type CT_OUTPUT'); ok((none { defined($_->{window}) } @nodes), 'no CT_OUTPUT contains a window'); ok((all { @{$_->{nodes}} > 0 } @nodes), 'all nodes have at least one leaf (workspace)'); my @workspaces; for my $ws (@nodes) { - my $content = first { $_->{type} == 2 } @{$ws->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$ws->{nodes}}; @workspaces = (@workspaces, @{$content->{nodes}}); } -ok((all { $_->{type} == 4 } @workspaces), 'all workspaces are of type CT_WORKSPACE'); +ok((all { $_->{type} eq 'workspace' } @workspaces), 'all workspaces are of type CT_WORKSPACE'); #ok((all { @{$_->{nodes}} == 0 } @workspaces), 'all workspaces are empty yet'); ok((none { defined($_->{window}) } @workspaces), 'no CT_OUTPUT contains a window'); diff --git a/testcases/t/117-workspace.t b/testcases/t/117-workspace.t index d8a8733b..04d9b9dd 100644 --- a/testcases/t/117-workspace.t +++ b/testcases/t/117-workspace.t @@ -196,8 +196,7 @@ sub workspace_numbers_sorted { my @outputs = @{$tree->{nodes}}; my @workspaces; for my $output (@outputs) { - # get the first CT_CON of each output - my $content = first { $_->{type} == 2 } @{$output->{nodes}}; + my $content = first { $_->{type} eq 'con' } @{$output->{nodes}}; @workspaces = (@workspaces, @{$content->{nodes}}); } diff --git a/testcases/t/122-split.t b/testcases/t/122-split.t index 361716c1..6afdd806 100644 --- a/testcases/t/122-split.t +++ b/testcases/t/122-split.t @@ -145,7 +145,7 @@ sub get_output_content { is(scalar @outputs, 1, 'exactly one output (testcase not multi-monitor capable)'); my $output = $outputs[0]; # get the first (and only) CT_CON - return first { $_->{type} == 2 } @{$output->{nodes}}; + return first { $_->{type} eq 'con' } @{$output->{nodes}}; } $tmp = fresh_workspace; diff --git a/testcases/t/185-scratchpad.t b/testcases/t/185-scratchpad.t index 5901f99c..edfc46e0 100644 --- a/testcases/t/185-scratchpad.t +++ b/testcases/t/185-scratchpad.t @@ -35,7 +35,7 @@ is($tree->{name}, 'root', 'root node is the first thing we get'); my @__i3 = grep { $_->{name} eq '__i3' } @{$tree->{nodes}}; is(scalar @__i3, 1, 'output __i3 found'); -my $content = first { $_->{type} == 2 } @{$__i3[0]->{nodes}}; +my $content = first { $_->{type} eq 'con' } @{$__i3[0]->{nodes}}; my @workspaces = @{$content->{nodes}}; my @workspace_names = map { $_->{name} } @workspaces; ok('__i3_scratch' ~~ @workspace_names, '__i3_scratch workspace found'); diff --git a/testcases/t/504-move-workspace-to-output.t b/testcases/t/504-move-workspace-to-output.t index 018707e6..efe0d6e7 100644 --- a/testcases/t/504-move-workspace-to-output.t +++ b/testcases/t/504-move-workspace-to-output.t @@ -77,10 +77,10 @@ sub workspaces_per_screen { my @outputs = @{$tree->{nodes}}; my $fake0 = first { $_->{name} eq 'fake-0' } @outputs; - my $fake0_content = first { $_->{type} == 2 } @{$fake0->{nodes}}; + my $fake0_content = first { $_->{type} eq 'con' } @{$fake0->{nodes}}; my $fake1 = first { $_->{name} eq 'fake-1' } @outputs; - my $fake1_content = first { $_->{type} == 2 } @{$fake1->{nodes}}; + my $fake1_content = first { $_->{type} eq 'con' } @{$fake1->{nodes}}; my @fake0_workspaces = map { $_->{name} } @{$fake0_content->{nodes}}; my @fake1_workspaces = map { $_->{name} } @{$fake1_content->{nodes}}; diff --git a/testcases/t/513-move-workspace.t b/testcases/t/513-move-workspace.t index 17c8de71..3e27a6c0 100644 --- a/testcases/t/513-move-workspace.t +++ b/testcases/t/513-move-workspace.t @@ -37,10 +37,10 @@ sub workspaces_per_screen { my @outputs = @{$tree->{nodes}}; my $fake0 = first { $_->{name} eq 'fake-0' } @outputs; - my $fake0_content = first { $_->{type} == 2 } @{$fake0->{nodes}}; + my $fake0_content = first { $_->{type} eq 'con' } @{$fake0->{nodes}}; my $fake1 = first { $_->{name} eq 'fake-1' } @outputs; - my $fake1_content = first { $_->{type} == 2 } @{$fake1->{nodes}}; + my $fake1_content = first { $_->{type} eq 'con' } @{$fake1->{nodes}}; my @fake0_workspaces = map { $_->{name} } @{$fake0_content->{nodes}}; my @fake1_workspaces = map { $_->{name} } @{$fake1_content->{nodes}};