panel.sh 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #!/usr/bin/env bash
  2. quote() {
  3. local q="$(printf '%q ' "$@")"
  4. printf '%s' "${q% }"
  5. }
  6. hc_quoted="$(quote "${herbstclient_command[@]:-herbstclient}")"
  7. hc() { "${herbstclient_command[@]:-herbstclient}" "$@" ;}
  8. monitor=${1:-0}
  9. geometry=( $(hc monitor_rect "$monitor") )
  10. if [ -z "$geometry" ] ;then
  11. echo "Invalid monitor $monitor"
  12. exit 1
  13. fi
  14. # geometry has the format W H X Y
  15. x=${geometry[0]}
  16. y=${geometry[1]}
  17. panel_width=${geometry[2]}
  18. panel_height=16
  19. font="-*-fixed-medium-*-*-*-12-*-*-*-*-*-*-*"
  20. bgcolor=$(hc get frame_border_normal_color)
  21. selbg=$(hc get window_border_active_color)
  22. selfg='#101010'
  23. ####
  24. # Try to find textwidth binary.
  25. # In e.g. Ubuntu, this is named dzen2-textwidth.
  26. if which textwidth &> /dev/null ; then
  27. textwidth="textwidth";
  28. elif which dzen2-textwidth &> /dev/null ; then
  29. textwidth="dzen2-textwidth";
  30. elif which xftwidth &> /dev/null ; then # For guix
  31. textwidth="xftwidth";
  32. else
  33. echo "This script requires the textwidth tool of the dzen2 project."
  34. exit 1
  35. fi
  36. ####
  37. # true if we are using the svn version of dzen2
  38. # depending on version/distribution, this seems to have version strings like
  39. # "dzen-" or "dzen-x.x.x-svn"
  40. if dzen2 -v 2>&1 | head -n 1 | grep -q '^dzen-\([^,]*-svn\|\),'; then
  41. dzen2_svn="true"
  42. else
  43. dzen2_svn=""
  44. fi
  45. if awk -Wv 2>/dev/null | head -1 | grep -q '^mawk'; then
  46. # mawk needs "-W interactive" to line-buffer stdout correctly
  47. # http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=593504
  48. uniq_linebuffered() {
  49. awk -W interactive '$0 != l { print ; l=$0 ; fflush(); }' "$@"
  50. }
  51. else
  52. # other awk versions (e.g. gawk) issue a warning with "-W interactive", so
  53. # we don't want to use it there.
  54. uniq_linebuffered() {
  55. awk '$0 != l { print ; l=$0 ; fflush(); }' "$@"
  56. }
  57. fi
  58. hc pad $monitor $panel_height
  59. {
  60. ### Event generator ###
  61. # based on different input data (mpc, date, hlwm hooks, ...) this generates events, formed like this:
  62. # <eventname>\t<data> [...]
  63. # e.g.
  64. # date ^fg(#efefef)18:33^fg(#909090), 2013-10-^fg(#efefef)29
  65. #mpc idleloop player &
  66. while true ; do
  67. # "date" output is checked once a second, but an event is only
  68. # generated if the output changed compared to the previous run.
  69. date +$'date\t^fg(#efefef)%H:%M^fg(#909090), %Y-%m-^fg(#efefef)%d'
  70. sleep 1 || break
  71. done > >(uniq_linebuffered) &
  72. childpid=$!
  73. hc --idle
  74. kill $childpid
  75. } 2> /dev/null | {
  76. IFS=$'\t' read -ra tags <<< "$(hc tag_status $monitor)"
  77. visible=true
  78. date=""
  79. windowtitle=""
  80. while true ; do
  81. ### Output ###
  82. # This part prints dzen data based on the _previous_ data handling run,
  83. # and then waits for the next event to happen.
  84. separator="^bg()^fg($selbg)|"
  85. # draw tags
  86. for i in "${tags[@]}" ; do
  87. case ${i:0:1} in
  88. '#')
  89. echo -n "^bg($selbg)^fg($selfg)"
  90. ;;
  91. '+')
  92. echo -n "^bg(#9CA668)^fg(#141414)"
  93. ;;
  94. ':')
  95. echo -n "^bg()^fg(#ffffff)"
  96. ;;
  97. '!')
  98. echo -n "^bg(#FF0675)^fg(#141414)"
  99. ;;
  100. *)
  101. echo -n "^bg()^fg(#ababab)"
  102. ;;
  103. esac
  104. if [ ! -z "$dzen2_svn" ] ; then
  105. # clickable tags if using SVN dzen
  106. echo -n "^ca(1,$hc_quoted focus_monitor \"$monitor\" && "
  107. echo -n "$hc_quoted use \"${i:1}\") ${i:1} ^ca()"
  108. else
  109. # non-clickable tags if using older dzen
  110. echo -n " ${i:1} "
  111. fi
  112. done
  113. echo -n "$separator"
  114. echo -n "^bg()^fg() ${windowtitle//^/^^}"
  115. # small adjustments
  116. right="$separator^bg() $date $separator"
  117. right_text_only=$(echo -n "$right" | sed 's.\^[^(]*([^)]*)..g')
  118. # get width of right aligned text.. and add some space..
  119. width=$($textwidth "$font" "$right_text_only ")
  120. echo -n "^pa($(($panel_width - $width)))$right"
  121. echo
  122. ### Data handling ###
  123. # This part handles the events generated in the event loop, and sets
  124. # internal variables based on them. The event and its arguments are
  125. # read into the array cmd, then action is taken depending on the event
  126. # name.
  127. # "Special" events (quit_panel/togglehidepanel/reload) are also handled
  128. # here.
  129. # wait for next event
  130. IFS=$'\t' read -ra cmd || break
  131. # find out event origin
  132. case "${cmd[0]}" in
  133. tag*)
  134. #echo "resetting tags" >&2
  135. IFS=$'\t' read -ra tags <<< "$(hc tag_status $monitor)"
  136. ;;
  137. date)
  138. #echo "resetting date" >&2
  139. date="${cmd[@]:1}"
  140. ;;
  141. quit_panel)
  142. exit
  143. ;;
  144. togglehidepanel)
  145. currentmonidx=$(hc list_monitors | sed -n '/\[FOCUS\]$/s/:.*//p')
  146. if [ "${cmd[1]}" -ne "$monitor" ] ; then
  147. continue
  148. fi
  149. if [ "${cmd[1]}" = "current" ] && [ "$currentmonidx" -ne "$monitor" ] ; then
  150. continue
  151. fi
  152. echo "^togglehide()"
  153. if $visible ; then
  154. visible=false
  155. hc pad $monitor 0
  156. else
  157. visible=true
  158. hc pad $monitor $panel_height
  159. fi
  160. ;;
  161. reload)
  162. exit
  163. ;;
  164. focus_changed|window_title_changed)
  165. windowtitle="${cmd[@]:2}"
  166. ;;
  167. #player)
  168. # ;;
  169. esac
  170. done
  171. ### dzen2 ###
  172. # After the data is gathered and processed, the output of the previous block
  173. # gets piped to dzen2.
  174. } 2> /dev/null | dzen2 -w $panel_width -x $x -y $y -fn "$font" -h $panel_height \
  175. -e "button3=;button4=exec:$hc_quoted use_index -1;button5=exec:$hc_quoted use_index +1" \
  176. -ta l -bg "$bgcolor" -fg '#efefef'