forked from r0adrunner/Space2Ctrl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paths2sctl
executable file
·180 lines (147 loc) · 4.83 KB
/
s2sctl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#! /bin/sh
set -e
program='space2super'
binary="$(dirname "$0")/$program"
config_dir="${XDG_CONFIG_HOME:-$HOME/.config}/$program"
config="$config_dir/config"
default_typed_space_timeout=500
typed_space_timeout=$(
awk '$1 == "timeout_millisec" { print $2; }' "$config" 2> /dev/null ||
echo "$default_typed_space_timeout")
log_file="$config_dir/$program.log"
original_xmodmap="$config_dir/xmodmap.original"
xmodmap_changes="$config_dir/xmodmap.changes"
quiet=false
_log() {
be_quiet=$quiet
if [ "$1" = '--force' ]; then
be_quiet=false
shift
fi
if [ "$be_quiet" = false ]; then
echo "$@" >&2
fi
}
_die() {
_log --force "$@"
exit 1
}
_check_command() {
checked_command=$1
if ! command -v "$checked_command" > /dev/null 2>&1; then
_die "'s2sctl' requires the '$checked_command' command to run."
fi
}
_check_command awk
_check_command pgrep
_check_command pkill
_check_command xmodmap
_signal() {
_signal_id=$1
pkill --exact "-$_signal_id" "$program"
}
_print_key_code_mappings() {
# Instructs `xmodmap` to print out the current keymap table in the form it can consume.
xmodmap -pke || _die 'Listing key code mappings failed.'
}
_print_space_key_mappings() {
_print_key_code_mappings | grep -w 'space' ||
_die 'Could not find any key code mappings of the Space key.'
}
_restore_original_key_code_mappings() {
xmodmap "$original_xmodmap" || _die 'Restoring the original key code mappings failed.'
}
is_running() {
pgrep --uid "$USER" --exact --count "$program" > /dev/null 2>&1
}
start() {
if is_running; then
_log "Space2Super is already active. Use 's2sctl restart' to restart it."
exit 0
fi
_log 'Starting Space2Super...'
mkdir -p "$config_dir" || _die "Could not create Space2Super directory at '$config_dir'."
_print_space_key_mappings > "$original_xmodmap"
# An `xmodmap` mapping line looks like: `keycode 65 = space NoSymbol space NoSymbol space space`,
# where values on the right indicate the `KeySym`s relevant to different modifier combinations,
# the first indicating no modifiers.
# Determine what the original Space key code was (most likely 65).
original_space_key_code=$(awk '{ print $2; exit; }' "$original_xmodmap")
if [ -z "$original_space_key_code" ]; then
_die "Could not find any key code associated with Space (see 'xmodmap -pke')."
fi
# All the `xmodmap` modifications should be applied at once for performance reasons.
{
# Change all mentions of `space` to `Super_L`.
awk '/keycode / {
# Start from after the `=` sign in `$3`.
for (field = 4; field <= NF; ++field) {
if ($field == "space")
$field = "Super_L";
};
print;
}' "$original_xmodmap"
# Map an unused key code to `space` when no modifiers are applied.
echo "keycode any = space"
} > "$xmodmap_changes" || _die 'Could not store the generated key code mapping changes.'
xmodmap "$xmodmap_changes" || {
_restore_original_key_code_mappings
_die "Applying key code mappings failed. You can check them in '$xmodmap_changes'."
}
# Find out what `xmodmap` has chosen for the `any` above to be able to revert it to nothing.
# `$4` is the no-modifier `KeySym`, `$2` is the key code between `keycode` and `=`.
_print_space_key_mappings |
awk '$4 == "space" { print "keycode " $2 " ="; }' >> "$original_xmodmap"
"$binary" "$original_space_key_code" "$typed_space_timeout" >> "$log_file" 2>&1 &
_log "Space2Super is now active (log file: $log_file)."
}
stop() {
if ! is_running; then
_die 'Space2Super is not running.'
fi
_log 'Stopping Space2Super...'
_restore_original_key_code_mappings
if _signal TERM; then
# Signalled. Wait a bit and check if it's done.
sleep 0.5
if is_running; then
# Still alive.
_signal KILL
_die 'The program did not terminate gracefully, sent SIGKILL.'
fi
fi
}
remap() {
is_running || return
xmodmap "$xmodmap_changes" || {
_restore_original_key_code_mappings
_die "Could not re-apply the key code mappings, you can check them in '$xmodmap_changes'."
}
}
if [ "$2" = '--quiet' ]; then
quiet=true
fi
case "$1" in
running)
# Exits with a zero code if Space2Super is running, non-zero otherwise.
is_running
;;
start)
start
;;
stop)
stop
;;
restart)
is_running && stop
start
;;
remap)
# Use to reconfigure XKB after external changes, like `setxkbmap`.
# Only applied if Space2Super is running.
remap
;;
*)
_die "Usage: $0 {start|stop|restart|running|remap}"
;;
esac