Skip to content

Instantly share code, notes, and snippets.

@nobrowser
Created July 9, 2019 01:26
Show Gist options
  • Save nobrowser/cbe0b6b23ef1d5dd791554f03e9831f3 to your computer and use it in GitHub Desktop.
Save nobrowser/cbe0b6b23ef1d5dd791554f03e9831f3 to your computer and use it in GitHub Desktop.
Choose a window ID under bspwm via dmenu
#! /bin/sh localperl
# This is actually -*-Perl-*- code
use strict;
use warnings;
use FileHandle;
use IPC::Open2;
use Getopt::Long;
use Text::Shorten qw(shorten_scalar);
use X11::Xlib;
use X11::Xlib::Display;
$main::display = X11::Xlib::Display->new;
$main::atomname = X11::Xlib::XInternAtom($main::display, 'WM_NAME', 0);
$main::atomstring = X11::Xlib::XInternAtom($main::display, 'STRING', 0);
$main::root = $main::display->RootWindow;
my ($xroot, $xparent) = (undef, undef);
@main::xkids = undef;
($xroot, $xparent, @main::xkids) = X11::Xlib::XQueryTree($main::display, $main::root);
sub get_window_name {
our ($display, $atomname, $atomstring, @xkids);
my $xid = $_[0];
return undef unless grep { $_ == $xid } @xkids;
my @atoms = X11::Xlib::XListProperties($display, $xid);
return undef unless grep { $_ == $atomname } @atoms;
my ($xtype, $xformat, $xitems, $xafter, $xdata) = (undef, undef, undef, undef, undef);
my $retval = X11::Xlib::XGetWindowProperty($display, $xid, $atomname, 0, 32, 0, $atomstring,
$xtype, $xformat, $xitems, $xafter, $xdata);
return undef if !defined $retval || $retval || !$xdata;
return $xdata;
}
sub safe_pipe {
my @argv = @_;
open(my $fh, "-|") || exec @argv;
my @lines;
while (<$fh>) {
push @lines, $_;
}
close $fh;
return @lines;
}
my @win_ids = safe_pipe('bspc', 'query', '-N');
my $brief;
GetOptions("brief" => \$brief);
my %ids_by_names;
GET_NAMES:
foreach my $windowid (@win_ids) {
chomp $windowid;
next GET_NAMES unless $windowid =~ m(^0x[0-9a-f]+$)i;
my $nameline = get_window_name(hex($windowid));
next GET_NAMES unless $nameline;
next GET_NAMES unless $nameline =~ m(^\s*(\S(.*\S)?)\s*$) ;
$nameline = $1;
if ($brief) {
$nameline =~ s(^[^[:alpha:]]*)(); next GET_NAMES unless $nameline;
$nameline = shorten_scalar($nameline, 16);
}
$ids_by_names{$nameline} = $windowid;
}
exit(1) unless %ids_by_names;
my $pid = open2(*Reader, *Writer, "dmenu -i");
while (my ($k, $v) = each %ids_by_names) {
printf Writer ("%s\n", $k);
}
close Writer;
my $selected_name = <Reader>;
waitpid($pid, 0);
exit(1) unless $selected_name;
chomp $selected_name;
print STDOUT $ids_by_names{$selected_name};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment