xappspicker 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. #!/bin/bash
  2. # documentation: README.md
  3. # or https://notabug.org/ohnonot/xscripts/blob/master/README.md
  4. ########################## FUNCTIONS BEGIN ####################################
  5. adjust_xapps ()
  6. {
  7. echo "echo \"$1\" | xrdb -merge" >> "$xappspicker_rc"
  8. }
  9. adjust_dmenu ()
  10. {
  11. : ${dmenurc=$HOME/.config/dmenu/dmenurc}
  12. if [ -w "$dmenurc" ]; then
  13. rm "$dmenurc"
  14. [ -n "$dmenufont" ] && echo -n "-fn $dmenufont " > "$dmenurc"
  15. echo "-nb ${fgbg[1]} -nf ${fgbg[0]} -sb ${fgbg[3]} -sf ${fgbg[2]} " >> "$dmenurc"
  16. fi
  17. }
  18. adjust_xsetroot ()
  19. {
  20. #~ echo ". $SCRIPT_DIR/posix_compliant_random_functions" >> "$xappspicker_rc"
  21. if [ -d "$bitmapdir" ] ;then
  22. #~ echo "xsetroot -fg \"$1\" -bg \"$2\" -bitmap \"\$(randombitmap \"$bitmapdir\")\"" >> "$xappspicker_rc"
  23. echo "xsetroot -fg \"$1\" -bg \"$2\" -bitmap \"\$(shuf -n1 -e $bitmapdir/*.xbm)\"" >> "$xappspicker_rc"
  24. elif [ -f "$themepath/xsetrootbitmap.xbm" ] ;then
  25. echo "xsetroot -fg \"$1\" -bg \"$2\" -bitmap \"$themepath/xsetrootbitmap.xbm\"" >> "$xappspicker_rc"
  26. else
  27. echo "xsetroot -fg \"$1\" -bg \"$2\" -mod \$(( \$(random)%15 + 2)) \$(( \$(random)%15 + 2))" >> "$xappspicker_rc"
  28. fi
  29. }
  30. grepcol ()
  31. {
  32. # uses a tiny python2 snippet
  33. # fgbg array: fgbg[0] is foreground, fgbg[1] is background
  34. fgbg=($(python2 -c 'import gtk
  35. w = gtk.Window()
  36. w.realize()
  37. style=w.get_style()
  38. print style.fg[gtk.STATE_NORMAL].to_string()
  39. print style.bg[gtk.STATE_NORMAL].to_string()
  40. print style.text[gtk.STATE_SELECTED].to_string()
  41. print style.base[gtk.STATE_SELECTED].to_string()' 2>/dev/null))
  42. # the third one is the background for selected text, aka Highlight
  43. hex12to6
  44. }
  45. hex12to6 ()
  46. {
  47. for (( i=0 ; i<${#fgbg[@]} ; i++ ))
  48. do
  49. # simply discard the last 2 digits of each red, green and blue
  50. fgbg[i]="#${fgbg[i]:1:2}${fgbg[i]:5:2}${fgbg[i]:9:2}"
  51. done
  52. }
  53. invert ()
  54. {
  55. # inverts colors
  56. r=${1:1:2}
  57. g=${1:3:2}
  58. b=${1:5:2}
  59. printf "#%02x%02x%02x\n" $((16#FF - 16#$r)) $((16#FF - 16#$g)) $((16#FF - 16#$b))
  60. }
  61. hextriplet2float ()
  62. {
  63. # convert the hex representation of one of r,g,b to a float between 0 and 1
  64. bc<<<"obase=10; ibase=16; scale=3; $1/FF"
  65. }
  66. float255 ()
  67. {
  68. # multiply a float between 0 and 1 by 255, doh.
  69. bc<<<"$1*255"
  70. }
  71. fixed_value ()
  72. {
  73. # sets the value of color $1 (format: #nnnnnn) to $2 (a float between 0 and 1),
  74. # leaving hue and saturation intact, and returns the resulting color.
  75. r=${1:1:2}
  76. r="$(hextriplet2float ${r^^})"
  77. g=${1:3:2}
  78. g="$(hextriplet2float ${g^^})"
  79. b=${1:5:2}
  80. b="$(hextriplet2float ${b^^})"
  81. rgb="$r,$g,$b"
  82. hsv="$(python2 -c "import colorsys
  83. print colorsys.rgb_to_hsv($rgb)")"
  84. huesat="${hsv%,*}"
  85. huesat="${huesat##*(}"
  86. hsv="$huesat,$2"
  87. rgb="$(python2 -c "import colorsys
  88. print colorsys.hsv_to_rgb($hsv)")"
  89. rg="${rgb%,*}"
  90. r="${rg%%,*}"
  91. r="${r##*(}"
  92. g="${rg##*,}"
  93. b="${rgb##*,}"
  94. b="${b%%)*}"
  95. r="$(float255 $r)"
  96. r="${r%%.*}"
  97. g="$(float255 $g)"
  98. g="${g%%.*}"
  99. b="$(float255 $b)"
  100. b="${b%%.*}"
  101. printf "#%02x%02x%02x" $r $g $b
  102. }
  103. adjust_tint2 ()
  104. {
  105. # when sourcing $xappspicker_rc without running this script, tint2 is NOT killed!
  106. if [ -r "$xappspicker_dir/tint2_pid" ]; then
  107. tint2pid="$(< "$xappspicker_dir/tint2_pid")"
  108. [[ "$(ps -q $tint2pid -o comm=)" == "tint2" ]] && kill $tint2pid
  109. unset tint2pid
  110. rm "$xappspicker_dir/tint2_pid"
  111. fi
  112. tint2dir="$HOME/.themes/$GTK2_CURRENT_THEME/tint2"
  113. if [ -r "$tint2dir/tint2rc" ];then
  114. echo "cd \"$tint2dir\"" >> "$xappspicker_rc"
  115. echo "tint2 -c \"./tint2rc\" &" >> "$xappspicker_rc"
  116. echo "echo \$! > \"$xappspicker_dir/tint2_pid\"" >> "$xappspicker_rc"
  117. elif [[ "$tint2_is_essential" == "1" ]]; then
  118. echo "tint2 &" >> "$xappspicker_rc"
  119. echo "echo \$! > \"$xappspicker_dir/tint2_pid\"" >> "$xappspicker_rc"
  120. fi
  121. }
  122. adjust_conky ()
  123. {
  124. kill $(pgrep -f 'conky -a xappspicker_identifier*')
  125. # conky changes its pid when it has the "background yes" configuration option,
  126. # and so saving $! to a pidfile saves the wrong pid.
  127. # instead, we uniquely identify this instance of conky by launching it with a bogus
  128. # command line option.
  129. conkydir="$HOME/.themes/$GTK2_CURRENT_THEME/conky"
  130. if [ -r "$conkydir/conkyrc" ];then
  131. echo "cd \"$conkydir\"" >> "$xappspicker_rc"
  132. echo "conky -a xappspicker_identifier -c \"./conkyrc\" &" >> "$xappspicker_rc"
  133. elif [[ "$conky_is_essential" == "1" ]]; then
  134. echo "conky -a xappspicker_identifier &" >> "$xappspicker_rc"
  135. fi
  136. }
  137. change_openbox_theme ()
  138. {
  139. if [ -r "$HOME/.themes/$GTK2_CURRENT_THEME/openbox-3/themerc" ] || [ -r "/usr/share/themes/$GTK2_CURRENT_THEME/openbox-3/themerc" ] ; then
  140. : ${obrc=$HOME/.config/openbox/rc.xml}
  141. theme="$(xmllint --html --nonet --xpath '//openbox_config/theme/name' "$obrc" 2>/dev/null)"
  142. theme="${theme%%</*>}"
  143. if [[ "x$theme" != "x" ]] ; then
  144. mv -f "$obrc.xappspicker.bak" "$obrc.xappspicker.bak2"
  145. cp "$obrc" "$obrc.xappspicker.bak"
  146. sed -i "s/$theme/<name>$GTK2_CURRENT_THEME/" "$obrc"
  147. openbox --reconfigure
  148. fi
  149. fi
  150. }
  151. ######################## FUNCTIONS END ########################################
  152. ######################## MAIN BEGIN ###########################################
  153. # the directory where the script itself (and files it depends upon) resides.
  154. # ( symlinking the executable to e.g. $HOME/bin does not break this )
  155. SCRIPT_DIR="$(readlink "$0")"
  156. if [ -z "$SCRIPT_DIR" ]; then
  157. SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
  158. else
  159. SCRIPT_DIR="${SCRIPT_DIR%/*}"
  160. fi
  161. ### GTK2_RC_FILES is probably already part of the env (at least on my systems)
  162. ### https://stackoverflow.com/a/11686912
  163. : ${GTK2_RC_FILES=$HOME/.gtkrc-2.0}
  164. # the latter we have to redo time and again, otherwise the script won't work
  165. # when run manually after a theme change.
  166. GTK2_CURRENT_THEME="$($(which grep) gtk-theme-name $GTK2_RC_FILES|cut -d\" -f2)"
  167. if [ -f "$HOME/.themes/$GTK2_CURRENT_THEME/gtk-2.0/gtkrc" ]
  168. then
  169. themepath="$HOME/.themes/$GTK2_CURRENT_THEME"
  170. else
  171. themepath="/usr/share/themes/$GTK2_CURRENT_THEME"
  172. fi
  173. # heavy lifting starts here
  174. grepcol
  175. base_fg="${fgbg[0]}"
  176. base_bg="${fgbg[1]}"
  177. sel_txt_fg="${fgbg[2]}"
  178. sel_txt_bg="${fgbg[3]}"
  179. if [ -r "$HOME/.config/xappspicker/config" ]; then
  180. . "$HOME/.config/xappspicker/config"
  181. elif [ -r "$SCRIPT_DIR/config" ]; then
  182. . "$SCRIPT_DIR/config"
  183. else
  184. echo "Fatal: Could not find config file in
  185. $HOME/.config/xappspicker/config
  186. $SCRIPT_DIR/config
  187. Exiting.
  188. "
  189. exit 1
  190. fi
  191. rm -f "$xappspicker_rc"
  192. mkdir -p "$xappspicker_dir"
  193. # prepare the values for xsetroot. please see man xsetroot.
  194. # 1.: do you want to choose a random bitmap from the following dir?
  195. # if not, set this to "", and xsetroot will choose:
  196. # a) the file xsetrootbitmap.xbm from $themedir, or, failing that
  197. # b) a random -mod.
  198. bitmapdir="$SCRIPT_DIR/$bitmapdir"
  199. # 2.: which color to choose as a base for the background? I choose the background for
  200. # selected text, usually the most colorful accent in the theme. It's the 4th and
  201. # last color in the array generated by grepcol() = ${fgbg[3]}
  202. # 3.: manipulate that color.
  203. # a) i prefer to darken the background to 20%, and the foreground to 10%
  204. #~ xsetrootbg="$(fixed_value "${fgbg[3]}" "0.2")"
  205. #~ xsetrootfg="$(fixed_value "${fgbg[3]}" "0.1")"
  206. # b) another possibility: color-invert (=negative) the colors
  207. #~ xsetrootbg="$(invert "${fgbg[0]}")" # that is the foreground
  208. #~ xsetrootfg="$(invert "${fgbg[1]}")" # that is the background
  209. # functions can be combined, too.
  210. [[ "$xapps_enabled" == "1" ]] && adjust_xapps "$xres"
  211. # which xapps will be affected?
  212. # un/comment or add desired values in config file.
  213. if [[ "$xsetroot_enabled" == "1" ]]; then
  214. adjust_xsetroot "$xsetrootfg" "$xsetrootbg"
  215. else
  216. [[ "$feh_instead_of_xsetroot" == "1" ]] && echo '. ~/.fehbg &' >> "$xappspicker_rc"
  217. fi
  218. # adjusting dmenu is simpler, we take all 4 colors from the array:
  219. # base fore/background, selected text fore/background.
  220. # since dmenu is not an Xapp, this is optional.
  221. # set to empty string to disable.
  222. #~ dmenurc="$HOME/.config/dmenu/dmenurc"
  223. # font definitions in dmenu 4.6 are unclear to me. they also differ from
  224. # suckless-tools 4.5 - one cannot pass xfont-strings.
  225. # the one below should work on all systems, or at least fail silently.
  226. # set to empty string to use default font.
  227. #~ dmenufont="terminus"
  228. [[ "$dmenu_enabled" == "1" ]] && adjust_dmenu
  229. # looks for a file tint2rc in a tint2 subfolder inside your theme folder
  230. # i.e. $themepath/tint2/tint2rc
  231. [[ "$tint2_enabled" == "1" ]] && adjust_tint2
  232. # looks for a file conkyrc in a conky subfolder inside your theme folder,
  233. # i.e. $themepath/conky/conkyrc
  234. [[ "$conky_enabled" == "1" ]] && adjust_conky
  235. [[ "$openbox_enabled" == "1" ]] && change_openbox_theme
  236. # if this file exists, and it is executable, then execute it.
  237. # this should usually be the last line added to "$xappspicker_rc"
  238. if [[ "$exec_enabled" == "1" ]]; then
  239. [[ "x$exec_path" == "x" ]] && exec_path="$themepath/xappspicker.exec"
  240. [ -x "$exec_path" ] && echo "\"$exec_path\" &" >> "$xappspicker_rc"
  241. fi
  242. # please do not remove this
  243. . "$xappspicker_rc"