i3_workspaces.pl 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. #!/usr/bin/env perl
  2. # vim:ts=4:sw=4:expandtab:ft=perl
  3. #
  4. # Print i3 workspaces on every change.
  5. #
  6. # Format:
  7. # For every workspace (x = workspace name)
  8. # - "FOCx" -> Focused workspace
  9. # - "INAx" -> Inactive workspace
  10. # - "ACTx" -> Ative workspace
  11. # - "URGx" -> Urgent workspace
  12. #
  13. # Uses AnyEvent I3 0.8 -> https://metacpan.org/module/AnyEvent::I3
  14. # Based in i3-wsbar of Michael Stapelberg -> http://code.stapelberg.de/git/i3/tree/contrib/i3-wsbar
  15. #
  16. # 16 feb 2015 - Electro7
  17. use strict;
  18. use warnings;
  19. use AnyEvent::I3;
  20. use AnyEvent;
  21. use v5.10;
  22. my $socket_path = undef;
  23. my ($workspaces, $outputs) = ([], {});
  24. my $w = AnyEvent->timer(
  25. after => 3,
  26. cb => sub {
  27. die "Connection to i3 timed out. Verify socket path ($socket_path)";
  28. exit 1;
  29. }
  30. );
  31. my $i3 = i3($socket_path);
  32. # Disable buffering
  33. $| = 1;
  34. STDERR->autoflush;
  35. STDOUT->autoflush;
  36. # Wait a short amount of time and try to connect to i3 again
  37. sub reconnect {
  38. print "reconecting\n";
  39. my $timer;
  40. $i3 = i3($socket_path);
  41. if (!defined($w)) {
  42. $w = AnyEvent->timer(
  43. after => 3,
  44. cb => sub {
  45. die "Connection to i3 timed out. Verify socket path ($socket_path)";
  46. exit 1;
  47. }
  48. );
  49. }
  50. my $c = sub {
  51. $timer = AnyEvent->timer(
  52. after => 0.01,
  53. cb => sub { $i3->connect->cb(\&connected) }
  54. );
  55. };
  56. $c->();
  57. }
  58. # Connection attempt succeeded or failed
  59. sub connected {
  60. my ($cv) = @_;
  61. if (!$cv->recv) {
  62. reconnect();
  63. return;
  64. }
  65. $w = undef;
  66. $i3->subscribe({
  67. workspace => \&ws_change,
  68. output => \&output_change,
  69. _error => sub { reconnect() }
  70. });
  71. ws_change();
  72. output_change();
  73. }
  74. # Called when a ws changes
  75. sub ws_change {
  76. # Request the current workspaces and update the output afterwards
  77. $i3->get_workspaces->cb(
  78. sub {
  79. my ($cv) = @_;
  80. $workspaces = $cv->recv;
  81. update_output();
  82. });
  83. }
  84. # Called when the reply to the GET_OUTPUTS message arrives
  85. sub got_outputs {
  86. my $reply = shift->recv;
  87. my %new = map { ($_->{name}, $_) } grep { $_->{active} } @{$reply};
  88. for my $name (keys %new) {
  89. $outputs->{$name} = $new{$name};
  90. }
  91. update_output();
  92. }
  93. sub output_change {
  94. $i3->get_outputs->cb(\&got_outputs)
  95. }
  96. sub update_output {
  97. my $out;
  98. for my $name (keys %{$outputs}) {
  99. $out .= "WSP";
  100. for my $ws (@{$workspaces}) {
  101. my $state = "INA";
  102. $state = "ACT" if $ws->{visible};
  103. $state = "URG" if $ws->{urgent};
  104. $state = "FOC" if $ws->{focused};
  105. my $name = $ws->{name};
  106. $out .= qq|$state$name |;
  107. }
  108. $out .= "\n";
  109. print $out;
  110. }
  111. }
  112. $i3->connect->cb(\&connected);
  113. # let AnyEvent do the rest ("endless loop")
  114. AnyEvent->condvar->recv