Last active
September 22, 2020 18:27
-
-
Save salewski/abc0c9dfc6657fec4bcadc55fc5c0017 to your computer and use it in GitHub Desktop.
invoked by inputplug(1) to respond to device add/remove events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash - | |
# SPDX-FileCopyrightText: <text> © 2020 Alan D. Salewski <[email protected]> </text> | |
# | |
# SPDX-License-Identifier: GPL-2.0-or-later | |
# on-new-kbd: Applies a canned X11 keyboard config, when invoked. | |
# | |
# Intended to be invoked by the inputplug(1) daemon, in response to | |
# devices being added/removed, enabled/disabled, etc. | |
# | |
# As featured in the article: | |
# | |
# "Left-hand ENTER key" | |
# by Alan D. Salewski | |
# 2020-09-22 | |
# https://salewski.github.io/2020/09/22/left-hand-enter-key.html | |
# | |
# | |
# Usage: | |
# ------ | |
# | |
# For interactive testing, do this: | |
# | |
# $ inputplug -d -c /path/to/on-new-kbd | |
# | |
# As part of your X11 startup process, add the following to your | |
# ~/.xsession (note: no '-d' opt -- will run as daemon, not in | |
# foreground): | |
# | |
# inputplug -c /path/to/on-new-kbd | |
# | |
# Output will be written to the location in hard-coded in $MY_LOG_FPATH | |
# below. | |
# | |
# Motivation: | |
# ----------- | |
# In X11, keyboard settings get applied only to the devices attached to | |
# the sytem when the settings are applied. If, for example, a USB | |
# keyboard is unplugged and then re-plugged, it will get default | |
# settings, not the override settings that we would have applied during | |
# X11 initialization. | |
# | |
# Because 'inputplug' monitors the system for XInput events, it can | |
# determine when a new device has been (re)added to the system. It | |
# invokes this program with the event metadata, which gives a chance to | |
# (re)apply our override settings. | |
# | |
# Attribution: | |
# ------------ | |
# Adapted from the approach suggested by unix.stackexchange.com user | |
# 'mosvy'[0] in the comment: | |
# | |
# https://unix.stackexchange.com/a/523959 | |
# | |
# Top-level of that thread: | |
# | |
# "Prevent keyboard layout reset when USB keyboard is plugged in" | |
# https://unix.stackexchange.com/questions/523635/prevent-keyboard-layout-reset-when-usb-keyboard-is-plugged-in | |
# | |
# [0] https://unix.stackexchange.com/users/308316/mosvy | |
# | |
# On Debian-based systems, the 'inputplug' program is supplied by the | |
# 'inputplug' Debian package. | |
declare -r PROG='on-new-kbd' | |
declare -r MY_LOG_DIR="${HOME}/var/log/${PROG}" | |
declare -r MY_LOG_FPATH="${MY_LOG_DIR}/${PROG}.log" | |
declare -r PROG_FOR_EVT_SLAVE_KEYBOARD_ENABLED="${HOME}/bin/ads-keyboard-setup" | |
if test -e "${MY_LOG_DIR}"; then :; else | |
mkdir -p "${MY_LOG_DIR}" | |
if test $? -ne 0; then | |
printf "${PROG} (error): was unable to create log directory: %s; bailing out\n" \ | |
"${MY_LOG_DIR}" 1>&2 | |
exit 1 | |
fi | |
fi | |
dt_now=$(date --rfc-3339 seconds) | |
if test $? -ne 0; then | |
printf "${PROG} (error): was unable to obtain the current date and time; bailing out\n" 1>&2 | |
exit 1 | |
fi | |
printf "${dt_now} ${PROG} (info): program started\n" | tee -a "${MY_LOG_FPATH}" | |
if test -x "${PROG_FOR_EVT_SLAVE_KEYBOARD_ENABLED}"; then :; else | |
printf "${dt_now} ${PROG} (error): no such program %s; bailing out" \ | |
"${PROG_FOR_EVT_SLAVE_KEYBOARD_ENABLED}" \ | |
| tee -a "${MY_LOG_FPATH}" 1>&2 | |
exit 1 | |
fi | |
# When invoked by 'inputplug', four command line parameters will be | |
# provided: | |
# | |
# event-type device-id device-type device-name | |
# | |
# See inputplug(1) for details. | |
if test $# -lt 4; then | |
printf "${dt_now} ${PROG} (error): expected 4 params, but got only %d; bailing out" "$#" \ | |
| tee -a "${MY_LOG_FPATH}" 1>&2 | |
exit 1 | |
fi | |
event_type=$1 | |
device_id=$2 | |
device_type=$3 | |
device_name=$4 | |
# No sanity checking of above parameters, since we do not know exactly | |
# what to expect. We do know that sometimes some of the values will | |
# legitimately be unset or null. We emit a report of what we received, | |
# and only respond to a tiny subset of the input that we recognize as an | |
# actionable for us. | |
# Examples: | |
# ========= | |
# | |
# Note that we get two different events when we unplug the keyboard, and | |
# two different events when we plug the keyboard back in. | |
# | |
# Unplug events: | |
# | |
# ----------------------------------------------- | |
# event_type: XIDeviceDisabled XIDeviceDisabled | |
# device_id: 10 10 | |
# device_type: XISlaveKeyboard XISlaveKeyboard | |
# device_name: is_unset_or_null | |
# ----------------------------------------------- | |
# event_type: XISlaveRemoved XISlaveRemoved | |
# device_id: 10 10 | |
# device_type: is_unset_or_null | |
# device_name: is_unset_or_null | |
# ----------------------------------------------- | |
# | |
# | |
# Plug event: | |
# | |
# ----------------------------------------------- | |
# event_type: XISlaveAdded XISlaveAdded | |
# device_id: 10 10 | |
# device_type: XIFloatingSlave XIFloatingSlave | |
# device_name: Microsoft Natural Keyboard Elite Microsoft Natural Keyboard Elite | |
# ----------------------------------------------- | |
# event_type: XIDeviceEnabled XIDeviceEnabled | |
# device_id: 10 10 | |
# device_type: XISlaveKeyboard XISlaveKeyboard | |
# device_name: Microsoft Natural Keyboard Elite Microsoft Natural Keyboard Elite | |
# ----------------------------------------------- | |
cat - <<EOF | tee -a "${MY_LOG_FPATH}" 1>&2 | |
${dt_now} ----------------------------------------------- | |
${dt_now} event_type: ${event_type:-is_unset_or_null} ${event_type-is_unset} | |
${dt_now} device_id: ${device_id:-is_unset_or_null} ${device_id-is_unset} | |
${dt_now} device_type: ${device_type:-is_unset_or_null} ${device_type-is_unset} | |
${dt_now} device_name: ${device_name:-is_unset_or_null} ${device_name-is_unset} | |
${dt_now} ----------------------------------------------- | |
EOF | |
case "${event_type} ${device_type}" in | |
'XIDeviceEnabled XISlaveKeyboard') | |
printf "${dt_now} ${PROG} (info): slave keyboard enabled; running config script\n" \ | |
| tee -a "${MY_LOG_FPATH}" 1>&2 | |
"${PROG_FOR_EVT_SLAVE_KEYBOARD_ENABLED}" 2>&1 | tee -a "${MY_LOG_FPATH}" 1>&2 | |
if test $? -ne 0; then | |
printf "${dt_now} ${PROG} (error): ads-keyboard-setup failed; bailing out" \ | |
| tee -a "${MY_LOG_FPATH}" 1>&2 | |
exit 1 | |
fi | |
;; | |
*) | |
printf "${dt_now} ${PROG} (info): uninteresting event; ignoring (okay)\n" \ | |
| tee -a "${MY_LOG_FPATH}" 1>&2 | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment