Permalink
Browse files

keyboard: turn down key repeat before going to lock screen

As mentioned here:

    https://twitter.com/wincent/status/1068234903811223552

Going to see if this can cure my lock screen woes. You can turn off key
repeat with:

    defaults write -g KeyRepeat 300000

But you have to log out for it to take effect. I did some reverse
engineering and header-file searching to figure out how:

    /System/Library/PreferencePanes/Keyboard.prefPane/Contents/MacOS/Keyboard

Is forcing the changes to take effect immediately, and discovered some
deprecated (sigh) APIs that hopefully will continue to exist for a
while:

    NXSetKeyRepeatInterval()
    NXKeyRepeatInterval()
    NXOpenEventStatus()

I bundled these up in a `dry` executable (short for "Don't Repeat
Yourself") that can be used to set the key repeat delay in seconds. Not
building or installing this automatically yet so that I can test it.

Calling `dry` from the `karabiner-kill` and `karabiner-boot` scripts,
and also switched to from running on systemWillSleep to screensDidLock,
which allows us to cover both normal screen saver and sleep events with
a single branch.
  • Loading branch information...
wincent committed Nov 30, 2018
1 parent 2c9c491 commit 46835b274a32f084f8bf53d32b9995a06d74936d
@@ -19,7 +19,7 @@ return {
init = (function()
local watcher = hs.caffeinate.watcher.new(
function(event)
if event == hs.caffeinate.watcher.systemWillSleep then
if event == hs.caffeinate.watcher.screensDidLock then
disable()
elseif event == hs.caffeinate.watcher.screensDidUnlock then
enable()
@@ -6,6 +6,10 @@ if [ -z "$UID" ]; then
UID=$(id -u)
fi
# In Hammerspoon, $PATH will be too minimal(/usr/bin:/bin:/usr/sbin:/sbin)
# to find the `dry` executable.
PATH=$PATH:$HOME/bin
# Depends on /private/etc/sudoers.d/karabiner-sudoers:
sudo launchctl load /Library/LaunchDaemons/org.pqrs.karabiner.karabiner_grabber.plist
sudo launchctl load /Library/LaunchDaemons/org.pqrs.karabiner.karabiner_observer.plist
@@ -14,4 +18,9 @@ launchctl enable gui/"$UID"/org.pqrs.karabiner.karabiner_console_user_server
launchctl bootstrap gui/"$UID" /Library/LaunchAgents/org.pqrs.karabiner.karabiner_console_user_server.plist
launchctl enable gui/"$UID"/org.pqrs.karabiner.karabiner_console_user_server
# Turn key repeat back on:
if command -v dry &> /dev/null; then
dry 0.033333 > /dev/null
fi
echo "🐣 Karabiner-Elements bootstrapped"
@@ -6,6 +6,15 @@ if [ -z "$UID" ]; then
UID=$(id -u)
fi
# In Hammerspoon, $PATH will be too minimal(/usr/bin:/bin:/usr/sbin:/sbin)
# to find the `dry` executable.
PATH=$PATH:$HOME/bin
# For good measure, turn off key repeat:
if command -v dry &> /dev/null; then
dry 300 > /dev/null
fi
launchctl bootout gui/"$UID" /Library/LaunchAgents/org.pqrs.karabiner.karabiner_console_user_server.plist
launchctl disable gui/"$UID"/org.pqrs.karabiner.karabiner_console_user_server
@@ -0,0 +1 @@
/dry
@@ -0,0 +1,12 @@
PREFIX ?= $(HOME)
CFLAGS := -ansi -pedantic -Wall -Wextra ${CFLAGS}
dry: main.c
${CC} ${CFLAGS} \
-framework CoreFoundation \
-framework CoreServices \
-framework IOKit \
-o dry main.c
install:
install -m755 dry ${PREFIX}/bin
@@ -0,0 +1,36 @@
/*
* dry (Don't Repeat Yourself)
*
* Usage: `dry 300`
*
* Sets the key repeat interval without requiring a logout.
*/
#include <stdio.h>
#include <stdlib.h>
#include <IOKit/hidsystem/event_status_driver.h>
int main(int argc, const char * argv[]) {
NXEventHandle handle;
double interval;
if (argc != 2) {
printf("Expected 1 argument (key repeat in seconds); got %d\n", argc - 1);
return EXIT_FAILURE;
}
handle = NXOpenEventStatus();
if (!handle) {
perror("NXOpenEventStatus");
return EXIT_FAILURE;
}
interval = NXKeyRepeatInterval(handle);
printf("Old interval: %lf\n", interval);
sscanf(argv[1], "%lf", &interval);
printf("New interval: %lf\n", interval);
NXSetKeyRepeatInterval(handle, interval);
return 0;
}

0 comments on commit 46835b2

Please sign in to comment.