#! /usr/bin/perl # xswitch - Graphicsl switch utility # Copyright (c) 2008 Joey Schulze # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. use strict; use warnings; use Getopt::Long; use Config::IniFiles; use Gtk2; my $config; my $info = {}; my $tooltips; my $opt_config = $ENV{'HOME'} . '/etc/xswitch.conf'; sub config_read { my $fname = shift; die "No configuration file found" unless -r $fname; my $cfg = new Config::IniFiles(-file => $fname); return $cfg; } sub config_process { my $fname; $info->{current} = ${$config->{sects}}[0]; } sub next_state { my $action = $config->val($info->{current}, 'action'); return $info->{current} unless defined $action; if ($action eq 'cycle') { my $i; for ($i=0;$info->{current} ne ${$config->{sects}}[$i] && $i<=$#{$config->{sects}};$i++) {}; if ($i == $#{$config->{sects}}) { return ${$config->{sects}}[0]; } else { return ${$config->{sects}}[$i+1]; } } return $info->{current}; } sub window_update { my $fname = $config->val($info->{current}, 'image'); if ($fname && defined(my $img = Gtk2::Image->new_from_file($fname))) { $info->{button}->set_image($img); $info->{button}->set_label(''); } else { $info->{button}->set_image(undef); $info->{button}->set_label($info->{current}); } my $tip = $config->val($info->{current}, 'tooltip'); if ($tip) { $tooltips->set_tip ($info->{button}, $tip); } else { $tooltips->set_tip ($info->{button}, ''); } } sub callback_command { my $cmd = $config->val($info->{current}, 'command'); if (length $cmd) { system("$cmd") == 0 or print STDERR "$cmd failed: $?\n"; } my $next = next_state; if ($next ne $info->{current}) { $info->{current} = $next; window_update; } } sub mainwindow { my $window = Gtk2::Window->new('popup'); $tooltips = new Gtk2::Tooltips; $tooltips->enable; $window->set_title('X-Switch'); $window->set_gravity('south-east'); $window->signal_connect('destroy' => sub { Gtk2->main_quit }); $info->{button} = Gtk2::Button->new(); $info->{button}->signal_connect('clicked' => \&callback_command); $info->{button}->set_border_width(0); window_update; $window->add($info->{button}); $window->show_all; } sub usage { print "xswitch [--help] [--config cfg]\n"; print "Provide a popup window for cycling actions\n"; print "e.g. for switching between keyboard layouts\n"; exit(0); } GetOptions('config=s' => \$opt_config, 'help' => \&usage); $config = config_read $opt_config; config_process; init Gtk2; mainwindow; Gtk2->main;