xfce/rofi-keybinds.sh 5.0 K raw
1
#!/bin/sh
2
# Requires: xfconf-query (xfce4-settings)
3
# Points the XFCE keyboard shortcuts at the rofi menus in ../rofi/scripts,
4
# and can put back whatever those keys did before.
5
#
6
# This is a script rather than a checked-in xfconf XML file because xfconf
7
# rewrites its own config atomically, by rename — which would replace a
8
# symlink from this repo with a regular file the first time anything changed
9
# a shortcut through the settings GUI.
10
#
11
# Usage: rofi-keybinds.sh            apply (idempotent, safe to re-run)
12
#        rofi-keybinds.sh --remove   restore what these keys did before
13
#        rofi-keybinds.sh --list     show which keys currently run rofi
14
#
15
# xfsettingsd watches xfconf, so changes take effect immediately — no logout.
16
set -u
17
18
CHANNEL=xfce4-keyboard-shortcuts
19
BACKUP="${XDG_DATA_HOME:-$HOME/.local/share}/rofi-keybinds.backup"
20
21
# Where the menu scripts live. The repo layout is the default; point
22
# ROFI_SCRIPTS somewhere else to bind an installed copy instead.
23
S=${ROFI_SCRIPTS:-$(CDPATH= cd -- "$(dirname -- "$0")/../rofi/scripts" 2>/dev/null && pwd)}
24
[ -n "${S:-}" ] && [ -d "$S" ] || S="$HOME/.config/rofi/scripts"
25
[ -d "$S" ] || { echo "rofi-keybinds: no rofi scripts directory found" >&2; exit 1; }
26
27
command -v xfconf-query >/dev/null 2>&1 ||
28
    { echo "rofi-keybinds: xfconf-query not found — is this an XFCE session?" >&2; exit 1; }
29
30
# key<TAB>command. Super+Tab, Super+f/h/l and Super+1-4 are missing from this
31
# list on purpose: xfwm4 grabs those for window and workspace handling, so a
32
# command bound to them would never fire.
33
binds() {
34
    cat <<BINDS
35
/commands/custom/<Super>d	rofi -show drun
36
/commands/custom/<Super>space	rofi -show drun
37
/commands/custom/<Alt>F2	rofi -show run
38
/commands/custom/<Super>r	rofi -show run
39
/commands/custom/<Super>w	rofi -show window
40
/commands/custom/<Shift><Super>f	rofi -show filebrowser
41
/commands/custom/<Super>v	$S/rofi-clip
42
/commands/custom/<Shift><Super>e	$S/rofi-emoji
43
/commands/custom/<Shift><Super>c	$S/rofi-calc
44
/commands/custom/<Shift><Super>x	$S/rofi-power
45
/commands/custom/<Shift><Super>n	$S/rofi-wifi
46
/commands/custom/<Shift><Super>u	$S/rofi-audio
47
/commands/custom/<Super>s	$S/rofi-screenshot
48
/commands/custom/Print	$S/rofi-screenshot
49
/commands/custom/<Super>slash	$S/rofi-websearch
50
BINDS
51
}
52
53
# Shortcuts for xfce4-screenshooter, which is not installed — these keys do
54
# nothing at all today, so they are dropped rather than repointed.
55
DEAD="/commands/custom/<Shift>Print
56
/commands/custom/<Alt>Print"
57
58
get() { xfconf-query -c "$CHANNEL" -p "$1" 2>/dev/null; }
59
exists() { xfconf-query -c "$CHANNEL" -p "$1" >/dev/null 2>&1; }
60
61
# One line per property, the first time it is touched: "prop<TAB>type<TAB>old
62
# value", with an empty value meaning the property did not exist. Re-running
63
# apply must not overwrite an entry, or the original would be lost behind a
64
# rofi command.
65
record() {
66
    mkdir -p "$(dirname "$BACKUP")"
67
    [ -f "$BACKUP" ] &&
68
        awk -F'\t' -v p="$1" '$1 == p { found = 1 } END { exit !found }' "$BACKUP" &&
69
        return 0
70
    printf '%s\t%s\t%s\n' "$1" "$2" "$3" >> "$BACKUP"
71
}
72
73
put() {
74
    if exists "$1"; then
75
        xfconf-query -c "$CHANNEL" -p "$1" -s "$3"
76
    else
77
        xfconf-query -c "$CHANNEL" -p "$1" -n -t "$2" -s "$3"
78
    fi
79
}
80
81
apply() {
82
    binds | while IFS='	' read -r prop cmd; do
83
        [ -n "$prop" ] || continue
84
        old=$(get "$prop")
85
        [ "$old" = "$cmd" ] && continue
86
87
        record "$prop" string "$old"
88
        put "$prop" string "$cmd" >/dev/null
89
90
        # The appfinder keys carry startup-notify. rofi never sends the
91
        # matching "I am up" message, so the busy cursor would spin for its
92
        # full timeout on every launch.
93
        sn="$prop/startup-notify"
94
        if exists "$sn"; then
95
            record "$sn" bool "$(get "$sn")"
96
            xfconf-query -c "$CHANNEL" -p "$sn" -s false
97
        fi
98
99
        printf '  %-40s → %s\n' "${prop#/commands/custom/}" "$cmd"
100
    done
101
102
    printf '%s\n' "$DEAD" | while read -r prop; do
103
        [ -n "$prop" ] && exists "$prop" || continue
104
        record "$prop" string "$(get "$prop")"
105
        xfconf-query -c "$CHANNEL" -p "$prop" -r
106
        printf '  %-40s → removed (xfce4-screenshooter is not installed)\n' "${prop#/commands/custom/}"
107
    done
108
}
109
110
remove() {
111
    [ -f "$BACKUP" ] || { echo "rofi-keybinds: nothing to restore"; exit 0; }
112
    while IFS='	' read -r prop type value; do
113
        [ -n "$prop" ] || continue
114
        if [ -z "$value" ]; then
115
            xfconf-query -c "$CHANNEL" -p "$prop" -r 2>/dev/null
116
            printf '  %-40s → unbound\n' "${prop#/commands/custom/}"
117
        else
118
            put "$prop" "$type" "$value" >/dev/null
119
            printf '  %-40s → %s\n' "${prop#/commands/custom/}" "$value"
120
        fi
121
    done < "$BACKUP"
122
    rm -f "$BACKUP"
123
}
124
125
case "${1:-}" in
126
    "")        echo "Binding rofi menus in $S:"; apply ;;
127
    --remove)  echo "Restoring shortcuts from $BACKUP:"; remove ;;
128
    --list)    xfconf-query -c "$CHANNEL" -p /commands/custom -lv | grep -i rofi ;;
129
    *)         echo "usage: rofi-keybinds.sh [--remove|--list]" >&2; exit 2 ;;
130
esac