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.
This commit is contained in:
parent
58297f4ab5
commit
6800524f2e
11
docs/ipc
11
docs/ipc
@ -277,7 +277,12 @@ name (string)::
|
|||||||
The internal name of this container. For all containers which are part
|
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
|
of the tree structure down to the workspace contents, this is set to a
|
||||||
nice human-readable name of the container.
|
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).
|
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)::
|
border (string)::
|
||||||
Can be either "normal", "none" or "1pixel", dependending on the
|
Can be either "normal", "none" or "1pixel", dependending on the
|
||||||
container’s border style.
|
container’s border style.
|
||||||
@ -670,12 +675,12 @@ but will still be present in the "old" property.
|
|||||||
"change": "focus",
|
"change": "focus",
|
||||||
"current": {
|
"current": {
|
||||||
"id": 28489712,
|
"id": 28489712,
|
||||||
"type":4,
|
"type": "workspace",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
"old": {
|
"old": {
|
||||||
"id": 28489715,
|
"id": 28489715,
|
||||||
"type": 4,
|
"type": "workspace",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -722,7 +727,7 @@ window title as "urxvt").
|
|||||||
"change": "new",
|
"change": "new",
|
||||||
"container": {
|
"container": {
|
||||||
"id": 35569536,
|
"id": 35569536,
|
||||||
"type": 2,
|
"type": "con",
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
src/ipc.c
25
src/ipc.c
@ -153,7 +153,30 @@ void dump_node(yajl_gen gen, struct Con *con, bool inplace_restart) {
|
|||||||
y(integer, (long int)con);
|
y(integer, (long int)con);
|
||||||
|
|
||||||
ystr("type");
|
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. */
|
/* provided for backwards compatibility only. */
|
||||||
ystr("orientation");
|
ystr("orientation");
|
||||||
|
@ -203,6 +203,23 @@ static int json_string(void *ctx, const unsigned char *val, unsigned int len) {
|
|||||||
json_node->border_style = BS_NORMAL;
|
json_node->border_style = BS_NORMAL;
|
||||||
else LOG("Unhandled \"border\": %s\n", buf);
|
else LOG("Unhandled \"border\": %s\n", buf);
|
||||||
free(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) {
|
} else if (strcasecmp(last_key, "layout") == 0) {
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
sasprintf(&buf, "%.*s", (int)len, val);
|
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) {
|
static int json_int(void *ctx, long val) {
|
||||||
LOG("int %ld for key %s\n", val, last_key);
|
LOG("int %ld for key %s\n", val, last_key);
|
||||||
#endif
|
#endif
|
||||||
|
/* For backwards compatibility with i3 < 4.8 */
|
||||||
if (strcasecmp(last_key, "type") == 0)
|
if (strcasecmp(last_key, "type") == 0)
|
||||||
json_node->type = val;
|
json_node->type = val;
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ sub get_workspace_names {
|
|||||||
for my $output (@outputs) {
|
for my $output (@outputs) {
|
||||||
next if $output->{name} eq '__i3';
|
next if $output->{name} eq '__i3';
|
||||||
# get the first CT_CON of each output
|
# 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}});
|
@cons = (@cons, @{$content->{nodes}});
|
||||||
}
|
}
|
||||||
[ map { $_->{name} } @cons ]
|
[ map { $_->{name} } @cons ]
|
||||||
@ -434,7 +434,7 @@ sub fresh_workspace {
|
|||||||
@{$tree->{nodes}};
|
@{$tree->{nodes}};
|
||||||
die "BUG: Could not find output $args{output}" unless defined($output);
|
die "BUG: Could not find output $args{output}" unless defined($output);
|
||||||
# Get the focused workspace on that output and switch to it.
|
# 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 $focused = $content->{focus}->[0];
|
||||||
my $workspace = first { $_->{id} == $focused } @{$content->{nodes}};
|
my $workspace = first { $_->{id} == $focused } @{$content->{nodes}};
|
||||||
$workspace = $workspace->{name};
|
$workspace = $workspace->{name};
|
||||||
@ -479,7 +479,7 @@ sub get_ws {
|
|||||||
my @workspaces;
|
my @workspaces;
|
||||||
for my $output (@outputs) {
|
for my $output (@outputs) {
|
||||||
# get the first CT_CON of each output
|
# 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}});
|
@workspaces = (@workspaces, @{$content->{nodes}});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -589,13 +589,13 @@ sub get_dock_clients {
|
|||||||
for my $output (@outputs) {
|
for my $output (@outputs) {
|
||||||
if (!defined($which)) {
|
if (!defined($which)) {
|
||||||
@docked = (@docked, map { @{$_->{nodes}} }
|
@docked = (@docked, map { @{$_->{nodes}} }
|
||||||
grep { $_->{type} == 5 }
|
grep { $_->{type} eq 'dockarea' }
|
||||||
@{$output->{nodes}});
|
@{$output->{nodes}});
|
||||||
} elsif ($which eq 'top') {
|
} 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);
|
@docked = (@docked, @{$first->{nodes}}) if defined($first);
|
||||||
} elsif ($which eq 'bottom') {
|
} elsif ($which eq 'bottom') {
|
||||||
my @matching = grep { $_->{type} == 5 } @{$output->{nodes}};
|
my @matching = grep { $_->{type} eq 'dockarea' } @{$output->{nodes}};
|
||||||
my $last = $matching[-1];
|
my $last = $matching[-1];
|
||||||
@docked = (@docked, @{$last->{nodes}}) if defined($last);
|
@docked = (@docked, @{$last->{nodes}}) if defined($last);
|
||||||
}
|
}
|
||||||
@ -645,7 +645,7 @@ sub focused_ws {
|
|||||||
my $tree = $i3->get_tree->recv;
|
my $tree = $i3->get_tree->recv;
|
||||||
my $focused = $tree->{focus}->[0];
|
my $focused = $tree->{focus}->[0];
|
||||||
my $output = first { $_->{id} == $focused } @{$tree->{nodes}};
|
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}};
|
my $first = first { $_->{fullscreen_mode} == 1 } @{$content->{nodes}};
|
||||||
return $first->{name}
|
return $first->{name}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ my @outputs = @{$tree->{nodes}};
|
|||||||
my $output;
|
my $output;
|
||||||
for my $o (@outputs) {
|
for my $o (@outputs) {
|
||||||
# get the first CT_CON of each output
|
# 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}})) {
|
if (defined(first { $_->{name} eq $tmp } @{$content->{nodes}})) {
|
||||||
$output = $o;
|
$output = $o;
|
||||||
last;
|
last;
|
||||||
|
@ -51,7 +51,7 @@ my $expected = {
|
|||||||
window => undef,
|
window => undef,
|
||||||
name => 'root',
|
name => 'root',
|
||||||
orientation => $ignore,
|
orientation => $ignore,
|
||||||
type => 0,
|
type => 'root',
|
||||||
id => $ignore,
|
id => $ignore,
|
||||||
rect => $ignore,
|
rect => $ignore,
|
||||||
window_rect => $ignore,
|
window_rect => $ignore,
|
||||||
@ -90,16 +90,16 @@ my @nodes = @{$tree->{nodes}};
|
|||||||
|
|
||||||
ok(@nodes > 0, 'root node has at least one leaf');
|
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((none { defined($_->{window}) } @nodes), 'no CT_OUTPUT contains a window');
|
||||||
ok((all { @{$_->{nodes}} > 0 } @nodes), 'all nodes have at least one leaf (workspace)');
|
ok((all { @{$_->{nodes}} > 0 } @nodes), 'all nodes have at least one leaf (workspace)');
|
||||||
my @workspaces;
|
my @workspaces;
|
||||||
for my $ws (@nodes) {
|
for my $ws (@nodes) {
|
||||||
my $content = first { $_->{type} == 2 } @{$ws->{nodes}};
|
my $content = first { $_->{type} eq 'con' } @{$ws->{nodes}};
|
||||||
@workspaces = (@workspaces, @{$content->{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((all { @{$_->{nodes}} == 0 } @workspaces), 'all workspaces are empty yet');
|
||||||
ok((none { defined($_->{window}) } @workspaces), 'no CT_OUTPUT contains a window');
|
ok((none { defined($_->{window}) } @workspaces), 'no CT_OUTPUT contains a window');
|
||||||
|
|
||||||
|
@ -196,8 +196,7 @@ sub workspace_numbers_sorted {
|
|||||||
my @outputs = @{$tree->{nodes}};
|
my @outputs = @{$tree->{nodes}};
|
||||||
my @workspaces;
|
my @workspaces;
|
||||||
for my $output (@outputs) {
|
for my $output (@outputs) {
|
||||||
# get the first CT_CON of each output
|
my $content = first { $_->{type} eq 'con' } @{$output->{nodes}};
|
||||||
my $content = first { $_->{type} == 2 } @{$output->{nodes}};
|
|
||||||
@workspaces = (@workspaces, @{$content->{nodes}});
|
@workspaces = (@workspaces, @{$content->{nodes}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ sub get_output_content {
|
|||||||
is(scalar @outputs, 1, 'exactly one output (testcase not multi-monitor capable)');
|
is(scalar @outputs, 1, 'exactly one output (testcase not multi-monitor capable)');
|
||||||
my $output = $outputs[0];
|
my $output = $outputs[0];
|
||||||
# get the first (and only) CT_CON
|
# get the first (and only) CT_CON
|
||||||
return first { $_->{type} == 2 } @{$output->{nodes}};
|
return first { $_->{type} eq 'con' } @{$output->{nodes}};
|
||||||
}
|
}
|
||||||
|
|
||||||
$tmp = fresh_workspace;
|
$tmp = fresh_workspace;
|
||||||
|
@ -35,7 +35,7 @@ is($tree->{name}, 'root', 'root node is the first thing we get');
|
|||||||
my @__i3 = grep { $_->{name} eq '__i3' } @{$tree->{nodes}};
|
my @__i3 = grep { $_->{name} eq '__i3' } @{$tree->{nodes}};
|
||||||
is(scalar @__i3, 1, 'output __i3 found');
|
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 @workspaces = @{$content->{nodes}};
|
||||||
my @workspace_names = map { $_->{name} } @workspaces;
|
my @workspace_names = map { $_->{name} } @workspaces;
|
||||||
ok('__i3_scratch' ~~ @workspace_names, '__i3_scratch workspace found');
|
ok('__i3_scratch' ~~ @workspace_names, '__i3_scratch workspace found');
|
||||||
|
@ -77,10 +77,10 @@ sub workspaces_per_screen {
|
|||||||
my @outputs = @{$tree->{nodes}};
|
my @outputs = @{$tree->{nodes}};
|
||||||
|
|
||||||
my $fake0 = first { $_->{name} eq 'fake-0' } @outputs;
|
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 = 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 @fake0_workspaces = map { $_->{name} } @{$fake0_content->{nodes}};
|
||||||
my @fake1_workspaces = map { $_->{name} } @{$fake1_content->{nodes}};
|
my @fake1_workspaces = map { $_->{name} } @{$fake1_content->{nodes}};
|
||||||
|
@ -37,10 +37,10 @@ sub workspaces_per_screen {
|
|||||||
my @outputs = @{$tree->{nodes}};
|
my @outputs = @{$tree->{nodes}};
|
||||||
|
|
||||||
my $fake0 = first { $_->{name} eq 'fake-0' } @outputs;
|
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 = 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 @fake0_workspaces = map { $_->{name} } @{$fake0_content->{nodes}};
|
||||||
my @fake1_workspaces = map { $_->{name} } @{$fake1_content->{nodes}};
|
my @fake1_workspaces = map { $_->{name} } @{$fake1_content->{nodes}};
|
||||||
|
Loading…
Reference in New Issue
Block a user