├── applications └── ximage.desktop ├── bin ├── xkiller ├── xcolorpick ├── ximage ├── system-hibernate ├── system-reboot ├── system-suspend ├── system-shutdown ├── rcalc ├── xf86-backlight ├── xscreenshot ├── xf86-audio └── xlock ├── .gitignore ├── Makefile └── README.md /applications/ximage.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Type=Application 3 | Name=sxiv 4 | GenericName=Image Viewer 5 | Exec=ximage %F 6 | MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp; 7 | NoDisplay=true 8 | Icon=sxiv 9 | -------------------------------------------------------------------------------- /bin/xkiller: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | # If xkill is running, it will be killed, 4 | # otherwise chosen application can be killed. 5 | 6 | # The advantage is that you can map a key-combo 7 | # and can disable killing hitting it again. 8 | if pidof xkill >/dev/null 2>&1; then 9 | killall xkill 10 | else 11 | xkill 12 | fi 13 | -------------------------------------------------------------------------------- /bin/xcolorpick: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | ### 4 | ### System variables 5 | ### 6 | MY_NAME="$( basename "${0}" )" 7 | MY_LOG_DIR="${HOME}/.log" 8 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 9 | MY_DATE="$( date '+%Y-%m-%d' )" 10 | MY_TIME="$( date '+%H:%M:%S' )" 11 | 12 | if [ ! -d "${MY_LOG_DIR}" ]; then 13 | mkdir -p "${MY_LOG_DIR}" 14 | fi 15 | if [ ! -f "${MY_LOG_FILE}" ]; then 16 | touch "${MY_LOG_FILE}" 17 | fi 18 | if [ ! -w "${MY_LOG_FILE}" ]; then 19 | chmod u+w "${MY_LOG_FILE}" 20 | fi 21 | 22 | 23 | 24 | ################################################################################ 25 | ## 26 | ## F U N C T I O N S 27 | ## 28 | ################################################################################ 29 | error() { 30 | printf "%s\n" "${1}" >&2 31 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 32 | } 33 | 34 | 35 | 36 | ################################################################################ 37 | ## 38 | ## E N T R Y P O I N T 39 | ## 40 | ################################################################################ 41 | 42 | if ! command -v grabc >/dev/null 2>&1; then 43 | error "Binary 'grabc' not available" 44 | exit 1 45 | fi 46 | 47 | if ! command -v zenity >/dev/null 2>&1; then 48 | error "Binary 'zenity' not available." 49 | exit 1 50 | fi 51 | 52 | 53 | color="$( grabc )" 54 | 55 | zenity --color-selection --color="${color}" 56 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Note: 2 | # To effectively apply the changes you will have 3 | # to re-index the git index (if there are already 4 | # commited files) 5 | # 6 | # $ git rm -r --cached . 7 | # $ git add . 8 | # $ git commit -m ".gitignore index rebuild" 9 | # 10 | 11 | 12 | ###################################### 13 | # CUSTOM 14 | ###################################### 15 | 16 | # Keep folders 17 | !.keepme 18 | 19 | ###################################### 20 | # GENERIC 21 | ###################################### 22 | 23 | ###### std ###### 24 | .lock 25 | *.log 26 | 27 | ###### patches/diffs ###### 28 | *.patch 29 | *.diff 30 | *.orig 31 | *.rej 32 | 33 | ###################################### 34 | # Operating Systems 35 | ###################################### 36 | 37 | ###### OSX ###### 38 | ._* 39 | .DS* 40 | .Spotlight-V100 41 | .Trashes 42 | 43 | ###### Windows ###### 44 | Thumbs.db 45 | ehthumbs.db 46 | Desktop.ini 47 | $RECYCLE.BIN/ 48 | *.lnk 49 | *.shortcut 50 | 51 | ###################################### 52 | # Editors 53 | ###################################### 54 | 55 | ###### Sublime ###### 56 | *.sublime-workspace 57 | *.sublime-project 58 | 59 | ###### Eclipse ###### 60 | .classpath 61 | .buildpath 62 | .project 63 | .settings/ 64 | 65 | ###### Netbeans ###### 66 | /nbproject/ 67 | 68 | ###### Intellij IDE ###### 69 | .idea/ 70 | .idea_modules/ 71 | 72 | ###### vim ###### 73 | *.swp 74 | *.swo 75 | *.swn 76 | *.swm 77 | *~ 78 | 79 | ###### TextMate ###### 80 | .tm_properties 81 | *.tmproj 82 | 83 | ###### BBEdit ###### 84 | *.bbprojectd 85 | *.bbproject 86 | -------------------------------------------------------------------------------- /bin/ximage: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Compatible with ranger 1.6.0 through 1.7.* 3 | # 4 | # This script searches image files in a directory, opens them all with sxiv and 5 | # sets the first argument to the first image displayed by sxiv. 6 | # 7 | # This is supposed to be used in rifle.conf as a workaround for the fact that 8 | # sxiv takes no file name arguments for the first image, just the number. Copy 9 | # this file somewhere into your $PATH and add this at the top of rifle.conf: 10 | # 11 | # mime ^image, has sxiv, X, flag f = path/to/this/script -- "$@" 12 | # 13 | # Implementation notes: this script is quite slow because of POSIX limitations 14 | # and portability concerns. First calling the shell function 'abspath' is 15 | # quicker than calling 'realpath' because it would fork a whole process, which 16 | # is slow. Second, we need to append a file list to sxiv, which can only be done 17 | # properly in two ways: arrays (which are not POSIX) or \0 sperated 18 | # strings. Unfortunately, assigning \0 to a variable is not POSIX either (will 19 | # not work in dash and others), so we cannot store the result of listfiles to a 20 | # variable. 21 | 22 | if [ $# -eq 0 ]; then 23 | echo "Usage: ${0##*/} PICTURES" 24 | exit 25 | fi 26 | 27 | [ "$1" == '--' ] && shift 28 | 29 | abspath () { 30 | case "$1" in 31 | /*) printf "%s\n" "$1";; 32 | *) printf "%s\n" "$PWD/$1";; 33 | esac 34 | } 35 | 36 | listfiles () { 37 | find -L "$(dirname "$target")" -maxdepth 1 -type f -iregex \ 38 | '.*\(jpe?g\|bmp\|png\|gif\)$' -print0 | sort -z 39 | } 40 | 41 | target="$(abspath "$1")" 42 | count="$(listfiles | grep -m 1 -ZznF "$target" | cut -d: -f1)" 43 | 44 | if [ -n "$count" ]; then 45 | listfiles | xargs -0 sxiv -n "$count" -- 46 | else 47 | sxiv -- "$@" # fallback 48 | fi 49 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Configuration 2 | SHELL = /bin/sh 3 | MKDIR_P = mkdir -p 4 | 5 | all: 6 | @echo "Type 'make install' or 'make uninstall'" 7 | @echo 8 | @echo "make install" 9 | @echo " Will copy files to /usr/local/bin" 10 | @echo "" 11 | @echo "make uninstall" 12 | @echo " Will remove files from /usr/local/bin" 13 | 14 | install: 15 | @# Create dir 16 | ${MKDIR_P} /usr/local/bin/ 17 | @# Copy files 18 | install -m 0755 bin/system-hibernate /usr/local/bin/system-hibernate 19 | install -m 0755 bin/system-reboot /usr/local/bin/system-reboot 20 | install -m 0755 bin/system-shutdown /usr/local/bin/system-shutdown 21 | install -m 0755 bin/system-suspend /usr/local/bin/system-suspend 22 | install -m 0755 bin/rcalc /usr/local/bin/rcalc 23 | install -m 0755 bin/xcolorpick /usr/local/bin/xcolorpick 24 | install -m 0755 bin/xf86-audio /usr/local/bin/xf86-audio 25 | install -m 0755 bin/xf86-backlight /usr/local/bin/xf86-backlight 26 | install -m 0755 bin/ximage /usr/local/bin/ximage 27 | install -m 0755 bin/xkiller /usr/local/bin/xkiller 28 | install -m 0755 bin/xlock /usr/local/bin/xlock 29 | install -m 0755 bin/xscreenshot /usr/local/bin/xscreenshot 30 | 31 | install -m 0644 applications/ximage.desktop /usr/share/applications/ximage.desktop 32 | 33 | 34 | uninstall: 35 | @# Remove files 36 | rm -f /usr/local/bin/system-hibernate 37 | rm -f /usr/local/bin/system-reboot 38 | rm -f /usr/local/bin/system-shutdown 39 | rm -f /usr/local/bin/system-suspend 40 | rm -f /usr/local/bin/rcalc 41 | rm -f /usr/local/bin/xcolorpick 42 | rm -f /usr/local/bin/xf86-audio 43 | rm -f /usr/local/bin/xf86-backlight 44 | rm -f /usr/local/bin/xkiller 45 | rm -f /usr/local/bin/xlock 46 | rm -f /usr/local/bin/xscreenshot 47 | 48 | rm -f /usr/share/applications/ximage.desktop 49 | -------------------------------------------------------------------------------- /bin/system-hibernate: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | ### 4 | ### System variables 5 | ### 6 | MY_NAME="$( basename "${0}" )" 7 | MY_LOG_DIR="${HOME}/.log" 8 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 9 | MY_DATE="$( date '+%Y-%m-%d' )" 10 | MY_TIME="$( date '+%H:%M:%S' )" 11 | 12 | 13 | 14 | ################################################################################ 15 | ## 16 | ## F U N C T I O N S 17 | ## 18 | ################################################################################ 19 | error() { 20 | printf "%s\n" "${1}" >&2 21 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 22 | } 23 | 24 | 25 | 26 | ################################################################################ 27 | ## 28 | ## E N T R Y P O I N T 29 | ## 30 | ################################################################################ 31 | 32 | if [ ! -d "${MY_LOG_DIR}" ]; then 33 | mkdir -p "${MY_LOG_DIR}" 34 | fi 35 | if [ ! -f "${MY_LOG_FILE}" ]; then 36 | touch "${MY_LOG_FILE}" 37 | fi 38 | if [ ! -w "${MY_LOG_FILE}" ]; then 39 | chmod u+w "${MY_LOG_FILE}" 40 | fi 41 | 42 | if command -v systemctl >/dev/null 2>&1; then 43 | _ret=0 44 | _err="$( systemctl hibernate 2>&1)" || _ret=$? 45 | if [ "${_ret}" != "0" ]; then 46 | error "'systemctl hibernate' did exit with non-zero: ${_ret}" 47 | error "${_err}" 48 | exit 1 49 | fi 50 | elif command -v dbus-send >/dev/null 2>&1; then 51 | _ret=0 52 | _err="$( dbus-send --system --print-reply \ 53 | --dest='org.freedesktop.UPower' \ 54 | /org/freedesktop/UPower \ 55 | org.freedesktop.UPower.Hibernate 2>&1 )" || _ret=$? 56 | if [ "${_ret}" != "0" ]; then 57 | error "'dbus-send' to hibernate did exit with non-zero: ${_ret}" 58 | error "${_err}" 59 | exit 1 60 | fi 61 | else 62 | error "You either need 'systemctl' or 'dbus-send'. None are available." 63 | exit 1 64 | fi 65 | -------------------------------------------------------------------------------- /bin/system-reboot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | ### 4 | ### System variables 5 | ### 6 | MY_NAME="$( basename "${0}" )" 7 | MY_LOG_DIR="${HOME}/.log" 8 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 9 | MY_DATE="$( date '+%Y-%m-%d' )" 10 | MY_TIME="$( date '+%H:%M:%S' )" 11 | 12 | 13 | 14 | ################################################################################ 15 | ## 16 | ## F U N C T I O N S 17 | ## 18 | ################################################################################ 19 | error() { 20 | printf "%s\n" "${1}" >&2 21 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 22 | } 23 | 24 | 25 | 26 | ################################################################################ 27 | ## 28 | ## E N T R Y P O I N T 29 | ## 30 | ################################################################################ 31 | 32 | if [ ! -d "${MY_LOG_DIR}" ]; then 33 | mkdir -p "${MY_LOG_DIR}" 34 | fi 35 | if [ ! -f "${MY_LOG_FILE}" ]; then 36 | touch "${MY_LOG_FILE}" 37 | fi 38 | if [ ! -w "${MY_LOG_FILE}" ]; then 39 | chmod u+w "${MY_LOG_FILE}" 40 | fi 41 | 42 | if command -v systemctl >/dev/null 2>&1; then 43 | _ret=0 44 | _err="$( systemctl reboot 2>&1)" || _ret=$? 45 | if [ "${_ret}" != "0" ]; then 46 | error "'systemctl reboot' did exit with non-zero: ${_ret}" 47 | error "${_err}" 48 | exit 1 49 | fi 50 | elif command -v dbus-send >/dev/null 2>&1; then 51 | _ret=0 52 | _err="$( dbus-send --system --print-reply \ 53 | --dest='org.freedesktop.login1' \ 54 | /org/freedesktop/login1 \ 55 | org.freedesktop.login1.Manager.Reboot boolean:true 2>&1 )" || _ret=$? 56 | if [ "${_ret}" != "0" ]; then 57 | error "'dbus-send' to reboot did exit with non-zero: ${_ret}" 58 | error "${_err}" 59 | exit 1 60 | fi 61 | else 62 | error "You either need 'systemctl' or 'dbus-send'. None are available." 63 | exit 1 64 | fi 65 | -------------------------------------------------------------------------------- /bin/system-suspend: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | ### 4 | ### System variables 5 | ### 6 | MY_NAME="$( basename "${0}" )" 7 | MY_LOG_DIR="${HOME}/.log" 8 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 9 | MY_DATE="$( date '+%Y-%m-%d' )" 10 | MY_TIME="$( date '+%H:%M:%S' )" 11 | 12 | 13 | 14 | ################################################################################ 15 | ## 16 | ## F U N C T I O N S 17 | ## 18 | ################################################################################ 19 | error() { 20 | printf "%s\n" "${1}" >&2 21 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 22 | } 23 | 24 | 25 | 26 | ################################################################################ 27 | ## 28 | ## E N T R Y P O I N T 29 | ## 30 | ################################################################################ 31 | 32 | if [ ! -d "${MY_LOG_DIR}" ]; then 33 | mkdir -p "${MY_LOG_DIR}" 34 | fi 35 | if [ ! -f "${MY_LOG_FILE}" ]; then 36 | touch "${MY_LOG_FILE}" 37 | fi 38 | if [ ! -w "${MY_LOG_FILE}" ]; then 39 | chmod u+w "${MY_LOG_FILE}" 40 | fi 41 | 42 | if command -v systemctl >/dev/null 2>&1; then 43 | _ret=0 44 | _err="$( systemctl suspend 2>&1)" || _ret=$? 45 | if [ "${_ret}" != "0" ]; then 46 | error "'systemctl suspend' did exit with non-zero: ${_ret}" 47 | error "${_err}" 48 | exit 1 49 | fi 50 | elif command -v dbus-send >/dev/null 2>&1; then 51 | _ret=0 52 | _err="$( dbus-send --system --print-reply \ 53 | --dest='org.freedesktop.login1' \ 54 | /org/freedesktop/login1 \ 55 | org.freedesktop.login1.Manager.Suspend boolean:true 2>&1 )" || _ret=$? 56 | if [ "${_ret}" != "0" ]; then 57 | error "'dbus-send' to suspend did exit with non-zero: ${_ret}" 58 | error "${_err}" 59 | exit 1 60 | fi 61 | else 62 | error "You either need 'systemctl' or 'dbus-send'. None are available." 63 | exit 1 64 | fi 65 | -------------------------------------------------------------------------------- /bin/system-shutdown: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | ### 4 | ### System variables 5 | ### 6 | MY_NAME="$( basename "${0}" )" 7 | MY_LOG_DIR="${HOME}/.log" 8 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 9 | MY_DATE="$( date '+%Y-%m-%d' )" 10 | MY_TIME="$( date '+%H:%M:%S' )" 11 | 12 | 13 | 14 | ################################################################################ 15 | ## 16 | ## F U N C T I O N S 17 | ## 18 | ################################################################################ 19 | error() { 20 | printf "%s\n" "${1}" >&2 21 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 22 | } 23 | 24 | 25 | 26 | ################################################################################ 27 | ## 28 | ## E N T R Y P O I N T 29 | ## 30 | ################################################################################ 31 | 32 | if [ ! -d "${MY_LOG_DIR}" ]; then 33 | mkdir -p "${MY_LOG_DIR}" 34 | fi 35 | if [ ! -f "${MY_LOG_FILE}" ]; then 36 | touch "${MY_LOG_FILE}" 37 | fi 38 | if [ ! -w "${MY_LOG_FILE}" ]; then 39 | chmod u+w "${MY_LOG_FILE}" 40 | fi 41 | 42 | if command -v systemctl >/dev/null 2>&1; then 43 | _ret=0 44 | _err="$( systemctl poweroff 2>&1)" || _ret=$? 45 | if [ "${_ret}" != "0" ]; then 46 | error "'systemctl poweroff' did exit with non-zero: ${_ret}" 47 | error "${_err}" 48 | exit 1 49 | fi 50 | elif command -v dbus-send >/dev/null 2>&1; then 51 | _ret=0 52 | _err="$( dbus-send --system --print-reply \ 53 | --dest='org.freedesktop.login1' \ 54 | /org/freedesktop/login1 \ 55 | org.freedesktop.login1.Manager.PowerOff boolean:true 2>&1 )" || _ret=$? 56 | if [ "${_ret}" != "0" ]; then 57 | error "'dbus-send' to power off did exit with non-zero: ${_ret}" 58 | error "${_err}" 59 | exit 1 60 | fi 61 | else 62 | error "You either need 'systemctl' or 'dbus-send'. None are available." 63 | exit 1 64 | fi 65 | -------------------------------------------------------------------------------- /bin/rcalc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # Usage: 4 | # 5 | # $ echo 5 + 5 | rcalc 6 | # $ rcalc 5 + 5 7 | # $ rcalc 8 | 9 | # Be strict 10 | set -e 11 | set -u 12 | set -o pipefail 13 | 14 | 15 | # ------------------------------------------------------------------------------------------------- 16 | # Globals 17 | # ------------------------------------------------------------------------------------------------- 18 | 19 | CALCULATION= 20 | RESULT= 21 | OUTPUT= 22 | 23 | 24 | # ------------------------------------------------------------------------------------------------- 25 | # Functions 26 | # ------------------------------------------------------------------------------------------------- 27 | 28 | function calculate() { 29 | local equation="${1}" 30 | qalc +u8 -nocurrencies "${equation}" 31 | } 32 | 33 | function get_result() { 34 | local calculation="${1}" 35 | echo "${calculation}" | sed 's/^.*=\s//g' 36 | } 37 | 38 | function clipboard() { 39 | local value="${1}" 40 | if command -v xsel >/dev/null 2>&1; then 41 | printf "%s" "${value}" | xsel -pi 42 | printf "%s" "${value}" | xsel -si 43 | printf "%s" "${value}" | xsel -bi 44 | else 45 | >&2 "[Warning] 'xsel' binary not available. Cannot copy value to clipboard." 46 | fi 47 | } 48 | 49 | function print_usage() { 50 | cat </dev/null 2>&1; then 110 | >&2 "[Error] 'qalc' binary not available, but required." 111 | exit 1 112 | fi 113 | 114 | 115 | ### 116 | ### Data was piped into this script 117 | ### 118 | if [ -p /dev/stdin ]; then 119 | while IFS= read line; do 120 | CALCULATION="$( calculate "${line}" )" 121 | RESULT="$( get_result "${CALCULATION}" )" 122 | OUTPUT="${CALCULATION}" 123 | # Store result into clipboard 124 | clipboard "${RESULT}" 125 | # Output result line 126 | echo "${OUTPUT}" 127 | done 128 | 129 | ### 130 | ### Data comes in via command line arguments 131 | ### 132 | elif [ "${#}" -gt "0" ]; then 133 | CALCULATION="$( calculate "${*}" )" 134 | RESULT="$( get_result "${CALCULATION}" )" 135 | OUTPUT="${CALCULATION}" 136 | # Store result into clipboard 137 | clipboard "${RESULT}" 138 | # Output result line 139 | echo "${OUTPUT}" 140 | 141 | ### 142 | ### Call without stdin and without command line args (make interactive) 143 | ### 144 | else 145 | exit 0 146 | while read line Change the interval for brightnes up/down.\n" 39 | printf " The default is 5 .\n\n" 40 | 41 | printf "HELP:\n" 42 | printf " -h Show help.\n" 43 | } 44 | 45 | 46 | 47 | ################################################################################ 48 | # 49 | # COMMAND LINE ARGUMENTS 50 | # 51 | ################################################################################ 52 | 53 | ############################################################ 54 | # Parse arguments 55 | ############################################################ 56 | while [ "${#}" -gt 0 ]; do 57 | case "${1}" in 58 | -c) 59 | shift 60 | if [ "${1}" != "up" ] && [ "${1}" != "down" ]; then 61 | printf "Error, -c must either be 'up' or 'down'.\n" 62 | print_usage_head 63 | exit 1 64 | fi 65 | ACTION="${1}" 66 | ;; 67 | -i) 68 | shift 69 | if ! printf "%d" "${1}" >/dev/null 2>&1; then 70 | printf "Error, the value for -i must be an integer.\n" 71 | print_usage_head 72 | exit 1 73 | fi 74 | INTERVAL="${1}" 75 | ;; 76 | -h) 77 | print_usage 78 | exit 79 | ;; 80 | *) 81 | printf "Unknown argument: %s\n" "${1}" 82 | print_usage_head 83 | exit 1 84 | ;; 85 | esac 86 | shift 87 | done 88 | 89 | ############################################################ 90 | # Check required arguments 91 | ############################################################ 92 | if [ "${ACTION}" = "" ]; then 93 | printf "Error, -c is mandatory.\n" 94 | print_usage_head 95 | exit 1 96 | fi 97 | 98 | 99 | 100 | ################################################################################ 101 | # 102 | # MAIN ENTRYPOINT 103 | # 104 | ################################################################################ 105 | 106 | ############################################################ 107 | # Build command 108 | ############################################################ 109 | 110 | if [ "${ACTION}" = "up" ]; then 111 | COMMAND="xbacklight -inc ${INTERVAL}" 112 | else 113 | COMMAND="xbacklight -dec ${INTERVAL}" 114 | fi 115 | 116 | 117 | ############################################################ 118 | # Run command 119 | ############################################################ 120 | 121 | eval "${COMMAND}" 122 | 123 | 124 | ############################################################ 125 | # Parse output 126 | ############################################################ 127 | 128 | CURRENT="$( printf "%d\n" "$(xbacklight -get)" 2>/dev/null )" 129 | MAX="100" 130 | PERCENT=$(( 100 * CURRENT / MAX)) 131 | 132 | 133 | ############################################################ 134 | # Get notification icon/text 135 | ############################################################ 136 | 137 | if [ ${PERCENT} -eq 0 ]; then 138 | ICON_STRING="notification-display-brightness-off" 139 | elif [ ${PERCENT} -lt 33 ]; then 140 | ICON_STRING="notification-display-brightness-low" 141 | elif [ ${PERCENT} -lt 66 ]; then 142 | ICON_STRING="notification-display-brightness-medium" 143 | elif [ ${PERCENT} -lt 99 ]; then 144 | ICON_STRING="notification-display-brightness-high" 145 | else 146 | ICON_STRING="notification-display-brightness-full" 147 | fi 148 | TEXT_STRING="Display brightness: ${PERCENT}%" 149 | 150 | i=$(( PERCENT / 10 )) 151 | j=$(( 10 - i )) 152 | TEXT_STRING="mon: " 153 | while [ $i -gt 0 ]; do 154 | TEXT_STRING="${TEXT_STRING}–" 155 | i=$(( i - 1 )) 156 | done 157 | TEXT_STRING="${TEXT_STRING}|" 158 | while [ $j -gt 0 ]; do 159 | TEXT_STRING="${TEXT_STRING}–" 160 | j=$(( j - 1 )) 161 | done 162 | 163 | TEXT_STRING="${TEXT_STRING} ${PERCENT}%" 164 | 165 | ############################################################ 166 | # Send notification 167 | ############################################################ 168 | 169 | notify-send "${TEXT_STRING}" -i ${ICON_STRING} -h int:value:${PERCENT} -h string:synchronous:brightness 170 | exit 171 | -------------------------------------------------------------------------------- /bin/xscreenshot: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | ### 4 | ### Defaults 5 | ### 6 | DEFAULT_TARGET_PATH="${HOME}/Desktop" 7 | DEFAULT_COMMAND="scrot" 8 | 9 | ### 10 | ### Credits 11 | ### 12 | MY_VERSION="v0.1" 13 | MY_DATE="2017-07-05" 14 | MY_URL="https://github.com/cytopia/i3-utils" 15 | 16 | 17 | ### 18 | ### System variables 19 | ### 20 | MY_NAME="$( basename "${0}" )" 21 | MY_LOG_DIR="${HOME}/.log" 22 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 23 | MY_DATE="$( date '+%Y-%m-%d' )" 24 | MY_TIME="$( date '+%H:%M:%S' )" 25 | 26 | if [ ! -d "${MY_LOG_DIR}" ]; then 27 | mkdir -p "${MY_LOG_DIR}" 28 | fi 29 | if [ ! -f "${MY_LOG_FILE}" ]; then 30 | touch "${MY_LOG_FILE}" 31 | fi 32 | if [ ! -w "${MY_LOG_FILE}" ]; then 33 | chmod u+w "${MY_LOG_FILE}" 34 | fi 35 | 36 | ################################################################################ 37 | ## 38 | ## F U N C T I O N S 39 | ## 40 | ################################################################################ 41 | error() { 42 | printf "%s\n" "${1}" >&2 43 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 44 | } 45 | 46 | print_usage() { 47 | echo "Usage: ${MY_NAME} [-c scrot|maim] [-m ] [-p ]" 48 | echo " ${MY_NAME} -h" 49 | echo " ${MY_NAME} -v" 50 | echo 51 | echo "Helper script for scrot." 52 | echo 53 | echo " -c scrot|maim (optional) Use scrot or main for screenshots." 54 | echo " Default: scrot" 55 | echo " -m (optional) What kind of screenshot to take." 56 | echo " -m window Screenshot of active window" 57 | echo " -m selection Screenshot of selected area" 58 | echo " -m multi Screenshot of all monitoris" 59 | echo " Default: current monitor only" 60 | echo 61 | echo " -p (optional) Specify path to save screenshots to." 62 | echo " Default: ${DEFAULT_TARGET_PATH}" 63 | echo 64 | echo " -h Show this help screen." 65 | echo " -v Show version information." 66 | } 67 | 68 | print_version() { 69 | printf "%s %s (%s) by cytopia\n" "${MY_NAME}" "${MY_VERSION}" "${MY_DATE}" 70 | printf "%s\n" "${MY_URL}" 71 | } 72 | 73 | 74 | 75 | ################################################################################ 76 | ## 77 | ## E NT R Y P O I N T 78 | ## 79 | ################################################################################ 80 | 81 | TARGET_PATH="${DEFAULT_TARGET_PATH}" 82 | COMMAND="${DEFAULT_COMMAND}" 83 | MODE="" 84 | 85 | while [ $# -gt 0 ]; do 86 | case "${1}" in 87 | -c) 88 | shift 89 | if [ "${1}" != "scrot" ] && [ "${1}" != "maim" ]; then 90 | error "Argument for -c: '${1}' is wrong. Should be: scrot or maim" 91 | exit 1 92 | fi 93 | COMMAND="${1}" 94 | ;; 95 | -m) 96 | shift 97 | if [ "${1}" != "window" ] && [ "${1}" != "selection" ] && [ "${1}" != "multi" ]; then 98 | error "Argument for -m: '${1}' is wrong. Should be one of the following: window, selection or multi" 99 | exit 1 100 | fi 101 | MODE="${1}" 102 | ;; 103 | -p) 104 | shift 105 | if [ ! -d "${1}" ]; then 106 | error "Argument for -p: Directory does not exist: ${1}" 107 | exit 1 108 | fi 109 | TARGET_PATH="${1}" 110 | ;; 111 | -h) 112 | print_usage 113 | exit 0 114 | ;; 115 | -v) 116 | print_version 117 | exit 0 118 | ;; 119 | *) 120 | error "Invalid argument supplied: ${1}" 121 | exit 1 122 | ;; 123 | esac 124 | shift 125 | done 126 | 127 | 128 | ### 129 | ### Error Checking 130 | ### 131 | if ! command -v "${COMMAND}" >/dev/null 2>&1; then 132 | error "binary '${COMMAND}' not found but required." 133 | exit 1 134 | fi 135 | if [ "${COMMAND}" = "maim" ]; then 136 | if ! command -v slop >/dev/null 2>&1; then 137 | error "binary 'slop' not found but required for maim." 138 | exit 1 139 | fi 140 | if ! command -v xdotool >/dev/null 2>&1; then 141 | error "binary 'xdotool' not found but required for maim." 142 | exit 1 143 | fi 144 | fi 145 | 146 | 147 | 148 | ### 149 | ### Run (scrot) 150 | ### 151 | if [ "${COMMAND}" = "scrot" ]; then 152 | 153 | if [ "${MODE}" = "window" ]; then 154 | scrot --silent --quality 100 --focused 'Screenshot %Y-%m-%d %H-%M-%S [window] ($wx$h).png' --exec "mv '\$f' '${TARGET_PATH}'" 155 | elif [ "${MODE}" = "selection" ]; then 156 | scrot --silent --quality 100 --select 'Screenshot %Y-%m-%d %H-%M-%S [selection] ($wx$h).png' --exec "mv '\$f' '${TARGET_PATH}'" 157 | elif [ "${MODE}" = "multi" ]; then 158 | scrot --silent --quality 100 --multidisp 'Screenshot %Y-%m-%d %H-%M-%S [all] ($wx$h).png' --exec "mv '\$f' '${TARGET_PATH}'" 159 | else 160 | scrot --silent --quality 100 'Screenshot %Y-%m-%d %H-%M-%S ($wx$h).png' --exec "mv '\$f' '${TARGET_PATH}'" 161 | fi 162 | 163 | ### 164 | ### Run (maim) 165 | ### 166 | elif [ "${COMMAND}" = "maim" ]; then 167 | 168 | if [ "${MODE}" = "window" ]; then 169 | maim --windowid="$(xdotool getactivewindow)" "${TARGET_PATH}/Screenshot $( date '+%Y-%m-%d %H-%M-%S' ) [window].png" 170 | elif [ "${MODE}" = "selection" ]; then 171 | maim --select "${TARGET_PATH}/Screenshot $( date '+%Y-%m-%d %H-%M-%S' ) [selection].png" 172 | elif [ "${MODE}" = "multi" ]; then 173 | maim "${TARGET_PATH}/Screenshot $( date '+%Y-%m-%d %H-%M-%S' ) [all].png" 174 | else 175 | maim "${TARGET_PATH}/Screenshot $( date '+%Y-%m-%d %H-%M-%S' ).png" 176 | fi 177 | 178 | fi 179 | 180 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # i3-utils-bin 2 | 3 | Binary utilities for a minimalistic [i3](https://github.com/i3/i3) setup. 4 | 5 | --- 6 | 7 | **This repository is part of the [i3-utils](https://github.com/cytopia/i3-utils).** (See also [i3-utils-systemd](https://github.com/cytopia/i3-utils-systemd)) 8 | 9 | --- 10 | 11 | ## Tools 12 | 13 | #### System tools 14 | 15 | | Tool | Description | 16 | |------|-------------| 17 | | [system-hibernate](bin/system-hibernate) | Wrapper script to hibternate as user. (systemd or dbus) | 18 | | [system-reboot](bin/system-reboot) | Wrapper script to reboot as user. (systemd or dbus) | 19 | | [system-shutdown](bin/system-shutdown) | Wrapper script to shutdown as user. (systemd or dbus) | 20 | | [system-suspend](bin/system-suspend) | Wrapper script to suspend as user. (systemd or dbus) | 21 | 22 | #### Hardware tools 23 | 24 | | Tool | Description | 25 | |------|-------------| 26 | | [xf86-audio](bin/xf86-audio) | Increase, decrease and mute currently selected (active) audio device. Supports notifications. | 27 | | [xf86-backlight](bin/xf86-backlight) | Adjust your screens backlight. Supports notifications. | 28 | 29 | #### X tools 30 | 31 | | Tool | Description | 32 | |------|-------------| 33 | | [xcolorpick](bin/xcolorpick) | Zenity based RGB color picker for any pixel on your screen. | 34 | | [ximage](bin/ximage) | Wrapper for [sxiv](https://github.com/muennich/sxiv) that allows for opening multiple files automatically within a directory. | 35 | | [ximage.desktop](applications/ximage.desktop) | Desktop application file for `ximage` registering png, jpg, jpeg and gif. | 36 | | [xkiller](bin/xkiller) | Wrapper for `xkill`. Xkill itself cannot be terminated when started from a hotkey. That is where `xkiller` comes into play. It can be terminated simply starting it again. (via hotkey, dunst, rofi or via the command line). | 37 | | [xlock](bin/xlock) | Wrapper for `i3lock` with blurred screenshot and optional custom overlay which will also suspend any notifications during lock and can be run in the background without locking the script itself, so that you can run another script afterwards (such as [system-suspend](bin/system-suspend)). | 38 | | [xscreenshot](bin/xscreenshot) | Wrapper for `scrot` or `maim`. | 39 | 40 | #### Rofi/Dmenu tools 41 | 42 | | Tool | Description | 43 | |------|-------------| 44 | | [rcalc](bin/rcalc) | A wrapper for `qalc` adding the ability to syncronize every result accross all existing clipboards. | 45 | 46 | 47 | ## Integration 48 | 49 | #### Requirements 50 | 51 | * [amixer](https://linux.die.net/man/1/amixer) 52 | * [convert](https://linux.die.net/man/1/convert) 53 | * [grabc](http://www.muquit.com/muquit/software/grabc/grabc.html) 54 | * [i3lock](https://github.com/i3/i3lock) 55 | * [notify-send](https://man.cx/notify-send) 56 | * [scrot](https://man.cx/scrot) or [maim](https://github.com/naelstrof/maim) 57 | * [sxiv](https://github.com/muennich/sxiv) 58 | * [systemd](https://github.com/systemd/systemd) or [ibus](https://github.com/ibus/ibus) 59 | * [xbacklight](https://linux.die.net/man/1/xbacklight) 60 | * [xsel](https://github.com/kfish/xsel) 61 | * [xkill](https://linux.die.net/man/1/xkill) 62 | * [zenity](https://github.com/GNOME/zenity) 63 | 64 | #### Install 65 | 66 | This will add binaries to `/usr/local/bin/`. 67 | 68 | ```bash 69 | $ sudo make install 70 | ``` 71 | 72 | #### Uninstall 73 | 74 | This will remove binaries from `/usr/local/bin/`. 75 | 76 | ```bash 77 | $ sudo make uninstall 78 | ``` 79 | 80 | #### Example usage for i3 81 | 82 | ```bash 83 | ### 84 | ### System 85 | ### 86 | 87 | set $mode_system System (l) lock, (e) logout, (s) suspend, (h) hibernate, (r) reboot, (p) poweroff 88 | mode "$mode_system" { 89 | bindsym l exec --no-startup-id system-lock, mode "default" 90 | bindsym e exec --no-startup-id i3-msg exit, mode "default" 91 | bindsym s exec --no-startup-id "system-lock -b; system-suspend", mode "default" 92 | bindsym h exec --no-startup-id "system-lock -b; system-hibernate", mode "default" 93 | bindsym r exec --no-startup-id system-reboot, mode "default" 94 | bindsym p exec --no-startup-id system-shutdown, mode "default" 95 | 96 | # Back to normal: Enter or Escape 97 | bindsym Return mode "default" 98 | bindsym Escape mode "default" 99 | } 100 | 101 | 102 | ### 103 | ### Hardware 104 | ### 105 | 106 | # Sreen Backlight brightness 107 | bindsym XF86MonBrightnessUp exec xf86-backlight -c up 108 | bindsym XF86MonBrightnessDown exec xf86-backlight -c down 109 | 110 | # Audio Volume 111 | bindsym XF86AudioRaiseVolume exec xf86-audio -D pulse -c up 112 | bindsym XF86AudioLowerVolume exec xf86-audio -D pulse -c down 113 | bindsym XF86AudioMute exec xf86-audio -D pulse -c toggle 114 | 115 | 116 | ### 117 | ### X Tools 118 | ### 119 | 120 | # Screenshot (with multi monitors) 121 | bindsym Print exec "xscreenshot -m multi" 122 | 123 | # Screenshot (select rectangle) 124 | bindsym $mod+Sys_Req exec "xscreenshot -m selection" 125 | 126 | # Screenshot (active window) 127 | bindsym $mod+Shift+Sys_Req exec "xscreenshot -m window" 128 | 129 | 130 | ### 131 | ### Rofi calculator 132 | ### 133 | 134 | bindsym $mod+space exec "exec rofi -show combi -combi-modi window,drun,run -modi combi,'calc:rcalc' -sidebar-mode" 135 | ``` 136 | 137 | ## Credits 138 | 139 | * [ranger](https://github.com/ranger/ranger): From where i am using `ximage` (original script is [rifle_sxiv.sh](https://github.com/ranger/ranger/blob/master/examples/rifle_sxiv.sh)) 140 | 141 | -------------------------------------------------------------------------------- /bin/xf86-audio: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | 4 | ################################################################################ 5 | # 6 | # VARIABLES 7 | # 8 | ################################################################################ 9 | 10 | ACTION= 11 | INTERVAL="3" 12 | DEVICE="" 13 | MIXER="Master" 14 | COMMAND= 15 | 16 | 17 | 18 | ################################################################################ 19 | # 20 | # FUNCTIONS 21 | # 22 | ################################################################################ 23 | 24 | print_usage_head() { 25 | printf "Usage: %s [OPTIONS] -c COMMAND\n" "${0}" 26 | printf " %s -a\n" "${0}" 27 | printf " %s -h\n" "${0}" 28 | } 29 | print_usage() { 30 | print_usage_head 31 | 32 | printf "\nThis script is a wrapper for amixer that will change the volume\n" 33 | printf "and send those changes to a notification daemine.\n\n" 34 | 35 | printf "COMMAND:\n" 36 | printf " -c up Increase volume.\n" 37 | printf " -c down Decrease volume.\n" 38 | printf " -c mute Mute volume.\n" 39 | printf " -c toggle Toggle mute/unmute.\n\n" 40 | 41 | printf "OPTIONS:\n" 42 | printf " -i Change the interval for volume up/down.\n" 43 | printf " The default is 3 (percent).\n\n" 44 | 45 | printf " -D Specify a device, such as 'pulse'.\n" 46 | printf " If omitted using 'default'.\n\n" 47 | 48 | printf " -M If omitted using 'Master'.\n" 49 | printf " Use -a to show all mixers.\n\n" 50 | 51 | printf "HELP:\n" 52 | printf " -a Show all mixers.\n" 53 | printf " -h Show help.\n" 54 | } 55 | 56 | get_all_mixers() { 57 | amixer | grep -E '^\w.*$' | grep -Eo "'.*'" | sed "s/'//g" 58 | } 59 | 60 | 61 | 62 | ################################################################################ 63 | # 64 | # COMMAND LINE ARGUMENTS 65 | # 66 | ################################################################################ 67 | 68 | ############################################################ 69 | # Parse arguments 70 | ############################################################ 71 | while [ "${#}" -gt 0 ]; do 72 | case "${1}" in 73 | -c) 74 | shift 75 | if [ "${1}" != "up" ] && [ "${1}" != "down" ] && [ "${1}" != "mute" ] && [ "${1}" != "toggle" ]; then 76 | printf "Error, -c must either be 'up', 'down', 'mute' or 'toggle'.\n" 77 | print_usage_head 78 | exit 1 79 | fi 80 | ACTION="${1}" 81 | ;; 82 | -i) 83 | shift 84 | if ! printf "%d" "${1}" >/dev/null 2>&1; then 85 | printf "Error, the value for -i must be an integer.\n" 86 | print_usage_head 87 | exit 1 88 | fi 89 | INTERVAL="${1}" 90 | ;; 91 | -D) 92 | shift 93 | DEVICE="${1}" 94 | ;; 95 | -M) 96 | shift 97 | MIXER="${1}" 98 | ;; 99 | -a) 100 | get_all_mixers 101 | exit 102 | ;; 103 | -h) 104 | print_usage 105 | exit 106 | ;; 107 | *) 108 | printf "Unknown argument: %s\n" "${1}" 109 | print_usage_head 110 | exit 1 111 | ;; 112 | esac 113 | shift 114 | done 115 | 116 | ############################################################ 117 | # Check required arguments 118 | ############################################################ 119 | if [ "${ACTION}" = "" ]; then 120 | printf "Error, -c is mandatory.\n" 121 | print_usage_head 122 | exit 1 123 | fi 124 | 125 | 126 | 127 | ################################################################################ 128 | # 129 | # MAIN ENTRYPOINT 130 | # 131 | ################################################################################ 132 | 133 | ############################################################ 134 | # Build command 135 | ############################################################ 136 | 137 | # Use specific device? 138 | if [ "${DEVICE}" != "" ]; then 139 | DEVICE="-D ${DEVICE}" 140 | fi 141 | 142 | # Build command 143 | if [ "${ACTION}" = "up" ]; then 144 | COMMAND="amixer ${DEVICE} sset ${MIXER} '${INTERVAL}%+' unmute" 145 | elif [ "${ACTION}" = "down" ]; then 146 | COMMAND="amixer ${DEVICE} sset ${MIXER} '${INTERVAL}%-' unmute" 147 | elif [ "${ACTION}" = "mute" ]; then 148 | COMMAND="amixer ${DEVICE} sset ${MIXER} mute" 149 | else 150 | COMMAND="amixer ${DEVICE} sset ${MIXER} toggle" 151 | fi 152 | 153 | 154 | ############################################################ 155 | # Run command 156 | ############################################################ 157 | 158 | OUTPUT="$( eval "${COMMAND}" )" 159 | 160 | 161 | ############################################################ 162 | # Parse output 163 | ############################################################ 164 | 165 | PERCENT="$( echo "${OUTPUT}" | grep -m 1 "%]" | cut -d "[" -f2 | cut -d "%" -f1 )" 166 | MUTED=0 167 | if ! amixer get "${MIXER}" | grep -q '\[on\]'; then 168 | MUTED=1 169 | fi 170 | 171 | 172 | ############################################################ 173 | # Get notification icon/text 174 | ############################################################ 175 | 176 | if [ "${MUTED}" = "1" ]; then 177 | ICON_STRING="notification-audio-volume-muted" 178 | TEXT_STRING="vol: muted" 179 | PERCENT=0 180 | else 181 | if [ "${PERCENT}" -lt "33" ]; then 182 | ICON_STRING="notification-audio-volume-low" 183 | else 184 | if [ "${PERCENT}" -lt "67" ]; then 185 | ICON_STRING="notification-audio-volume-medium" 186 | else 187 | ICON_STRING="notification-audio-volume-high" 188 | fi 189 | fi 190 | 191 | 192 | i=$(( PERCENT / 10 )) 193 | j=$(( 10 - i )) 194 | TEXT_STRING="vol: " 195 | while [ $i -gt 0 ]; do 196 | TEXT_STRING="${TEXT_STRING}–" 197 | i=$(( i - 1 )) 198 | done 199 | TEXT_STRING="${TEXT_STRING}|" 200 | while [ $j -gt 0 ]; do 201 | TEXT_STRING="${TEXT_STRING}–" 202 | j=$(( j - 1 )) 203 | done 204 | 205 | TEXT_STRING="${TEXT_STRING} ${PERCENT}%" 206 | 207 | fi 208 | 209 | 210 | ############################################################ 211 | # Send notification 212 | ############################################################ 213 | 214 | notify-send "${TEXT_STRING}" -i ${ICON_STRING} -h int:value:${PERCENT} -h string:synchronous:volume 215 | exit 216 | -------------------------------------------------------------------------------- /bin/xlock: -------------------------------------------------------------------------------- 1 | #!/bin/sh -eu 2 | 3 | 4 | ### 5 | ### Defaults 6 | ### 7 | DEFAULT_BACKGROUND="0" 8 | DEFAULT_SCALE="3" 9 | DEFAULT_OVERLAY_PATH="" 10 | DEFAULT_NOTIFY_DAEMON="dunst" 11 | DEFAULT_MUTE="0" 12 | 13 | ### 14 | ### Credits 15 | ### 16 | MY_VERSION="v0.1" 17 | MY_DATE="2017-07-05" 18 | MY_URL="https://github.com/cytopia/i3-utils" 19 | 20 | ### 21 | ### System variables 22 | ### 23 | MY_NAME="$( basename "${0}" )" 24 | MY_LOG_DIR="${HOME}/.log" 25 | MY_LOG_FILE="${MY_LOG_DIR}/${MY_NAME}.err" 26 | MY_DATE="$( date '+%Y-%m-%d' )" 27 | MY_TIME="$( date '+%H:%M:%S' )" 28 | 29 | if [ ! -d "${MY_LOG_DIR}" ]; then 30 | mkdir -p "${MY_LOG_DIR}" 31 | fi 32 | if [ ! -f "${MY_LOG_FILE}" ]; then 33 | touch "${MY_LOG_FILE}" 34 | fi 35 | if [ ! -w "${MY_LOG_FILE}" ]; then 36 | chmod u+w "${MY_LOG_FILE}" 37 | fi 38 | 39 | 40 | 41 | ################################################################################ 42 | ## 43 | ## F U N C T I O N S 44 | ## 45 | ################################################################################ 46 | 47 | # Test if argument is an integer. 48 | # 49 | # @param mixed 50 | # @return integer 0: is int | 1: not an int 51 | isint() { 52 | echo "${1}" | grep -Eq '^([0-9]|[1-9][0-9]*)$' 53 | } 54 | 55 | 56 | error() { 57 | printf "%s\n" "${1}" >&2 58 | printf "[%s] [%s] %s\n" "${MY_DATE}" "${MY_TIME}" "${1}" >> "${MY_LOG_FILE}" 59 | } 60 | 61 | print_usage() { 62 | echo "Usage: ${MY_NAME} [-b] [-m] [-s <1-100>] [-o ] [-n ]" 63 | echo " ${MY_NAME} -h" 64 | echo " ${MY_NAME} -v" 65 | echo 66 | echo "Helper script for i3lock." 67 | echo 68 | echo " -b (optional) Background mode." 69 | echo " The whole script is put into background so that you can" 70 | echo " run another script afterwards, such as system suspend/hibernat." 71 | echo " The default is to run in foreground mode." 72 | echo 73 | echo " -m (optional) Mute sound before locking the screen." 74 | echo 75 | echo " The whole script is put into background so that you can" 76 | echo " -s <1-100> (optional) Scale factor in percent." 77 | echo " The default is 3." 78 | echo 79 | echo " -o (optional) Path to an image to overlay onto lockscreen." 80 | echo " The default is not to use an overlay image." 81 | echo 82 | echo " -n (optional) Binary name of the notification daemon to suspend" 83 | echo " while the screen is locked. It should be suspended so" 84 | echo " that no notifications will be displayed while you are" 85 | echo " away with a locked screen." 86 | echo " The default is 'dunst'." 87 | echo 88 | echo " -h Show this help screen." 89 | echo " -v Show version information." 90 | } 91 | 92 | print_version() { 93 | printf "%s %s (%s) by cytopia\n" "${MY_NAME}" "${MY_VERSION}" "${MY_DATE}" 94 | printf "%s\n" "${MY_URL}" 95 | } 96 | 97 | lock_screen() { 98 | # 1-100% 99 | _scale_factor="${1}" 100 | # Path to overlay image 101 | _overlay_path="${2}" 102 | # i3lock foreground mode? 103 | _i3lock_background="${3}" 104 | 105 | _upscale_factor="$(( 100 * 100 / _scale_factor ))" 106 | _screenshot="$( mktemp --suffix='.png' )" 107 | 108 | # Ensure we do not abort here in case of ImageMagick error 109 | if command -v maim >/dev/null 2>&1; then 110 | echo "maim" 111 | maim --quality 10 --delay=0.0 "${_screenshot}.jpg" 112 | else 113 | echo "scrot" 114 | scrot --quality 100 --silent "${_screenshot}.jpg" 115 | fi 116 | mv "${_screenshot}.jpg" "${_screenshot}" 117 | convert ${_screenshot} -scale ${_scale_factor}% -scale ${_upscale_factor}% ${_screenshot} 118 | 119 | # Add overlay (optional) 120 | if [ -f "${_overlay_path}" ]; then 121 | # Ensure we do not abort here in case of ImageMagick error 122 | convert "${_screenshot}" "${_overlay_path}" -gravity center -geometry +0+0 -composite -matte "${_screenshot}" 123 | fi 124 | 125 | # Lock screen 126 | if [ "${_i3lock_background}" = "1" ]; then 127 | i3lock --show-failed-attempts --image="${_screenshot}" 128 | else 129 | i3lock --nofork --show-failed-attempts --image="${_screenshot}" 130 | fi 131 | } 132 | suspend_notify() { 133 | _notify_daemon="${1}" 134 | 135 | # Suspend notification daemon 136 | pkill -u "${USER}" -USR1 "${_notify_daemon}" 137 | } 138 | resume_notify() { 139 | _notify_daemon="${1}" 140 | 141 | # Wait until i3lock is closed (screen not locked anymore) 142 | while pidof i3lock >/dev/null 2>&1; do 143 | sleep 1 144 | done 145 | # Resume notification daemon 146 | pkill -u "${USER}" -USR2 "${_notify_daemon}" 147 | } 148 | mute_sound() { 149 | if ! _err="$( amixer sset 'Master' mute 2>&1 >/dev/null )"; then 150 | error "${_err}" 151 | exit 1 152 | fi 153 | } 154 | 155 | 156 | ################################################################################ 157 | ## 158 | ## E N T R Y P O I N T 159 | ## 160 | ################################################################################ 161 | 162 | BACKGROUND="${DEFAULT_BACKGROUND}" 163 | SCALE="${DEFAULT_SCALE}" 164 | OVERLAY_PATH="${DEFAULT_OVERLAY_PATH}" 165 | NOTIFY_DAEMON="${DEFAULT_NOTIFY_DAEMON}" 166 | MUTE="${DEFAULT_MUTE}" 167 | 168 | while [ $# -gt 0 ]; do 169 | case "${1}" in 170 | -b) 171 | BACKGROUND="1" 172 | ;; 173 | -m) 174 | MUTE="1" 175 | ;; 176 | -s) 177 | shift 178 | if ! isint "${1}"; then 179 | error "Argument for -s: Is not an integer: ${1}" 180 | exit 1 181 | fi 182 | if [ "${1}" -lt 0 ] || [ "${1}" -gt 100 ]; then 183 | error "Argument for -s: Must be between 1 and 100. Specified: ${1}" 184 | exit 1 185 | fi 186 | SCALE="${1}" 187 | ;; 188 | 189 | -o) 190 | shift 191 | if [ ! -f "${1}" ]; then 192 | error "Argument for -o: File does not exist: ${1}" 193 | exit 1 194 | fi 195 | OVERLAY_PATH="${1}" 196 | ;; 197 | -n) 198 | shift 199 | NOTIFY_DAEMON="${1}" 200 | ;; 201 | -h) 202 | print_usage 203 | exit 0 204 | ;; 205 | -v) 206 | print_version 207 | exit 0 208 | ;; 209 | *) 210 | error "Invalid argument supplied: ${1}" 211 | exit 1 212 | ;; 213 | esac 214 | shift 215 | done 216 | 217 | 218 | ### 219 | ### Error Checking 220 | ### 221 | if ! command -v maim >/dev/null 2>&1; then 222 | if ! command -v scrot >/dev/null 2>&1; then 223 | error "binary 'maim' or 'scrot' not found but required." 224 | exit 1 225 | fi 226 | fi 227 | if ! command -v convert >/dev/null 2>&1; then 228 | error "binary 'convert' not found but required." 229 | exit 1 230 | fi 231 | if ! command -v i3lock >/dev/null 2>&1; then 232 | error "binary 'i3lock' not found but required." 233 | exit 1 234 | fi 235 | if [ "${MUTE}" = "1" ]; then 236 | if ! command -v amixer >/dev/null 2>&1; then 237 | error "binary 'amixer' not found but required when using -m option." 238 | exit 1 239 | fi 240 | fi 241 | 242 | # Make sure not to start another i3lock instance, 243 | # if it is already running. 244 | if pidof i3lock >/dev/null 2>&1; then 245 | error "i3lock is already running, aborting." 246 | exit 1 247 | fi 248 | 249 | # Dunst shows notifications in lock screen by default. 250 | # In order to prevent that, we need to suspend the dunst 251 | # process prior locking and resume after the lock process 252 | # finishes. 253 | 254 | 255 | # Suspend notification daemon 256 | suspend_notify "${NOTIFY_DAEMON}" 257 | 258 | # Mute sound if desired 259 | if [ "${MUTE}" = "1" ]; then 260 | mute_sound 261 | fi 262 | 263 | # Lock screen foreground or background task 264 | # depening on the command line argument 265 | lock_screen "${SCALE}" "${OVERLAY_PATH}" "${BACKGROUND}" 266 | 267 | # Resume notification service. 268 | # In case of background service, the function will be brought 269 | # into background itself and the script finishes. 270 | # This way you can start other services after this script 271 | # such as suspend to RAM/Disk and during wake-up, you will still 272 | # have a locked screen with resuming notification during unlock 273 | if [ "${BACKGROUND}" = "1" ]; then 274 | resume_notify "${NOTIFY_DAEMON}" & 275 | else 276 | resume_notify "${NOTIFY_DAEMON}" 277 | fi 278 | --------------------------------------------------------------------------------