Commit fe2b4e41 authored by epsi sayidina's avatar epsi sayidina

herbstluftwm tags with dzen2

parent ff9f8786
package gmc;
use warnings;
use strict;
use Exporter;
our @ISA = 'Exporter';
our @EXPORT = qw(%color);
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# google material colors
# https://material.io/guidelines/style/color.html
# Associative Array (Hash)
our %color = (
'white' => '#ffffff',
'black' => '#000000',
'grey50' => '#fafafa',
'grey100' => '#f5f5f5',
'grey200' => '#eeeeee',
'grey300' => '#e0e0e0',
'grey400' => '#bdbdbd',
'grey500' => '#9e9e9e',
'grey600' => '#757575',
'grey700' => '#616161',
'grey800' => '#424242',
'grey900' => '#212121',
'red50' => '#ffebee',
'red100' => '#ffcdd2',
'red200' => '#ef9a9a',
'red300' => '#e57373',
'red400' => '#ef5350',
'red500' => '#f44336',
'red600' => '#e53935',
'red700' => '#d32f2f',
'red800' => '#c62828',
'red900' => '#b71c1c',
'redA100' => '#ff8a80',
'redA200' => '#ff5252',
'redA400' => '#ff1744',
'redA700' => '#d50000',
'pink50' => '#fce4ec',
'pink100' => '#f8bbd0',
'pink200' => '#f48fb1',
'pink300' => '#f06292',
'pink400' => '#ec407a',
'pink500' => '#e91e63',
'pink600' => '#d81b60',
'pink700' => '#c2185b',
'pink800' => '#ad1457',
'pink900' => '#880e4f',
'pinkA100' => '#ff80ab',
'pinkA200' => '#ff4081',
'pinkA400' => '#f50057',
'pinkA700' => '#c51162',
'blue50' => '#e3f2fd',
'blue100' => '#bbdefb',
'blue200' => '#90caf9',
'blue300' => '#64b5f6',
'blue400' => '#42a5f5',
'blue500' => '#2196f3',
'blue600' => '#1e88e5',
'blue700' => '#1976d2',
'blue800' => '#1565c0',
'blue900' => '#0d47a1',
'blueA100' => '#82b1ff',
'blueA200' => '#448aff',
'blueA400' => '#2979ff',
'blueA700' => '#2962ff',
'yellow50' => '#fffde7',
'yellow100' => '#fff9c4',
'yellow200' => '#fff59d',
'yellow300' => '#fff176',
'yellow400' => '#ffee58',
'yellow500' => '#ffeb3b',
'yellow600' => '#fdd835',
'yellow700' => '#fbc02d',
'yellow800' => '#f9a825',
'yellow900' => '#f57f17',
'yellowA100' => '#ffff8d',
'yellowA200' => '#ffff00',
'yellowA400' => '#ffea00',
'yellowA700' => '#ffd600',
'teal50' => '#e0f2f1',
'teal100' => '#b2dfdb',
'teal200' => '#80cbc4',
'teal300' => '#4db6ac',
'teal400' => '#26a69a',
'teal500' => '#009688',
'teal600' => '#00897b',
'teal700' => '#00796b',
'teal800' => '#00695c',
'teal900' => '#004d40',
'tealA100' => '#a7ffeb',
'tealA200' => '#64ffda',
'tealA400' => '#1de9b6',
'tealA700' => '#00bfa5',
'green50' => '#e8f5e9',
'green100' => '#c8e6c9',
'green200' => '#a5d6a7',
'green300' => '#81c784',
'green400' => '#66bb6a',
'green500' => '#4caf50',
'green600' => '#43a047',
'green700' => '#388e3c',
'green800' => '#2e7d32',
'green900' => '#1b5e20',
'greenA100' => '#b9f6ca',
'greenA200' => '#69f0ae',
'greenA400' => '#00e676',
'greenA700' => '#00c853',
'orange50' => '#fff3e0',
'orange100' => '#ffe0b2',
'orange200' => '#ffcc80',
'orange300' => '#ffb74d',
'orange400' => '#ffa726',
'orange500' => '#ff9800',
'orange600' => '#fb8c00',
'orange700' => '#f57c00',
'orange800' => '#ef6c00',
'orange900' => '#e65100',
'orangeA100' => '#ffd180',
'orangeA200' => '#ffab40',
'orangeA400' => '#ff9100',
'orangeA700' => '#ff6d00',
'deepOrange50' => '#fbe9e7',
'deepOrange100' => '#ffccbc',
'deepOrange200' => '#ffab91',
'deepOrange300' => '#ff8a65',
'deepOrange400' => '#ff7043',
'deepOrange500' => '#ff5722',
'deepOrange600' => '#f4511e',
'deepOrange700' => '#e64a19',
'deepOrange800' => '#d84315',
'deepOrange900' => '#bf360c',
'deepOrangeA100' => '#ff9e80',
'deepOrangeA200' => '#ff6e40',
'deepOrangeA400' => '#ff3d00',
'deepOrangeA700' => '#dd2c00'
);
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# end of perl module
1;
package helper;
use warnings;
use strict;
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# helpers
# script arguments
sub get_monitor {
my @arguments = @_;
my $num_args = $#arguments;
# ternary operator
my $monitor = ($num_args > 0) ? $arguments[0] : 0;
return $monitor;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# geometry calculation
sub get_geometry {
my $monitor = shift;
my $geometry_qx = qx(herbstclient monitor_rect "$monitor");
if ($geometry_qx eq "") {
print "Invalid monitor $monitor\n";
exit 1
}
my @geometry = split / /, $geometry_qx;
return @geometry;
}
sub get_top_panel_geometry {
my $height = shift;
my @geometry = @_;
# geometry has the format X Y W H
return ($geometry[0], $geometry[1], $geometry[2], $height);
}
sub get_bottom_panel_geometry {
my $height = shift;
my @geometry = @_;
# geometry has the format X Y W H
return ($geometry[0], $geometry[3]-$height, $geometry[2], $height);
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# dzen Parameters
sub get_dzen2_parameters {
my $monitor = shift;
my $panel_height = shift;
my @geometry = get_geometry($monitor);
my ($xpos, $ypos, $width, $height) =
get_top_panel_geometry($panel_height, @geometry);
my $bgcolor = '#000000';
my $fgcolor = '#ffffff';
my $font = '-*-takaopgothic-medium-*-*-*-12-*-*-*-*-*-*-*';
my $parameters = " -x $xpos -y $ypos -w $width -h $height";
$parameters .= " -fn '$font'";
$parameters .= " -ta l -bg '$bgcolor' -fg '$fgcolor'";
$parameters .= " -title-name dzentop";
return $parameters;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# end of perl module
1;
package output;
use warnings;
use strict;
use File::Basename;
use lib dirname(__FILE__);
use gmc;
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# initialize
# custom tag names
my @tag_shows = ('一 ichi', '二 ni', '三 san', '四 shi',
'五 go', '六 roku', '七 shichi', '八 hachi', '九 kyū', '十 jū');
# initialize variable segment
my $segment_windowtitle = '';
my @tags_status = [];
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# decoration
my $separator = "^bg()^fg($color{'black'})|^bg()^fg()";
# http://fontawesome.io/
my $font_awesome = "^fn(FontAwesome-9)";
# Powerline Symbol
my $right_hard_arrow = "^fn(powerlinesymbols-14)^fn()";
my $right_soft_arrow = "^fn(powerlinesymbols-14)^fn()";
my $left_hard_arrow = "^fn(powerlinesymbols-14)^fn()";
my $left_soft_arrow = "^fn(powerlinesymbols-14)^fn()";
# theme
my $pre_icon = "^fg($color{'yellow500'})$font_awesome";
my $post_icon = "^fn()^fg()";
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# main
sub get_statusbar_text {
my $monitor = shift;
my $text = '';
# draw tags
foreach my $tag_status (@tags_status) {
$text .= output_by_tag($monitor, $tag_status);
}
# draw window title
$text .= output_leftside_top();
return $text;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# each segments
sub output_by_tag {
my $monitor = shift;
my $text = '';
my $tag_status = shift;
my $tag_index = substr($tag_status, 1, 1);
my $tag_mark = substr($tag_status, 0, 1);
my $tag_name = $tag_shows[$tag_index - 1]; # zero based
# ----- pre tag
if ($tag_mark eq '#') {
$text .= "^bg($color{'blue500'})^fg($color{'black'})";
$text .= $right_hard_arrow;
$text .= "^bg($color{'blue500'})^fg($color{'white'})";
} elsif ($tag_mark eq '+') {
$text .= "^bg($color{'yellow500'})^fg($color{'grey400'})";
} elsif ($tag_mark eq ':') {
$text .= "^bg()^fg($color{'white'})";
} elsif ($tag_mark eq '!') {
$text .= "^bg($color{'red500'})^fg($color{'white'})";
} else {
$text .= "^bg()^fg($color{'grey600'})";
}
# ----- tag by number
# assuming using dzen2_svn
# clickable tags if using SVN dzen
$text .= "^ca(1,herbstclient focus_monitor \"$monitor\" && ";
$text .= "herbstclient use \"$tag_index\") $tag_name ^ca() ";
# ----- post tag
if ($tag_mark eq '#') {
$text .= "^bg($color{'black'})^fg($color{'blue500'})$right_hard_arrow";
}
return $text;
}
sub output_leftside_top {
my $text = " ^r(5x0) $separator ^r(5x0) ";
$text .= $segment_windowtitle;
return $text;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# setting variables, response to event handler
sub set_tag_value {
my $monitor = shift;
my $tag_status_qx = qx(herbstclient tag_status $monitor);
$tag_status_qx =~ s/^\s+|\s+$//g;
@tags_status = split(/\t/, $tag_status_qx);
}
sub set_windowtitle {
my $windowtitle = shift;
my $icon = "$pre_icon$post_icon";
$segment_windowtitle = " $icon ^bg()^fg($color{'grey700'}) $windowtitle";
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# end of perl module
1;
#!/usr/bin/perl
# This is a modularized config for herbstluftwm tags in dzen2 statusbar
use warnings;
use strict;
use File::Basename;
use lib dirname(__FILE__);
use helper;
use pipehandler;
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# initialize
my $panel_height = 24;
my $monitor = helper::get_monitor(@ARGV);
# do `man herbsluftclient`, and type \pad to search what it means
#system("herbstclient pad $monitor $panel_height 0 $panel_height 0");
my $dzen2_parameters = helper::get_dzen2_parameters($monitor, $panel_height);
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# main
# remove all dzen2 instance
system('pkill dzen2');
# run process in the background
pipehandler::detach_dzen2($monitor, $dzen2_parameters);
# optional transparency
pipehandler::detach_transset();
package pipehandler;
use warnings;
use strict;
use IO::Pipe;
use File::Basename;
use lib dirname(__FILE__);
use output;
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# pipe
sub handle_command_event {
my $monitor = shift;
my $event = shift;
# find out event origin
my @column = split(/\t/, $event);
my $origin = $column[0];
if ($origin eq 'reload') {
system('pkill dzen2');
} elsif ($origin eq 'quit_panel') {
exit;
} elsif ( # avoiding the unstable ~~ smartmatch operator
($origin eq 'tag_changed')
or ($origin eq 'tag_flags')
or ($origin eq 'tag_added')
or ($origin eq 'tag_removed')
) {
output::set_tag_value($monitor);
} elsif ( ($origin eq 'window_title_changed')
or ($origin eq 'focus_changed')
) {
output::set_windowtitle($column[2]);
}
}
sub do_content {
my $monitor = shift;
my $pipe_out = shift;
# initialize statusbar before loop
output::set_tag_value($monitor);
my $text = output::get_statusbar_text($monitor);
print $pipe_out $text."\n";
flush $pipe_out;
# start a pipe
my $pipe_in = IO::Pipe->new();
my $command = 'herbstclient --idle';
my $handle = $pipe_in->reader($command);
my $event = '';
while(<$pipe_in>) {
# wait for next event
$event = $_;
handle_command_event($monitor, $event);
$text = output::get_statusbar_text($monitor);
print $pipe_out $text;
flush $pipe_out;
}
$pipe_in->close();
}
sub run_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pipe_out = IO::Pipe->new();
my $command = "dzen2 $parameters";
my $handle = $pipe_out->writer($command);
do_content($monitor, $pipe_out);
$pipe_out->close();
}
sub detach_dzen2 {
my $monitor = shift;
my $parameters = shift;
my $pid = fork;
return if $pid; # in the parent process
run_dzen2($monitor, $parameters);
exit;
}
sub detach_transset {
my $pid = fork;
return if $pid; # in the parent process
sleep 1;
# you may use either xorg-transset instead or transset-df
# https://github.com/wildefyr/transset-df
system('transset .8 -n dzentop >/dev/null');
exit;
}
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# end of perl module
1;
# ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- ----
# google material colors
# https://material.io/guidelines/style/color.html
# Associative Array (Dictionary)
color = {
'white' : '#ffffff',
'black' : '#000000',
'grey50' : '#fafafa',
'grey100' : '#f5f5f5',
'grey200' : '#eeeeee',
'grey300' : '#e0e0e0',
'grey400' : '#bdbdbd',
'grey500' : '#9e9e9e',
'grey600' : '#757575',
'grey700' : '#616161',
'grey800' : '#424242',
'grey900' : '#212121',
'red50' : '#ffebee',
'red100' : '#ffcdd2',
'red200' : '#ef9a9a',
'red300' : '#e57373',
'red400' : '#ef5350',
'red500' : '#f44336',
'red600' : '#e53935',
'red700' : '#d32f2f',
'red800' : '#c62828',
'red900' : '#b71c1c',
'redA100' : '#ff8a80',
'redA200' : '#ff5252',
'redA400' : '#ff1744',
'redA700' : '#d50000',
'pink50' : '#fce4ec',
'pink100' : '#f8bbd0',
'pink200' : '#f48fb1',
'pink300' : '#f06292',
'pink400' : '#ec407a',
'pink500' : '#e91e63',
'pink600' : '#d81b60',
'pink700' : '#c2185b',
'pink800' : '#ad1457',
'pink900' : '#880e4f',
'pinkA100' : '#ff80ab',
'pinkA200' : '#ff4081',
'pinkA400' : '#f50057',
'pinkA700' : '#c51162',
'blue50' : '#e3f2fd',
'blue100' : '#bbdefb',
'blue200' : '#90caf9',
'blue300' : '#64b5f6',
'blue400' : '#42a5f5',
'blue500' : '#2196f3',
'blue600' : '#1e88e5',
'blue700' : '#1976d2',
'blue800' : '#1565c0',
'blue900' : '#0d47a1',
'blueA100' : '#82b1ff',
'blueA200' : '#448aff',
'blueA400' : '#2979ff',
'blueA700' : '#2962ff',
'yellow50' : '#fffde7',
'yellow100' : '#fff9c4',
'yellow200' : '#fff59d',
'yellow300' : '#fff176',
'yellow400' : '#ffee58',
'yellow500' : '#ffeb3b',
'yellow600' : '#fdd835',
'yellow700' : '#fbc02d',
'yellow800' : '#f9a825',
'yellow900' : '#f57f17',
'yellowA100' : '#ffff8d',
'yellowA200' : '#ffff00',
'yellowA400' : '#ffea00',
'yellowA700' : '#ffd600',
'teal50' : '#e0f2f1',
'teal100' : '#b2dfdb',
'teal200' : '#80cbc4',
'teal300' : '#4db6ac',
'teal400' : '#26a69a',
'teal500' : '#009688',
'teal600' : '#00897b',
'teal700' : '#00796b',
'teal800' : '#00695c',
'teal900' : '#004d40',
'tealA100' : '#a7ffeb',
'tealA200' : '#64ffda',
'tealA400' : '#1de9b6',
'tealA700' : '#00bfa5',
'green50' : '#e8f5e9',
'green100' : '#c8e6c9',
'green200' : '#a5d6a7',
'green300' : '#81c784',
'green400' : '#66bb6a',
'green500' : '#4caf50',
'green600' : '#43a047',
'green700' : '#388e3c',
'green800' : '#2e7d32',
'green900' : '#1b5e20',
'greenA100' : '#b9f6ca',
'greenA200' : '#69f0ae',
'greenA400' : '#00e676',
'greenA700' : '#00c853',
'orange50' : '#fff3e0',
'orange100' : '#ffe0b2',
'orange200' : '#ffcc80',
'orange300' : '#ffb74d',
'orange400' : '#ffa726',
'orange500' : '#ff9800',
'orange600' : '#fb8c00',
'orange700' : '#f57c00',
'orange800' : '#ef6c00',
'orange900' : '#e65100',
'orangeA100' : '#ffd180',
'orangeA200' : '#ffab40',
'orangeA400' : '#ff9100',
'orangeA700' : '#ff6d00',
'deepOrange50' : '#fbe9e7',
'deepOrange100' : '#ffccbc',
'deepOrange200' : '#ffab91',
'deepOrange300' : '#ff8a65',
'deepOrange400' : '#ff7043',
'deepOrange500' : '#ff5722',
'deepOrange600' : '#f4511e',
'deepOrange700' : '#e64a19',
'deepOrange800' : '#d84315',
'deepOrange900' : '#bf360c',
'deepOrangeA100' : '#ff9e80',
'deepOrangeA200' : '#ff6e40',
'deepOrangeA400' : '#ff3d00',
'deepOrangeA700' : '#dd2c00'
}