axsuul
axsuul

Reputation: 7490

Key repeats are delayed in my Hammerspoon script

I have my CAPSLOCK bound to F18 (karabiner) to act as a modifier key. I'm trying to simulate CAPSLOCK+h, j, k, l to act as VIM movement keys. Everything works but there's an issue with delay when repeating. That is, it's very slow when I press down the CAPSLOCK+h which should simulate pressing the "<-" key repeatedly but it's very delayed and only sends one per second. Any ideas on why that's happening? My init.lua is below:

-- A global variable for the Hyper Mode
k = hs.hotkey.modal.new({}, "F17")

-- Enter Hyper Mode when F18 (Hyper/Capslock) is pressed
pressedF18 = function()
  k.triggered = false
  k.modifier = false
  k:enter()

  trigger_modifier = function()
    k.modifier = true
  end

  -- Only trigger as modifier if held longer than thisj
  hs.timer.doAfter(0.35, trigger_modifier)
end

-- Arrow keys
k:bind({}, 'h', function()
  hs.eventtap.keyStroke({}, 'Left')
  k.triggered = true
end)

k:bind({}, 'j', function()
  hs.eventtap.keyStroke({}, 'Down')
  k.triggered = true
end)

k:bind({}, 'k', function()
  hs.eventtap.keyStroke({}, 'Up')
  k.triggered = true
end)

k:bind({}, 'l', function()
  hs.eventtap.keyStroke({}, 'Right')
  k.triggered = true
end)

-- Leave Hyper Mode when F18 (Hyper/Capslock) is pressed,
--   send ESCAPE if no other keys are pressed.
releasedF18 = function()
  k:exit()

  if not k.triggered then
    -- If hotkey held longer than this amount of time
    -- let it remain as modifier and don't send ESCAPE
    if not k.modifier then
      hs.eventtap.keyStroke({}, 'ESCAPE')
    else
      print("Modifier detected")
    end
  end
end

-- Bind the Hyper key
f18 = hs.hotkey.bind({}, 'F18', pressedF18, releasedF18)

Upvotes: 6

Views: 1971

Answers (1)

Elliot DeNolf
Elliot DeNolf

Reputation: 2999

I had some similar slowness. It looks like there was some slowness introduced in one of the latest versions. You can call the lower level function using the fastKeyStroke function below. I've included my hjkl implementation so you can see it used. Also note that I'm passing 5 parameters into hs.hotkey.bind as specified in the docs for key repeating.

local hyper = {"shift", "cmd", "alt", "ctrl"}

local fastKeyStroke = function(modifiers, character)
  local event = require("hs.eventtap").event
  event.newKeyEvent(modifiers, string.lower(character), true):post()
  event.newKeyEvent(modifiers, string.lower(character), false):post()
end

hs.fnutils.each({
  -- Movement
  { key='h', mod={}, direction='left'},
  { key='j', mod={}, direction='down'},
  { key='k', mod={}, direction='up'},
  { key='l', mod={}, direction='right'},
  { key='n', mod={'cmd'}, direction='left'},  -- beginning of line
  { key='p', mod={'cmd'}, direction='right'}, -- end of line
  { key='m', mod={'alt'}, direction='left'},  -- back word
  { key='.', mod={'alt'}, direction='right'}, -- forward word
}, function(hotkey)
  hs.hotkey.bind(hyper, hotkey.key, 
      function() fastKeyStroke(hotkey.mod, hotkey.direction) end,
      nil,
      function() fastKeyStroke(hotkey.mod, hotkey.direction) end
    )
  end
)

Source about the slowness

Upvotes: 8

Related Questions