Hammerspoon: Modifier key doesn't get released

Created on 1 Oct 2016  Â·  10Comments  Â·  Source: Hammerspoon/hammerspoon

I'm binding my Harmony Hub keyboard commands to Plex shortcuts.

I simply to this to bind F7 to command+L (next subtitle):

hs.hotkey.bind({}, "f7", function()
    hs.eventtap.keyStroke({"cmd"}, "L")
end)

But it seems that the command key doesn't get released, since Plex keeps on switching subtitles. (just like when I manually press command+L on my keyboard and then release the L key while keeping the command key pressed).

Most helpful comment

As to the sluggishness for repeats, that was introduced to address another issue where the up and down events were coming in too fast for some particular use (I don't recall the particulars). But the hs.eventtap.keyStroke function is really just a wrapper to another function, you can easily write your own to fit your needs:

myDoKeyStroke = 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

will revert back to the previous version. You can add a hs.timer.usleep(#) in between the two newKeyEvent lines if you find that you do need a delay, just not the one that is currently hard-coded.

A future update should make the current delay in hs.eventtap.keyStroke of 200000 ms user adjustable, but there are other things that need to be adjusted within the module as well, so I don't have a time frame yet...

All 10 comments

I would generally always recommend using the releasedfn parameter of hs.hotkey.bind() rather than the pressedfn one, when you're emitting events. So, add a nil argument before your function.

Having said that, I did notice that the hs.eventtap.keyStroke() function doesn't wait between posting its keydown and keyup events, which may be related. The next release will wait 200ms between each event. If changing to releasedfn doesn't help, hopefully this delay, will :)

I'll go ahead and close this Issue for now, but please feel free to re-open it if it's not fixed after the next release is out.

Hey @cmsj, I noticed this change after updating to the latest release (0.9.49). Now hs.eventtap.keyStroke events are delayed, and delays during key-repeats (key being held down) are very noticeable. Is there a way to disable this behavior?

Here's my particular use case. I have assigned hotkeys to the ctrl+h/j/k/l, so that pressing them moves left/down/up/right, just like in Vim. Now with the delay, this mapping feels much more laggy.

Here's my lua:

local move = function(direction) hs.eventtap.keyStroke({}, direction) end
local moveLeft = function() move("left") end
local moveDown = function() move("down") end
local moveUp = function() move("up") end
local moveRight = function() move("right") end

function mod.init()
    hs.hotkey.bind({"ctrl"}, "h", moveLeft, nil, moveLeft)
    hs.hotkey.bind({"ctrl"}, "j", moveDown, nil, moveDown)
    hs.hotkey.bind({"ctrl"}, "k", moveUp, nil, moveUp)
    hs.hotkey.bind({"ctrl"}, "l", moveRight, nil, moveRight)
end

Thanks!

Hi, thanks for your suggestions! Just dropping by to provide some feedback. I've updated the app and I'm also using releasedfn, but neither seem to fix this problem unfortunately. I'm thinking the modifier key never gets released, is there any way to test this theory?

Not sure about the modifier not being released... the first suggestion about attaching to the key release function of hs.hotkey, rather than the key down function, has always fixed issues like that for me. You can add a line like print(hs.inspect(hs.eventtap.checkKeyboardModifiers())) to the end of the keybinding function to check the state of the keyboard modifiers immediately after the keystroke line, like this:

hs.hotkey.bind({}, "f7", nil, function()
    hs.eventtap.keyStroke({"cmd"}, "L")
    print(hs.inspect(hs.eventtap.checkKeyboardModifiers()))
end)

It should log the following to the hammerspoon console:

{
  fn = true
}

Which indicates that only the fn modifier is in effect... which is an odd modifier that shows up when you press the fn key on your laptop keyboard, but also when you use certain other keys like arrow keys, page-up/down, F1-F12, etc... basically, it means things are working correctly and the "cmd" modifier was in fact released.

As to the sluggishness for repeats, that was introduced to address another issue where the up and down events were coming in too fast for some particular use (I don't recall the particulars). But the hs.eventtap.keyStroke function is really just a wrapper to another function, you can easily write your own to fit your needs:

myDoKeyStroke = 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

will revert back to the previous version. You can add a hs.timer.usleep(#) in between the two newKeyEvent lines if you find that you do need a delay, just not the one that is currently hard-coded.

A future update should make the current delay in hs.eventtap.keyStroke of 200000 ms user adjustable, but there are other things that need to be adjusted within the module as well, so I don't have a time frame yet...

Ok, I've cleared my entire config and pasted in the code that you provided, the console showed:

{
  cmd = true,
  ["⌘"] = true
}

I even put the inspect inside a 10 second doAfter timer, and it still showed the same output. Also tried it with different modifiers, same result (but with shift/alt = true etc.).

The only way I can replicate your results is if Accessibility is disabled for Hammerspoon. Type the following into your Hammerspoon console to check: hs.accessibilityState(true)

If it is in fact disabled, then a dialog will appear and you should click on "Open System Preferences" and it will take you to the Privacy tab of the Security & Privacy preferences panel. Click on the lock at the bottom, enter your password, and then place a checkmark next to the Hammerspoon icon. Then quit and restart Hammerspoon.

If it isn't disabled (i.e. you get the result of true to the hs.accessibilityState(true) command, then I'm not sure... you'll need to post your full init.lua file so I can review it.

hs.accessibilityState(true) returns true and the Accessibility settings are set correctly. You can download my init.lua.zip, but it also happens when removing everything but this:

hs.hotkey.bind({}, "f7", nil, function()
    hs.eventtap.keyStroke({"cmd"}, "L")
end)

Since accessibility is enabled, I'm at a loss... I'll review your init.lua, but if as you say it also fails when that's the extent of your init.lua, then I doubt I'll see anything that jumps out at me... what else do you have enabled in the Accessibility pane of Security & Privacy that might be intercepting/modifying events? And I guess, just in case it suggest anything to anyone, what Mac and OS are you running? Is this on an external USB or bluetooth keyboard?

I admit I'm reaching a bit here, but if we can narrow it down to a specific setup or a specific interaction with another application then we can maybe work around it or at least include it in the known issues...

Yeah it's strange. The device is a Logitech Harmony Hub that connects over Bluetooth (it's not actually a real keyboard, but it can send keyboard commands).

I'm running the latest version of OSX Sierra on a Late 2012 Mac Mini. Nothing else is enabled in the Accessibility pane.

As you can see in my init.lua, I added a quickfix:

hs.timer.doAfter(0, function()
    hs.eventtap.keyStroke({"shift"}, "")
end)

This seems to force the command key to get released, maybe this gives you a clue what could cause this?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

latenitefilms picture latenitefilms  Â·  3Comments

asmagill picture asmagill  Â·  4Comments

jasonrudolph picture jasonrudolph  Â·  4Comments

lazandrei19 picture lazandrei19  Â·  4Comments

iliyang picture iliyang  Â·  4Comments