README and upload xkbhyprmodfix
This commit is contained in:
parent
312f39b4e1
commit
462aecc59c
|
@ -1,3 +1,9 @@
|
|||
# xkbhyprmodfix
|
||||
|
||||
Replace CapsLock with Hyper_L without keybinds assigned to Hyper clashing with other modifiers on Mod4.
|
||||
Replace CapsLock with Hyper_L without keybinds assigned to Hyper clashing with those on Super.
|
||||
|
||||
Creates a new xkb keymap, "HyperCaps", identical to the user's current keyboard layout, except with CapsLock replaced with Hyper and Hyper_L moved to Mod3. The symbol file for the current layout and the xkb rules files in `/usr/share/X11/xkb` are cloned to `/usr/local/share/X11/xkb/`, edited, and then symlinked to. The original unmodified files are backed up.
|
||||
|
||||
This is a workaround to desktop environments such as KDE overwriting any keyboard setup done with xinit configuration files.
|
||||
|
||||
Must be run as root (to grant access to `/usr/share` and `/usr/local/share`).
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
#!/bin/sh
|
||||
|
||||
# test for root
|
||||
[ $(id -u) = 0 ] || { printf "%s\n" "xkbhyprmodfix: must be run as root user"; exit 2; }
|
||||
|
||||
rundate="$(date '+%s')" # UNIX timestamp for backups
|
||||
|
||||
# get keyboard layout info
|
||||
xkbinfo=$(setxkbmap -query)
|
||||
layouts=$(echo "$xkbinfo" | grep "^layout:" | sed -E "s/layout:[[:space:]]+//g")
|
||||
variants=$(echo "$xkbinfo" | grep "^variant:" | sed -E "s/variant:[[:space:]]+//g")
|
||||
|
||||
# extract layout and variant settings if only one setting, otherwise ask the user to select which layout they want to modify
|
||||
echo "$layouts" | grep -q "," || { layout="$layouts"; variant="$variants"; }
|
||||
while ! [ "$layout" ]; do
|
||||
layoutcount=$(echo "$layouts" | tr ',' ' ' | wc -w)
|
||||
printf "%s " "Multiple keyboard layouts detected ($layouts). Select one to proceed (1-$layoutcount)"
|
||||
read -r selection
|
||||
case "$selection" in
|
||||
''|*[!0-9]*)
|
||||
printf "%s\n" "Invalid selection '$selection'."
|
||||
continue
|
||||
;;
|
||||
esac
|
||||
{ [ "$selection" -gt 0 ] && [ "$selection" -le "$layoutcount" ]; } || { printf "%s\n" "Invalid selection '$selection'."; continue; }
|
||||
layout=$(echo "$layouts" | cut -d"," -f"$selection")
|
||||
variant=$(echo "$variants" | cut -d"," -f"$selection")
|
||||
done
|
||||
|
||||
# new keyboard will duplicate the existing one
|
||||
# the default layout of that language is not a variant, meaning $variant will be empty, but is referred to as "basic" in the symbol file
|
||||
# $variant is copied into a new variable which is set to "basic" if blank
|
||||
# similarly, "basic" is a valid variant but is considered as no variant in the .lst files
|
||||
# $variant is set to blank if it is "basic"
|
||||
variant_inherit="$variant"
|
||||
[ -n "$variant_inherit" ] || variant_inherit="basic"
|
||||
[ "$variant" = "basic" ] && variant=
|
||||
|
||||
xkbdir=/usr/share/X11/xkb
|
||||
localxkbdir=/usr/local/share/X11/xkb_hypercaps
|
||||
locallayout="$localxkbdir"/symbols/"$layout"
|
||||
|
||||
[ -e "$localxkbdir" ] && {
|
||||
printf "%s " "Filepath '$localxkbdir' exists. Files found at this path or its subdirectories may be overwritten. Continue? (y/n)"
|
||||
read -r selection
|
||||
[ "$selection" = "y" ] || [ "$selection" = "Y" ] || { printf "%s\n" "Exiting."; exit 2; }
|
||||
}
|
||||
|
||||
# make sure the layout exists in symbols and hypercaps layout is not already applied
|
||||
[ -f "$xkbdir"/symbols/"$layout" ] || { printf "%s\n" "Error: $xkbdir/symbols/$layout not found. Exiting."; exit 2; }
|
||||
grep -q 'xkb_symbols "hypercaps" {' "$xkbdir"/symbols/"$layout" && { printf "%s\n" "Error: hypercaps layout for layout '$layout' already exists."; exit 2; }
|
||||
|
||||
# Get layout title
|
||||
lstfile=$(wc -l "$xkbdir"/rules/*.lst | grep -v "total$" | sort -b -r -h | sed 's/^[[:space:]]\+[0-9]\+ //g; 1q') # Use the longest .lst file
|
||||
[ -n "$variant" ] \
|
||||
&& lstpattern="^[[:space:]]{2}${variant}[[:space:]]+$layout:[[:space:]]" \
|
||||
|| lstpattern="^[[:space:]]{2}${layout}[[:space:]]{8,}"
|
||||
layouttitle=$(grep -E "$lstpattern" "$lstfile" | head -n 1 | sed -E "s/$lstpattern//g")
|
||||
[ -n "$layouttitle" ] || { printf "%s\n" "Warning: Keyboard layout name not found in '$lstfile'. Defaulting to '$layout (HyperCaps)' as name."; layouttitle="$layout ()"; }
|
||||
hypercapstitle=$(echo "$layouttitle" | sed -E 's/\((.+)\)$/\(\1, HyperCaps\)/; s/\(\)/(HyperCaps)/')
|
||||
echo "$hypercapstitle" | grep -q "HyperCaps)" || hypercapstitle="$layouttitle (HyperCaps)"
|
||||
|
||||
# file setup
|
||||
mkdir -p "$localxkbdir"/symbols
|
||||
mkdir -p "$localxkbdir"/rules
|
||||
cp -f "$xkbdir"/symbols/"$layout" "$locallayout"
|
||||
cp -f -d -t "$localxkbdir"/rules/ "$xkbdir"/rules/base.xml "$xkbdir"/rules/base.lst \
|
||||
"$xkbdir"/rules/evdev.xml "$xkbdir"/rules/evdev.lst \
|
||||
"$xkbdir"/rules/xorg.xml "$xkbdir"/rules/xorg.lst
|
||||
|
||||
# append new keyboard layout to copied symbol file if it does not already exist
|
||||
grep -q 'xkb_symbols "hypercaps" {' "$locallayout" || \
|
||||
printf "\n%s\n%s\n\t%s\n\t%s\n\t%s\n\t%s\n\t%s\n%s\n" \
|
||||
"partial alphanumeric_keys" \
|
||||
"xkb_symbols \"hypercaps\" {" \
|
||||
"include \"$layout($variant_inherit)\"" \
|
||||
"replace key <HYPR> { [ Super_L, Super_L ] };" \
|
||||
"name[Group1]=\"$hypercapstitle\";" \
|
||||
"key <CAPS> { [ Hyper_L ] };" \
|
||||
"modifier_map Mod3 { <CAPS> };" \
|
||||
"};" >> "$locallayout"
|
||||
|
||||
|
||||
# modify copied rule files if layout is not already applied
|
||||
grep -q "<description>$hypercapstitle</description>" "$localxkbdir"/rules/*.xml || \
|
||||
sed -i '/<description>'"$layouttitle"'<\/description>/,/<\/layout>/{/<\/variantList>/i\
|
||||
<variant>\
|
||||
<configItem>\
|
||||
<name>hypercaps</name>\
|
||||
<description>'"$hypercapstitle"'</description>\
|
||||
</configItem>\
|
||||
</variant>
|
||||
}' "$localxkbdir"/rules/base.xml "$localxkbdir"/rules/evdev.xml
|
||||
|
||||
grep -q "<description>$hypercapstitle</description>" "$localxkbdir"/rules/*.xml || \
|
||||
sed -i '/<description>'"$layouttitle"'<\/description>/,/<\/layout>/{/<\/configItem>/a\
|
||||
<variantList>\
|
||||
<variant>\
|
||||
<configItem>\
|
||||
<name>hypercaps</name>\
|
||||
<description>'"$hypercapstitle"'</description>\
|
||||
</configItem>\
|
||||
</variant>\
|
||||
</variantList>
|
||||
}' "$localxkbdir"/rules/base.xml "$localxkbdir"/rules/evdev.xml
|
||||
|
||||
|
||||
grep -q "hypercaps $layout: $hypercapstitle" "$localxkbdir"/rules/*.lst || \
|
||||
sed -i "/^! variant$/a \ \ hypercaps $layout: $hypercapstitle" "$localxkbdir"/rules/*.lst
|
||||
|
||||
#
|
||||
# danger zone
|
||||
#
|
||||
|
||||
# backup original files and alias modified copies
|
||||
cp -d -f "$xkbdir"/symbols/"$layout" "$xkbdir"/symbols/"${layout}"."${rundate}".bak \
|
||||
&& ln -s -f "$locallayout" "$xkbdir"/symbols/"$layout" \
|
||||
|| { printf "%s\n" "Unable to apply modified symbol layout to $xkbdir/symbols/$layout"; exit 2; }
|
||||
|
||||
for ext in xml lst; do
|
||||
for file in base evdev xorg; do
|
||||
cp -d -f "$xkbdir"/rules/"${file}"."${ext}" "$xkbdir"/rules/"${file}"."${rundate}"."${ext}" \
|
||||
&& ln -s -f "$localxkbdir"/rules/"${file}"."${ext}" "$xkbdir"/rules/"${file}"."${ext}" \
|
||||
|| { printf "%s\n" "Unable to replace rule file '${file}.${ext}"; exit 2; }
|
||||
done
|
||||
done
|
Loading…
Reference in New Issue