From 91d9e9d099b6098262a261d7f6985a3fa2f9cd46 Mon Sep 17 00:00:00 2001 From: Shawn Badger Date: Sat, 20 Jul 2024 14:43:19 -0600 Subject: [PATCH 1/2] Add Linux support for both wayland and x11 --- INSTALL.md | 11 ++++++ linux/activate.sh | 28 +++++++++++++++ linux/graphite | 54 ++++++++++++++++++++++++++++ linux/graphite.xslt | 41 +++++++++++++++++++++ linux/install.sh | 86 +++++++++++++++++++++++++++++++++++++++++++++ linux/uninstall.sh | 30 ++++++++++++++++ 6 files changed, 250 insertions(+) create mode 100755 linux/activate.sh create mode 100644 linux/graphite create mode 100644 linux/graphite.xslt create mode 100755 linux/install.sh create mode 100755 linux/uninstall.sh diff --git a/INSTALL.md b/INSTALL.md index 24d3889..bcae5b6 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -11,3 +11,14 @@ 5. Go to System Settings > Keyboard Layouts 6. Click the + button, and search for Graphite + + +# Linux + +1. Run `sudo ./linux/install.sh` + +2. Log out, log back in (or reboot) + +3. Run `./linux/activate.sh` or manually set the layout in your window manager + +4. To remove the layout, run `./linux/uninstall.sh` diff --git a/linux/activate.sh b/linux/activate.sh new file mode 100755 index 0000000..37b78b6 --- /dev/null +++ b/linux/activate.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + +if [ "$XDG_CURRENT_DESKTOP" == "GNOME" ]; then + gsettings set org.gnome.desktop.input-sources sources "[('xkb', 'us+graphite')]" + #gsettings set org.gnome.desktop.input-sources xkb-options "['ctrl:nocaps']" + +elif [ "$XDG_CURRENT_DESKTOP" == "KDE" ]; then + kwriteconfig6 --file kxkbrc --group Layout --key LayoutList us + kwriteconfig6 --file kxkbrc --group Layout --key VariantList graphite + #kwriteconfig6 --file kxkbrc --group Layout --key Options caps:backspace # Uncomment for CAPS to be BKSP + #kwriteconfig6 --file kxkbrc --group Layout --key Options ctrl:nocaps # Uncomment for CAPS to be CTRL + dbus-send --session --type=signal --reply-timeout=100 --dest=org.kde.keyboard /Layouts org.kde.keyboard.reloadConfig + +else + if [ "$XDG_SESSION_TYPE" == "wayland" ]; then + echo "You're running Wayland with a compositor other than Gnome or KDE" + echo "I don't know how to enable the layout for your compositor." + echo "You will need to manually enable it in your window manager." + exit 1 + else + setxkbmap us -variant graphite + #setxkbmap us -variant graphite -option ctrl:nocaps + fi +fi + +echo "" +echo "Graphite Layout should now be the active layout" +echo "" diff --git a/linux/graphite b/linux/graphite new file mode 100644 index 0000000..36a243a --- /dev/null +++ b/linux/graphite @@ -0,0 +1,54 @@ + +partial alphanumeric_keys +xkb_symbols "graphite" { + include "us" + name[Group1]= "English (Graphite)"; + + key { [ grave, asciitilde ] }; + key { [ 1, exclam ] }; + key { [ 2, at ] }; + key { [ 3, numbersign ] }; + key { [ 4, dollar ] }; + key { [ 5, percent ] }; + key { [ 6, asciicircum ] }; + key { [ 7, ampersand ] }; + key { [ 8, asterisk ] }; + key { [ 9, parenleft ] }; + key { [ 0, parenright ] }; + key { [ bracketleft, braceleft ] }; + key { [ bracketright, braceright ] }; + key { [ b, B ] }; + key { [ l, L ] }; + key { [ d, D ] }; + key { [ w, W ] }; + key { [ z, Z ] }; + key { [ apostrophe, underscore ] }; + key { [ f, F ] }; + key { [ o, O ] }; + key { [ u, U ] }; + key { [ j, J ] }; + key { [ semicolon, colon ] }; + key { [ equal, plus ] }; + key { [ backslash, bar ] }; + key { [ n, N ] }; + key { [ r, R ] }; + key { [ t, T ] }; + key { [ s, S ] }; + key { [ g, G ] }; + key { [ y, Y ] }; + key { [ h, H ] }; + key { [ a, A ] }; + key { [ e, E ] }; + key { [ i, I ] }; + key { [ comma, question ] }; + key { [ q, Q ] }; + key { [ x, X ] }; + key { [ m, M ] }; + key { [ c, C ] }; + key { [ v, V ] }; + key { [ k, K ] }; + key { [ p, P ] }; + key { [ period, greater ] }; + key { [ minus, quotedbl ] }; + key { [ slash, less ] }; +}; diff --git a/linux/graphite.xslt b/linux/graphite.xslt new file mode 100644 index 0000000..1ac23f0 --- /dev/null +++ b/linux/graphite.xslt @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + GRAPHITE BEGIN + + + + + + graphite + + English (Graphite) + + + + + + GRAPHITE END + + + + + + + + + + diff --git a/linux/install.sh b/linux/install.sh new file mode 100755 index 0000000..948bc73 --- /dev/null +++ b/linux/install.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env bash +# +# Installs or reinstalls the Graphite keyboard layout (X11 or Wayland) +# Once installed, you may need to logout or reboot for the layout to be available. +# +# Linux (and especially wayland) is not set up to add custom keyboard layouts easily. +# setxkbmap can use a user-writable directory to add layous, but it isn't available +# for wayland. Alternative approaches such as xremap and kmonad will work too, but +# I needed a native mechanism without those dependencies, because not all systems +# have access to the internet. +# +# This script uses xslt (via the `xsltproc` tool) to modify the system xkb registry +# xml file. I expect most distros include this tool as part of their base install. +# + +#set -x +set -e + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +LAYOUT_FILE=${SCRIPT_DIR}/graphite +XSLT_FILE=${SCRIPT_DIR}/graphite.xslt +XKB_DIR=/usr/share/X11/xkb +SYMBOLS_DIR=${XKB_DIR}/symbols +RULES_DIR=${XKB_DIR}/rules +EVDEV_XML=${RULES_DIR}/evdev.xml + +add_layout_to_registry() { + # Backup the system's xkb evdev.xml file if we haven't already, just in case + if ! test -f ${EVDEV_XML}.bak; then + echo "Backing up evdev.xml file" + cp ${EVDEV_XML} ${EVDEV_XML}.bak + fi + + # Add the layout to evdev.xml and store the result in /tmp/evdev.xml + TMP_FILE=$(mktemp -q /tmp/evdev.XXXXXX) + #echo "Modifying xkb evdev.xml file and storing temporarily at ${TMP_FILE}" + pushd ${RULES_DIR} >/dev/null + xsltproc --nodtdattr -o ${TMP_FILE} ${XSLT_FILE} evdev.xml + if ! [ "$?" == "0" ]; then + echo "Failed to update the xkb registry"; + popd + exit 1 + fi + popd >/dev/null + + # Now copy it over the top of the system's xkb evdev file + cp ${TMP_FILE} ${EVDEV_XML} + rm ${TMP_FILE} + echo "Updated xkb registry" +} + +add_layout_symbols() { + # Append the layout to the end of the 'us' symbols file + #echo "Appending contents of ${LAYOUT_FILE} to ${SYMBOLS_DIR}/us" + echo "//---GRAPHITE BEGIN---" >> ${SYMBOLS_DIR}/us + cat ${LAYOUT_FILE} >> ${SYMBOLS_DIR}/us + echo "//---GRAPHITE END---" >> ${SYMBOLS_DIR}/us + echo "Added Graphite as US layout variant" +} + +install_layout() { + add_layout_symbols + add_layout_to_registry +} + +uninstall_layout() { + sed -i '/^\/\/---GRAPHITE BEGIN---/,/^\/\/---GRAPHITE END---/d' ${SYMBOLS_DIR}/us + sed -i '/GRAPHITE BEGIN/,/GRAPHITE END/d' ${EVDEV_XML} +} + +verify_user_is_root() { + if [ ! "${EUID:-$(id -u)}" -eq 0 ]; then + echo "This script must unfortunately be run with sudo"; + exit 1 + fi +} + + +verify_user_is_root +uninstall_layout +install_layout + +echo "" +echo "Successfully installed!" +echo "You may need to logout or reboot before the layout will become available." +echo "" diff --git a/linux/uninstall.sh b/linux/uninstall.sh new file mode 100755 index 0000000..4cf2502 --- /dev/null +++ b/linux/uninstall.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +# +# Uninstalls the Graphite keyboard layout +# + +#set -x +set -e + +SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd) +XKB_DIR=/usr/share/X11/xkb +SYMBOLS_DIR=${XKB_DIR}/symbols +RULES_DIR=${XKB_DIR}/rules +EVDEV_XML=${RULES_DIR}/evdev.xml + +uninstall_layout() { + sed -i '/^\/\/---GRAPHITE BEGIN---/,/^\/\/---GRAPHITE END---/d' ${SYMBOLS_DIR}/us + echo "Removed Graphite layout symbols" + sed -i '/GRAPHITE BEGIN/,/GRAPHITE END/d' ${EVDEV_XML} + echo "Removed Graphite from xkb registry" +} + +verify_user_is_root() { + if [ ! "${EUID:-$(id -u)}" -eq 0 ]; then + echo "This script must unfortunately be run with sudo"; + exit 1 + fi +} + +verify_user_is_root +uninstall_layout From 5aee88288f4ef540d1b4c93d509d9188d46b3c70 Mon Sep 17 00:00:00 2001 From: Shawn Badger Date: Sat, 27 Jul 2024 11:28:06 -0600 Subject: [PATCH 2/2] Verify that xsltproc is available --- linux/install.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/linux/install.sh b/linux/install.sh index 948bc73..0644d9b 100755 --- a/linux/install.sh +++ b/linux/install.sh @@ -70,12 +70,20 @@ uninstall_layout() { verify_user_is_root() { if [ ! "${EUID:-$(id -u)}" -eq 0 ]; then - echo "This script must unfortunately be run with sudo"; + echo "This script must unfortunately be run with sudo" + exit 1 + fi +} + +verify_tools_available() { + if ! command -v xsltproc >/dev/null 2>&1; then + echo "This script requires that xsltproc is available. Please install it first." exit 1 fi } +verify_tools_available verify_user_is_root uninstall_layout install_layout