]> git.sur5r.net Git - i3/i3/blobdiff - i3-save-tree
Merge branch 'release-4.16.1'
[i3/i3] / i3-save-tree
index 6ac3e1b1a2564b83e3dffa522fc01f9b657b2681..da5e6deddedb4bd1078f2b9c091fd8d9c3a0d626 100755 (executable)
@@ -13,11 +13,13 @@ use POSIX qw(locale_h);
 use File::Find;
 use File::Basename qw(basename);
 use File::Temp qw(tempfile);
+use List::Util qw(first);
 use Getopt::Long;
 use Pod::Usage;
 use AnyEvent::I3;
 use JSON::XS;
 use List::Util qw(first);
+use Encode qw(decode);
 use v5.10;
 use utf8;
 use open ':encoding(UTF-8)';
@@ -40,19 +42,27 @@ my $result = GetOptions(
 
 die "Could not parse command line options" unless $result;
 
-if (!defined($workspace) && !defined($output)) {
-    die "One of --workspace or --output need to be specified";
-}
-
-unless (defined($workspace) ^ defined($output)) {
+if (defined($workspace) && defined($output)) {
     die "Only one of --workspace or --output can be specified";
 }
 
+$workspace = decode('utf-8', $workspace);
+$output = decode('utf-8', $output);
+
 my $i3 = i3();
 if (!$i3->connect->recv) {
     die "Could not connect to i3";
 }
 
+sub get_current_workspace {
+    my $current = first { $_->{focused} } @{$i3->get_workspaces->recv};
+    return $current->{name};
+}
+
+if (!defined($workspace) && !defined($output)) {
+    $workspace = get_current_workspace();
+}
+
 sub filter_containers {
     my ($tree, $pred) = @_;
 
@@ -88,6 +98,8 @@ my %allowed_keys = map { ($_, 1) } qw(
     name
     geometry
     window_properties
+    marks
+    rect
 );
 
 sub strip_containers {
@@ -105,12 +117,13 @@ sub strip_containers {
 
     delete $tree->{geometry} if zero_rect($tree->{geometry});
 
+    # Retain the rect for floating containers to keep their positions.
+    delete $tree->{rect} unless $tree->{type} eq 'floating_con';
+
     delete $tree->{current_border_width} if $tree->{current_border_width} == -1;
 
     for my $key (keys %$tree) {
-        next if exists($allowed_keys{$key});
-
-        delete $tree->{$key};
+        delete $tree->{$key} unless exists($allowed_keys{$key});
     }
 
     for my $key (qw(nodes floating_nodes)) {
@@ -149,12 +162,16 @@ sub dump_containers {
         say "$ws// $desc with " . @{$tree->{nodes}} . " children";
     }
 
-    # Turn “window_properties” into “swallows” expressions.
-    my $swallows = {};
-    for my $property (keys %{$tree->{window_properties}}) {
-        $swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$';
+    # Turn “window_properties” into “swallows” expressions, but only for leaf
+    # nodes. It only makes sense for leaf nodes to swallow anything.
+    if (leaf_node($tree)) {
+        my $swallows = {};
+        for my $property (keys %{$tree->{window_properties}}) {
+            $swallows->{$property} = '^' . quotemeta($tree->{window_properties}->{$property}) . '$'
+                if $property ne 'transient_for';
+        }
+        $tree->{swallows} = [ $swallows ];
     }
-    $tree->{swallows} = [ $swallows ];
     delete $tree->{window_properties};
 
     my @keys = sort keys %$tree;
@@ -208,7 +225,7 @@ my $tree = $i3->get_tree->recv;
 my $dump;
 if (defined($workspace)) {
     $dump = filter_containers($tree, sub {
-        $_->{type} eq 'workspace' && $_->{name} eq $workspace
+        $_->{type} eq 'workspace' && ($_->{name} eq $workspace || ($workspace =~ /^\d+$/ && $_->{num} eq $workspace))
     });
 } else {
     $dump = filter_containers($tree, sub {
@@ -238,7 +255,7 @@ for my $key (qw(nodes floating_nodes)) {
 
 =head1 SYNOPSIS
 
-    i3-save-tree [--workspace=name] [--output=name]
+    i3-save-tree [--workspace=name|number] [--output=name]
 
 =head1 DESCRIPTION
 
@@ -251,19 +268,20 @@ specification. When a window is mapped (made visible on the screen) that
 matches the specification, i3 will put it into that place and kill the
 placeholder.
 
+If neither argument is specified, the currently focused workspace will be used.
+
 =head1 OPTIONS
 
 =over
 
-=item B<--workspace=name>
+=item B<--workspace=name|number>
 
-Specifies the workspace that should be dumped, e.g. 1. Either this or --output
-need to be specified.
+Specifies the workspace that should be dumped, e.g. 1. This can either be a
+name or the number of a workspace.
 
 =item B<--output=name>
 
-Specifies the output that should be dumped, e.g. LVDS-1. Either this or
---workspace need to be specified.
+Specifies the output that should be dumped, e.g. LVDS-1.
 
 =back