Statusbar for FVWM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
A Statusbar for FVWM | |
==================== | |
My configs for the statusbar seen at the bottom of my screenshot | |
http://i.imgur.com/RaeCY46.png?1 | |
3 files below :- | |
1] Lines from my main config that relate to the statusbar. On my laptop, whenever the | |
volume/brightness are changed, a SendToModule command is sent to the FuBarStats module | |
to update the volume/brightness in the statusbar. | |
2] modules/FuBar This file is Read during startup. It contains an FvwmButtons config, | |
and starts two modules, the Fvwmbuttons module and an fvwmperl module FuBarStats | |
3] lib/FuBarStats An fvwmperl module that monitors various system info, and continually | |
updates the FvwmButtons module via SendToModule commands. It is well enough commented, I hope. | |
Parts of this won't work for you. You will need your own icons within the ImagePath for the statusbar. | |
And parts of FuBarStats related to volume/brightness may not work on your laptop. | |
#### MORE INFO ABOUT FVWMPERL MODULES | |
## Read the hidden fvwmperl manpages | |
$ fvwm-perllib man index | |
## A folder full of simple fvwmperl examples | |
ftp://ftp.fvwm.org/pub/fvwm/devel/sources/tests/perl/ | |
## An excellent fvwmperl module example | |
http://www.fvwmforums.org/phpBB3/viewtopic.php?f=38&t=3069&hilit=fvwmsleep | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#### From my ~/.fvwm/config | |
## To start the FuBar module | |
AddToFunc StartFunction I Read modules/FuBar | |
## Win + S : Hide/Unhide the statusbar | |
Key S A 4 ToggleFuBar | |
Key XF86AudioRaiseVolume A A VolumeUp | |
Key XF86AudioLowerVolume A A VolumeDown | |
Key XF86MonBrightnessDown A A BrightDown | |
Key XF86MonBrightnessUp A A BrightUp | |
DestroyFunc BrightUp | |
AddToFunc BrightUp | |
+ I Exec sudo /root/bin/bl_up.sh | |
+ I Schedule 300 SendToModule FuBarStats show_bright | |
DestroyFunc BrightDown | |
AddToFunc BrightDown | |
+ I Exec sudo /root/bin/bl_down.sh | |
+ I Schedule 300 SendToModule FuBarStats show_bright | |
DestroyFunc VolumeUp | |
AddToFunc VolumeUp | |
+ I Exec amixer set Master "3%+" -q &>/dev/null | |
+ I Schedule 300 SendToModule FuBarStats show_volume | |
DestroyFunc VolumeDown | |
AddToFunc VolumeDown | |
+ I Exec amixer set Master "3%-" -q &>/dev/null | |
+ I Schedule 300 SendToModule FuBarStats show_volume |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## vim: syntax=fvwm: | |
## | |
## FBBar - a combined system-tray and status-bar. | |
## | |
## The statusbar is implemented as an FvwmButtons module. An fvwmperl | |
## module FuBarStats uses Sys::Statistics::Linux to monitor system info, | |
## and to keep FuBar updated with the info. | |
DestroyModuleConfig FuBar: * | |
*FuBar: Geometry 1366x20 | |
*FuBar: Columns 1366 | |
*FuBar: Rows 20 | |
*FuBar: Padding 0 0 | |
*FuBar: BoxSize fixed | |
*FuBar: Frame 0 | |
*FuBar: Fore gray65 | |
*FuBar: Back gray9 | |
*FuBar: Font -misc-tamsyn-bold-r-normal--20-145-100-100-c-100-iso8859-1 | |
## DESKTOP 120x | |
*FuBar: (20x20) | |
*FuBar: (80x20, id z1, Back gray10, Fore gray60, Title "four") | |
#*FuBar: (220x20) | |
*FuBar: (20x20) | |
## VOLUME 100x | |
*FuBar: (20x20, Colorset 73, Icon volume.xbm) | |
*FuBar: (20x20) | |
*FuBar: (40x20, id q1, Title (Right) "54%") | |
*FuBar: (35x20) | |
## BRIGHTNESS 100x | |
*FuBar: (20x20, Colorset 73, Icon bright.xbm) | |
*FuBar: (15x20) | |
*FuBar: (40x20, id q2, Title (Right) "54%") | |
*FuBar: (35x20) | |
# 60p = 40p + 20p | |
## CELCIUS 80x | |
*FuBar: (20x20, Colorset 73, Icon celcius.xbm) | |
*FuBar: (15x20) | |
*FuBar: (40x20, id celsius, Title (Right) "54°") | |
*FuBar: (30x20) | |
## NETRX 140x | |
*FuBar: (30x20, Colorset 73, Icon bar_down.xbm) | |
*FuBar: (20x20) | |
*FuBar: (80x20, id z5, Title (Right) "234KB/s") | |
*FuBar: (30x20) | |
# 76p = 56p + 20p | |
## NETTX 140x | |
*FuBar: (30x20, Colorset 73, Icon bar_up.xbm) | |
*FuBar: (20x20) | |
*FuBar: (80x20, id z6, Title (Right) "234KB/s") | |
*FuBar: (30x20) | |
## MEMORY 140x | |
*FuBar: (25x20, Colorset 73, Icon mem.xbm) | |
*FuBar: (20x20) | |
*FuBar: (60x20, id z4, Title (Right) "528M") | |
*FuBar: (35x20) | |
## CPU 130x | |
*FuBar: (25x20, Colorset 73, Icon bar_cpu2.xbm) | |
*FuBar: (20x20) | |
*FuBar: (40x20, id z2, Title (Right) "99%") | |
*FuBar: (40x20) | |
*FuBar: (97x20) | |
## DATE/TIME 235x | |
*FuBar: (24x20, Colorset 73, Icon bar_clock3.xbm) | |
*FuBar: (25x20) | |
*FuBar: (60x20, id z7, Title (Right) " 3 Jul") | |
*FuBar: (10x20) | |
*FuBar: (70x20, id z8, Title (Right) " 15:58:") | |
*FuBar: (20x20, id z9, Title (Right) "22") | |
*FuBar: (25x20) | |
#*FuBar: (1x20, Colorset 74) | |
## TOTAL 1185x | |
## PADDING = 1366-1185 = 181 | |
#### FUBAR STYLES | |
## tamsyn-bold-20 char == 10px * 20px | |
## Each gohufont-14 char is 8p wide. | |
Colorset 72 fg gray60, bg gray10 | |
#Colorset 73 fg LightSlateGray, bg Gray20 | |
Colorset 73 fg #5B80A6, bg Gray20 | |
#DestroyStyle FuBar | |
Style FuBar !Title, !Handles, !Borders, | |
Style FuBar Sticky, StaysOnTop, WindowListSkip, CirculateSkip, NeverFocus, Layer 7 | |
Style FuBar PositionPlacement 0p 748p, InitialMapCommand Move 0p 748p | |
UpdateStyles | |
DestroyFunc ToggleFuBar | |
AddToFunc ToggleFuBar | |
+ I Next (CirculateHit, FuBar, Sticky) LowerFuBar | |
+ I Next (CirculateHit, FuBar, Sticky) Break | |
+ I Next (CirculateHit, FuBar, !Sticky) RaiseFuBar | |
DestroyFunc LowerFuBar | |
AddToFunc LowerFuBar | |
+ I Move 0p 753p | |
+ I Schedule 200 Move 0p 758p | |
+ I Schedule 400 Move 0p 763p | |
+ I Schedule 600 Move 0p 768p | |
+ I Schedule 620 ThisWindow WindowStyle !Sticky | |
DestroyFunc RaiseFuBar | |
AddToFunc RaiseFuBar | |
+ I Move 0p 763p | |
+ I Schedule 200 Move 0p 758p | |
+ I Schedule 400 Move 0p 753p | |
+ I Schedule 600 Move 0p 748p | |
+ I Schedule 620 ThisWindow WindowStyle Sticky | |
UpdateStyles | |
KillModule FvwmButtons FuBar | |
KillModule FuBarStats | |
Module FvwmButtons FuBar | |
Module FuBarStats | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
## Fvwm module to collect system stats, and use them to update | |
## the various values and fields of the FvwmButtons statusbar. | |
use strict ; | |
use warnings ; | |
use v5.18 ; | |
use lib `fvwm-perllib dir`; | |
use FVWM::Module; | |
use Sys::Statistics::Linux ; | |
use POSIX ; | |
#use Data::Dump qw( dump ) ; | |
## Name of the target FvwmButtons statusbar module. | |
my $fbmodname = "FuBar" ; | |
## Seconds duration between each statusbar update. | |
my $pollinterval = 1 ; | |
## Count of the total number of updates so far. | |
my $cnt = 0 ; | |
## Vars to store date and time. | |
my $last_hrsmins = my $last_date = "" ; | |
## To queue up fvwm cmnds before they are sent. | |
my @cmds = () ; | |
## Hash ref to store info from the stats module $lxs | |
my $stats ; | |
## Desktop number, from the last time it was checked. | |
my $last_desk = 1 ; | |
## Text labels associated with each desktop number. | |
my @desks = ( | |
"zero ", " one ", " two ", "three", "four ", | |
"five ", " six ", "seven", "eight", "nine ", | |
) ; | |
## To gather system info from /proc | |
my $lxs = Sys::Statistics::Linux->new( | |
cpustats => 1, | |
diskstats => 1, | |
netstats => 1, | |
) ; | |
## memstats => 1, | |
## To send commands to the statusbar via FVWM. | |
my $module = new FVWM::Module( | |
Name => 'FuBarStats', | |
Debug => 0, | |
); | |
## Store the name of this fvwmperl module. | |
my $modname = $module->name ; | |
## Initialize the stats module. | |
$lxs->init ; | |
## Setup alarm for periodic statusbar updates. | |
$SIG{ALRM} = \&polling ; | |
## Tracker to detect and update any desktop changes. | |
my $page_tracker = $module->track("PageInfo") ; | |
$page_tracker->observe(sub { | |
my ($module, $tracker, $info) = @_; | |
update_desk($info->{desk_n}) ; | |
}); | |
## Handler to intercept SendToModule cmnds sent from FVWM | |
$module->addHandler(M_STRING, \&process_cmd); | |
## Start by refreshing all statusbar fields. | |
update_bar() ; | |
show_bright() ; | |
show_volume() ; | |
update_celsius() ; | |
## Begin the periodic updates. | |
alarm($pollinterval) ; | |
## Continually listen to events from fvwm, except when | |
## interrupted periodically by alarm. | |
$module->event_loop ; | |
#### SUBROUTINES | |
## To process fvwm events and act upon them. In this case, the events are | |
## generated by SendToModule cmnds that prompt us to check the values for | |
## volume/brightness, and display their updated values accordingly. | |
sub process_cmd { | |
my ($module, $event) = @_ ; | |
my ($s) = $event->_text ; | |
my ($command, $arg) = $s =~ /\s*(\w+)\s*(.*)/ ; | |
my %cmd = ( | |
show_volume => sub { show_volume() }, | |
show_bright => sub { show_bright() }, | |
) ; | |
if (defined $cmd{$command}) { | |
$cmd{$command}() ; | |
} else { | |
$module->showMessage("unknown command \"$command\""); | |
} | |
} | |
## Help to set up periodic updates via alarm() | |
sub polling { | |
update_bar() if not -e '/tmp/stopfubar' ; | |
alarm($pollinterval) ; | |
return ; | |
} | |
## The main subroutine is run periodically via alarm() to | |
## update the various statusbar values and fields. | |
sub update_bar { | |
## Refresh the system stats. | |
$stats = $lxs->get ; | |
update_datetime() ; | |
update_cpustats() ; | |
update_memstats() if $cnt%5 == 0 ; | |
update_celsius() if $cnt%10 == 0 ; | |
update_netstats() ; | |
sendcmds() ; | |
$cnt++ ; | |
} | |
sub update_celsius { | |
my $celsius = readpipe("cat /sys/devices/virtual/thermal/thermal_zone0/temp") ; | |
$celsius = rounded($celsius/1000) ; | |
$celsius .= "°" ; | |
addcmd("SendToModule $fbmodname ChangeButton celsius Title \"${celsius}\"") ; | |
} | |
sub update_datetime { | |
my ( $sec, $min, $hr, $mday, $mnth, $foo ) = localtime() ; | |
my @mnths = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec ) ; | |
my $padsec = sprintf "%02d", $sec ; | |
my $date = "$mday ".$mnths[$mnth] ; | |
my $hrsmins = sprintf "%02d:%02d:", $hr, $min ; | |
addcmd("SendToModule $fbmodname ChangeButton z9 Title $padsec") ; | |
if ($date ne $last_date) { | |
addcmd("SendToModule $fbmodname ChangeButton z7 Title \"${date}\"") ; | |
$last_date = $date ; | |
} | |
if ($hrsmins ne $last_hrsmins) { | |
addcmd("SendToModule $fbmodname ChangeButton z8 Title ${hrsmins}") ; | |
$last_hrsmins = $hrsmins ; | |
} | |
} | |
sub update_cpustats { | |
## The cpu equation for Sys::Statistics::Linux::CpuStats: | |
## user + system + iowait = 100 - idle = total | |
## Here we seek total cpu minus iowait. | |
my $user = $stats->{cpustats}->{cpu}->{user} ; | |
my $system = $stats->{cpustats}->{cpu}->{system} ; | |
my $cpu = rounded($user + $system) ; | |
$cpu = 99 if $cpu == 100 ; | |
addcmd("SendToModule $fbmodname ChangeButton z2 Title ${cpu}%") ; | |
} | |
## sub update_memstats { | |
## | |
## ## After some investigation, it seems that the memory usage | |
## ## is being over-reported by the Sys::Statistics::Linux::MemStats | |
## ## module when compared to the free cmnd. So obviously, a | |
## ## different method of calculating memory usage is being used. | |
## | |
## my $total = $stats->{memstats}->{memtotal} ; | |
## my $realfree = $stats->{memstats}->{realfree} ; | |
## my $realused = rounded(($total - $realfree)/1024) ; | |
## addcmd("SendToModule $fbmodname ChangeButton z4 Title ${realused}Mb") ; | |
## } | |
sub update_memstats { | |
## It turns out the stats module over-reports memory usage, | |
## so I'm using free cmnd instead. | |
my $used = 0 ; | |
foreach (`free -m`) { | |
if (/^Mem:\s+\d+\s+(\d+)\s/) { | |
$used = $1 | |
} | |
} | |
if ($used) { | |
addcmd("SendToModule $fbmodname ChangeButton z4 Title ${used}Mb") | |
} | |
} | |
sub update_netstats { | |
## Gather disk read/write stats. | |
my $rxbyts = my $txbyts = 0 ; | |
foreach my $netdev (keys %{$stats->{netstats}}) { | |
next if $netdev eq "lo" ; | |
$rxbyts += $stats->{netstats}->{$netdev}->{rxbyt} ; | |
$txbyts += $stats->{netstats}->{$netdev}->{txbyt} ; | |
} ; | |
## Reformat rx/tx to use KB/s or MB/s . | |
my $netrx = $rxbyts < 1048576 ? | |
sprintf "%4.0fKB/s", $rxbyts/1024 : | |
sprintf "%4.1fMB/s", $rxbyts/1048576 ; | |
my $nettx = $txbyts < 1048576 ? | |
sprintf "%4.0fKB/s", $txbyts/1024 : | |
sprintf "%4.1fMB/s", $txbyts/1048576 ; | |
addcmd("SendToModule $fbmodname ChangeButton z5 Title ${netrx}") ; | |
addcmd("SendToModule $fbmodname ChangeButton z6 Title ${nettx}") ; | |
} | |
sub update_desk { | |
my $curr_desk = shift ; | |
return 0 if $curr_desk == $last_desk ; | |
my $desk = $desks[$curr_desk] ; | |
$last_desk = $curr_desk ; | |
addcmd("SendToModule $fbmodname ChangeButton z1 Title \"${desk}\"") ; | |
sendcmds() ; | |
} | |
sub show_bright { | |
my $bright_max = 255 ; | |
my $bl_device="/sys/class/backlight/radeon_bl0/brightness" ; | |
my $actual = `cat $bl_device` ; | |
chomp $actual ; | |
my $bright = ceiling($actual, $bright_max) ; | |
addcmd("SendToModule $fbmodname ChangeButton q2 Title ${bright}%") ; | |
sendcmds() ; | |
} | |
sub show_volume { | |
foreach my $x (`amixer scontents` ) { | |
if ($x =~ /^\s+Mono:\s+Playback.+\[(\d\d?\d?)%\].+$/) { | |
my $vol = $1 < 100 ? $1 : 99 ; | |
addcmd("SendToModule $fbmodname ChangeButton q1 Title ${vol}%") ; | |
sendcmds() ; | |
} | |
} | |
} | |
sub ceiling { | |
my ($num, $max) = @_ ; | |
$num = 0 unless defined $num ; | |
$num = $num > $max ? $max : $num ; | |
$num = nearest(1, $num*100/$max) ; | |
return $num < 100 ? $num : 99 ; | |
} | |
## Cribbed from Math::Round | |
sub nearest { | |
my $targ = abs(shift); | |
my $half = 0.50000000000008 ; | |
my @res = map { | |
if ($_ >= 0) { $targ * int(($_ + $half * $targ) / $targ); } | |
else { $targ * POSIX::ceil(($_ - $half * $targ) / $targ); } | |
} @_ ; | |
return (wantarray) ? @res : $res[0] ; | |
} | |
## Cribbed from Math::Round | |
sub rounded { | |
my $x; | |
my $half = 0.50000000000008 ; | |
my @res = map { | |
if ($_ >= 0) { POSIX::floor($_ + $half); } | |
else { POSIX::ceil($_ - $half); } | |
} @_; | |
return (wantarray) ? @res : $res[0]; | |
} | |
## Two subroutines that add/store and send fvwm cmnds. | |
sub addcmd { push @cmds, $_[0] } ; | |
sub sendcmds { | |
foreach (@cmds) { $module->send($_) } ; | |
@cmds = () ; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment