├── reload ├── reloaded ├── restart ├── restarted ├── i3-config.d ├── cfg06 ├── apps01 ├── cfg02 ├── cfg09 ├── urxvt.Xdefaults ├── cfg08 ├── cfg01 ├── cfg05 ├── apps00 ├── cfg04 ├── cfg07 ├── cfg00 ├── cfg03 └── dunstrc ├── .gitignore ├── i3scripts ├── i3-double-digit-command ├── i3-emacsclient ├── i3-file-watcher ├── i3-scratchpad ├── i3-mode ├── i3-app-mode ├── i3-keyboard ├── i3-launcher ├── i3-command-prompt ├── i3-status ├── i3-dispatcher ├── i3-list-windows ├── i3-mouse ├── i3-config-scripts ├── i3-recorder ├── i3-triple-digit-command ├── i3-focus-app-by-alias ├── i3-marks └── i3-transcribe ├── compton.conf ├── compton.conf-16-04-LTS ├── myscripts ├── tvheadend-start ├── my-file-watcher └── my-usb-disks ├── LICENSE ├── i3-status-config ├── i3-config ├── README.md └── Makefile /reload: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /reloaded: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /restart: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /restarted: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /i3-config.d/cfg06: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # .gitignore 2 | 3 | nohup.out 4 | 5 | # shellcheck errors 6 | 7 | i3scripts/*log 8 | myscripts/*log 9 | 10 | # 11 | # Done. 12 | # 13 | -------------------------------------------------------------------------------- /i3-config.d/apps01: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | 3 | declare -A audioactions=( 4 | ["str5cc7e6ef20c9"]="pactl set-sink-input-mute XYZZY_ARGS" 5 | ["str33ace9ae71db"]="pactl set-sink-input-mute XYZZY_ARGS" 6 | ["str337069dc07c6"]="pactl set-sink-input-mute XYZZY_ARGS" 7 | ) 8 | 9 | # 10 | # Done. 11 | # 12 | -------------------------------------------------------------------------------- /i3scripts/i3-double-digit-command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-double-digit-command 4 | # 5 | 6 | # RESERVED. Functionality moved into triple-digit-command file. If we 7 | # add another file, editing the Makefile is faciltated by search and 8 | # replace. 9 | 10 | # 11 | # Start here. 12 | # 13 | 14 | /bin/true 15 | 16 | # 17 | # Done. 18 | # 19 | -------------------------------------------------------------------------------- /i3-config.d/cfg02: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # 3 | # CLUSTER BINDINGS BEGIN HERE 4 | # 5 | 6 | # This key chord works for my right hand. reserved. 7 | bindsym Control+Delete nop 8 | 9 | # Kill a workspace. I think it needs both hands. 10 | bindsym Control+Mod4+Delete [workspace="__focused__"] kill 11 | 12 | # 13 | # CLUSTER BINDINGS END HERE 14 | # 15 | -------------------------------------------------------------------------------- /compton.conf: -------------------------------------------------------------------------------- 1 | # 2 | # http://askubuntu.com/questions/751149/screen-tearing-when-using-i3-none-when-using-unity 3 | # 4 | 5 | backend = "xrender"; 6 | ### vsync = "opengl-swc"; 7 | 8 | ### glx-copy-from-front = true; 9 | ### glx-swap-method = 2; 10 | xrender-sync = true; 11 | xrender-sync-fence = true; 12 | 13 | # Transparency settings for i3. 14 | opacity-rule = [ 15 | "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'" 16 | ]; 17 | 18 | # 19 | # Done. 20 | # 21 | -------------------------------------------------------------------------------- /compton.conf-16-04-LTS: -------------------------------------------------------------------------------- 1 | # 2 | # http://askubuntu.com/questions/751149/screen-tearing-when-using-i3-none-when-using-unity 3 | # 4 | # compton --config ~/Programs/dotfiles/compton.conf -b 5 | # 6 | 7 | backend = "glx"; 8 | vsync = "opengl-swc"; 9 | 10 | glx-copy-from-front = true; 11 | glx-swap-method = 2; 12 | xrender-sync = true; 13 | xrender-sync-fence = true; 14 | 15 | # Transparency settings for i3. 16 | opacity-rule = [ 17 | "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'" 18 | ]; 19 | 20 | # 21 | # Done. 22 | # 23 | -------------------------------------------------------------------------------- /myscripts/tvheadend-start: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # tvheadend-start, formerly my-tvheadend 4 | # 5 | # - tvheadend built from source, running from build directory. 6 | # - I've had to hardcode the build directory and the hostname. 7 | # 8 | 9 | case "$(hostname)" in 10 | (quietpc) 11 | tvhpath=/home/"${USER}"/kaiju/packages/tvheadend/tvheadend 12 | cd "${tvhpath}" || exit 13 | # shellcheck disable=SC2154 14 | xfce4-terminal --title="tvh-server-$(hostname)" -x ./build.linux/tvheadend --noacl 15 | compton-trans -c -o 88 16 | # Firefox refuses to open without first saving. 17 | # This additional script purges unwanted tickets. 18 | tvheadend-firefox /home/"${USER}"/kaiju/Downloads 19 | ;; 20 | esac 21 | 22 | # 23 | # Done. 24 | # 25 | -------------------------------------------------------------------------------- /i3-config.d/cfg09: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | 3 | # 4 | # I3BAR SETTINGS BEGIN HERE. 5 | # 6 | 7 | # Start i3bar to display a workspace bar (plus the system information i3status 8 | # finds out, if available) 9 | bar { 10 | # Show the bar on the 1920x1080 screens: 11 | output $lmon 12 | output $cmon 13 | output $rmon 14 | # Hardcoded path! 15 | i3bar_command /usr/bin/i3bar 16 | position bottom 17 | status_command $i3barstatuscommand 18 | font pango:DejaVu Sans 11 19 | # 20 | bindsym button2 nop 21 | bindsym button3 $i3mouse movement toggle 22 | # Opacity is to be used with restraint. primarily on terminals. 23 | # Mouse wheel rotate up/down applies opacity to focused window. 24 | bindsym button4 exec compton-trans -c -o 80 25 | bindsym button5 exec compton-trans -c -o 100 26 | } 27 | 28 | # 29 | # I3BAR SETTINGS END HERE. 30 | # 31 | -------------------------------------------------------------------------------- /i3scripts/i3-emacsclient: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This is a helper script. In "config.d/apps00" various two character 4 | # commands each launch or focus a single program. Extending this to 5 | # launch two file manager instances in a workspace was trivial, but 6 | # adding terminals to an emacsclient workspace wasn't! Calling this 7 | # script from apps00 makes things easier. The apps that should run 8 | # alongside emacsclient are started in a subshell that isn't blocked 9 | # by emacsclient. 10 | 11 | # The $1 parameter is a hook for reusing this script to add other apps 12 | # alongside emacsclient. 13 | 14 | case "$1" in 15 | ('t') 16 | # Two terminals, one above the other, to the right of Emacs, 17 | # Emacs has focus. 18 | (sleep 3 && i3-msg '[title="Emacs*"] focus') & 19 | (sleep 2 && xfce4-terminal && \ 20 | i3-msg "splitv, exec xfce4-terminal") & 21 | ;; 22 | esac 23 | emacsclient -c 24 | 25 | # 26 | # Done. 27 | # 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 EllaTheCat 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /i3scripts/i3-file-watcher: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Writing to the $i3/command file causes the $i3/execute file to 4 | # evaluate the contents of the $i3/command file. 5 | # 6 | 7 | # 8 | # Start here. 9 | # 10 | 11 | # Create the directory and files. Set the strictest permissions. 12 | i3=/dev/shm/$USER/i3 13 | mkdir -p "${i3}" 14 | touch "$i3/command" 15 | chmod 600 "$i3/command" 16 | touch "$i3/execute" 17 | chmod 700 "$i3/execute" 18 | 19 | # Set the file contents. The command is initialised with a nop. The 20 | # execute command has to be expanded at dispatch time. Single quotes 21 | # ensure that the string is not expanded when copied into the execute 22 | # file. Shellcheck doesn't think this is what we want so the warning 23 | # is disabled. Note: "echo" joins its string arguments with a space. 24 | 25 | # shellcheck disable=SC2016 26 | echo 'eval /bin/false' > "${i3}/command" 27 | # Full path to i3-dispatcher. 28 | # shellcheck disable=SC2016 29 | echo 'eval $HOME/local/i3/bin/i3-dispatcher forward' \ 30 | '$(cat /dev/shm/$USER/i3/command)' > "${i3}/execute" 31 | # Be careful! Use no terminal here! Use no ampersand here! 32 | inotify-hookable --watch-files "${i3}"/command --on-modify-command "${i3}"/execute 33 | 34 | # 35 | # Done. 36 | # 37 | jh 38 | -------------------------------------------------------------------------------- /i3-config.d/urxvt.Xdefaults: -------------------------------------------------------------------------------- 1 | URxvt.saveLines: 999999 2 | URxvt.scrollBar: true 3 | URxvt.foreground: #f9f7f1 4 | URxvt.depth: 32 5 | URxvt.secondaryScroll: true 6 | !URxvt.font: xft:DejaVu Sans Mono for Powerline:pixelsize=14:antialias=true 7 | URxvt.perl-ext-common: default,matcher,selection-to-clipboard 8 | URxvt.urlLauncher: chromium 9 | URxvt.matcher.button: 1 10 | URxvt.tabbed.saveLines: 2000 11 | URxvt.tabbed.scrollBar: false 12 | URxvt.tabbed.secondaryScroll: true 13 | URxvt.tabbed.font: xft:Bitstream Vera Sans Mono:pixelsize=12:antialias=true 14 | URxvt.font: xft:Bitstream Vera Sans Mono:pixelsize=12:antialias=true 15 | URxvt.intensityStyles: false 16 | 17 | !! black dark/light 18 | *color0: #073642 19 | *color8: #002b36 20 | 21 | !! red dark/light 22 | *color1: #dc322f 23 | *color9: #cb4b16 24 | 25 | !! green dark/light 26 | *color2: #859900 27 | *color10: #586e75 28 | 29 | !! yellow dark/light 30 | *color3: #b58900 31 | *color11: #657b83 32 | 33 | !! blue dark/light 34 | *color4: #268bd2 35 | *color12: #839496 36 | 37 | !! magenta dark/light 38 | *color5: #d33682 39 | *color13: #6c71c4 40 | 41 | !! cyan dark/light 42 | *color6: #2aa198 43 | *color14: #93a1a1 44 | 45 | !! white dark/light 46 | *color7: #eee8d5 47 | *color15: #fdf6e3 48 | 49 | URxvt.background: [80]#000000 50 | !! *transparent: true 51 | URxvt*inheritPixmap: true 52 | URxvt*.transparent: true 53 | URxvt*.shading: 30 54 | -------------------------------------------------------------------------------- /i3scripts/i3-scratchpad: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-scratchpad 4 | # 5 | 6 | # Constants copied from i3-config must maintain consistency. 7 | 8 | ###export lmon="HDMI2" 9 | export cmon="HDMI1" 10 | ###export rmon="HDMI1" 11 | 12 | # 13 | # Toggle the scratchpad terminal between show and hide. 14 | # 15 | toggle_terminal() 16 | { 17 | # Only one key binding is required, the first keypress performs 18 | # initialisation and hides the terminal again. 19 | if [ "_$(xdotool search --classname "Scratchpad" | head -1)" = "_" ]; then 20 | xfce4-terminal --title=Scratchpad & 21 | # Allow the terminal enough time to initialise. 22 | # This value needs to be "just right", ymmv. 23 | sleep 0.3 24 | # Set the instance to identify the scratchpad. 25 | xdotool getwindowfocus set_window --classname "Scratchpad" 26 | compton-trans -c -o 88 27 | i3-msg "[instance=\"Scratchpad\"] resize set 80 ppt 80 ppt" 28 | i3-msg "[instance=\"Scratchpad\"] move position center" 29 | i3-msg "[instance=\"Scratchpad\"] move scratchpad" 30 | else 31 | # Remove any accumulated workspace marks before showing the 32 | # window. Numeric marks are removed as a side effect. 33 | i3-msg "[instance=\"Scratchpad\"] unmark, scratchpad show;" 34 | fi 35 | } 36 | 37 | # 38 | # Start here. 39 | # 40 | 41 | "$1" 42 | 43 | # 44 | # Done. 45 | # 46 | -------------------------------------------------------------------------------- /myscripts/my-file-watcher: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Writing to the $i3/command file causes the $i3/execute file to 4 | # evaluate the contents of the $i3/command file. 5 | # 6 | 7 | # Requires: inotify-hookable - a package provided by ubuntu and debian 8 | # distros. I have no idea how to provide it in Arch or Manjaro, sorry. 9 | 10 | 11 | # 12 | # Start here. 13 | # 14 | 15 | # Create the directory and files. Set the strictest permissions. 16 | i3=/dev/shm/tasker 17 | mkdir -p "${i3}" 18 | touch "$i3/command" 19 | chmod 750 "$i3/command" 20 | touch "$i3/execute" 21 | chmod 700 "$i3/execute" 22 | 23 | # Set the file contents. The command is initialised with a 24 | # nop. The execute command has to be expanded at dispatch 25 | # time. Single quotes ensure that the string is not expanded 26 | # when copied into the execute file. Shellcheck doesn't think 27 | # this is what we want so the warning is disabled. Note: 28 | # "echo" joins its string arguments with a space. 29 | 30 | # shellcheck disable=SC2016 31 | echo 'eval /bin/false' > "${i3}/command" 32 | # shellcheck disable=SC2016 33 | echo '(eval /dev/shm/tasker/command)' > "${i3}/execute" 34 | # Kill the running inotify-hookable and start another. 35 | pkill -f "inotify-hookable --watch-files $i3/command" 36 | # Be careful! Use no terminal here! Use no ampersand here! 37 | inotify-hookable --watch-files "${i3}"/command --on-modify-command "${i3}"/execute 38 | 39 | # 40 | # Done. 41 | # 42 | -------------------------------------------------------------------------------- /i3scripts/i3-mode: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-mode 4 | # 5 | # Dim the screen and label the title bar of the current window to 6 | # indicate swtching to Primary and Secondary modes. Labels are 7 | # removed when the current window loses focus. 8 | # 9 | 10 | outputs=$(xrandr | grep ' connect' | awk '{print $1}') 11 | 12 | case "$1" in 13 | (default) 14 | i3-msg 'mode "default"' 15 | i3-msg "unmark default, unmark Primary, unmark Secondary" 16 | for output in ${outputs} ; do 17 | xrandr --output "${output}" --brightness 1.0 18 | done 19 | ;; 20 | (Primary) 21 | i3-msg 'mode "Primary"' 22 | i3-msg "unmark default, unmark Secondary" 23 | i3-msg "mark --add --toggle Primary" 24 | for output in ${outputs} ; do 25 | xrandr --output "${output}" --brightness 0.8 26 | done 27 | i3-msg -t subscribe '[ "window" ]' 28 | i3-msg "unmark Primary" 29 | ;; 30 | (Secondary) 31 | i3-msg 'mode "Secondary"' 32 | i3-msg "unmark Primary, unmark default" 33 | i3-msg "mark --add --toggle Secondary" 34 | for output in ${outputs} ; do 35 | xrandr --output "${output}" --brightness 0.6 36 | done 37 | i3-msg -t subscribe '[ "window" ]' 38 | i3-msg "unmark Secondary" 39 | ;; 40 | (*) 41 | # This is the equivalent of the default case in 'C'. 42 | # This shouldn't ever happen but I've seen it occur. 43 | i3-msg 'mode "default"' 44 | ;; 45 | esac 46 | 47 | # 48 | # Done. 49 | # 50 | -------------------------------------------------------------------------------- /i3scripts/i3-app-mode: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # A proof-of-concept for selecting the i3/swaymode according to the application 4 | # 5 | # - Written to be sway-friendly, no xdotool used. 6 | # - https://www.reddit.com/r/swaywm/comments/s2j35r/comment/hsxgyc6/?utm_source=share&utm_medium=web2x&context=3 7 | 8 | # 9 | # Set the mode according to the application title. 10 | # - You must supply the modes and add cases here. 11 | # - There is a 'default mode' default case. 12 | # - I have two modes, Primary and Secondary, available for testing. 13 | # 14 | app_mode() 15 | { 16 | # shellcheck disable=SC2030 17 | # shellcheck disable=SC2034 18 | i3-msg -t subscribe -m '[ "window" ]' | while read -r unused 19 | do 20 | i3-msg -t get_tree | jq '.. | select(.type?) | select(.focused==true).name' 21 | done | 22 | while read -r line 23 | do 24 | case $line in 25 | (*Emacs*) 26 | i3-msg mode Primary 27 | ;; 28 | (*Firefox*) 29 | i3-msg mode Secondary 30 | ;; 31 | (*) 32 | i3-msg mode default 33 | ;; 34 | esac 35 | # shellcheck disable=SC2031 36 | echo "$line" 37 | done 38 | } 39 | 40 | # 41 | # Start here 42 | # 43 | 44 | # Invoke with the function you wish to call as parameter. Running 45 | # wihout a parameter invokes the app_mode function. 46 | ${1:-app_mode} 47 | 48 | # 49 | # Done. 50 | # 51 | -------------------------------------------------------------------------------- /myscripts/my-usb-disks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # my-usb-disks 4 | # 5 | 6 | 7 | # 8 | # 2021-08-26: I now have just the one external USB drive 'banana' 9 | # connected to my machine 'quietpc'. 10 | # 11 | # 2021-01-28: hd-idle takes sda/sdb/sdc/sdd argument(s) but the system 12 | # no longer guarantees how these map to drives. 13 | # 14 | 15 | # The value of the variable matches sd[abcd] on my machine, with its one 16 | # solid state drive and two hard drives, and is likely to be 'sdd', but 17 | # we play safe and interrogate. The identify option tells us the value. 18 | banana=$(df -h | grep "usb-Seagate_M3_Portable_BFF77E010D000086-0:0-part1") 19 | banana=${banana:5:3} 20 | 21 | # 22 | # Set auto spindown time. 23 | # 24 | configure () 25 | { 26 | case "$1" in 27 | (banana) 28 | sudo /usr/sbin/hd-idle -i 0 -a "${banana}" -i 1200 29 | ;; 30 | esac 31 | } 32 | 33 | # 34 | # Spindown without logout. 35 | # 36 | spindown () 37 | { 38 | case "$1" in 39 | (banana) 40 | sudo /usr/sbin/hd-idle -t "${banana}" 41 | ;; 42 | esac 43 | } 44 | 45 | # 46 | # Start here. 47 | # 48 | 49 | # Do a "belt and braces" check for "safe" script arguments because 50 | # "sudo" and "/etc/sudoers.d" are involved. 51 | case "$1" in 52 | (configure|spindown) 53 | case "$2" in 54 | (banana) 55 | "$1" "$2" 56 | ;; 57 | esac 58 | ;; 59 | (identify) 60 | echo "banana -> ${banana}" 61 | ;; 62 | esac 63 | 64 | # 65 | # Done. 66 | # 67 | -------------------------------------------------------------------------------- /i3scripts/i3-keyboard: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-keyboard (Xubuntu 20.04 LTS) 4 | # 5 | 6 | # 7 | # Bind standalone modifier keys. 8 | # 9 | 10 | # 11 | # Put Menu and Escape keys on both sides of the space bar. If your 12 | # machine is a laptop, consider using Print to provide Menu. 13 | # 14 | xcapekeys() 15 | { 16 | killall -q xcape 17 | # Keycode 108 is ISO_Level3_Shift on my keyboard. 18 | k1='Super_L=Menu' 19 | k2='Alt_L=Escape' 20 | k3='#108=Escape' 21 | # The timeout is a compromise. ymmv. 22 | xcape -t 667 -e "$k1;$k2;$k3" 23 | } 24 | 25 | # 26 | # Set the keyboard layout. 27 | # 28 | xmodmapkeys() 29 | { 30 | # Keycode 51 is to the lower left of Return on my UK keyboard. 31 | # This function makes the asciitilde easier to type than the key 32 | # left of 1, and makes Return better resemble a US keyboard. 33 | ### xmodmap -e 'keycode 51 = Return asciitilde' 34 | xmodmap -e 'pointer = default' 35 | } 36 | 37 | # 38 | # Housekeeping. 39 | # 40 | resetkeys() 41 | { 42 | # In the past "stuck" modifier keys have been an issue. This 43 | # should let the user type again. 44 | i3-msg mode default 45 | xdotool key --clearmodifiers Return 46 | } 47 | 48 | # 49 | # Troubleshooting. 50 | # 51 | # - This is the fix for "setxkbmap" settings that revert spontaneously. 52 | # - Using the file "/etc/default/keyboard" to store settings is persistent. 53 | # - These are EllaTheCat's settings: 54 | # 55 | # KBMODEL="pc105"' 56 | # XKBLAYOUT="us"' 57 | # 'XKBVARIANT="altgr-intl"' 58 | # 'XKBOPTIONS="ctrl:nocaps"' 59 | # 60 | 61 | # 62 | # Start here. 63 | # 64 | 65 | "$1" "${@:2}" 66 | 67 | # 68 | # Done. 69 | # 70 | -------------------------------------------------------------------------------- /i3scripts/i3-launcher: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-launcher 4 | # 5 | 6 | # 7 | # Launch a media player instance and register it. 8 | # - Assume 'mpv' if the command omits the media player. 9 | # 10 | # (1) mpv, vlc, ... 11 | # (.) stream 12 | # 13 | start () 14 | { 15 | if [ "${1:0:1}" = "/" ] || [ "${1:0:7}" = "http://" ]; then 16 | # Absolute paths can be detected reliably. 17 | i3-msg "exec --no-startup-id mpv ${*}" 18 | else 19 | # Allowing arbitrary programs is insecure. 20 | i3-msg "exec --no-startup-id $1 ${*:2}" 21 | fi 22 | } 23 | 24 | # 25 | # Kill the oldest running instance of a media player. 26 | # - Assume 'mpv' if the command omits the media player. 27 | # - A simple TV channel zapper is the canonical use case. 28 | # 29 | # (1) mpv, vlc, ... 30 | # (.) stream 31 | # 32 | stop () 33 | { 34 | # An mpv instance has 2 pids, often contiguous, (N,N+1), but I 35 | # have seen (N,N+2), hence separate kills. 36 | if [ "${1:0:1}" = "/" ] || [ "${1:0:7}" = "http://" ]; then 37 | pid0="$(pgrep --oldest -f "mpv")" 38 | kill "${pid0}" 39 | pid1="$(pgrep --oldest -f "mpv")" 40 | kill "${pid1}" 41 | else 42 | pid0="$(pgrep --oldest -f "$1")" 43 | kill "${pid0}" 44 | pid1="$(pgrep --oldest -f "$1")" 45 | kill "${pid1}" 46 | fi 47 | } 48 | 49 | # 50 | # Start here. 51 | # 52 | 53 | echo "i3-launcher is deprecated" 54 | 55 | # start|stop stream 56 | # start|stop mpv|vlc|... stream 57 | 58 | case "$1" in 59 | (start) 60 | start "${@:2}" 61 | ;; 62 | (stop) 63 | stop "${@:2}" 64 | ;; 65 | esac 66 | 67 | # 68 | # Done. 69 | # 70 | -------------------------------------------------------------------------------- /i3scripts/i3-command-prompt: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-command-prompt. 4 | # 5 | 6 | # The "Command Interface" file is frequently modified. 7 | dir="/dev/shm/${USER}/i3" 8 | file="command" 9 | 10 | # 11 | # Pass the command entered into the dmenu command prompt into the 12 | # command interface. 13 | # 14 | menu() 15 | { 16 | # In order to reduce manual keystrokes, the Return key is pressed 17 | # automatically after the timeout expires. 18 | commandtimeout=${2:-5} 19 | ( sleep "${commandtimeout}" && \ 20 | [ "$(pgrep -c -f 'dmenu -b -fn pango:DejaVu Sans 11 -p Command: ')" \ 21 | -gt 0 ] && xdotool key Return 22 | ) & # Explicit subshell. 23 | numlockx on 24 | # This is the stub of a menu because the timeout doesn't allow 25 | # enough time to navigate. Spaces are mapped to linefeeds. 26 | promptnumber=${1:-0} 27 | cmd=$(echo "cancel" | sed 's/\ /\n/g' | \ 28 | dmenu -b -fn 'pango:DejaVu Sans 11' -p 'Command: ' \ 29 | -m "${promptnumber}") 30 | if [ "${cmd}" = "cancel" ]; then 31 | numlockx off 32 | else 33 | numlockx off 34 | echo "${cmd}" > "${dir}/${file}" 35 | fi 36 | } 37 | 38 | # 39 | # Pass the specified command directly into the command interface. 40 | # 41 | nomenu() 42 | { 43 | echo "$1" > "${dir}/${file}" # $1 is the command. 44 | } 45 | 46 | # 47 | # Start here. 48 | # 49 | case "$1" in 50 | (menu) 51 | "$1" "$(cat "${dir}/prompt")" "$2" # $2 is the timeout. 52 | ;; 53 | (nomenu) 54 | "$1" "$2" # $2 is the command. 55 | ;; 56 | (number) 57 | echo "$2" > "${dir}/prompt" # $2 is the number. 58 | ;; 59 | esac 60 | 61 | # 62 | # Done. 63 | # 64 | -------------------------------------------------------------------------------- /i3scripts/i3-status: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-status (a wrapper around i3status) 4 | 5 | i3status "$@" | while : 6 | do 7 | read -r line 8 | compositor=$(pgrep -c -f '(compton|picom)') 9 | wcam=$(lsof /dev/video0 | awk '{print $1}' | grep -v COMMAND | uniq | sed 's/skypeforl*/skype/g') 10 | wcam=${wcam:-'idle'} 11 | wmic=$(pactl list sources | grep -A 7 alsa_input.usb-Alcor_Micro__Corp._TeckNet-02.mono-fallback | grep -c 'Mute: no') 12 | eval "$(xdotool getmouselocation --shell)" 13 | ccmt='cc offline' 14 | if [ "$(ping -c 1 -W 1 192.168.1.114 | grep -c "1 received")" -ne 0 ]; then 15 | ccmt="cc $(ssh cheesecake /opt/vc/bin/vcgencmd measure_temp)" 16 | fi 17 | # Use the (truncated) UUID to obtain the device. 18 | titan=$(df -h | grep f9fd1893) 19 | orion=$(df -h | grep 9a2b3d26) 20 | kaiju=$(df -h | grep 94bd806f) 21 | titan=$(sudo /usr/sbin/hddtemp "${titan:0:8}" | awk '{print $3}') 22 | orion=$(sudo /usr/sbin/hddtemp "${orion:0:8}" | awk '{print $3}') 23 | kaiju=$(sudo /usr/sbin/hddtemp "${kaiju:0:8}" | awk '{print $3}') 24 | pactl list sink-inputs | grep 'Sink Input'| tail -1 | \ 25 | sed 's/Sink Input \#//g' > /dev/shm/"$USER"/i3/app-pulse-id 26 | api=$(cat /dev/shm/"$USER"/i3/app-pulse-id) 27 | # BIOS order. 28 | cpu0=$(sensors | grep fan1 | awk '{print $2}') # CPU_FAN 120mm rear 29 | sys1=$(sensors | grep fan3 | awk '{print $2}') # SYS_FAN1 120mm disks 30 | sys2=$(sensors | grep fan5 | awk '{print $2}') # SYS_FAN2 80mm cooler 31 | echo "| ($X $Y) | api ${api} | compton ${compositor} | ${ccmt} | cam ${wcam} | mic ${wmic} | ${cpu0} ${sys1} ${sys2} | ${kaiju} ${orion} ${titan} | ${line}" || exit 1 32 | done 33 | 34 | # 35 | # Done. 36 | # 37 | -------------------------------------------------------------------------------- /i3-status-config: -------------------------------------------------------------------------------- 1 | # i3status configuration file. 2 | # see "man i3status" for documentation. 3 | 4 | # It is important that this file is edited as UTF-8. 5 | # The following line should contain a sharp s: 6 | # ß 7 | # If the above line is not correctly displayed, fix your editor first! 8 | 9 | general { 10 | colors = true 11 | interval = 3 12 | } 13 | 14 | order += "disk /" 15 | order += "disk /mnt/94bd806f-4aa9-4514-b2fc-9688182fa571" 16 | order += "disk /mnt/9a2b3d26-e2c9-4ae0-a979-66657c45b43c" 17 | order += "disk /mnt/f9fd1893-75d3-4034-ab58-dffb88063e13" 18 | ### order += "wireless _first_" 19 | ### order += "ethernet _first_" 20 | ### order += "battery all" 21 | order += "cpu_temperature 0" 22 | order += "load" 23 | order += "tztime local" 24 | 25 | wireless _first_ { 26 | format_up = "W: (%quality at %essid) %ip" 27 | format_down = "W: down" 28 | } 29 | 30 | ethernet _first_ { 31 | # if you use %speed, i3status requires root privileges 32 | format_up = "E: %ip (%speed)" 33 | format_down = "E: down" 34 | } 35 | 36 | battery all { 37 | format = "%status %percentage %remaining" 38 | } 39 | 40 | cpu_temperature 0 { 41 | format = "T: %degrees °C" 42 | path = "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp1_input" 43 | } 44 | 45 | tztime local { 46 | format = "%Y-%m-%d %H:%M:%S" 47 | } 48 | 49 | load { 50 | format = "%1min" 51 | } 52 | 53 | disk "/" { 54 | format = "%avail" 55 | } 56 | 57 | disk "/mnt/94bd806f-4aa9-4514-b2fc-9688182fa571" { 58 | format = "%avail" 59 | } 60 | 61 | disk "/mnt/9a2b3d26-e2c9-4ae0-a979-66657c45b43c" { 62 | format = "%avail" 63 | } 64 | disk "/mnt/f9fd1893-75d3-4034-ab58-dffb88063e13" { 65 | format = "%avail" 66 | } 67 | 68 | # 69 | # Done. 70 | # 71 | -------------------------------------------------------------------------------- /i3scripts/i3-dispatcher: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-dispatcher 4 | # 5 | 6 | # 7 | # Forward the command to a dedicated function. 8 | # 9 | forward () 10 | { 11 | # DANGER WILL ROBINSON! Do not "tidy up" (= "delete") this line: 12 | export PATH=${HOME}/local/i3/bin:${PATH} 13 | case "$1" in 14 | ([0-9][0-9][0-9]) 15 | # Sent from numpad command prompt. The numpad layout is 16 | # allegedly faster than the Menu key command prompt due 17 | # to the numbers being close together. 18 | nohup "${HOME}"/local/i3/bin/i3-triple-digit-command "$1" 19 | ;; 20 | ([0-9][0-9]) 21 | # Sent from numpad command prompt. 22 | # "triple" is not a typo here. 23 | nohup "${HOME}"/local/i3/bin/i3-triple-digit-command "$1" 24 | ;; 25 | ([a-z][0-9]) 26 | # Sent from command prompt. 27 | nohup "${HOME}"/local/i3/bin/i3-focus-app-by-alias focus "$1" 28 | ;; 29 | ([a-z][a-z]) 30 | # Sent from command prompt. 31 | nohup "${HOME}"/local/i3/bin/i3-focus-app-by-alias focus "$1" 32 | ;; 33 | (clip|edit) 34 | # Sent from Tasker & AutoVoice. 35 | nohup "${HOME}"/local/i3/bin/i3-transcribe "${@}" 36 | ;; 37 | (interrupt) 38 | # I use this to overlay each of my screens with a specific 39 | # image when my phone is ringing. The user should supply 40 | # the code to be executed on the target inside Tasker. 41 | eval "${*:2}" 42 | ;; 43 | (*) 44 | notify-send "i3-dispatcher:" \ 45 | "Command not found: <$*> request rejected." 46 | ;; 47 | esac 48 | } 49 | 50 | 51 | # 52 | # Start here. 53 | # 54 | 55 | 56 | forward "${@:2}" 57 | 58 | # 59 | # Done. 60 | # 61 | -------------------------------------------------------------------------------- /i3scripts/i3-list-windows: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # 4 | 5 | # 6 | # Inside a dmenu, display the title and the mark for all marked 7 | # windows in a row or column format set by $1. Select a dmenu item to 8 | # visit the associated window which this function will place on a 9 | # specified output $2. 10 | # 11 | menu () 12 | { 13 | # I must do better with 'jq', the following code was crufted up on 14 | # the command line to extract text blocks like this from the jq: 15 | # "reddit: the front page of the internet - Google Chrome" 16 | # [ 17 | # "36" 18 | # ] 19 | # Added the null filter in i3 4.19 (2020-11-15). 20 | # One of the "services" windows "*commands" "*marks" is marked 21 | # with the workspace name only, the other is unmarked, hence one 22 | # will not be listed here. It is not a coding mistake.. 23 | menu="$(i3-msg -t get_tree | jq '.. | objects | .name,.marks' | \ 24 | grep -B1 -A1 '[[]' | tr -d \\n[ | sed 's/--/\n/g' | \ 25 | grep -v 'null' | grep -v "$2")" 26 | # Argument parsing is order dependent. $1 required $2 optional. 27 | # S1 How menu items are laid out. $2 Where to put the window. 28 | case "$1" in 29 | (row) 30 | pair=$(echo "${menu}" | dmenu -b -m 0 -fn 'pango:DejaVu Sans 11') ;; 31 | (column) 32 | pair=$(echo "${menu}" | dmenu -b -m 0 -fn 'pango:DejaVu Sans 11' -l 25) ;; 33 | esac 34 | # The list item format is ->"string1" "string2"<- e.g. the above 35 | # becomes: "reddit...Google Chrome" "36" 36 | for s in ${pair}; do mark=${s/,/}; done 37 | if [ "_${mark}" != "_" ]; then 38 | i3-msg "[ con_mark=${mark} ] focus" 39 | i3-msg "[ con_mark=${mark} ] move workspace to output $2" 40 | fi 41 | } 42 | 43 | # 44 | # Start here. 45 | # 46 | 47 | # command line 48 | # i3-list-windows menu column output 49 | # this-script function $1 $2 50 | # function signature 51 | 52 | "$1" "${@:2}" 53 | 54 | # 55 | # Done. 56 | # 57 | -------------------------------------------------------------------------------- /i3-config.d/cfg08: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | 3 | # 4 | # EXECUTABLE SETTINGS BEGIN HERE. 5 | # 6 | 7 | # Microphones' defaults (see key bindings). 1 = mute here. 8 | exec --no-startup-id pactl set-source-mute $usbaudiosource 1 9 | exec --no-startup-id pactl set-source-mute $analogaudiosource 1 10 | exec --no-startup-id pactl set-source-mute $webcamaudiosource 1 11 | 12 | # My "xubuntu fix broken bluetooth" incantation. 13 | # Authenticated automatically by '/etc/sudoers.d/shevek'. 14 | # Do not use dunst if you use this. 15 | # The Bluetooth icon should appear in xfce4-panel. 16 | exec --no-startup-id sudo systemctl restart bluetooth 17 | exec --no-startup-id sudo modprobe btusb 18 | 19 | # The volume on the 3.5mm analog jack occasionally assumes a value 20 | # much higher than 100% during startup, prevent speaker damage. 21 | exec --no-startup-id pactl set-sink-volume $analogaudiosink 70% 22 | 23 | # EllaTheCat's inotify method for remote launching as local. 24 | $etcfilewatcher 25 | 26 | # These are i3wm variables, not bash variables. 27 | set $dir "/dev/shm/${USER}/i3" 28 | set $file "command" 29 | # The command prompt dmenu screen number safe default is zero. 30 | $i3cmdprompt number 0 31 | 32 | # We should be able to focus or launch from i3 config (or a bash 33 | # script) as we already do via the command prompt. 34 | # 35 | # These are the last commands to execute. They are invoked and are 36 | # waiting to execute, meanwhile the remaining commands and scripts of 37 | # 'i3-config' are invoked and executed. Some juggling is required to 38 | # achieve a visually satisfying result. 39 | 40 | # VGA1 41 | exec --no-startup-id sleep 20s && echo 'tv' > $dir/$file 42 | exec --no-startup-id sleep 22s && echo 'tm' > $dir/$file 43 | # HDMI1 / xfce4-panel 44 | exec --no-startup-id sleep 25s && echo 'ds' > $dir/$file 45 | exec --no-startup-id sleep 27s && echo 'f0' > $dir/$file 46 | exec --no-startup-id sleep 30s && echo 'g0' > $dir/$file 47 | exec --no-startup-id sleep 33s && echo 'e0' > $dir/$file 48 | 49 | # 50 | # EXECUTABLE SETTINGS END HERE. 51 | # 52 | -------------------------------------------------------------------------------- /i3scripts/i3-mouse: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-mouse 4 | 5 | # 6 | # Set how fast or slow the mouse moves, enable or disable it. 7 | # 8 | movement () 9 | { 10 | # This fancy method works on 20.04.02 LTS, but I believe that the 11 | # id can be hardcoded to a value. 12 | # xinput --list --short 13 | # PixArt Microsoft USB Optical Mouse id=11 14 | id=$(xinput list | grep Mouse | cut -d= -f 2 | cut -f 1) 15 | 16 | # The fast|slow changed for 20.04.02 LTS, the property is a 17 | # homogeneous scaling matrix for [x,y,w], so adjust x,y gains on 18 | # the leading diagonal, positions [0]/[0][0] and [4]/[1,1], as 19 | # floats. 20 | 21 | case "$1" in 22 | (disable) 23 | xinput --set-prop "${id}" "Device Enabled" "0" 24 | ;; 25 | (enable) 26 | xinput --set-prop "${id}" "Device Enabled" "1" 27 | ;; 28 | (fast) 29 | xset m 2 0 30 | # I have dual 16:9 monitors side by side so xgain was set 31 | # 32/9 faster than ygain, but I prefer 16/9 (3.2:1.8). 32 | xinput set-prop "${id}" "Coordinate Transformation Matrix" \ 33 | 3.2 0.0 0.0 0.0 1.8 0.0 0 0 1 34 | ;; 35 | (slow) 36 | xset m 1 0 37 | # KISS for fine control, xgain equal to ygain.. 38 | xinput set-prop "${id}" "Coordinate Transformation Matrix" \ 39 | 0.4 0.0 0.0 0.0 0.4 0.0 0 0 1 40 | ;; 41 | (toggle) 42 | # I bind this to button3 when the mouse is inside the i3bar. 43 | # The test is quick-and-dirty, the RHS is matrix[0][0]. 44 | xgain=$(xinput --list-props "${id}" | \ 45 | grep "Coordinate" | awk '{print $5}') 46 | if [ "_${xgain:0:3}" = "_3.2" ]; then 47 | movement slow 48 | else 49 | movement fast 50 | fi 51 | esac 52 | } 53 | 54 | # 55 | # Start here. 56 | # 57 | 58 | "$1" "${@:2}" 59 | 60 | # 61 | # Done. 62 | # 63 | -------------------------------------------------------------------------------- /i3-config.d/cfg01: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # 3 | # NUMPAD BINDINGS BEGIN HERE. 4 | # 5 | 6 | # Numpad keys that are unaffected by the NumLock state: 7 | # There are five: arithmetic signs / * - + and the enter key. 8 | # Bind KP_Delete & KP_Decimal identically to make a sixth. 9 | # Do not rebind KP_Enter! This is a design decision. 10 | 11 | # Inverted T cursor keys. 12 | bindsym KP_Divide move up 13 | bindsym KP_Home move left 14 | bindsym KP_Up move down 15 | bindsym KP_Prior move right 16 | 17 | # Inverted T cursor keys. 18 | bindsym KP_Begin focus up 19 | bindsym KP_End focus left 20 | bindsym KP_Down focus down 21 | bindsym KP_Next focus right 22 | 23 | # Rotated T cursor keys. 24 | # Why would the modifier be allocated like this? 25 | bindsym Ctrl+KP_Left workspace prev_on_output 26 | bindsym KP_Right workspace next_on_output 27 | bindsym KP_Left workspace prev 28 | bindsym Ctrl+KP_Right workspace next 29 | 30 | # Microphone muting (for privacy and phone conferencing). 31 | # The i3bar may be used to display the microphone status: 32 | # 0 == muted; 1 == not muted == a "hot" microphone. 33 | # These are NOT bound in Primary or Secondary modes. 34 | bindsym KP_Delete \ 35 | exec --no-startup-id pactl set-source-mute $webcamaudiosource toggle 36 | bindsym KP_Multiply \ 37 | exec --no-startup-id pactl set-source-mute $analogaudiosource toggle 38 | 39 | # My machine has HDMI driving DVI on the monitor so I use a dedicated 40 | # audio out connector. 41 | exec --no-startup-id pactl set-default-sink $iec958audiosink 42 | 43 | # Volume controls. The upper and smaller key is volume up, the lower 44 | # and larger key is volume down. These control whatever pulseaudio 45 | # thinks id the default. 46 | bindsym KP_Add \ 47 | exec --no-startup-id /bin/bash -c \ 48 | "pactl set-sink-input-volume @DEFAULT_SINK@ $(cat /dev/shm/$USER/i3/app-pulse-id) -6%" 49 | bindsym KP_Subtract \ 50 | exec --no-startup-id /bin/bash -c \ 51 | "pactl set-sink-input-volume @DEFAULTSINK@ $(cat /dev/shm/$USER/i3/app-pulse-id) +6%" 52 | 53 | # 54 | # NUMPAD BINDINGS END HERE. 55 | # 56 | -------------------------------------------------------------------------------- /i3scripts/i3-config-scripts: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # The "services" (note the "fingers in the air" quotes) are intended 4 | # to run contnuously for the session lifetime. 5 | # 6 | # The early code was both over-engineered and clueless, hence there is 7 | # legacy stuff that persists as I carefully excise the pretentious 8 | # bits and address the cluelessness. 9 | # 10 | # 2021-04-03: The commands and marks "services" interact with starting 11 | # and restarting i3 itself. This has been encapsulated in the command 12 | # 'i3-config-scripts restart'; calling any other command is trouble. 13 | # 14 | # 2021-09-19: The hardcoded paths to i3-marks and i3-commands are a 15 | # maintenance burden. 16 | # 17 | # 2021-11-04: i3-config-scripts restart 18 | # 19 | case "$1" in 20 | (start) 21 | case "$2" in 22 | (marks) 23 | (xfce4-terminal -T "$(date +%T) marks" \ 24 | -x "${HOME}/local/i3/bin/i3-marks" update) & 25 | i3-marks numeric 26 | ;; 27 | (commands) 28 | (xfce4-terminal -T "$(date +%T) commands" \ 29 | -x "${HOME}/local/i3/bin/i3-file-watcher") & 30 | i3-marks numeric 31 | ;; 32 | esac 33 | ;; 34 | (stop) 35 | case "$2" in 36 | (marks) 37 | # This kills everything shown in status. 38 | [ "$(pgrep -c -f i3-marks)" -gt 0 ] && killall i3-marks 39 | ;; 40 | (commands) 41 | # 42 | cmd="--watch-files /dev/shm/$USER/i3/command" 43 | exe="--on-modify-command /dev/shm/$USER/i3/execute" 44 | pkill -f "perl /usr/bin/inotify-hookable ${cmd} ${exe}" 45 | ;; 46 | esac 47 | ;; 48 | (restart) 49 | # 2021-03-17: Shutdown both services before restarting the WM, 50 | # allow time for WM restart, then restart both services. KISS. 51 | $0 stop commands 52 | $0 stop marks 53 | if [ "$(i3-msg -t get_workspaces | grep -c wm)" -ne 0 ]; then 54 | i3-msg "[workspace=\"wm\"] kill" 55 | sleep 3 56 | i3-msg "restart" 57 | sleep 5 58 | fi 59 | i3-msg "workspace \"wm\"" 60 | sleep 2 61 | $0 start commands 62 | $0 start marks 63 | ;; 64 | esac 65 | 66 | # 67 | # Done. 68 | # 69 | -------------------------------------------------------------------------------- /i3scripts/i3-recorder: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This module captures desktop video inside a clipping rectangle in 4 | # sync with associated audio. Resource usage is roughly proportional to 5 | # the rectangle area as defined by variables xy and wh. 6 | 7 | # Full HD on 2nd monitor counting from left to right is the default. 8 | xy_default=+1920,0 9 | wh_default=1920x1080 10 | 11 | # Geometry can be set from the command line. 12 | xy=${3:-$xy_default} 13 | wh=${4:-$wh_default} 14 | # 15 | # 2 pass recording: pass 1 does realtime lossless capture, pass 2 does 16 | # encoding as a postprocess. The absurd resource usage is deliberate, 17 | # the end result must not blur text. Consequently the storage for the 18 | # output of pass 1 has to be fast. Full HD video ~45 Mbytes/s 19 | # 20 | pass1dir=${HOME}/orion/grabber/Videos/ 21 | pass2dir=${HOME}/orion/grabber/Videos/ 22 | pass1file=grab.mkv 23 | pass2file=grab.mp4 24 | # 25 | # HDMI is reported as disconnected on my machine (because DVI to DVI 26 | # cable) hence audio recording uses the monitor input associated with 27 | # the audio output. I like the 3.5mm jack simplicity but it is analog 28 | # and can be noisy. External USB sound cards have worked. I currently 29 | # use the SPDIF output to obtain electrical separation. 30 | # 31 | audiosink=alsa_output.pci-0000_00_1b.0.analog-stereo 32 | audiosink=alsa_output.pci-0000_00_1b.0.iec958-stereo 33 | 34 | # 35 | # Set the duration limit to fit recordings within available storage. 36 | # 37 | record() 38 | { 39 | case "$1 $2" in 40 | (video?start) 41 | rm -f "${pass1dir}/${pass1file}" 42 | (ffmpeg \ 43 | -f pulse -ac 2 -i "${audiosink}.monitor" \ 44 | -f x11grab -s "${wh}" -r 25 -i :0.0"${xy}" -c:v huffyuv \ 45 | -q:v 0 -y "${pass1dir}/${pass1file}") & 46 | ;; 47 | (video?stop) 48 | pkill -f "ffmpeg -f pulse" 49 | ffmpeg -i "${pass1dir}/${pass1file}" -c:v mpeg4 -c:a mp3 \ 50 | -q:v 0 -y "${pass2dir}/${pass2file}" 51 | ;; 52 | (video?[1-9][0-9]|video?[1-9][0-9][0-9]|video?[1-7][0-9][0-9][0-9]) 53 | record 'video' 'start' 54 | sleep "$2" 55 | record 'video' 'stop' 56 | ;; 57 | (*) 58 | echo "record: video command argument: $2 not supported" 59 | exit 1 60 | ;; 61 | esac 62 | } 63 | 64 | 65 | # 66 | # Start here. 67 | # 68 | 69 | mkdir -p "${pass1dir}" "${pass2dir}" 70 | 71 | record "$1" "$2" "${@:3}" 72 | 73 | # 74 | # Done. 75 | # 76 | -------------------------------------------------------------------------------- /i3-config.d/cfg05: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # 3 | # SECONDARY MODE BEGINS HERE. 4 | # 5 | 6 | # Secondary Mode. 7 | # Entered from primary mode using Menu. 8 | # Use this mode for settings, not window management. 9 | mode "Secondary" { 10 | 11 | # Protect the exit from this mode. 12 | # Using space is a design decision, please do not change. 13 | bindsym space $default 14 | 15 | bindsym q nop 16 | bindsym w nop 17 | 18 | bindsym r nop 19 | 20 | bindsym t nop 21 | bindsym y nop 22 | 23 | bindsym i nop 24 | bindsym o nop 25 | bindsym p nop 26 | 27 | bindsym bracketleft nop 28 | bindsym bracketright nop 29 | 30 | # Select an audio output. 31 | bindsym a $default, exec --no-startup-id pactl move-sink-input \ 32 | "$(pactl list short sink-inputs | awk '{print $1}')" $analogaudiosink ; 33 | bindsym h $default, exec --no-startup-id pactl move-sink-input \ 34 | "$(pactl list short sink-inputs | awk '{print $1}')" $hdmiaudiosink ; 35 | bindsym b $default, exec --no-startup-id pactl move-sink-input \ 36 | "$(pactl list short sink-inputs | awk '{print $1}')" $bluetoothaudiosink ; 37 | bindsym u $default, exec --no-startup-id pactl move-sink-input \ 38 | "$(pactl list short sink-inputs | awk '{print $1}')" $usbaudiosink ; 39 | 40 | # Mnemonic mouse keys 41 | bindsym s $default, $i3mouse slow 42 | bindsym f $default, $i3mouse fast 43 | bindsym d $default, $i3mouse disable 44 | bindsym e $default, $i3mouse enable 45 | 46 | # Compositor enable and disable bindings. G evokes "3D >gDef->Pri->Sec. 84 | bindsym Menu $default 85 | bindsym Print $default 86 | } 87 | 88 | # 89 | # SECONDARY MODE ENDS HERE. 90 | # 91 | -------------------------------------------------------------------------------- /i3-config.d/apps00: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | 3 | declare -A wsapps=( 4 | ["e0"]="i3-emacsclient t" 5 | ["e1"]="i3-emacsclient t" 6 | ["e2"]="i3-emacsclient t" 7 | ["e3"]="i3-emacsclient t" 8 | ["e4"]="i3-emacsclient t" 9 | ["e5"]="i3-emacsclient t" 10 | ["e6"]="i3-emacsclient t" 11 | ["e7"]="i3-emacsclient t" 12 | ["e8"]="emacsclient -c" 13 | ["e9"]="emacsclient -c" 14 | ["f0"]="firefox" ["f1"]="firefox" 15 | ["f2"]="firefox" ["f3"]="firefox" 16 | ["f4"]="firefox" ["f5"]="firefox" 17 | ["f6"]="firefox" ["f7"]="firefox" 18 | ["f8"]="firefox" ["f9"]="firefox" 19 | ["g0"]="google-chrome" ["g1"]="google-chrome" 20 | ["g2"]="google-chrome" ["g3"]="google-chrome" 21 | ["g4"]="google-chrome" ["g5"]="google-chrome" 22 | ["g6"]="google-chrome" ["g7"]="google-chrome" 23 | ["g8"]="google-chrome" ["g9"]="google-chrome" 24 | ["n0"]="i3-msg 'exec nautilus' && i3-msg 'exec nautilus'" 25 | ["n1"]="i3-msg 'exec nautilus' && i3-msg 'exec nautilus'" 26 | ["n2"]="i3-msg 'exec nautilus' && i3-msg 'exec nautilus'" 27 | ["n3"]="i3-msg 'exec nautilus' && i3-msg 'exec nautilus'" 28 | ["t0"]="exo-open --launch FileManager && exo-open --launch FileManager" 29 | ["t1"]="exo-open --launch FileManager && exo-open --launch FileManager" 30 | ["t2"]="exo-open --launch FileManager && exo-open --launch FileManager" 31 | ["t3"]="exo-open --launch FileManager" 32 | ["t4"]="exo-open --launch FileManager" 33 | ["t5"]="exo-open --launch FileManager" 34 | ["ae"]="calc" 35 | ["ap"]="impress" 36 | ["aw"]="writer" 37 | ["gi"]="gigolo" 38 | ["go"]="gigolo" 39 | ["hb"]="${HOME}/local/public/bin/handbrake-cpulimit" 40 | ["md"]="meld" 41 | ["sc"]="xfce4-terminal -e scrcpy" 42 | ["sk"]="skype" 43 | ["sp"]="spotify" 44 | ["sy"]="synaptic-pkexec" 45 | ["tb"]="thunderbird" 46 | ["tf"]="tvheadend-firefox" 47 | ["tm"]="xfce4-terminal -T 'bpytop' -e bpytop" 48 | ["tv"]="tvheadend-start" 49 | ["vm"]="virtualbox" 50 | ["vp"]="vlc" 51 | 52 | ) # ---------------------------------------------------------------- # 53 | 54 | declare -A not_wsapps=( 55 | ["ds"]="dropbox start" 56 | ["em"]="emacsclient -c" 57 | ["ff"]="firefox" 58 | ["gc"]="google-chrome" 59 | ["mx"]="pavucontrol" 60 | ["ns"]="nautilus -w" 61 | ["th"]="exo-open --launch FileManager" 62 | ["tt"]="xfce4-terminal -T 'xfce4-terminal'" 63 | ["we"]="i3-msg 'workspace 1' && sleep 0.2 && i3-msg 'workspace 2' && sleep 0.2 && i3-msg 'workspace 3'" 64 | ["wf"]="feh --bg-fill --no-xinerama ${HOME}/local/public/share/fehbg.png" 65 | ["ws"]="feh --bg-fill -bg-tile ${HOME}/local/private/share/ws1.jpg ${HOME}/local/private/share/ws2.jpg ${HOME}/local/private/share/ws3.jpg" 66 | ["wb"]="feh --bg-center --bg-fill --no-xinerama ${HOME}/local/public/share/books3.png" 67 | ["wz"]="(zenity --info --text='workspace non-empty')&" 68 | ) # ---------------------------------------------------------------- # 69 | 70 | # The we command [e]xposes workspaces 1 & 2 & 3 together. These are 71 | # normally made inaccessible by the cfg03 double digit bindings for 72 | # workspaces 10 to 99. They are assigned to left and right outputs. 73 | # Neither 1 nor 2 nor 3 is tiled so the entire backdrop is visible. 74 | 75 | # The wz command puts up a dialog box that, being a window, keeps an 76 | # otherwise empty workspace alive. Show off the backdrop! 77 | 78 | # The wf command shows a picture of a beach taken by EllaTheCat you 79 | # are welcome to use as desktop wallpaper. It's 43 Mbytes so isn't on 80 | # github. md5sum 23df3bc586eb2c4951fbf43ca1112882 fehbg.png 81 | -------------------------------------------------------------------------------- /i3scripts/i3-triple-digit-command: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-triple-digit-command 4 | # 5 | 6 | # Copy from i3-config, paste and edit to be bash environment variables. 7 | export analogaudiosink=alsa_output.pci-0000_00_1b.0.analog-stereo 8 | ###### bluetoothaudiosink=bluez_sink.00_01_01_00_12_CB 9 | export bluetoothaudiosink=bluez_sink.30_22_00_00_C7_F5.a2dp_sink 10 | export hdmiaudiosink=alsa_output.pci-0000_00_03.0.hdmi-stereo 11 | usbaudiosink=alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo 12 | 13 | # Reverse engineered. >wave arms and mumble< 14 | usbaudiocard=alsa_card.usb-C-Media_Electronics_Inc._USB_Audio_Device-00 15 | usbaudioport=analog-output-speaker 16 | 17 | # 18 | # - Manage containers with marks. 19 | # - Manage USB audio volumes. 20 | # - Manage USB audio latency. 21 | # 22 | i3_triple_digit() 23 | { 24 | case "$1" in 25 | ([1][0-9][0-9]) 26 | # Audio latency offset. The two digits are interpreted as 27 | # a percentage of one second. 28 | arg="${1:1:2}" 29 | pactl set-port-latency-offset \ 30 | ${usbaudiocard} ${usbaudioport} "${arg}0000" 31 | ;; 32 | ([2][0-9][0-9]) 33 | # Volume settings 00 to 99. Although pavucontrol allows as 34 | # high as 150% the API doesn't. 35 | arg="${1:1:2}%" # USB volume as a percentage. 36 | pactl set-sink-volume ${usbaudiosink} "${arg}" 37 | ;; 38 | ([3][0-9][0-9]) 39 | # Volume settings 00 to 99. Although pavucontrol allows as 40 | # high as 150% the API doesn't. 41 | arg="${1:1:2}%" # Line Out volume as a percentage. 42 | pactl set-sink-volume ${analogaudiosink} "${arg}" 43 | ;; 44 | ([4][0-9][0-9]) 45 | # Visit a two-digit mark using numpad or voice. 46 | arg="${1:1:2}" 47 | for mark in $(i3-msg -t get_marks | sed 's/,/ /g' | sed 's/[][]//g') 48 | do 49 | if [ "\"${arg}\"" = "${mark}" ]; then 50 | i3-msg "[con_mark=\"${arg}\"] focus" 51 | return 52 | fi 53 | done 54 | notify-send "i3-triple-digit:" \ 55 | "Mark not found: >${arg}<, visit request rejected." 56 | ;; 57 | ([5][0-9][0-9]) 58 | # Swap this container with the matching marked container. 59 | arg="${1:1:2}" 60 | for mark in $(i3-msg -t get_marks | sed 's/,/ /g' | sed 's/[][]//g') 61 | do 62 | if [ "\"${arg}\"" = "${mark}" ]; then 63 | i3-msg "swap container with mark ${arg}" 64 | return 65 | fi 66 | done 67 | notify-send "i3-triple-digit:" \ 68 | "Mark not found: >${arg}<, swap request rejected." 69 | ;; 70 | ([6][0-9][0-9]) 71 | # Volume settings 00 to 99. Although pavucontrol allows as 72 | # high as 150% the API doesn't. 73 | arg="${1:1:2}%" # Line Out volume as a percentage. 74 | pactl set-sink-volume ${bluetoothaudiosink} "${arg}" 75 | ;; 76 | ([7][0-9][0-9]) 77 | arg="${1:1:2}" 78 | i3-msg "resize set width ${arg}ppt" 79 | ;; 80 | ([089][0-9][0-9]) 81 | # Any other 3 digit matches. 82 | arg="${1:1:2}" 83 | notify-send "i3-triple-digit:" \ 84 | "Command alias not found: >${arg}<, request rejected" 85 | ;; 86 | esac 87 | } 88 | 89 | # 90 | # Start here. 91 | # 92 | 93 | i3_triple_digit "$1" 94 | 95 | # 96 | # Done. 97 | # 98 | -------------------------------------------------------------------------------- /i3scripts/i3-focus-app-by-alias: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # i3-focus-app-by-alias 4 | # 5 | 6 | # 7 | # The dictionary "wsapps" should only contain entries for apps that 8 | # have dedicated workspaces, whereas "not_wsapps" is for adding an 9 | # emacs frame or web/file browser tab/window to "wsapps" windows. 10 | # 11 | 12 | ###INSERT_APPS00_HERE### 13 | 14 | # 15 | # Focus a running instance of an app given its command alias, 16 | # launching the instance beforehand as necessary. 17 | # 18 | focus () 19 | { 20 | case "$1" in 21 | ([e][0-9]) 22 | # Run emacs server for the emacsclients. 23 | if [ "$(pgrep -c -f "emacs --daemon -rv")" -eq 0 ]; then 24 | (emacs --daemon -rv) & 25 | sleep 3 26 | fi 27 | ;; 28 | esac 29 | case "$1" in 30 | ([a-z][0-9]|[a-z][a-z]) 31 | # The app can launch in its dedicated workspace. 32 | # shellcheck disable=SC2154 33 | wsapp=${wsapps[$1]} 34 | # The app can only launch in the current workspace. 35 | # shellcheck disable=SC2154 36 | not_wsapp=${not_wsapps[$1]} 37 | 38 | # A workspace whose name matches the command alias. 39 | ws=$(i3-msg -t get_workspaces | jq '.[] | .name'| grep "$1") 40 | # The current workspace. Thank you i3wm subreddit. 41 | cws=$(i3-msg -t get_workspaces | jq -r '.[] | select(.focused).name') 42 | 43 | if [ "_${wsapp}" != "_" ]; then 44 | # Why does this work? Initially app "xy" is marked 45 | # "[xy]". The mark may be passed on to other apps in 46 | # the workspace. 47 | status=$(i3-msg "[workspace=\"$1\" con_mark=\"${1:0:2}\"] focus") 48 | # "No window matches given criteria" is not an 49 | # error here, it's one of two desired outcomes. 50 | case "${status}" in 51 | (*true*) 52 | i3-msg "workspace --no-auto-back-and-forth \"$1\"" 53 | notify-send "i3-focus-apps-by-alias" "$(printf "%s\n%s" \ 54 | "the current workspace has changed to [$1]," \ 55 | "${wsapp} was already running.")" 56 | ;; 57 | (*false*) 58 | # We want the script to terminate hence using i3-msg. 59 | i3-msg "workspace --no-auto-back-and-forth \"$1\"" 60 | # The enhanced PATH is exported by the dispatcher. 61 | # The i3-msg recipient can't see the enhanced PATH. 62 | # Extract and prepend the path directory components. 63 | # The executable name remains after removing the 64 | # "longest matching suffix", defined by space star. 65 | # Get the full path to the executable, remove the 66 | # name part, prepend the rest to the command. 67 | arg0=${wsapp%% *} 68 | path=$(command -v "${arg0}") # "which" 69 | path=${path/${arg0}/} 70 | i3-msg "exec --no-startup-id ${path}${wsapp}" 71 | notify-send "i3-focus-apps-by-alias" "$(printf "%s\n%s" \ 72 | "the current workspace has changed to [$1]," \ 73 | "${wsapp} has been launched.")" 74 | ;; 75 | esac 76 | elif [ "_${not_wsapp}" != "_" ]; then 77 | arg0=${not_wsapp%% *} 78 | path=$(command -v "${arg0}") 79 | path=${path/${arg0}/} 80 | i3-msg "exec --no-startup-id ${path}${not_wsapp}" 81 | notify-send "i3-focus-apps-by-alias" "$(printf "%s\n%s" \ 82 | "the current workspace >${cws}<is unchanged," \ 83 | "${not_wsapp} has been launched.")" 84 | elif [ "_$ws" != "_" ]; then 85 | i3-msg "workspace --no-auto-back-and-forth \"$1\"" 86 | notify-send "i3-focus-apps-by-alias" "$(printf "%s\n%s" \ 87 | "the current workspace has changed to [$1]," \ 88 | "no app has been launched.")" 89 | else 90 | i3-msg "workspace --no-auto-back-and-forth \"$1\"" 91 | i3-msg "exec --no-startup-id xfce4-terminal" 92 | notify-send "i3-focus-apps-by-alias" "$(printf "%s\n%s" \ 93 | "the current workspace has changed to [$1]," \ 94 | "xfce4-terminal has been launched.")" 95 | fi 96 | esac 97 | } 98 | 99 | 100 | # 101 | # Start here. 102 | # 103 | 104 | # focus $1 ... 105 | "${@}" 106 | 107 | # 108 | # Done. 109 | # 110 | -------------------------------------------------------------------------------- /i3scripts/i3-marks: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | # 5 | # Assign a 2 digit mark to a window. 6 | # 7 | numeric() 8 | { 9 | # Generate a random 2 digit mark. Reject and retry if it matches 10 | # an assigned mark. The retry loop takes more time as the number 11 | # of marked containers approaches 100. 12 | while : ; do 13 | id=$((10#$(date +%N) % 100)) 14 | id=$(printf "%02d" "${id}") 15 | count=$(for m in $(i3-msg -t get_marks | grep '[0-9][0-9]' | sed 's/,/\ /g'); 16 | do echo "${m}"; done | grep -c "${id}") 17 | if [ "${count}" -eq 0 ]; then break; fi 18 | done 19 | sleep 1 # No need for caller to wait for the window. 20 | windowid=$(printf "0x%x" "$(xdotool getwindowfocus)") 21 | i3-msg "[id=\"${windowid}\"] mark --toggle \"${id}\"" 22 | i3-msg "[con_mark=\"${id}\"] focus" 23 | } 24 | 25 | # 26 | # Mark the focused window with the workspace name defined by the 27 | # command alias. 28 | # 29 | # - Note: These marks could and should be hidden by prefixing with an 30 | # - underscore. They are exposed for debug and test convenience only. 31 | # 32 | commandalias() 33 | { 34 | cws=$(i3-msg -t get_workspaces | jq -r '.[] | select(.focused).name') 35 | 36 | windowid=$(printf "0x%x" "$(xdotool getwindowfocus)") 37 | # Fetch all marks in a list and walk that list, ignoring any mark 38 | # that isn't a workspace mark as indicated by a lowercase letter 39 | # followed by another or a digit. Remove any matching workspace 40 | # mark on the current window. Numeric marks (two digits) remain. 41 | for mark in $(i3-msg -t get_marks | \ 42 | sed 's/"[0-9][0-9]"//g' | sed 's/,/ /g'| sed 's/[][]//g') 43 | do 44 | i3-msg "[id=\"${windowid}\"] unmark ${mark}" 45 | done 46 | 47 | # Apply the new workspace mark, replacing the old one. 48 | i3-msg "[id=\"${windowid}\"] mark --add --replace ${cws}" 49 | } 50 | 51 | # 52 | # If a workspace is empty and a terminal is launched from there, the 53 | # terminal will be made floating, but should any other window appear, 54 | # it will be tiled. 55 | # 56 | # This is associated with a bug that inflates a window to be bigger 57 | # than the screen. It should be called at the end of commandalias() in 58 | # a backgrounded subshell thus: (floating) & 59 | # 60 | floating() 61 | { 62 | count=0 63 | # shellcheck disable=SC2034 64 | for w in $(xdotool search --onlyvisible --desktop \ 65 | "$(xprop -notype -root _NET_CURRENT_DESKTOP | \ 66 | cut -c 24-)" "" 2>/dev/null) ; do 67 | count=$((count + 1)) 68 | done 69 | 70 | case "${count}" in 71 | (1) 72 | cc="[workspace=\"__focused__\" instance=\"xfce4-terminal\"]" 73 | cmds="floating enable, resize set 60 ppt 60 ppt, move position center;" 74 | i3-msg "$(printf "%s %s" "${cc}" "${cmds}")" 75 | ;; 76 | (2) 77 | cc="[workspace=\"__focused__\" instance=\"xfce4-terminal\"]" 78 | cmds="floating disable;" 79 | i3-msg "$(printf "%s %s" "${cc}" "${cmds}")" 80 | ;; 81 | esac 82 | } 83 | 84 | 85 | # 86 | # Warp the mouse to normalised window coords (0.33,0.33) inside the 87 | # window in focus. Allow a fraction of a second for the requested 88 | # window to gain focus. 89 | # 90 | # https://www.reddit.com/r/i3wm/comments/nr73k6/ 91 | # mouse_following_the_focused_window/ 92 | # h0f4var?utm_source=share&utm_medium=web2x&context=3 93 | # 94 | mousewarp () 95 | { 96 | sleep 0.2 97 | HERE="$(xdotool getwindowfocus)" 98 | 99 | ULX=$(xwininfo -id "$HERE" | grep " Absolute upper-left X:" | awk '{print $4}') 100 | ULY=$(xwininfo -id "$HERE" | grep " Absolute upper-left Y:" | awk '{print $4}') 101 | 102 | # If there is no window, ULX == 1 and ULY == 1. 103 | if [ "$ULX" != "-1" ] || [ "$ULY" != "-1" ]; then 104 | eval "$(xdotool getwindowgeometry --shell "$HERE")" 105 | 106 | ((NX="$WIDTH"/3)) 107 | ((NY="$HEIGHT"/3)) 108 | 109 | xdotool mousemove --window "$WINDOW" "$NX" "$NY" 110 | fi 111 | } 112 | 113 | 114 | # 115 | # When the monitor indicates a window change, walk the "linked list" 116 | # with "commandalias" at the head. 117 | # 118 | update() 119 | { 120 | # shellcheck disable=SC2034 121 | i3-msg -t subscribe -m '[ "window" ]' | \ 122 | while read -r line ; do commandalias; read -r line; read -r line; done 123 | # Why 3 reads? I thought I had seen each event sending 3 lines. 124 | # With just 1 read, CPU usage rises, the marks on the title bar 125 | # flicker. This ought to be investigated further, but it works. 126 | } 127 | 128 | 129 | # 130 | # Start here. 131 | # 132 | 133 | case "_$1" in 134 | (_numeric) 135 | numeric 136 | ;; 137 | (_commandalias) 138 | commandalias 139 | ;; 140 | (_floating) 141 | floating 142 | ;; 143 | (_mousewarp) 144 | mousewarp 145 | ;; 146 | (_update) 147 | update 148 | ;; 149 | esac 150 | 151 | # 152 | # Done. 153 | # 154 | -------------------------------------------------------------------------------- /i3scripts/i3-transcribe: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | 4 | export lmon=HDMI2 5 | export cmon=HDMI1 6 | 7 | 8 | # 9 | # Enhance the 'all lower case' text sent from AutoVoice and put the 10 | # result into the Emacs buffer "Clipboard". 11 | # 12 | clipboard () 13 | { 14 | # Restore the quotes substituted in Tasker to avoid misbehaviour. 15 | # shellcheck disable=SC2002 16 | contents=$(echo "$*" | sed 's/DQUOTE/\"/g' | sed "s/SQUOTE/\'/g") 17 | # Make the string more "sentence-like". 18 | contents=$(mksentence "${contents}") 19 | # Insert into both clipboards and then paste into Emacs. 20 | echo "${contents}" | xclip -selection primary # mouse button 2 21 | echo "${contents}" | xclip -selection clipboard # emacs control y 22 | emacsclient -e "(switch-to-buffer \"Clipboard\" )" 23 | emacsclient -e "(with-current-buffer \"Clipboard\" (yank))" 24 | } 25 | 26 | mksentence () 27 | { 28 | s=$(mkeye "$1") 29 | s=$(mkfirst "$s") 30 | s=$(mklast "$s") 31 | echo "$s" 32 | } 33 | 34 | # 35 | # Capitalise the 1st person singular pronoun 'I'. 36 | # 37 | mkeye () 38 | { 39 | # This is adequate for most sentences. 40 | # "I know I am i'm sure I am i'm h a p p y" 41 | # >I know I am i'm sure I am I'm h a p p y< 42 | 43 | s="${1/^i\ /I\ }" # Capital 'I' at beginning. 44 | s="${s/i\ /I\ }" # Capital 'I' then space 45 | s="${s/i\ /I\ }" 46 | s="${s/i\ /I\ }" 47 | s="${s/i\ /I\ }" 48 | s="${s/i\'/I\'}" # Capital 'I' then apostrophe. 49 | s="${s/i\'/I\'}" 50 | echo "$s" 51 | } 52 | 53 | # 54 | # Capitalise the 1st letter of the 1st word of a sentence. 55 | # 56 | mkfirst () 57 | { 58 | echo "${1^}" # bash 4.0 59 | } 60 | 61 | # 62 | # Close sentence with '.' or '?' or '!'. 63 | # - Unfortunately the format is specified before the text of the sentence. 64 | # 65 | mklast () 66 | { 67 | case "$1" in 68 | # Use this to override the question heuristic. 69 | # Say "full stop" or "stop" to be reliably recognised. 70 | # Google actually punctuates in response to the former. 71 | (\.*|Stop*) 72 | s=${1/\.\ /} 73 | s=${s/Stop\ /} 74 | s=$(mkfirst "$s") 75 | printf "%s." "${s}" 76 | ;; 77 | # Say "question" to be reliably recognised. 78 | (Question*) 79 | s=${1/Question\ /} 80 | s=$(mkfirst "$s") 81 | printf "%s?" "${s}" 82 | ;; 83 | # Say "shout" to be reliably recognised. 84 | (Shout*) 85 | s=${1/Shout\ /} 86 | s=$(mkfirst "$s") 87 | printf "%s!" "${s}" 88 | ;; 89 | # Use a simple heuristic with "question words" as a fallback 90 | # should you either forget to prefix or should AutoVoice miss 91 | # the first word as sometimes happens. 92 | (What\ *|When\ *|Where\ *|Which\ *|Who\ *|How\ *|Do\ *) 93 | printf "%s?" "$1" 94 | ;; 95 | # This default is frequently correct. 96 | (*) 97 | printf "%s." "$1" 98 | ;; 99 | esac 100 | } 101 | 102 | # 103 | # A simple line oriented text editor. 104 | # - On short commands, AutoVoice freeform speech recognition is infuriating. 105 | # 106 | editor () 107 | { 108 | # Apply a special mark to the active window so we can go back to 109 | # said window, without disturbing any existing marks there. 110 | i3-msg 'mark --add --toggle xyzzy' 111 | # Focus the clipboard window. This may not be necessary but play 112 | # safe until the code is stable. 113 | i3-msg '[title="Emacs : Clipboard"] focus' 114 | case "$1" in 115 | (goto) 116 | emacsclient -e "(set-buffer \"Clipboard\")" 117 | emacsclient -e "(with-current-buffer \"Clipboard\" (move-beginning-of-line 1))" 118 | emacsclient -e "(with-current-buffer \"Clipboard\" (goto-line $2))" 119 | ;; 120 | (mark) 121 | emacsclient -e "(set-buffer \"Clipboard\")" 122 | emacsclient -e "(with-current-buffer \"Clipboard\" (move-beginning-of-line 1))" 123 | emacsclient -e "(with-current-buffer \"Clipboard\" (goto-line $2))" 124 | emacsclient -e "(with-current-buffer \"Clipboard\" (set-mark-command 1))" 125 | ;; 126 | (kill) 127 | emacsclient -e "(set-buffer \"Clipboard\")" 128 | emacsclient -e "(with-current-buffer \"Clipboard\" (kill-line ${2:-1}))" 129 | ;; 130 | (yank) 131 | emacsclient -e "(set-buffer \"Clipboard\")" 132 | emacsclient -e "(with-current-buffer \"Clipboard\" (yank ${2:-1}))" 133 | ;; 134 | esac 135 | # Return to the formerly active window labelled with the special 136 | # mark then remove said mark. The delay is cosmetic above 500ms. 137 | sleep 0.8 138 | i3-msg '[con_mark="xyzzy"] focus' 139 | i3-msg 'unmark xyzzy' 140 | } 141 | 142 | # 143 | # Start here. 144 | # 145 | 146 | # clip text 147 | # edit goto|mark|kill|yank line|line|count|item 148 | 149 | case "$1" in 150 | (clip) 151 | clipboard "${@:2}" 152 | ;; 153 | (edit) 154 | editor "${@:2}" 155 | ;; 156 | (*) 157 | ;; 158 | esac 159 | 160 | # 161 | # Done. 162 | # 163 | -------------------------------------------------------------------------------- /i3-config.d/cfg04: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # 3 | # Primary mode. 4 | # Use this mode for window management, not settings. 5 | mode "Primary" { 6 | 7 | # Protect the exit from this mode. 8 | # Using space is a design decision, please do not change. 9 | bindsym space $default 10 | 11 | # This is independent of the similarly named configuration setting. 12 | bindsym q $default, workspace back_and_forth 13 | 14 | # (W)orkspace. If the workspace does not exist beforehand it is 15 | # created, if it already exists, it is focused. 16 | bindsym w $default, exec --no-startup-id i3-input -f $i3inputfont -l 2 \ 17 | -P '(workspace): ' -F 'workspace "%s"' 18 | 19 | # (R)ename a workspace. 20 | bindsym r $default, exec --no-startup-id i3-input -f $i3inputfont -l 2 \ 21 | -P '(rename this workspace to): ' \ 22 | -F 'rename workspace to "%s"' 23 | 24 | # Launch a terminal. Including the preceding splits feels natural 25 | # to me. I urge you to try it. 26 | bindsym t $default, split h, exec xfce4-terminal 27 | bindsym y $default, split v, exec xfce4-terminal 28 | 29 | # Focus the workspace with the latest [u]rgency hint. 30 | bindsym u $default, [urgent=latest] focus 31 | 32 | # [I]nfo on keyboard bindings. $help is available as a fallback. 33 | # https://github.com/glennular/i3help 34 | # https://www.reddit.com/r/i3wm/comments/k3ifyq/i3help_keyboard_binding_help_dialog_gtk/ 35 | bindsym i $default, exec --no-startup-id i3help -f ~/.i3/config 36 | 37 | # P for Parent. O for Offspring. 38 | bindsym o $default, focus child 39 | bindsym p $default, focus parent 40 | 41 | # Scratchpad (generic) - equal is unshifted plus. 42 | bindsym minus $default, move scratchpad 43 | bindsym equal $default, scratchpad show 44 | bindsym grave $default, focus, floating toggle; 45 | 46 | # Scratchpad for the pulseaudio sound settings. 47 | bindsym bracketleft $default, [title="Volume Control"] move scratchpad 48 | bindsym bracketright $default, [title="Volume Control"] unmark, scratchpad show; 49 | 50 | # Command prompt. Thumb and middle finger of the left hand. 51 | bindsym Tab $default, $i3cmdprompt menu 4 52 | # The backslash to the left of Z on a UK keyboard US intl layout. 53 | bindcode 94 $default, $i3cmdprompt menu 4 54 | # Configure the dmenu monitor number of the command prompt on-the-fly. 55 | bindsym 1 $default, $i3cmdprompt number 1 56 | bindsym 2 $default, $i3cmdprompt number 2 57 | bindsym 0 $default, $i3cmdprompt number 0 58 | # Toggle a side-by-side pair to one-above-the-other. 59 | # A for Above. 60 | bindsym a $default, focus right, split v, focus left, move right, move up ; 61 | # Toggle a one-above-the-other pair to side-by-side. 62 | # S for Side by Side. 63 | bindsym s $default, focus down, split h, focus up, move down, move left; 64 | 65 | # Layouts. Unfortunately the t and tab keys are already allocated. 66 | bindsym d $default, layout default 67 | bindsym e $default, layout tabbed 68 | 69 | # Enter [f]ullscreen mode for the focused container. This races 70 | # with the marks "service" that makes single windows floating with 71 | # a transpaent frame to reveal wallpaper. It is currently working 72 | # and robust but ideally these bindings should call into i3-marks. 73 | bindsym f $default, floating disable, fullscreen toggle; 74 | bindsym g $default, floating disable, fullscreen toggle global; 75 | 76 | # Increase or decrease the height or width symmetrically. 77 | # I orient myself by how the border separating windows moves. 78 | # Consider swapping the HL or JK directions if not to your liking. 79 | bindsym h resize grow right 6 px or 1 ppt, resize grow left 6 px or 1 ppt 80 | bindsym j resize shrink down 6 px or 1 ppt, resize shrink up 6 px or 1 ppt 81 | bindsym k resize grow up 6 px or 1 ppt, resize grow down 6 px or 1 ppt 82 | bindsym l resize shrink left 6 px or 1 ppt, resize shrink right 6 px or 1 ppt 83 | 84 | # Toggle between being a tiled|floating window. 85 | # Toggle focus between tiled|floating windows. 86 | bindsym semicolon floating toggle 87 | bindsym apostrophe focus mode_toggle 88 | 89 | bindsym Return nop 90 | 91 | # Move workspace to another output. 92 | bindsym z $default, move workspace to output $lmon 93 | bindsym x $default, move workspace to output $cmon 94 | bindsym c $default, move workspace to output $rmon 95 | 96 | # Split directions. 97 | bindsym v split v 98 | bindsym b split h 99 | 100 | # Place a numeric mark on the focused window's title bar. 101 | # The mark is a two digit [n]umber. 102 | # Note: A command prompt version loses track of focus? 103 | bindsym n $default, $i3marks numeric 104 | 105 | # (M)ove container to named workspace. 106 | bindsym m $default, exec --no-startup-id i3-input -f $i3inputfont -l 2 \ 107 | -P '(move container to workspace): ' \ 108 | -F 'move container to workspace "%s"' 109 | 110 | # [D]menu showing window titles and their associated marks. 111 | # The use case is finding the title a mark is associated with. 112 | # Selecting an item visits the mark. 113 | bindsym comma $default, $i3listwindows menu column $lmon 114 | bindsym period $default, $i3listwindows menu column $cmon 115 | bindsym slash $default, $i3listwindows menu column $rmon 116 | 117 | # Pressing cycles through the three modes. Pri->Sec->Def->Pri. 118 | bindsym Menu $secondary 119 | bindsym Print $secondary 120 | } 121 | -------------------------------------------------------------------------------- /i3-config: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # 3 | # i3 version 4.18 (2020-02-17) Xubuntu 20.04 LTS 01 May 2020 4 | # 5 | # Combines EllaTheCat's advocacy of marks and modes with the de facto 6 | # standard i3 bindings. 7 | 8 | # IMPORTANT. 9 | # 10 | # You *must* run 'make' successfully from the "dopamine-2020" 11 | # directory to complete installation! 12 | 13 | # ESSENTIALS. 14 | # 15 | # - i3 defines bindings and settings such that "first one wins". 16 | # - A corollary is that essentials be defined as early as possible. 17 | 18 | 19 | # Choose a terminal you can use to repair a broken configuration. 20 | bindsym Mod4+Return exec xfce4-terminal 21 | 22 | # 23 | # CONSTANTS. 24 | # 25 | 26 | # Mod4 (Windows) key is the default, Mod1 (Alt) is the alternative. 27 | # Setting $mod to Mod3 "disables" the classic bindings. 28 | set $mod Mod4 29 | 30 | # In default mode, this facilitates move and resize using the mouse 31 | # without having to precisely position the mouse on window edges. 32 | floating_modifier Mod4 33 | 34 | set $default exec --no-startup-id ~/local/i3/bin/i3-mode default 35 | set $primary exec --no-startup-id ~/local/i3/bin/i3-mode Primary 36 | set $secondary exec --no-startup-id ~/local/i3/bin/i3-mode Secondary 37 | 38 | # Helpers. Embedding the path explicitly is belt and braces. 39 | set $i3cmdprompt exec --no-startup-id ~/local/i3/bin/i3-command-prompt 40 | set $i3configscripts exec --no-startup-id ~/local/i3/bin/i3-config-scripts 41 | set $i3dispatcher exec --no-startup-id ~/local/i3/bin/i3-dispatcher 42 | set $i3filewatcher exec_always --no-startup-id ~/local/i3/bin/i3-file-watcher 43 | set $i3marks exec --no-startup-id ~/local/i3/bin/i3-marks 44 | set $i3mode exec --no-startup-id ~/local/i3/bin/i3-mode 45 | set $i3mouse exec --no-startup-id ~/local/i3/bin/i3-mouse 46 | set $i3listwindows exec --no-startup-id ~/local/i3/bin/i3-list-windows 47 | # A wrapper around "i3status". Referenced in the i3bar declaration. 48 | set $i3barstatuscommand ~/local/i3/bin/i3-status 49 | # Use JSON IPC to control 'mpv' (from Tasker). 50 | set $etcfilewatcher exec_always --no-startup-id ~/local/public/bin/etc-file-watcher 51 | 52 | # Use 'xrandr' with no arguments to list monitor names and geometry. 53 | # Assign outputs to monitors from left to right, repeat last assignment, 54 | # thus a dual monitor config can refer to $lmon and $rmon. 55 | set $lmon HDMI2 56 | set $cmon HDMI1 57 | set $rmon VGA1 58 | # 2022-06-08: I still have two monitors, on outputs HDMI1 as $lmon and 59 | # HDMI2 as $cmon, but quietpc has 3 outputs, achieved by connecting 60 | # VGA1 as $rmon to the VGA input of $cmon. 61 | 62 | ## Type 'pactl list sinks' to list audio outputs. 63 | set $analogaudiosink alsa_output.pci-0000_00_1b.0.analog-stereo 64 | ### $bluetoothaudiosink bluez_sink.00_01_01_00_12_CB 65 | set $bluetoothaudiosink bluez_sink.30_22_00_00_C7_F5.a2dp_sink 66 | set $hdmiaudiosink alsa_output.pci-0000_00_03.0.hdmi-stereo 67 | ### $usbaudiosink alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo 68 | set $usbaudiosink=alsa_output.usb-Generic_USB2.0_Device_20121120222017-01.analog-stereo 69 | set $iec958audiosink=alsa_output.pci-0000_00_1b.0.iec958-stereo 70 | 71 | # Type 'pactl list sources' to list audio inputs. 72 | # Between 20.04 LTS and 16.04 LTS there are minor differences. 73 | set $webcamaudiosource alsa_input.usb-Alcor_Micro__Corp._TeckNet-02.mono-fallback 74 | set $analogaudiosource alsa_input.pci-0000_00_1b.0.analog-stereo 75 | set $usbaudiosource alsa_input.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.mono-fallback 76 | 77 | # Font for i3-input. 78 | set $i3inputfont "pango:DejaVu Sans 11" 79 | 80 | # Refactoring the associated script(s) might require stubs. 81 | set $stub nop 82 | 83 | # Conmmands to respectively invoke and kill a compositor which I need 84 | # to be OFF by default in case the Ubuntu Software Updater appears. 85 | set $compositor exec --no-startup-id compton -b --config ~/.config/compton.conf 86 | set $nocompositor exec --no-startup-id killall compton 87 | 88 | # This script parses the installed i3 config file. 89 | set $help exec --no-startup-id xfce4-terminal -T Bindings -x /bin/bash -c \ 90 | "grep -v \# ~/.i3/config | grep -v 'bindsym [1-8] mode' \ 91 | cpp - | grep -E 'bind|mode|bar|}' | sed 's/(standard input)://g' | less" 92 | 93 | # 94 | # BINDINGS 95 | # 96 | 97 | ###INSERT_CFG00_HERE### 98 | 99 | # Menu is a design decision please do not change. 100 | # I have used 'xcape' to bind Super_L to Menu for the left hand. 101 | # Pressing cycles through the three modes. Def->Pri->Sec->Def. 102 | bindsym Menu $primary 103 | bindsym Print $primary 104 | 105 | # KP_Insert is a design decision please do not change. 106 | # Command prompt in one keypress. Faciltates 3 digit commands. 107 | bindsym KP_Insert $i3cmdprompt menu 4 108 | 109 | # "HJKL" replaces "JKL:" because I'm used to "vi","b" can replace "h" 110 | # (for horizontal) because they look similar and it's adjacent to "v" 111 | # (for vertical). 112 | 113 | # Narcolepsy safety net. 114 | ### TODO 115 | 116 | ###INSERT_CFG01_HERE### 117 | 118 | ###INSERT_CFG02_HERE### 119 | 120 | # 121 | # MODES 122 | # 123 | 124 | ###INSERT_CFG03_HERE### 125 | 126 | ###INSERT_CFG04_HERE### 127 | 128 | ###INSERT_CFG05_HERE### 129 | 130 | # The reload and refresh modes are for the sole use of the Makefile. 131 | mode "reload" { 132 | bindsym space $default 133 | } 134 | mode "restart" { 135 | bindsym space $default 136 | } 137 | 138 | # 139 | # SETTINGS 140 | # 141 | 142 | # Desktop wallpaper. 'nitrogen' broke 2021-09-02. 143 | exec_always --no-startup-id ${HOME}/.fehbg 144 | 145 | ###INSERT_CFG07_HERE### 146 | 147 | ###INSERT_CFG08_HERE### 148 | 149 | ###INSERT_CFG09_HERE### 150 | 151 | # Additional Menu and Escape keys. 152 | exec_always --no-startup-id ~/local/i3/bin/i3-keyboard xmodmapkeys 153 | exec_always --no-startup-id ~/local/i3/bin/i3-keyboard xcapekeys 154 | 155 | # Various diagnostic terminals for "services". 156 | assign [title="marks$"] wm 157 | assign [title="commands$"] wm 158 | 159 | # i3 "services". 160 | $i3configscripts restart 161 | 162 | # 163 | # Done. 164 | # 165 | -------------------------------------------------------------------------------- /i3-config.d/cfg07: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | 3 | # 4 | # NON EXECUTABLE SETTINGS BEGIN HERE. 5 | # 6 | 7 | # Font for window titles. The font for the bar is set explicitly. 8 | font pango:DejaVu Sans 11 9 | 10 | # Do not set this to yes. The toggling behaviour this would provide is 11 | # described in the User Guide and is not my cup of tea. Setting 'no' 12 | # does not preclude a ' toggle workspaces' key binding that works. 13 | workspace_auto_back_and_forth no 14 | 15 | # u/airblader has said that i3 names the initially empty workspace on 16 | # a screen using a simple algorithm. 17 | 18 | workspace "1" output $lmon 19 | workspace "2" output $cmon 20 | workspace "3" output $rmon 21 | 22 | # 2022-06-08: I still have two monitors, on outputs HDMI1 as $lmon and 23 | # HDMI2 as $cmon, but quietpc has 3 outputs, achieved by connecting 24 | # VGA1 as $rmon to the VGA input of $cmon. 25 | 26 | # Editor and Browser mixes. 27 | workspace "e0" output $cmon 28 | workspace "f0" output $lmon 29 | workspace "g0" output $cmon 30 | workspace "e4" output $lmon 31 | workspace "f4" output $cmon 32 | workspace "g4" output $lmon 33 | 34 | assign [class="mpv"] mp 35 | assign [title="VLC media player$"] vp 36 | 37 | workspace "mp" output $lmon 38 | workspace "vp" output $lmon 39 | 40 | # Nautilus pairs 41 | workspace "n0" output $lmon 42 | workspace "n1" output $lmon 43 | workspace "n2" output $cmon 44 | workspace "n3" output $cmon 45 | 46 | # This is experimental. Define two command aliases per application, 47 | # try to position them usefully. 48 | workspace "gi" output $lmon 49 | workspace "go" output $cmon 50 | 51 | # Plumbing. 52 | assign [title="PulseAudio Mixer"] mx 53 | assign [class="Xfce4-terminal" title="tvheadend"] tv 54 | 55 | workspace "wm" output $lmon 56 | workspace "am" output $cmon 57 | workspace "tv" output $cmon 58 | 59 | # Although making all VirtualBox windows 'layout tabbed' works 60 | # extremely well with an interactive VM. 61 | assign [title="VirtualBox Manager"] vm 62 | ### assign [title="tbs5922e" instance="VirtualBox Machine"] v0 63 | ### assign [title="manjaro sway" instance="VirtualBox Machine"] v1 64 | ### assign [title="dtvkit32" instance="VirtualBox Machine"] v9 65 | 66 | workspace "vm" output $cmon 67 | ### workspace "v0" output $cmon 68 | ### workspace "v1" output $cmon 69 | ### workspace "v9" output $cmon 70 | 71 | assign [instance="wireshark"] ws 72 | assign [title="Bluetooth Devices"] bt 73 | assign [title="DVB Inspector"] di 74 | assign [title="Meld$"] md 75 | assign [title="SM-G930F"] s7 76 | 77 | # Windows that look'n'feel better when floating. 78 | for_window [class="ffplay"] floating enable; 79 | for_window [instance="dtvkit"] floating enable; 80 | for_window [instance="xfce4-notifyd$"] floating enable; 81 | for_window [instance="yad"] floating enable; 82 | for_window [title="Cheese"] floating enable; 83 | for_window [title="Do Not Panic"] floating enable; 84 | for_window [title="File Operation Progress"] floating enable; 85 | for_window [title="Scratchpad"] floating enable; 86 | for_window [title="Unlock Keyring"] floating enable; 87 | 88 | # xfce4 dialogs. I have 2 monitors but 3 outputs; HDM11 and VGA1 are 89 | # on the same monitor. Note the positioning of the dialog by its top 90 | # left corner. 91 | for_window [title="Add New Items"] \ 92 | floating enable, move absolute position 2400 48; 93 | for_window [title="Edit Launcher"] \ 94 | floating enable, move absolute position 2400 48; 95 | for_window [title="^Launcher"] \ 96 | floating enable, move absolute position 2400 48; 97 | # xfce4 panel widgets. 98 | for_window [title="PulseAudio Volume Meter"] \ 99 | floating enable, move absolute position 2400 48; 100 | 101 | # ImageMagick, respect. 102 | for_window [class="Display"] floating enable; 103 | for_window [class="Display-im6"] floating enable; 104 | for_window [class="Display-im6.q16"] floating enable; 105 | 106 | # Turning off the compositor sidesteps a long standing software 107 | # updater bug that hides everything but the title bar. 108 | for_window [title="Software Updater"] floating enable, $nocompositor; 109 | 110 | # On ${cmon} leaving ${lmon} and {rmon} clear for fullscreen video. 111 | for_window [title="Live Caption"] floating enable,move absolute position 1968 480; 112 | 113 | # Windows that look'n'feel better when tiled. 114 | for_window [title="Bluetooth Devices"] floating disable; 115 | 116 | # Windows that look'n'feel better floating or tiled, but which one? 117 | # Provide both, ensure at least two words in the condition criterion. 118 | # With space separating the words = enabled, underscore = disabled. 119 | for_window [title="Volume Control"] \ 120 | floating enable, move absolute position 2400 48, \ 121 | resize set 50 ppt 80 ppt; 122 | for_window [title="Volume_Control"] floating disable; 123 | 124 | # A long standing issue with ImageMagick dialogs. The list is 125 | # incomplete but sufficient. 126 | for_window [class="Display-im6" title="Browse and Select a File"] \ 127 | floating enable, move absolute position 2000 100, resize set 50 ppt 50 ppt; 128 | for_window [class="Display-im6.q16" title="Browse and Select a File"] \ 129 | floating enable, move absolute position 2000 100, resize set 50 ppt 50 ppt; 130 | 131 | # Apply i3 vim-like marks. 132 | for_window [class="mpv"] $i3marks numeric 133 | for_window [instance="Navigator"] $i3marks numeric 134 | for_window [instance="emacs"] $i3marks numeric 135 | for_window [instance="gl"] $i3marks numeric 136 | for_window [instance="google-chrome"] $i3marks numeric 137 | for_window [instance="xfce4-terminal"] $i3marks numeric 138 | for_window [title="SM G930F"] $i3marks numeric 139 | 140 | # Windows to maximise. 141 | for_window [title="Meld$"] layout tabbed; 142 | for_window [title="Spotify"] layout tabbed; 143 | for_window [title="Clementine"] layout tabbed; 144 | for_window [title="VirtualBox Manager"] layout tabbed; 145 | 146 | # Windows to hide. 147 | for_window [title="KeyClick"] move scratchpad; 148 | for_window [title="Command Interface"] move scratchpad; 149 | for_window [title="Window Change Monitor"] move scratchpad; 150 | for_window [title="HDMI-USB"] move scratchpad; 151 | 152 | # Windows that annoy me, that I can't fix. 153 | for_window [title="Add Security Exception"] kill; 154 | 155 | # Colours for windows. Defaults changed to better distinguish are: 156 | # 1. green title bar and border when focused. 157 | # 2. gold title bar when focused inactive, 158 | # 3. grey title bar otherwise. 159 | # class | border | background | text | indicator | child_border 160 | client.focused #333333 #008800 #ffffff #2e9ef4 #185522 161 | client.focused_inactive #333333 #555500 #dddddd #484e50 #5f676a 162 | client.unfocused #333333 #444444 #bbbbbb #292d2e #222222 163 | client.urgent #880000 #444444 #ffffff #880000 #900000 164 | client.placeholder #000000 #444444 #ffffff #000000 #0c0c0c 165 | 166 | # Mouse behaviour wrt windows. Prefer click-to-focus, default is no. 167 | focus_follows_mouse no 168 | # Focus wrapping isn't as simple as I once believed. 169 | focus_wrapping off 170 | 171 | # 172 | # NON EXECUTABLE SETTINGS END HERE. 173 | # 174 | -------------------------------------------------------------------------------- /i3-config.d/cfg00: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # etc i3 configuration file 3 | # etc isn't et cetera, etc is EllaThcat! 4 | # 5 | 6 | # Choose your cursor keys. Default is like 'vi'. Beware binding a key 7 | # to two operations within a mode. The resulting cursor keypad is the 8 | # only one. 9 | set $h h 10 | set $j j 11 | set $k k 12 | set $l l # or semicolon or right arrow or ctrl-F 13 | 14 | # Each output is associated with a letter, the first three letters are 15 | # {z,x,c}.xc Defining three names. The values shewn here were provided by 16 | # 'xrandr' on my machine. 17 | set $zop HDMI2 18 | set $xop HDMI1 19 | set $cop VGA1 20 | 21 | # On-screen help popup. 22 | set $help exec --no-startup-id /usr/local/bin/i3help -f ~/.i3/this 23 | 24 | # Dismiss all objects in all workspaces on the specified output. 25 | set $killzop $i3configbash "kill" $zop 26 | set $killxop $i3configbash "kill" $xop 27 | set $killcop $i3configbash "kill" $cop 28 | 29 | # BINDINGS DEFINITIONS BEGIN HERE. 30 | 31 | mode "kill - space to cancel" { 32 | # Dismiss the focused object. 33 | bindsym q kill, mode "default" 34 | # Dismiss ALL floating objects. 35 | bindsym f [floating] kill, mode "default" 36 | # Dismiss all objects in the current workspace. 37 | bindsym w [workspace="__focused__"] kill, mode "default" 38 | # Dismiss all objects in the specifed output. 39 | bindsym z $killoutput $zop, mode "default" 40 | bindsym x $killoutput $xop, mode "default" 41 | bindsym c $killoutput $cop, mode "default" 42 | # Dismiss the xfce4-panel. 43 | bindsym p mode "default", $noetcpanel 44 | bindsym space mode "default" 45 | } 46 | 47 | mode "layouts" { 48 | # One nice thing about modes is that a mnemonic exists among the 49 | # available keys, e.g. these three have matching initial letters. 50 | bindsym d layout default 51 | bindsym s layout stacking 52 | bindsym t layout tabbed 53 | 54 | # Doh, no obvious mnemonic, f => sdft contiguous => one region. 55 | bindsym f layout toggle split 56 | 57 | # Pivot bindings. An experiment by EllaTheCat. 58 | # With A focused, change the column AB into the r_ow AB. 59 | bindsym r mode "default", \ 60 | focus down, split h, focus up, move down, move left; 61 | # With A focused, change the row AB into the c_olumn AB. 62 | bindsym c mode "default", \ 63 | focus right, split v, focus left, move right, move up ; 64 | 65 | bindsym space mode "default" 66 | } 67 | 68 | mode "f_ocus - m_ove r_esize" { 69 | bindsym $h focus left 70 | bindsym $j focus down 71 | bindsym $k focus up 72 | bindsym $l focus right 73 | 74 | bindsym a focus parent # adult 75 | bindsym s focus child # son 76 | bindsym d focus child # daughter 77 | bindsym p focus parent # parent 78 | bindsym o focus child # offspring 79 | 80 | bindsym u mode "default", [urgent=latest] focus 81 | 82 | bindsym f mode "default", focus mode_toggle; 83 | 84 | bindsym m mode "m_ove - r_esize f_ocus" 85 | bindsym r mode "r_esize - f_ocus m_ove" 86 | 87 | bindsym grave mode "etcmode" 88 | bindsym space mode "default" 89 | } 90 | 91 | mode "m_ove - r_esize f_ocus" { 92 | bindsym $h move left 93 | bindsym $j move down 94 | bindsym $k move up 95 | bindsym $l move right 96 | 97 | bindsym f mode "f_ocus - m_ove r_esize" 98 | bindsym r mode "r_esize - f_ocus m_ove" 99 | 100 | bindsym grave mode "etcmode" 101 | bindsym space mode "default" 102 | } 103 | 104 | mode "r_esize - f_ocus m_ove" { 105 | bindsym $h resize shrink width 10 px or 10 ppt 106 | bindsym $j resize grow height 10 px or 10 ppt 107 | bindsym $k resize shrink height 10 px or 10 ppt 108 | bindsym $l resize grow width 10 px or 10 ppt 109 | 110 | bindsym f mode "f_ocus - m_ove r_esize" 111 | bindsym m mode "m_ove - r_esize f_ocus" 112 | 113 | bindsym grave mode "etcmode" 114 | bindsym space mode "default" 115 | } 116 | 117 | mode "output z" { 118 | bindsym m mode "default", move workspace to output $zop 119 | bindsym $j workspace prev_on_output 120 | bindsym $k workspace next_on_output 121 | bindsym space mode "default" 122 | } 123 | mode "output x" { 124 | bindsym m mode "default", move workspace to output $xop 125 | bindsym $j workspace prev_on_output 126 | bindsym $k workspace next_on_output 127 | bindsym space mode "default" 128 | } 129 | mode "output c" { 130 | bindsym m mode "default", move workspace to output $cop 131 | bindsym $j workspace prev_on_output 132 | bindsym $k workspace next_on_output 133 | bindsym space mode "default" 134 | } 135 | 136 | mode "workspace" { 137 | bindsym $h workspace prev 138 | bindsym $j workspace prev_on_output 139 | bindsym $k workspace next_on_output 140 | bindsym $l workspace next 141 | 142 | # This is unusual syntax but it works for me. 143 | bindsym z mode "output z" 144 | bindsym x mode "output x" 145 | bindsym c mode "output c" 146 | 147 | # Prepare to move a 2 digit workspace 10 to 99. 148 | bindsym w mode "move_workspace" 149 | 150 | # 1st digit of a 2 digit workspace 10 to 99 to be focused. 151 | bindsym 1 mode ws1 152 | bindsym 2 mode ws2 153 | bindsym 3 mode ws3 154 | bindsym 4 mode ws4 155 | bindsym 5 mode ws5 156 | bindsym 6 mode ws6 157 | bindsym 7 mode ws7 158 | bindsym 8 mode ws8 159 | bindsym 9 mode ws9 160 | 161 | # (R)ename a workspace. 162 | bindsym r mode "default", exec --no-startup-id i3-input -f $i3inputfont -l 2 \ 163 | -P '(rename this workspace to): ' \ 164 | -F 'rename workspace to "%s"' 165 | 166 | # Move [f]ocused (thing:container,window) to a workspace. 167 | bindsym f mode "default", exec --no-startup-id i3-input -f $i3inputfont -l 2 \ 168 | -P '(move focused to workspace): ' \ 169 | -F 'move focused to workspace "%s"' 170 | 171 | # (V)isit a workspace. If the workspace does not exist beforehand 172 | # it is created, if it already exists, it is focused. 173 | bindsym v mode "default", exec --no-startup-id i3-input -f $i3inputfont -l 2 \ 174 | -P '(workspace): ' -F 'workspace "%s"' 175 | 176 | bindsym grave mode "etcmode" 177 | bindsym space mode "default" 178 | } 179 | 180 | mode "move workspace" { 181 | # 1st digit of a 2 digit workspace 10 to 99 to be moved. 182 | # 2nd digit is in etc's "dopamine-2020" repo file "cfg03". 183 | bindsym 1 mode cws1 184 | bindsym 2 mode cws2 185 | bindsym 3 mode cws3 186 | bindsym 4 mode cws4 187 | bindsym 5 mode cws5 188 | bindsym 6 mode cws6 189 | bindsym 7 mode cws7 190 | bindsym 8 mode cws8 191 | bindsym 9 mode cws9 192 | 193 | bindsym grave mode "etcmode" 194 | bindsym space mode "default" 195 | } 196 | 197 | mode "screen" { 198 | bindsym f floating disable, toggle fullscreen; 199 | bindsym g floating disable, toggle fullscreen global; 200 | 201 | bindsym --release b mode "default", \ 202 | exec --no-startup-id xset dpms force off; 203 | 204 | bindsym grave mode "etcmode" 205 | bindsym space mode "default" 206 | } 207 | 208 | # 209 | # 210 | # 211 | mode "etcmode" { 212 | 213 | bindsym q mode "kill - space to cancel"; 214 | 215 | bindsym t mode "default", split h, $etcterminal; 216 | bindsym y mode "default", split v, $etcterminal; 217 | bindsym p mode "default", $etcpanel 218 | 219 | bindsym d mode "default", exec dmenu_run 220 | 221 | bindsym b mode "default", split h 222 | bindsym v mode "default", split v 223 | 224 | bindsym f mode "f_ocus - m_ove r_esize" 225 | bindsym m mode "m_ove - r_esize f_ocus" 226 | bindsym r mode "r_esize - f_ocus m_ove" 227 | 228 | bindsym l mode "layouts" 229 | bindsym s mode "screen" 230 | bindsym w mode "workspace" 231 | 232 | # Toggle a window between being tiled and being floating, with 233 | # xywh options for the tidy-minded. 234 | bindsym f mode "default", floating enable, \ 235 | resize set 30 ppt 30 ppt, move position center; 236 | bindsym g mode "default", floating enable, \ 237 | resize set 60 ppt 60 ppt, move position center; 238 | bindsym x mode "default", floating toggle; 239 | 240 | # Surround the cursor with a circular red throbbing thing. 241 | bindsym c mode "default", exec --no-startup-id xfce4-find-cursor 242 | # Cheat sheet for bindings should be at the top-level. 243 | # https://github.com/glennular/i3help 244 | bindsym i mode "default", $help; 245 | # The exemplary i3 user guide! 246 | bindsym u exec --no-startup-id \ 247 | xdg-open https://i3wm.org/docs/userguide.html 248 | 249 | # This binding must be provided in all modes except default. 250 | bindsym space mode "default" 251 | } 252 | # On a PC105 keyboard the "grave" key is to the left of the '1' 253 | # key. Self-inserts when the mode is active. 254 | bindsym grave mode "etcmode" 255 | 256 | # 257 | # 258 | # 259 | mode "etcsays" { 260 | bindsym space mode "default" 261 | } 262 | # On a PC 105 keyboard the key with code 94 is in between the left 263 | # Shift key and the 'z' key. Self-inserts when the mode is active. 264 | bindcode 94 mode "etcsays" 265 | 266 | # DEPRECATED_BEGIN 267 | 268 | # Commands to respectively invoke and kill a compositor which must be 269 | # OFF by default on Ubuntu 20.04 LTS for the Ubuntu Software Updater. 270 | set $compositor exec --no-startup-id compton -b --config ~/.config/compton.conf 271 | set $nocompositor exec --no-startup-id killall compton 272 | 273 | # DEPRECATED_ENDS 274 | 275 | # 276 | # BINDINGS DEFINITIONS END HERE. 277 | # 278 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dopamine-2020 - Customising the i3 tiling window manager. 2 | 3 | ## What's in the repository? 4 | 5 | This repository consists of the config and scripts I'm using with i3 6 | 4.18.1 on Xubuntu 20.04 LTS. 7 | 8 | ## Disclaimer 9 | 10 | I took the opportunity to refactor my i3 config and scripts into this 11 | new repository after installing the latest versions of distro and i3. 12 | Everything is on git master not on topic branches. 13 | 14 | ## Ambitions 15 | 16 | - The default configuration is close to being 100% compatible with the 17 | standard i3 keybindings as shown in the i3 user's guide. You can use 18 | it immediately. 19 | 20 | - The config file and scripts have "magic comments". These are 21 | postprocessing directives that could, for example, customise a single 22 | base configuration for different users or different machines. 23 | 24 | - I greatly admire the i3 mission statement about clean code. I'm not 25 | in their league, but I've tried to make the code modular and 26 | maintainable. If nothing else, it's commented and documented. 27 | 28 | ## Why dopamine? 29 | 30 | Dopamine is a chemical that functions as a neurotransmitter in human 31 | brains. I have Parkinson's Disease ("PD") because the cells that make 32 | dopamine in my brain are dying prematurely. Lack of dopamine causes 33 | the hand and arm tremors and the overall slowness of movement typical 34 | of Parkinson's Disease. 35 | 36 | The i3 window manager lets me address the ergonomics of a user 37 | interface for people with PD. I want to share both the code and the 38 | lessons learned, what works and what doesn't, because I'm no expert, 39 | just an enthusiast. Plus you lucky people without PD might like it! 40 | 41 | This is the third such repository I've made. This time, I'm hoping to 42 | make it easy for people to download and run, either as a whole or in 43 | standalone pieces. 44 | 45 | ## Installation 46 | Dopamine wants to be installed anywhere beneath ${HOME}, in a 47 | directory accessible to git. Decide in which directory the git clone 48 | will be done, change to that directory and do: 49 | 50 | git clone git@github.com:EllaTheCat/dopamine-2020.git 51 | make 52 | 53 | ## Running "make" 54 | 55 | - Copies config files from your local repository to where i3 expects 56 | them at runtime. 57 | - Copies script files from your local repository to a folder that 58 | should be on your ${PATH}. I chose ${HOME}/local/bin precisely 59 | because no-one else does, in order to avoid conflicts. Feel free to 60 | make it a symlink to ${HOME}/bin or whatever. 61 | - Modifies the copies with your customisations. 62 | - Sets the runtime file and folder permissions. 63 | - Runs the i3 reload command should the i3 config have changed. 64 | - Runs the i3 restart command when i3-status or i3bar has changed. 65 | 66 | ## Running "make -n" 67 | 68 | - Performs a dry-run, printing to the console whatever commands 69 | would have been executed without the "-n" argument. 70 | 71 | ## Classic default mode bindings 72 | By default, the i3 config file includes a set of $mod+keysym bindings 73 | corresponding to the bindings described in the i3 User's Guide. I 74 | realised that without these, a user would struggle to use i3, and 75 | hence would not persevere with their evaluation. 76 | 77 | Conversely, I find modifier+key bindings difficult, and don't want to 78 | operate them accidentally, so I'd prefer to remove them. 79 | 80 | ## Building a custom i3 config 81 | 82 | Looking at i3-config you'll see several "magic comments": 83 | 84 | ###INSERT_CFG00_HERE### 85 | ###INSERT_CFG01_HERE### 86 | 87 | The Makefile first deploys "i3-config" as "$HOME/.i3/config" and 88 | then runs sed scripts that perform in-place replacement of any 89 | magic comments with the contents of the files they reference. 90 | These "cfg" files live in "i3-config.d': 91 | 92 | - cfg00 - Classic bindings 93 | - cfg01 - Numpad bindings 94 | - cfg02 - Cluster bindings. 95 | - cfg03 - Reserved 96 | - cfg04 - Primary bindings 97 | - cfg05 - Secondary bindings 98 | - cfg06 - Reserved 99 | - cfg07 - Settings (non-executable) 100 | - cfg08 - Settings (executable) 101 | - cfg09 - Settings (i3bar, debug mode) 102 | 103 | There's nothing to stop competent users editing "cfg" files, and this 104 | is to be encouraged. I think, in practice, a user would have to accept 105 | my changes via 'git pull' and then restore their cfg files with their 106 | changes. I think the use of multiple cfg files makes that manual chore 107 | slightly easier. What has been done is a step forward but it's not 108 | enough. 109 | 110 | ## Three modes, one key to bind them 111 | 112 | In addition to "default" mode, this config adds Primary and Secondary 113 | modes. There are other modes, like resize, but they aren't essential. 114 | The Menu key cycles round the three essential modes : 115 | 116 | default -> Primary -> Secondary -> default 117 | 118 | and the spacebar goes back to default. 119 | 120 | ## Primary mode 121 | This mode does much the same as default mode. The difference is the 122 | difference between emacs and vi, modifiers versus modes, two handed 123 | versus one handed. Easier for people with PD. 124 | 125 | ## Secondary mode 126 | This mode is used for settings. It's quite sparse, which may help 127 | laptop users. 128 | 129 | ## Mode and modifier symmetry 130 | The left Windows key behaves like Menu when pressed solo and Super_L 131 | when modifying another key, thanks to "xcape". It's important for 132 | accessibility to have both behaviours avaiiable on either side. Both 133 | Alt keys are mapped to Escape when used solo; it follows that Win and 134 | Alt can be swapped as some users prefer. 135 | 136 | ## Mode indication 137 | When not in default mode the word Primary or Secondary is shown on a 138 | red tab next to the workspace tabs. Furthermore, comared to default 139 | mode, the screen dims slightly in Primary mode and dims slightly more 140 | in Secondary mode. 141 | 142 | ## Command prompt 143 | The command prompt is a dmenu. It is invoked with one of the key 144 | sequences {Menu, Tab}, or {Menu, backslash} when the layout makes it 145 | comfortable. It then reads two characters, and forwards them to the 146 | "i3-filewatcher" script (q.v.). 147 | 148 | The command prompt can also be invoked by KP_Insert, which configures 149 | the numpad to read in two or three digits, and as before, forwards 150 | them to the "i3-filewatcher" script. 151 | 152 | Both methods timeout after four seconds and send a key event 153 | equivalent to pressing Enter (Return). My PD makes the delay 154 | acceptable and the automatic Enter key appreciated. 155 | The delay is implemented wth sleep() and configurable. 156 | The Enter key automation can be disabled. 157 | 158 | ## Tasker, AutoVoice, AutoTools 159 | Tasker is a popular android application that lets users write android 160 | programs to run on their phone or tablet. AutoVoice is a Tasker plugin 161 | for speech-to-text. AutoTools is a Tasker plugin that provides "ssh". 162 | together, they can let the user send commands from the phone to the 163 | "i3-filewatcher" script. 164 | 165 | ## File Watcher 166 | The file watcher watches the file "/dev/shm/$USER/i3/command". 167 | Whenever the command prompt or Tasker writes a command to that file, 168 | the command is forwarded to the dispatcher for processing. There is 169 | no acknowledgement for commands. 170 | 171 | ## Dispatcher 172 | The dispatcher receives a command sent by the file watcher, and uses 173 | pattern matching to invoke command-specific scripts. 174 | 175 | ## Focus App By Alias. 176 | A command alias typically consists of two characters that refer to a 177 | command and its parameters. Typing the command alias switches to the 178 | running application, launching it if not already running. 179 | 180 | This looked easy but the implementation has required the "Window 181 | Change Monitor". This is an i3-msg subscription to window events and a 182 | monitor that marks the focused window with the workspace name. 183 | 184 | There should be only one window per output marked with the name of the 185 | workspace. Two marks with the same name on the same workspace is a 186 | major bug. 187 | 188 | ## Launcher 189 | Deprecated in favour of android apps. To be removed. 190 | 191 | ## Transcribe 192 | Deprecated in favour of android apps. To be retained. 193 | 194 | This is a niche feature, speech to text, that just happens to be 195 | important for EllaTheCat. 196 | 197 | On the phone, saying "OK Google" triggers speech to text. The 198 | resulting lowercase text is written to the File Watcher via the ssh 199 | conection. Eventually punctuated text appears in an Emacs buffer 200 | "Clipboard". 201 | 202 | ## i3-config-scripts 203 | 204 | The "i3-config-scripts" file tidies up the management of "services" 205 | that run in the background. 206 | 207 | i3-config-scripts restart 208 | 209 | Invoked wih arguments as above, preceded by 'exec' in i3-config, it 210 | starts the commands and mark "services" after everything else in the 211 | i3-config startup sequence. 212 | 213 | i3-config-scripts restart 214 | 215 | Invoked as above from a terminal, it stops the commands and marks 216 | "services", restarts the i3 window manager, then starts the two 217 | "services" again. I had not realised that restarting i3 required 218 | restarting the "services". The date and time of the last startup 219 | appears in the window title. 220 | 221 | ## i3-status 222 | 223 | The i3-status script (note the dash) wraps the i3status script (that 224 | comes with i3) such that extra indicators can be prepended to those of 225 | i3status. You can revert to i3status only by editing the i3bar config 226 | in i3-config.d/cfg09. i3-status prepends the following variables: 227 | 228 | - ${Wmic} ${umic} ${rmic} each shows 0 when muted, 1 when active. 229 | 230 | - ${wcam} This is set to "idle" by default, unless it is active, in 231 | which case the name of the program accessing the webcam is 232 | shown. 233 | 234 | - ${ccmt} My desktop PC has Intel mobo graphics that have recently 235 | developed screen tearing on video. My workaround is to use a 236 | Raspberry Pi Model 4 running Kodi and LibreElec on the Broadcom 237 | video core. This variable tracks on-chip temperature. With passive 238 | cooling, no fan, rendering SD video fullscreen, the temperature is 239 | 45'C, ambient is 19'C. A one second ping fails should the Raspberry 240 | Pi be offline, so the refresh of the bar is set to three seconds. 241 | 242 | - ${cursor} This shows the mouse position (x,y) pixel co-ordinates, 243 | origin top left of the leftmost screen. i3 usage of the mouse is 244 | reduced, ao it's easier to lose it, hence this helps find it. 245 | 246 | ## settings-2020 247 | 248 | settings-2020 is a sibling github repo of dopamine-2020. It holds my 249 | dotfiles, configs and scripts in a directory along with a Makefile 250 | that installs them in their runtime locations. Scripts are vetted by 251 | the ShellCheck utility. I intend that the scripts in the myscripts 252 | directory will be moved from dopamine-2020 to settings-2020. 253 | 254 | settings-2020 also manages sensitive information. On the one hand I 255 | want to share but on the other hand I want my privacy preserved. 256 | 257 | [eof] 258 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Makefile for dopamine-2020 3 | # 4 | # Requires : shellcheck 5 | # 6 | SHELL=/bin/bash 7 | 8 | # The i3 config file to be installed. 9 | I3CFG=$(HOME)/.i3/config 10 | 11 | # The compton/picom config file to be installed. 12 | COMPOSITORCFG=$(HOME)/.config/compton.conf 13 | 14 | # The i3status config file to be installed. 15 | I3STATUSCFG=$(HOME)/.i3status.conf 16 | # Directory where helper scripts will be installed. 17 | # 2021-09-19: "${HOME}/local/bin" is now deprecated. 18 | I3BIN=$(HOME)/local/i3/bin 19 | 20 | # The dunst config file to be installed. 21 | NOTIFIERCFG=${HOME}/.config/dunst/dunstrc 22 | 23 | # Local git repo directory, where the Makefile lives, and from where 24 | # tt should be invoked. 25 | DOPAMINE=$(shell readlink -f $(shell pwd)) 26 | 27 | # Generic helper scripts for i3 that everyone needs. 28 | I3SCRIPTS=$(shell readlink -f "$(DOPAMINE)/i3scripts") 29 | # Custom helper scripts for i3 for your niche use cases. 30 | # I've included examples. 31 | MYSCRIPTS=$(shell readlink -f "$(DOPAMINE)/myscripts") 32 | 33 | # Install permissions for: directories, executables, configurations. 34 | DIRMODE=755 35 | EXEMODE=755 36 | CFGMODE=644 37 | 38 | .installdirs: $(I3BIN) 39 | 40 | .installconfigs: $(I3CFG) $(I3STATUSCFG) $(COMPOSITORCFG) $(NOTIFIERCFG) 41 | 42 | .installscripts: \ 43 | $(I3BIN)/i3-app-mode \ 44 | $(I3BIN)/i3-command-prompt \ 45 | $(I3BIN)/i3-config-scripts \ 46 | $(I3BIN)/i3-file-watcher \ 47 | $(I3BIN)/i3-dispatcher \ 48 | $(I3BIN)/i3-emacsclient \ 49 | $(I3BIN)/i3-focus-app-by-alias \ 50 | $(I3BIN)/i3-launcher \ 51 | $(I3BIN)/i3-keyboard \ 52 | $(I3BIN)/i3-list-windows \ 53 | $(I3BIN)/i3-marks \ 54 | $(I3BIN)/i3-mode \ 55 | $(I3BIN)/i3-mouse \ 56 | $(I3BIN)/i3-scratchpad \ 57 | $(I3BIN)/i3-transcribe \ 58 | $(I3BIN)/i3-triple-digit-command \ 59 | $(I3BIN)/i3-recorder \ 60 | $(I3BIN)/i3-status 61 | 62 | .installextras: \ 63 | $(I3BIN)/tvheadend-start $(I3BIN)/my-file-watcher 64 | .installflags: \ 65 | reloaded \ 66 | restarted 67 | 68 | 69 | all : .installdirs .installconfigs .installscripts .installextras .installflags 70 | 71 | # .installflags 72 | # 73 | # Flags ensure that reload and restart are each performed no more than 74 | # once and that all changes have been made beforehand. 75 | 76 | reloaded: reload 77 | touch $@ 78 | i3-msg "reload" 79 | 80 | restarted: restart 81 | @touch $@ 82 | @$(I3BIN)/i3-config-scripts restart 83 | 84 | # It no longer necessary to run this script by hand after running 85 | # 'make' but the automatic restart rules are "better safe than sorry" 86 | # such that you may prefer to disable them to avoid visual disturbance 87 | # upon restartafter any config change, even a bindsym, which is 88 | # overkill. I intend to write better rules. 89 | # 90 | # Should discretionary manual invocation be your preference, comment 91 | # out the entiree 'restarted:' rule immediately above this comment and 92 | # use the 'wm' target immediately below instead. 93 | 94 | wm: 95 | @$(I3BIN)/i3-config-scripts restart 96 | 97 | # Note: An annoyance remains with the script: a dialog complains about 98 | # the notification area being lost on first invocation. ToDo: Dismiss 99 | # the dialog automatically assuming no fix for root cause. 100 | 101 | # .installdirs 102 | 103 | $(I3BIN): 104 | @install -m $(DIRMODE) -d $(I3BIN) 105 | 106 | # .installconfigs 107 | 108 | # This rule immediately modifies the recently installed file. 109 | $(I3CFG): i3-config \ 110 | i3-config.d/cfg00 i3-config.d/cfg01 i3-config.d/cfg02 \ 111 | i3-config.d/cfg03 i3-config.d/cfg04 i3-config.d/cfg05 \ 112 | i3-config.d/cfg07 i3-config.d/cfg08 i3-config.d/cfg09 \ 113 | i3-config.d/apps00 \ 114 | i3-config.d/apps01 115 | @install -m $(CFGMODE) i3-config $@ 116 | @sed -e '/###INSERT_CFG00_HERE###/ {' -e 'r i3-config.d/cfg00' -e 'd' -e '}' \ 117 | -i $(I3CFG) 118 | @sed -e '/###INSERT_CFG01_HERE###/ {' -e 'r i3-config.d/cfg01' -e 'd' -e '}' \ 119 | -i $(I3CFG) 120 | @sed -e '/###INSERT_CFG02_HERE###/ {' -e 'r i3-config.d/cfg02' -e 'd' -e '}' \ 121 | -i $(I3CFG) 122 | @sed -e '/###INSERT_CFG03_HERE###/ {' -e 'r i3-config.d/cfg03' -e 'd' -e '}' \ 123 | -i $(I3CFG) 124 | @sed -e '/###INSERT_CFG04_HERE###/ {' -e 'r i3-config.d/cfg04' -e 'd' -e '}' \ 125 | -i $(I3CFG) 126 | @sed -e '/###INSERT_CFG05_HERE###/ {' -e 'r i3-config.d/cfg05' -e 'd' -e '}' \ 127 | -i $(I3CFG) 128 | @sed -e '/###INSERT_CFG07_HERE###/ {' -e 'r i3-config.d/cfg07' -e 'd' -e '}' \ 129 | -i $(I3CFG) 130 | @sed -e '/###INSERT_CFG08_HERE###/ {' -e 'r i3-config.d/cfg08' -e 'd' -e '}' \ 131 | -i $(I3CFG) 132 | @sed -e '/###INSERT_CFG09_HERE###/ {' -e 'r i3-config.d/cfg09' -e 'd' -e '}' \ 133 | -i $(I3CFG) 134 | @touch restart 135 | 136 | $(COMPOSITORCFG): compton.conf 137 | @install -m $(CFGMODE) compton.conf $@ 138 | @touch restart 139 | 140 | $(NOTIFIERCFG): i3-config.d/dunstrc 141 | @$(I3BIN)/i3-config-scripts stop dunst 142 | @install -m $(CFGMODE) i3-config.d/dunstrc $@ 143 | @$(I3BIN)/i3-config-scripts start dunst 144 | 145 | $(I3STATUSCFG): i3-status-config 146 | @install -m $(CFGMODE) i3-status-config $@ 147 | @touch restart 148 | 149 | # .installscripts 150 | 151 | $(I3BIN)/i3-app-mode: \ 152 | $(I3SCRIPTS)/i3-app-mode \ 153 | $(I3SCRIPTS)/i3-app-mode.log 154 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-app-mode $(I3BIN) 155 | 156 | $(I3SCRIPTS)/i3-app-mode.log: $(I3SCRIPTS)/i3-app-mode 157 | @shellcheck $(I3SCRIPTS)/i3-app-mode > $@ 158 | 159 | $(I3BIN)/i3-command-prompt: \ 160 | $(I3SCRIPTS)/i3-command-prompt \ 161 | $(I3SCRIPTS)/i3-command-prompt.log 162 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-command-prompt $(I3BIN) 163 | 164 | $(I3SCRIPTS)/i3-command-prompt.log: $(I3SCRIPTS)/i3-command-prompt 165 | @shellcheck $(I3SCRIPTS)/i3-command-prompt > $@ 166 | 167 | $(I3BIN)/i3-config-scripts: \ 168 | $(I3SCRIPTS)/i3-config-scripts \ 169 | $(I3SCRIPTS)/i3-config-scripts.log 170 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-config-scripts $(I3BIN) 171 | 172 | $(I3SCRIPTS)/i3-config-scripts.log: $(I3SCRIPTS)/i3-config-scripts 173 | @shellcheck $(I3SCRIPTS)/i3-config-scripts > $@ 174 | 175 | $(I3BIN)/i3-file-watcher: \ 176 | $(I3SCRIPTS)/i3-file-watcher \ 177 | $(I3SCRIPTS)/i3-file-watcher.log 178 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-file-watcher $(I3BIN) 179 | 180 | $(I3SCRIPTS)/i3-file-watcher.log: $(I3SCRIPTS)/i3-file-watcher 181 | @shellcheck $(I3SCRIPTS)/i3-file-watcher > $@ 182 | 183 | $(I3BIN)/i3-dispatcher: \ 184 | $(I3SCRIPTS)/i3-dispatcher \ 185 | $(I3SCRIPTS)/i3-dispatcher.log 186 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-dispatcher $(I3BIN) 187 | 188 | $(I3SCRIPTS)/i3-dispatcher.log: $(I3SCRIPTS)/i3-dispatcher 189 | @shellcheck $(I3SCRIPTS)/i3-dispatcher > $@ 190 | 191 | $(I3BIN)/i3-emacsclient: \ 192 | $(I3SCRIPTS)/i3-emacsclient \ 193 | $(I3SCRIPTS)/i3-emacsclient.log 194 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-emacsclient $(I3BIN) 195 | 196 | $(I3SCRIPTS)/i3-emacsclient.log: $(I3SCRIPTS)/i3-emacsclient 197 | @shellcheck $(I3SCRIPTS)/i3-emacsclient > $@ 198 | 199 | # This rule immediately modifies the recently installed file. 200 | $(I3BIN)/i3-focus-app-by-alias: \ 201 | $(I3SCRIPTS)/i3-focus-app-by-alias \ 202 | $(I3SCRIPTS)/i3-focus-app-by-alias.log \ 203 | i3-config.d/apps00 204 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-focus-app-by-alias $(I3BIN) 205 | @sed -e '/###INSERT_APPS00_HERE###/ {' -e 'r i3-config.d/apps00' -e 'd' -e '}' \ 206 | -i $(I3BIN)/i3-focus-app-by-alias 207 | 208 | $(I3SCRIPTS)/i3-focus-app-by-alias.log: $(I3SCRIPTS)/i3-focus-app-by-alias 209 | @shellcheck $(I3SCRIPTS)/i3-focus-app-by-alias > $@ 210 | 211 | $(I3BIN)/i3-launcher: \ 212 | $(I3SCRIPTS)/i3-launcher \ 213 | $(I3SCRIPTS)/i3-launcher.log 214 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-launcher $(I3BIN) 215 | 216 | $(I3SCRIPTS)/i3-launcher.log: $(I3SCRIPTS)/i3-launcher 217 | @shellcheck $(I3SCRIPTS)/i3-launcher > $@ 218 | 219 | $(I3BIN)/i3-keyboard: \ 220 | $(I3SCRIPTS)/i3-keyboard \ 221 | $(I3SCRIPTS)/i3-keyboard.log 222 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-keyboard $(I3BIN) 223 | 224 | $(I3SCRIPTS)/i3-keyboard.log: $(I3SCRIPTS)/i3-keyboard 225 | @shellcheck $(I3SCRIPTS)/i3-keyboard > $@ 226 | 227 | $(I3BIN)/i3-list-windows: \ 228 | $(I3SCRIPTS)/i3-list-windows \ 229 | $(I3SCRIPTS)/i3-list-windows.log 230 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-list-windows $(I3BIN) 231 | 232 | $(I3SCRIPTS)/i3-list-windows.log: $(I3SCRIPTS)/i3-list-windows 233 | @shellcheck $(I3SCRIPTS)/i3-list-windows > $@ 234 | 235 | $(I3BIN)/i3-marks: \ 236 | $(I3SCRIPTS)/i3-marks \ 237 | $(I3SCRIPTS)/i3-marks.log \ 238 | i3-config.d/apps01 239 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-marks $(I3BIN) 240 | @touch restart 241 | 242 | $(I3SCRIPTS)/i3-marks.log: $(I3SCRIPTS)/i3-marks 243 | @shellcheck $(I3SCRIPTS)/i3-marks > $@ 244 | 245 | $(I3BIN)/i3-mode: \ 246 | $(I3SCRIPTS)/i3-mode \ 247 | $(I3SCRIPTS)/i3-mode.log 248 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-mode $(I3BIN) 249 | 250 | $(I3SCRIPTS)/i3-mode.log: $(I3SCRIPTS)/i3-mode 251 | @shellcheck $(I3SCRIPTS)/i3-mode > $@ 252 | 253 | $(I3BIN)/i3-mouse: \ 254 | $(I3SCRIPTS)/i3-mouse \ 255 | $(I3SCRIPTS)/i3-mouse.log 256 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-mouse $(I3BIN) 257 | 258 | $(I3SCRIPTS)/i3-mouse.log: $(I3SCRIPTS)/i3-mouse 259 | @shellcheck $(I3SCRIPTS)/i3-mouse > $@ 260 | 261 | $(I3BIN)/i3-scratchpad: \ 262 | $(I3SCRIPTS)/i3-scratchpad \ 263 | $(I3SCRIPTS)/i3-scratchpad.log 264 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-scratchpad $(I3BIN) 265 | 266 | $(I3SCRIPTS)/i3-scratchpad.log: $(I3SCRIPTS)/i3-scratchpad 267 | @shellcheck $(I3SCRIPTS)/i3-scratchpad > $@ 268 | 269 | $(I3BIN)/i3-transcribe: \ 270 | $(I3SCRIPTS)/i3-transcribe \ 271 | $(I3SCRIPTS)/i3-transcribe.log 272 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-transcribe $(I3BIN) 273 | 274 | $(I3SCRIPTS)/i3-transcribe.log: $(I3SCRIPTS)/i3-transcribe 275 | @shellcheck $(I3SCRIPTS)/i3-transcribe > $@ 276 | 277 | $(I3BIN)/i3-triple-digit-command: \ 278 | $(I3SCRIPTS)/i3-triple-digit-command \ 279 | $(I3SCRIPTS)/i3-triple-digit-command.log 280 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-triple-digit-command $(I3BIN) 281 | 282 | $(I3SCRIPTS)/i3-triple-digit-command.log: $(I3SCRIPTS)/i3-triple-digit-command 283 | @shellcheck $(I3SCRIPTS)/i3-triple-digit-command > $@ 284 | 285 | $(I3BIN)/i3-recorder: \ 286 | $(I3SCRIPTS)/i3-recorder \ 287 | $(I3SCRIPTS)/i3-recorder.log 288 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-recorder $(I3BIN) 289 | 290 | $(I3SCRIPTS)/i3-recorder.log: $(I3SCRIPTS)/i3-recorder 291 | @shellcheck $(I3SCRIPTS)/i3-recorder > $@ 292 | 293 | $(I3BIN)/i3-status: \ 294 | $(I3SCRIPTS)/i3-status \ 295 | $(I3SCRIPTS)/i3-status.log 296 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-status $(I3BIN) 297 | @touch restart 298 | 299 | $(I3SCRIPTS)/i3-status.log: $(I3SCRIPTS)/i3-status 300 | @shellcheck $(I3SCRIPTS)/i3-status > $@ 301 | 302 | $(I3BIN)/i3-reserved: \ 303 | $(I3SCRIPTS)/i3-reserved \ 304 | $(I3SCRIPTS)/i3-reserved.log 305 | @install -m $(EXEMODE) $(I3SCRIPTS)/i3-reserved $(I3BIN) 306 | 307 | $(I3SCRIPTS)/i3-reserved.log: $(I3SCRIPTS)/i3-reserved 308 | @shellcheck $(I3SCRIPTS)/i3-reserved > $@ 309 | 310 | # .installextras 311 | 312 | # Using a pattern rule for the extras avoids the need for editing the 313 | # Makefile when the user adds or removes a script. Unfortunately I 314 | # can't redirect the shellcheck output to a file, but any shellcheck 315 | # errors are displayed. Shellcheck errors will prevent installation. 316 | 317 | $(I3BIN)/%: $(MYSCRIPTS)/% 318 | @shellcheck $< 319 | @install -m $(EXEMODE) $< $(I3BIN) 320 | 321 | $(I3CONFIG)/i3status.conf : $(I3SCRIPTS)/i3-status 322 | @echo "Workaround for bug tbc." 323 | @touch $< 324 | # 325 | # Done. 326 | # 327 | -------------------------------------------------------------------------------- /i3-config.d/cfg03: -------------------------------------------------------------------------------- 1 | # -*- Mode: Shell-script -*- 2 | # 3 | # Double-digit workspaces for i3wm. 4 | 5 | # 6 | # - The standard workspace bindings should be removed. 7 | # - The workspaces [0-9] and 0[0-9] are not available. 8 | # - The limitations above exist to keep things simple. 9 | # 10 | 11 | bindsym $mod+1 mode ws1 12 | bindsym $mod+2 mode ws2 13 | bindsym $mod+3 mode ws3 14 | bindsym $mod+4 mode ws4 15 | bindsym $mod+5 mode ws5 16 | bindsym $mod+6 mode ws6 17 | bindsym $mod+7 mode ws7 18 | bindsym $mod+8 mode ws8 19 | bindsym $mod+9 mode ws9 20 | 21 | 22 | bindsym $mod+Shift+1 mode cws1 23 | bindsym $mod+Shift+2 mode cws2 24 | bindsym $mod+Shift+3 mode cws3 25 | bindsym $mod+Shift+4 mode cws4 26 | bindsym $mod+Shift+5 mode cws5 27 | bindsym $mod+Shift+6 mode cws6 28 | bindsym $mod+Shift+7 mode cws7 29 | bindsym $mod+Shift+8 mode cws8 30 | bindsym $mod+Shift+9 mode cws9 31 | 32 | 33 | # 34 | # You shouldn't need to edit anything below here. 35 | # 36 | 37 | 38 | mode "ws1" { 39 | bindsym 0 mode default, workspace 10 40 | bindsym 1 mode default, workspace 11 41 | bindsym 2 mode default, workspace 12 42 | bindsym 3 mode default, workspace 13 43 | bindsym 4 mode default, workspace 14 44 | bindsym 5 mode default, workspace 15 45 | bindsym 6 mode default, workspace 16 46 | bindsym 7 mode default, workspace 17 47 | bindsym 8 mode default, workspace 18 48 | bindsym 9 mode default, workspace 19 49 | } 50 | 51 | 52 | mode "ws2" { 53 | bindsym 0 mode default, workspace 20 54 | bindsym 1 mode default, workspace 21 55 | bindsym 2 mode default, workspace 22 56 | bindsym 3 mode default, workspace 23 57 | bindsym 4 mode default, workspace 24 58 | bindsym 5 mode default, workspace 25 59 | bindsym 6 mode default, workspace 26 60 | bindsym 7 mode default, workspace 27 61 | bindsym 8 mode default, workspace 28 62 | bindsym 9 mode default, workspace 29 63 | } 64 | 65 | 66 | mode "ws3" { 67 | bindsym 0 mode default, workspace 30 68 | bindsym 1 mode default, workspace 31 69 | bindsym 2 mode default, workspace 32 70 | bindsym 3 mode default, workspace 33 71 | bindsym 4 mode default, workspace 34 72 | bindsym 5 mode default, workspace 35 73 | bindsym 6 mode default, workspace 36 74 | bindsym 7 mode default, workspace 37 75 | bindsym 8 mode default, workspace 38 76 | bindsym 9 mode default, workspace 39 77 | } 78 | 79 | 80 | mode "ws4" { 81 | bindsym 0 mode default, workspace 40 82 | bindsym 1 mode default, workspace 41 83 | bindsym 2 mode default, workspace 42 84 | bindsym 3 mode default, workspace 43 85 | bindsym 4 mode default, workspace 44 86 | bindsym 5 mode default, workspace 45 87 | bindsym 6 mode default, workspace 46 88 | bindsym 7 mode default, workspace 47 89 | bindsym 8 mode default, workspace 48 90 | bindsym 9 mode default, workspace 49 91 | } 92 | 93 | 94 | mode "ws5" { 95 | bindsym 0 mode default, workspace 50 96 | bindsym 1 mode default, workspace 51 97 | bindsym 2 mode default, workspace 52 98 | bindsym 3 mode default, workspace 53 99 | bindsym 4 mode default, workspace 54 100 | bindsym 5 mode default, workspace 55 101 | bindsym 6 mode default, workspace 56 102 | bindsym 7 mode default, workspace 57 103 | bindsym 8 mode default, workspace 58 104 | bindsym 9 mode default, workspace 59 105 | } 106 | 107 | 108 | mode "ws6" { 109 | bindsym 0 mode default, workspace 60 110 | bindsym 1 mode default, workspace 61 111 | bindsym 2 mode default, workspace 62 112 | bindsym 3 mode default, workspace 63 113 | bindsym 4 mode default, workspace 64 114 | bindsym 5 mode default, workspace 65 115 | bindsym 6 mode default, workspace 66 116 | bindsym 7 mode default, workspace 67 117 | bindsym 8 mode default, workspace 68 118 | bindsym 9 mode default, workspace 69 119 | } 120 | 121 | 122 | mode "ws7" { 123 | bindsym 0 mode default, workspace 70 124 | bindsym 1 mode default, workspace 71 125 | bindsym 2 mode default, workspace 72 126 | bindsym 3 mode default, workspace 73 127 | bindsym 4 mode default, workspace 74 128 | bindsym 5 mode default, workspace 75 129 | bindsym 6 mode default, workspace 76 130 | bindsym 7 mode default, workspace 77 131 | bindsym 8 mode default, workspace 78 132 | bindsym 9 mode default, workspace 79 133 | } 134 | 135 | 136 | mode "ws8" { 137 | bindsym 0 mode default, workspace 80 138 | bindsym 1 mode default, workspace 81 139 | bindsym 2 mode default, workspace 82 140 | bindsym 3 mode default, workspace 83 141 | bindsym 4 mode default, workspace 84 142 | bindsym 5 mode default, workspace 85 143 | bindsym 6 mode default, workspace 86 144 | bindsym 7 mode default, workspace 87 145 | bindsym 8 mode default, workspace 88 146 | bindsym 9 mode default, workspace 89 147 | } 148 | 149 | 150 | mode "ws9" { 151 | bindsym 0 mode default, workspace 90 152 | bindsym 1 mode default, workspace 91 153 | bindsym 2 mode default, workspace 92 154 | bindsym 3 mode default, workspace 93 155 | bindsym 4 mode default, workspace 94 156 | bindsym 5 mode default, workspace 95 157 | bindsym 6 mode default, workspace 96 158 | bindsym 7 mode default, workspace 97 159 | bindsym 8 mode default, workspace 98 160 | bindsym 9 mode default, workspace 99 161 | } 162 | 163 | 164 | mode "cws1" { 165 | bindsym 0 mode default, move container to workspace 10 166 | bindsym 1 mode default, move container to workspace 11 167 | bindsym 2 mode default, move container to workspace 12 168 | bindsym 3 mode default, move container to workspace 13 169 | bindsym 4 mode default, move container to workspace 14 170 | bindsym 5 mode default, move container to workspace 15 171 | bindsym 6 mode default, move container to workspace 16 172 | bindsym 7 mode default, move container to workspace 17 173 | bindsym 8 mode default, move container to workspace 18 174 | bindsym 9 mode default, move container to workspace 19 175 | } 176 | 177 | 178 | mode "cws2" { 179 | bindsym 0 mode default, move container to workspace 20 180 | bindsym 1 mode default, move container to workspace 21 181 | bindsym 2 mode default, move container to workspace 22 182 | bindsym 3 mode default, move container to workspace 23 183 | bindsym 4 mode default, move container to workspace 24 184 | bindsym 5 mode default, move container to workspace 25 185 | bindsym 6 mode default, move container to workspace 26 186 | bindsym 7 mode default, move container to workspace 27 187 | bindsym 8 mode default, move container to workspace 28 188 | bindsym 9 mode default, move container to workspace 29 189 | } 190 | 191 | 192 | mode "cws3" { 193 | bindsym 0 mode default, move container to workspace 30 194 | bindsym 1 mode default, move container to workspace 31 195 | bindsym 2 mode default, move container to workspace 32 196 | bindsym 3 mode default, move container to workspace 33 197 | bindsym 4 mode default, move container to workspace 34 198 | bindsym 5 mode default, move container to workspace 35 199 | bindsym 6 mode default, move container to workspace 36 200 | bindsym 7 mode default, move container to workspace 37 201 | bindsym 8 mode default, move container to workspace 38 202 | bindsym 9 mode default, move container to workspace 39 203 | } 204 | 205 | 206 | mode "cws4" { 207 | bindsym 0 mode default, move container to workspace 40 208 | bindsym 1 mode default, move container to workspace 41 209 | bindsym 2 mode default, move container to workspace 42 210 | bindsym 3 mode default, move container to workspace 43 211 | bindsym 4 mode default, move container to workspace 44 212 | bindsym 5 mode default, move container to workspace 45 213 | bindsym 6 mode default, move container to workspace 46 214 | bindsym 7 mode default, move container to workspace 47 215 | bindsym 8 mode default, move container to workspace 48 216 | bindsym 9 mode default, move container to workspace 49 217 | } 218 | 219 | 220 | mode "cws5" { 221 | bindsym 0 mode default, move container to workspace 50 222 | bindsym 1 mode default, move container to workspace 51 223 | bindsym 2 mode default, move container to workspace 52 224 | bindsym 3 mode default, move container to workspace 53 225 | bindsym 4 mode default, move container to workspace 54 226 | bindsym 5 mode default, move container to workspace 55 227 | bindsym 6 mode default, move container to workspace 56 228 | bindsym 7 mode default, move container to workspace 57 229 | bindsym 8 mode default, move container to workspace 58 230 | bindsym 9 mode default, move container to workspace 59 231 | } 232 | 233 | 234 | mode "cws6" { 235 | bindsym 0 mode default, move container to workspace 60 236 | bindsym 1 mode default, move container to workspace 61 237 | bindsym 2 mode default, move container to workspace 62 238 | bindsym 3 mode default, move container to workspace 63 239 | bindsym 4 mode default, move container to workspace 64 240 | bindsym 5 mode default, move container to workspace 65 241 | bindsym 6 mode default, move container to workspace 66 242 | bindsym 7 mode default, move container to workspace 67 243 | bindsym 8 mode default, move container to workspace 68 244 | bindsym 9 mode default, move container to workspace 69 245 | } 246 | 247 | 248 | mode "cws7" { 249 | bindsym 0 mode default, move container to workspace 70 250 | bindsym 1 mode default, move container to workspace 71 251 | bindsym 2 mode default, move container to workspace 72 252 | bindsym 3 mode default, move container to workspace 73 253 | bindsym 4 mode default, move container to workspace 74 254 | bindsym 5 mode default, move container to workspace 75 255 | bindsym 6 mode default, move container to workspace 76 256 | bindsym 7 mode default, move container to workspace 77 257 | bindsym 8 mode default, move container to workspace 78 258 | bindsym 9 mode default, move container to workspace 79 259 | } 260 | 261 | 262 | mode "cws8" { 263 | bindsym 0 mode default, move container to workspace 80 264 | bindsym 1 mode default, move container to workspace 81 265 | bindsym 2 mode default, move container to workspace 82 266 | bindsym 3 mode default, move container to workspace 83 267 | bindsym 4 mode default, move container to workspace 84 268 | bindsym 5 mode default, move container to workspace 85 269 | bindsym 6 mode default, move container to workspace 86 270 | bindsym 7 mode default, move container to workspace 87 271 | bindsym 8 mode default, move container to workspace 88 272 | bindsym 9 mode default, move container to workspace 89 273 | } 274 | 275 | 276 | mode "cws9" { 277 | bindsym 0 mode default, move container to workspace 90 278 | bindsym 1 mode default, move container to workspace 91 279 | bindsym 2 mode default, move container to workspace 92 280 | bindsym 3 mode default, move container to workspace 93 281 | bindsym 4 mode default, move container to workspace 94 282 | bindsym 5 mode default, move container to workspace 95 283 | bindsym 6 mode default, move container to workspace 96 284 | bindsym 7 mode default, move container to workspace 97 285 | bindsym 8 mode default, move container to workspace 98 286 | bindsym 9 mode default, move container to workspace 99 287 | } 288 | 289 | # 290 | # Done. 291 | # 292 | -------------------------------------------------------------------------------- /i3-config.d/dunstrc: -------------------------------------------------------------------------------- 1 | # -*- mode: shell-script; -*- 2 | 3 | [global] 4 | ### Display ### 5 | 6 | # Which monitor should the notifications be displayed on. 7 | monitor = 0 8 | 9 | # Display notification on focused monitor. Possible modes are: 10 | # mouse: follow mouse pointer 11 | # keyboard: follow window with keyboard focus 12 | # none: don't follow anything 13 | # 14 | # "keyboard" needs a window manager that exports the 15 | # _NET_ACTIVE_WINDOW property. 16 | # This should be the case for almost all modern window managers. 17 | # 18 | # If this option is set to mouse or keyboard, the monitor option 19 | # will be ignored. 20 | follow = mouse 21 | # EllaTheCat: "keyboard" may be causing this: 22 | # WARNING: BadWindow (invalid Window parameter) 23 | 24 | 25 | # The geometry of the window: 26 | # [{width}]x{height}[+/-{x}+/-{y}] 27 | # The geometry of the message window. 28 | # The height is measured in number of notifications everything else 29 | # in pixels. If the width is omitted but the height is given 30 | # ("-geometry x2"), the message window expands over the whole screen 31 | # (dmenu-like). If width is 0, the window expands to the longest 32 | # message displayed. A positive x is measured from the left, a 33 | # negative from the right side of the screen. Y is measured from 34 | # the top and down respectively. 35 | # The width can be negative. In this case the actual width is the 36 | # screen width minus the width defined in within the geometry option. 37 | geometry = "384x3-80+160" 38 | 39 | # Show how many messages are currently hidden (because of geometry). 40 | indicate_hidden = yes 41 | 42 | # Shrink window if it's smaller than the width. Will be ignored if 43 | # width is 0. 44 | shrink = no 45 | 46 | # The transparency of the window. Range: [0; 100]. 47 | # This option will only work if a compositing window manager is 48 | # present (e.g. xcompmgr, compiz, etc.). 49 | transparency = 0 50 | 51 | # The height of the entire notification. If the height is smaller 52 | # than the font height and padding combined, it will be raised 53 | # to the font height and padding. 54 | notification_height = 96 55 | 56 | # Draw a line of "separator_height" pixel height between two 57 | # notifications. 58 | # Set to 0 to disable. 59 | separator_height = 2 60 | 61 | # Padding between text and separator. 62 | padding = 8 63 | 64 | # Horizontal padding. 65 | horizontal_padding = 8 66 | 67 | # Defines width in pixels of frame around the notification window. 68 | # Set to 0 to disable. 69 | frame_width = 3 70 | 71 | # Defines color of the frame around the notification window. 72 | frame_color = "#aaaaaa" 73 | 74 | # Define a color for the separator. 75 | # possible values are: 76 | # * auto: dunst tries to find a color fitting to the background; 77 | # * foreground: use the same color as the foreground; 78 | # * frame: use the same color as the frame; 79 | # * anything else will be interpreted as a X color. 80 | separator_color = frame 81 | 82 | # Sort messages by urgency. 83 | sort = yes 84 | 85 | # Don't remove messages, if the user is idle (no mouse or keyboard input) 86 | # for longer than idle_threshold seconds. 87 | # Set to 0 to disable. 88 | # A client can set the 'transient' hint to bypass this. See the rules 89 | # section for how to disable this if necessary 90 | idle_threshold = 120 91 | 92 | ### Text ### 93 | 94 | font = Monospace 8 # 8 is default 95 | 96 | # The spacing between lines. If the height is smaller than the 97 | # font height, it will get raised to the font height. 98 | line_height = 0 99 | 100 | # Possible values are: 101 | # full: Allow a small subset of html markup in notifications: 102 | # bold 103 | # italic 104 | # strikethrough 105 | # underline 106 | # 107 | # For a complete reference see 108 | # . 109 | # 110 | # strip: This setting is provided for compatibility with some broken 111 | # clients that send markup even though it's not enabled on the 112 | # server. Dunst will try to strip the markup but the parsing is 113 | # simplistic so using this option outside of matching rules for 114 | # specific applications *IS GREATLY DISCOURAGED*. 115 | # 116 | # no: Disable markup parsing, incoming notifications will be treated as 117 | # plain text. Dunst will not advertise that it has the body-markup 118 | # capability if this is set as a global setting. 119 | # 120 | # It's important to note that markup inside the format option will be parsed 121 | # regardless of what this is set to. 122 | markup = full 123 | 124 | # The format of the message. Possible variables are: 125 | # %a appname 126 | # %s summary 127 | # %b body 128 | # %i iconname (including its path) 129 | # %I iconname (without its path) 130 | # %p progress value if set ([ 0%] to [100%]) or nothing 131 | # %n progress value if set without any extra characters 132 | # %% Literal % 133 | # Markup is allowed 134 | format = "%s\n%b" 135 | 136 | # Alignment of message text. 137 | # Possible values are "left", "center" and "right". 138 | alignment = left 139 | 140 | # Show age of message if message is older than show_age_threshold 141 | # seconds. 142 | # Set to -1 to disable. 143 | show_age_threshold = 60 144 | 145 | # Split notifications into multiple lines if they don't fit into 146 | # geometry. 147 | word_wrap = yes 148 | 149 | # When word_wrap is set to no, specify where to make an ellipsis in long lines. 150 | # Possible values are "start", "middle" and "end". 151 | ellipsize = middle 152 | 153 | # Ignore newlines '\n' in notifications. 154 | ignore_newline = no 155 | 156 | # Stack together notifications with the same content 157 | stack_duplicates = true 158 | 159 | # Hide the count of stacked notifications with the same content 160 | hide_duplicate_count = false 161 | 162 | # Display indicators for URLs (U) and actions (A). 163 | show_indicators = yes 164 | 165 | ### Icons ### 166 | 167 | # Align icons left/right/off 168 | icon_position = off 169 | 170 | # Scale larger icons down to this size, set to 0 to disable 171 | max_icon_size = 32 172 | 173 | # Paths to default icons. 174 | icon_path = /usr/share/icons/gnome/16x16/status/:/usr/share/icons/gnome/16x16/devices/ 175 | 176 | ### History ### 177 | 178 | # Should a notification popped up from history be sticky or timeout 179 | # as if it would normally do. 180 | sticky_history = yes 181 | 182 | # Maximum amount of notifications kept in history 183 | history_length = 20 184 | 185 | ### Misc/Advanced ### 186 | 187 | # dmenu path. 188 | dmenu = /usr/bin/dmenu -p dunst: 189 | 190 | # Browser for opening urls in context menu. 191 | browser = /usr/bin/sensible-browser 192 | 193 | # Always run rule-defined scripts, even if the notification is suppressed 194 | always_run_script = true 195 | 196 | # Define the title of the windows spawned by dunst 197 | title = Dunst 198 | 199 | # Define the class of the windows spawned by dunst 200 | class = Dunst 201 | 202 | # Print a notification on startup. 203 | # This is mainly for error detection, since dbus (re-)starts dunst 204 | # automatically after a crash. 205 | startup_notification = false 206 | 207 | # Manage dunst's desire for talking 208 | # Can be one of the following values: 209 | # crit: Critical features. Dunst aborts 210 | # warn: Only non-fatal warnings 211 | # mesg: Important Messages 212 | # info: all unimportant stuff 213 | # debug: all less than unimportant stuff 214 | verbosity = mesg 215 | 216 | # Define the corner radius of the notification window 217 | # in pixel size. If the radius is 0, you have no rounded 218 | # corners. 219 | # The radius will be automatically lowered if it exceeds half of the 220 | # notification height to avoid clipping text and/or icons. 221 | corner_radius = 0 222 | 223 | ### Legacy 224 | 225 | # Use the Xinerama extension instead of RandR for multi-monitor support. 226 | # This setting is provided for compatibility with older nVidia drivers that 227 | # do not support RandR and using it on systems that support RandR is highly 228 | # discouraged. 229 | # 230 | # By enabling this setting dunst will not be able to detect when a monitor 231 | # is connected or disconnected which might break follow mode if the screen 232 | # layout changes. 233 | force_xinerama = false 234 | 235 | ### mouse 236 | 237 | # Defines action of mouse event 238 | # Possible values are: 239 | # * none: Don't do anything. 240 | # * do_action: If the notification has exactly one action, or one is marked as default, 241 | # invoke it. If there are multiple and no default, open the context menu. 242 | # * close_current: Close current notification. 243 | # * close_all: Close all notifications. 244 | mouse_left_click = close_current 245 | mouse_middle_click = do_action 246 | mouse_right_click = close_all 247 | 248 | # Experimental features that may or may not work correctly. Do not expect them 249 | # to have a consistent behaviour across releases. 250 | [experimental] 251 | # Calculate the dpi to use on a per-monitor basis. 252 | # If this setting is enabled the Xft.dpi value will be ignored and instead 253 | # dunst will attempt to calculate an appropriate dpi value for each monitor 254 | # using the resolution and physical size. This might be useful in setups 255 | # where there are multiple screens with very different dpi values. 256 | per_monitor_dpi = false 257 | 258 | [shortcuts] 259 | 260 | # Shortcuts are specified as [modifier+][modifier+]...key 261 | # Available modifiers are "ctrl", "mod1" (the alt-key), "mod2", 262 | # "mod3" and "mod4" (windows-key). 263 | # Xev might be helpful to find names for keys. 264 | 265 | # Close notification. 266 | close = ctrl+space 267 | 268 | # Close all notifications. 269 | close_all = ctrl+shift+space 270 | 271 | # Redisplay last message(s). 272 | # On the US keyboard layout "grave" is normally above TAB and left 273 | # of "1". Make sure this key actually exists on your keyboard layout, 274 | # e.g. check output of 'xmodmap -pke' 275 | history = ctrl+grave 276 | 277 | # Context menu. 278 | context = ctrl+shift+period 279 | 280 | [urgency_low] 281 | # IMPORTANT: colors have to be defined in quotation marks. 282 | # Otherwise the "#" and following would be interpreted as a comment. 283 | background = "#222222" 284 | foreground = "#888888" 285 | timeout = 10 286 | # Icon for notifications with low urgency, uncomment to enable 287 | #icon = /path/to/icon 288 | 289 | [urgency_normal] 290 | background = "#285577" 291 | foreground = "#ffffff" 292 | timeout = 10 293 | # Icon for notifications with normal urgency, uncomment to enable 294 | #icon = /path/to/icon 295 | 296 | [urgency_critical] 297 | background = "#900000" 298 | foreground = "#ffffff" 299 | frame_color = "#ff0000" 300 | timeout = 0 301 | # Icon for notifications with critical urgency, uncomment to enable 302 | #icon = /path/to/icon 303 | 304 | # Every section that isn't one of the above is interpreted as a rules to 305 | # override settings for certain messages. 306 | # 307 | # Messages can be matched by 308 | # appname (discouraged, see desktop_entry) 309 | # body 310 | # category 311 | # desktop_entry 312 | # icon 313 | # match_transient 314 | # msg_urgency 315 | # stack_tag 316 | # summary 317 | # 318 | # and you can override the 319 | # background 320 | # foreground 321 | # format 322 | # frame_color 323 | # fullscreen 324 | # new_icon 325 | # set_stack_tag 326 | # set_transient 327 | # timeout 328 | # urgency 329 | # 330 | # Shell-like globbing will get expanded. 331 | # 332 | # Instead of the appname filter, it's recommended to use the desktop_entry filter. 333 | # GLib based applications export their desktop-entry name. In comparison to the appname, 334 | # the desktop-entry won't get localized. 335 | # 336 | # SCRIPTING 337 | # You can specify a script that gets run when the rule matches by 338 | # setting the "script" option. 339 | # The script will be called as follows: 340 | # script appname summary body icon urgency 341 | # where urgency can be "LOW", "NORMAL" or "CRITICAL". 342 | # 343 | # NOTE: if you don't want a notification to be displayed, set the format 344 | # to "". 345 | # NOTE: It might be helpful to run dunst -print in a terminal in order 346 | # to find fitting options for rules. 347 | 348 | # Disable the transient hint so that idle_threshold cannot be bypassed from the 349 | # client 350 | #[transient_disable] 351 | # match_transient = yes 352 | # set_transient = no 353 | # 354 | # Make the handling of transient notifications more strict by making them not 355 | # be placed in history. 356 | #[transient_history_ignore] 357 | # match_transient = yes 358 | # history_ignore = yes 359 | 360 | # fullscreen values 361 | # show: show the notifications, regardless if there is a fullscreen window opened 362 | # delay: displays the new notification, if there is no fullscreen window active 363 | # If the notification is already drawn, it won't get undrawn. 364 | # pushback: same as delay, but when switching into fullscreen, the notification will get 365 | # withdrawn from screen again and will get delayed like a new notification 366 | #[fullscreen_delay_everything] 367 | # fullscreen = delay 368 | #[fullscreen_show_critical] 369 | # msg_urgency = critical 370 | # fullscreen = show 371 | 372 | #[espeak] 373 | # summary = "*" 374 | # script = dunst_espeak.sh 375 | 376 | #[script-test] 377 | # summary = "*script*" 378 | # script = dunst_test.sh 379 | 380 | #[ignore] 381 | # # This notification will not be displayed 382 | # summary = "foobar" 383 | # format = "" 384 | 385 | #[history-ignore] 386 | # # This notification will not be saved in history 387 | # summary = "foobar" 388 | # history_ignore = yes 389 | 390 | #[skip-display] 391 | # # This notification will not be displayed, but will be included in the history 392 | # summary = "foobar" 393 | # skip_display = yes 394 | 395 | #[signed_on] 396 | # appname = Pidgin 397 | # summary = "*signed on*" 398 | # urgency = low 399 | # 400 | #[signed_off] 401 | # appname = Pidgin 402 | # summary = *signed off* 403 | # urgency = low 404 | # 405 | #[says] 406 | # appname = Pidgin 407 | # summary = *says* 408 | # urgency = critical 409 | # 410 | #[twitter] 411 | # appname = Pidgin 412 | # summary = *twitter.com* 413 | # urgency = normal 414 | # 415 | #[stack-volumes] 416 | # appname = "some_volume_notifiers" 417 | # set_stack_tag = "volume" 418 | # 419 | # vim: ft=cfg 420 | --------------------------------------------------------------------------------