I'm playing around with the idea of creating an X11 desktop panel using something like Tkx (ActivePerl) or Tcl::Tk, so I was experimenting with some of the X11 modules on CPAN to get a window list, which would be a necessity to create a task list applet for my panel.
I found X11::Tops which gets a window list, including the window titles and their "icon names" (the names for a task switcher applet), but not their icon images. So I used its source code and looked up the X11 docs and wrote the following:
Basically I used the source of X11::Tops to figure out how to get the list of window ID's and pull info out of them, but added support for pulling the _NET_WM_ICON (icon data) and _NET_WM_ICON_GEOMETRY (icon geometry).
According to
So, my code gets a big binary blog of data for _NET_WM_ICON and I tried dumping it to a file to see if Linux would recognize it as any sort of image file (regardless of the .png extension, Linux should see it as its real file type even if the extension was wrong).
If I run the `file` command on the files it created, some of them return GLS_BINARY_LSB_FIRST and some return just "data"
I've narrowed the problem down to, somehow I need to parse and unpack this binary blob I get from X11:rotocol to get the actual image data in some format I can use. Does anybody know more about unpacking this data? I'm not a C programmer and I dunno what "_NET_WM_ICON CARDINAL[][2+n]/32" is supposed to mean.
Kirsle.net | My personal homepage
I found X11::Tops which gets a window list, including the window titles and their "icon names" (the names for a task switcher applet), but not their icon images. So I used its source code and looked up the X11 docs and wrote the following:
Code:
#!/usr/bin/perl -w
# see also: [URL unfurl="true"]http://standards.freedesktop.org/wm-spec/wm-spec-latest.html[/URL]
use 5.10.0;
use strict;
use warnings;
use X11::Protocol;
use MIME::Base64 qw(encode_base64);
my @getpropconst = ('AnyPropertyType', 0, -1, 0);
# based on X11::Tops but to get more info
my $X = X11::Protocol->new();
my $xtops = {};
$xtops->{X} = $X;
$xtops->{root} = $X->root; # assumes only 1 screen
$xtops->{$_} = $X->InternAtom($_, 0) for qw(
_NET_CLIENT_LIST
_XCHAR_CHAR
_XCHAR_COMMAND
);
$xtops->{$_} = $X->atom($_) for qw(
_WIN_CLIENT_LIST
_NET_ACTIVE_WINDOW
_NET_CLIENT_LIST_STACKING
WM_CLASS
WM_NAME
WM_ICON_NAME
_NET_WM_ICON_GEOMETRY
_NET_WM_ICON
STRING
WM_NORMAL_HINTS
WM_SIZE_HINTS
);
$xtops->{$_} || croak("failed to create atom $_") for qw(
_XCHAR_CHAR
_XCHAR_COMMAND
);
# fetch the ID's taken from X11::Tops::fetch_ids()
my $_NET_CLIENT_LIST = $xtops->{_NET_CLIENT_LIST};
my ($value,$type,$format,$bytes_after) =
$X->GetProperty($xtops->{root}, $_NET_CLIENT_LIST, @getpropconst);
my @ids = unpack('L*', $value);
print "Window IDs: @ids\n";
foreach my $id (@ids) {
# Window class
my $WM_CLASS = $xtops->{WM_CLASS};
{
my ($value,$type,$format,$bytes_after) = $X->GetProperty($id, $WM_CLASS, @getpropconst);
my ($instance,$class) = split("\0", $value);
print "Window ID: $id\nInstance: $instance\nClass: $class\n";
}
# Get its title
my $WM_NAME = $xtops->{WM_NAME};
my $wintitle;
{
my ($value,$type,$format,$bytes_after) = $X->GetProperty($id, $WM_NAME, @getpropconst);
print "Title: $value\n";
$wintitle = $value;
}
# Icon title
my $WM_ICON_NAME = $xtops->{WM_ICON_NAME};
{
my ($value,$type,$format,$bytes_after) = $X->GetProperty($id, $WM_ICON_NAME, @getpropconst);
print "Icon name: $value\n";
}
# Get icon geometry
my $WM_ICON_GEOMETRY = $xtops->{_NET_WM_ICON_GEOMETRY};
{
my ($value,$type,$format,$bytes_after) = $X->GetProperty($id, $WM_ICON_GEOMETRY, @getpropconst);
print "Geometry: $value\n";
}
# Get its icon image
my $WM_ICON = $xtops->{_NET_WM_ICON};
{
my ($value,$type,$format,$bytes_after) = $X->GetProperty($id, $WM_ICON, @getpropconst);
print "Icon: " . length($value) . "\n\n";
open (TEST, ">$wintitle.png");
binmode TEST;
print TEST $value;
close (TEST);
my @atoms = $X->ListProperties($id);
my @names = map { $X->atom_name($_) } @atoms;
print "props: @names\n";
}
}
Basically I used the source of X11::Tops to figure out how to get the list of window ID's and pull info out of them, but added support for pulling the _NET_WM_ICON (icon data) and _NET_WM_ICON_GEOMETRY (icon geometry).
According to
_NET_WM_ICON
_NET_WM_ICON CARDINAL[][2+n]/32
This is an array of possible icons for the client. This specification does not stipulate what size these icons should be, but individual desktop environments or toolkits may do so. The Window Manager MAY scale any of these icons to an appropriate size.
This is an array of 32bit packed CARDINAL ARGB with high byte being A, low byte being B. The first two cardinals are width, height. Data is in rows, left to right and top to bottom.
So, my code gets a big binary blog of data for _NET_WM_ICON and I tried dumping it to a file to see if Linux would recognize it as any sort of image file (regardless of the .png extension, Linux should see it as its real file type even if the extension was wrong).
If I run the `file` command on the files it created, some of them return GLS_BINARY_LSB_FIRST and some return just "data"
I've narrowed the problem down to, somehow I need to parse and unpack this binary blob I get from X11:rotocol to get the actual image data in some format I can use. Does anybody know more about unpacking this data? I'm not a C programmer and I dunno what "_NET_WM_ICON CARDINAL[][2+n]/32" is supposed to mean.
Kirsle.net | My personal homepage
Code:
perl -e '$|=$i=1;print" oo\n<|>\n_|_";x:sleep$|;print"\b",$i++%2?"/":"_";goto x;'