perlx11gtk3

How to list all X11 windows using Gtk3::Gdk


I have a Perl Gtk3 script in which I'd like to get a list of all X11 windows open on the current display.

So far, I have:

#!/usr/bin/perl -w
package Gtk3::Gdk::X11;
use strict;
use Glib::Object::Introspection;
Glib::Object::Introspection->setup(basename => 'GdkX11', version  => '3.0', package  => 'Gtk3::Gdk');

package main;
use strict;
use Gtk3 -init;
use Data::Dumper;
my $x_root = Gtk3::Gdk::x11_get_default_root_xwindow();
print "x_root = " . Dumper $x_root;
my $gdk_screen = Gtk3::Gdk::Screen::get_default();
print "gdk_screen = " . Dumper $gdk_screen;
my $wm_name = $gdk_screen->get_window_manager_name;
print "wm_name = '$wm_name'\n";
my $gdk_display = Gtk3::Gdk::Display::open(':0');
print "gdk_display = " . Dumper $gdk_display;
my $gdk_root = Gtk3::Gdk::X11Window::foreign_new_for_display($x_root, $gdk_display, $x_root);
print "gdk_root = " . Dumper $gdk_root;
my $a_net_client_list = Gtk3::Gdk::atom_intern('_NET_CLIENT_LIST', 1);
print "a_net_client_list = " . Dumper $a_net_client_list;
my $a_window = Gtk3::Gdk::atom_intern('WINDOW', 1);
print "a_window = " . Dumper $a_window;
my $wins = Gtk3::Gdk::property_get($gdk_root, $a_net_client_list, $a_window, 0, 1024, 0);
print "wins = " . Dumper $wins;

But that results in:

x_root = $VAR1 = 2443;
gdk_screen = $VAR1 = bless( {}, 'Gtk3::Gdk::X11Screen' );
wm_name = 'Xfwm4'
gdk_display = $VAR1 = bless( {}, 'Gtk3::Gdk::X11Display' );
gdk_root = $VAR1 = bless( {}, 'Gtk3::Gdk::X11Window' );
a_net_client_list = $VAR1 = bless( do{\(my $o = 129)}, 'Gtk3::Gdk::Atom');
a_window = $VAR1 = bless( do{\(my $o = 33)}, 'Gtk3::Gdk::Atom' );
**
ERROR:gperl-i11n-marshal-struct.c:43:struct_to_sv: assertion failed: (!own)
Aborted (core dumped)

If there's a way to use libwnck3 in Perl, that might work too.


Solution

  • I found a solution (although not my preferred one):

    #!/usr/bin/perl -w
    use strict;
    use Gtk3 -init;
    use Glib::Object::Introspection;
    Glib::Object::Introspection->setup(basename => 'GdkX11', version  => '3.0', package  => 'Gtk3::Gdk');
    Glib::Object::Introspection->setup(basename => 'Wnck', version  => '3.0', package  => 'Wnck');
    
    my $screen = Wnck::Screen::get_default();
    $screen->force_update;
    for my $win (@{$screen->get_windows}) {
            my $name = $win->get_name;
            my $ws = $win->get_workspace;
            my $w = $ws ? $ws->get_number : -1;
            printf "(%04d, %04d) %04dx%04d:%2s $name\n", $win->get_geometry, $w;
    }
    

    The reason I'd rather not use Wnck is because the documentation says: the use of this library is relatively expensive in terms of resources. My application doesn't need most of the features that Wnck offers so it's a bit overkill.