]> git.sur5r.net Git - i3/i3/blobdiff - lib/AnyEvent/I3.pm
use i3 --get-socketpath by default for determining the socket path
[i3/i3] / lib / AnyEvent / I3.pm
index 953de81e76cc1156db5bbf186c6f2df4ef51b535..33347638ca9c4b0f3995a051f0ba0ac8f5203a7b 100644 (file)
@@ -15,11 +15,11 @@ AnyEvent::I3 - communicate with the i3 window manager
 
 =cut
 
-our $VERSION = '0.05';
+our $VERSION = '0.09';
 
 =head1 VERSION
 
-Version 0.05
+Version 0.09
 
 =head1 SYNOPSIS
 
@@ -29,7 +29,7 @@ then subscribe to events or send messages and receive their replies.
 
     use AnyEvent::I3 qw(:all);
 
-    my $i3 = i3("~/.i3/ipc.sock");
+    my $i3 = i3();
 
     $i3->connect->recv or die "Error connecting";
     say "Connected to i3";
@@ -41,15 +41,19 @@ then subscribe to events or send messages and receive their replies.
 
     use AnyEvent::I3;
 
-    my $workspaces = i3->workspaces->recv;
+    my $workspaces = i3->get_workspaces->recv;
     say "Currently, you use " . @{$workspaces} . " workspaces";
 
 =head1 EXPORT
 
 =head2 $i3 = i3([ $path ]);
 
-Creates a new C<AnyEvent::I3> object and returns it. C<path> is the path of
-the UNIX socket to connect to.
+Creates a new C<AnyEvent::I3> object and returns it.
+
+C<path> is an optional path of the UNIX socket to connect to. It is strongly
+advised to NOT specify this unless you're absolutely sure you need it.
+C<AnyEvent::I3> will automatically figure it out by querying the running i3
+instance on the current DISPLAY which is almost always what you want.
 
 =head1 SUBROUTINES/METHODS
 
@@ -64,9 +68,13 @@ use constant TYPE_COMMAND => 0;
 use constant TYPE_GET_WORKSPACES => 1;
 use constant TYPE_SUBSCRIBE => 2;
 use constant TYPE_GET_OUTPUTS => 3;
+use constant TYPE_GET_TREE => 4;
+use constant TYPE_GET_MARKS => 5;
+use constant TYPE_GET_BAR_CONFIG => 6;
 
 our %EXPORT_TAGS = ( 'all' => [
-    qw(i3 TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS)
+    qw(i3 TYPE_COMMAND TYPE_GET_WORKSPACES TYPE_SUBSCRIBE TYPE_GET_OUTPUTS
+       TYPE_GET_TREE TYPE_GET_MARKS TYPE_GET_BAR_CONFIG)
 ] );
 
 our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
@@ -87,13 +95,37 @@ sub i3 {
 
 =head2 $i3 = AnyEvent::I3->new([ $path ])
 
-Creates a new C<AnyEvent::I3> object and returns it. C<path> is the path of
-the UNIX socket to connect to.
+Creates a new C<AnyEvent::I3> object and returns it.
+
+C<path> is an optional path of the UNIX socket to connect to. It is strongly
+advised to NOT specify this unless you're absolutely sure you need it.
+C<AnyEvent::I3> will automatically figure it out by querying the running i3
+instance on the current DISPLAY which is almost always what you want.
 
 =cut
 sub new {
     my ($class, $path) = @_;
 
+    if (!$path) {
+        # This effectively circumvents taint mode checking for $ENV{PATH}. We
+        # do this because users might specify PATH explicitly to call i3 in a
+        # custom location (think ~/.bin/).
+        my $paths = $ENV{PATH};
+        if ($paths =~ /^(.*)$/) {
+            $ENV{PATH} = $1;
+        }
+        chomp($path = qx(i3 --get-socketpath));
+        # Circumventing taint mode again: the socket can be anywhere on the
+        # system and that’s okay.
+        if ($path =~ /^([^\0]+)$/) {
+            $path = $1;
+        } else {
+            warn "Asking i3 for the socket path failed. Is DISPLAY set and is i3 in your PATH?";
+        }
+    }
+
+    # This is the old default path (v3.*). This fallback line can be removed in
+    # a year from now. -- Michael, 2012-07-09
     $path ||= '~/.i3/ipc.sock';
 
     # Check if we need to resolve ~
@@ -142,6 +174,7 @@ sub connect {
                 for my $type (keys %{$cb}) {
                     next if ($type & $event_mask) == $event_mask;
                     $cb->{$type}->();
+                    delete $cb->{$type};
                 }
 
                 # Trigger _error callback, if set
@@ -287,7 +320,7 @@ sub _ensure_connection {
 
     return if defined($self->{ipchdl});
 
-    $self->connect->recv or die "Unable to connect to i3"
+    $self->connect->recv or die "Unable to connect to i3 (socket path " . $self->{path} . ")";
 }
 
 =head2 get_workspaces
@@ -322,6 +355,54 @@ sub get_outputs {
     $self->message(TYPE_GET_OUTPUTS)
 }
 
+=head2 get_tree
+
+Gets the layout tree from i3 (>= v4.0).
+
+    my $tree = i3->get_tree->recv;
+    say Dumper($tree);
+
+=cut
+sub get_tree {
+    my ($self) = @_;
+
+    $self->_ensure_connection;
+
+    $self->message(TYPE_GET_TREE)
+}
+
+=head2 get_marks
+
+Gets all the window identifier marks from i3 (>= v4.1).
+
+    my $marks = i3->get_marks->recv;
+    say Dumper($marks);
+
+=cut
+sub get_marks {
+    my ($self) = @_;
+
+    $self->_ensure_connection;
+
+    $self->message(TYPE_GET_MARKS)
+}
+
+=head2 get_bar_config
+
+Gets the bar configuration for the specific bar id from i3 (>= v4.1).
+
+    my $config = i3->get_bar_config($id)->recv;
+    say Dumper($config);
+
+=cut
+sub get_bar_config {
+    my ($self, $id) = @_;
+
+    $self->_ensure_connection;
+
+    $self->message(TYPE_GET_BAR_CONFIG, $id)
+}
+
 =head2 command($content)
 
 Makes i3 execute the given command