New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to specific layout on command left key press only? #1039

Closed
piskov opened this Issue Oct 11, 2016 · 4 comments

Comments

Projects
None yet
3 participants
@piskov

piskov commented Oct 11, 2016

Since Karabiner is down in Siera a lot of us stuck with switching between keyboard layouts using ugly ctlr+space.

Is it possible in hammerspoon to do the following:

  1. On left command key press switch to “en” keyboard layout
  2. On right command key press switch to another, e. g. “ru” keyboard layout.

I’ve tried to do the following:

hs.hotkey.bind(nil, 58, function()
    hs.keycodes.setLayout("Russian - Ilya Birman Typography")
end)


hs.hotkey.bind(nil, 61, function()
    hs.keycodes.setLayout("English - Ilya Birman Typography")
end)

… but it’s not working. 58 and 61 are codes for left and right alts (since I don’t know the correct codes for left and right command). And the layout names are correct of what layouts are installed on my mac.

@asmagill

This comment has been minimized.

Show comment
Hide comment
@asmagill

asmagill Oct 11, 2016

Member

You can't bind just a modifier as a hotkey, but you can use the eventtap module... something like this would probably work:

layoutWatcher = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, function(e)
    local flags = e:getFlags()
    if flags.cmd and not (flags.alt or flags.shift or flags.ctrl or flags.fn) then
        local keyCode = e:getKeyCode()
        if keyCode == 0x37 then
            print("~~ left cmd key")
        elseif keyCode == 0x36 then
            print("~~ right cmd key")
        end
    end    
end):start()
Member

asmagill commented Oct 11, 2016

You can't bind just a modifier as a hotkey, but you can use the eventtap module... something like this would probably work:

layoutWatcher = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, function(e)
    local flags = e:getFlags()
    if flags.cmd and not (flags.alt or flags.shift or flags.ctrl or flags.fn) then
        local keyCode = e:getKeyCode()
        if keyCode == 0x37 then
            print("~~ left cmd key")
        elseif keyCode == 0x36 then
            print("~~ right cmd key")
        end
    end    
end):start()
@asmagill

This comment has been minimized.

Show comment
Hide comment
@asmagill

asmagill Oct 11, 2016

Member

Thinking about it, though, you'll probably want to set up a timer and make sure that no key press or flag changes occur within a specific timeout to make sure that the cmd key is just the command key and not part of a key-sequence (like cmd-Q, etc.)

I do something like that in this file here which checks to see if a command key is pressed and held to display a cheatsheet like display: https://github.com/asmagill/hammerspoon-config/blob/master/utils/_keys/cheatsheet.lua#L253

Member

asmagill commented Oct 11, 2016

Thinking about it, though, you'll probably want to set up a timer and make sure that no key press or flag changes occur within a specific timeout to make sure that the cmd key is just the command key and not part of a key-sequence (like cmd-Q, etc.)

I do something like that in this file here which checks to see if a command key is pressed and held to display a cheatsheet like display: https://github.com/asmagill/hammerspoon-config/blob/master/utils/_keys/cheatsheet.lua#L253

@piskov piskov closed this Oct 12, 2016

@piskov

This comment has been minimized.

Show comment
Hide comment
@piskov

piskov Oct 13, 2016

Skipped timer alltogether by adding couple of variables. Changes language on command KeyUp event, but only if nothing happened after command KeyDown (e. g. another key press, mouse click, scroll, etc.)

No previous Lua or Hammerspoon experience whatsoever, so may contain bugs or be not very optimised.

local module = {}
module.showPopUp = false
module.leftCmdLayout = "English - Ilya Birman Typography"
module.rightCmdLayout = "Russian - Ilya Birman Typography"


module.eventwatcher1 = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, function(e)

    local flags = e:getFlags()

    if flags.cmd
       and not (flags.alt or flags.shift or flags.ctrl or flags.fn)
    then
        module.cmdWasPressed = true
        module.cmdShouldBeIgnored = false
        return false;
    end

    if flags.cmd
       and (flags.alt or flags.shift or flags.ctrl or flags.fn)
       and module.cmdWasPressed
    then
        module.cmdShouldBeIgnored = true
        return false;
    end

    if not flags.cmd
    then
        if module.cmdWasPressed
       and not module.cmdShouldBeIgnored
        then
            local keyCode = e:getKeyCode()

            if keyCode == 0x37 then
                hs.keycodes.setLayout(module.leftCmdLayout)

        if module.showPopUp then
            hs.alert.show("English", 0.2)
        end

        elseif keyCode == 0x36 then
        hs.keycodes.setLayout(module.rightCmdLayout)

        if module.showPopUp then
            hs.alert.show("Russian", 0.2)
        end
        end
    end

    module.cmdWasPressed = false
    module.cmdShouldBeIgnored = false
    end

    return false;
end):start()


module.eventwatcher2 = hs.eventtap.new({"all", hs.eventtap.event.types.flagsChanged}, function(e)

    local flags = e:getFlags()

    if flags.cmd and module.cmdWasPressed then
    module.cmdShouldBeIgnored = true
    end

    return false;
end):start()

piskov commented Oct 13, 2016

Skipped timer alltogether by adding couple of variables. Changes language on command KeyUp event, but only if nothing happened after command KeyDown (e. g. another key press, mouse click, scroll, etc.)

No previous Lua or Hammerspoon experience whatsoever, so may contain bugs or be not very optimised.

local module = {}
module.showPopUp = false
module.leftCmdLayout = "English - Ilya Birman Typography"
module.rightCmdLayout = "Russian - Ilya Birman Typography"


module.eventwatcher1 = hs.eventtap.new({hs.eventtap.event.types.flagsChanged}, function(e)

    local flags = e:getFlags()

    if flags.cmd
       and not (flags.alt or flags.shift or flags.ctrl or flags.fn)
    then
        module.cmdWasPressed = true
        module.cmdShouldBeIgnored = false
        return false;
    end

    if flags.cmd
       and (flags.alt or flags.shift or flags.ctrl or flags.fn)
       and module.cmdWasPressed
    then
        module.cmdShouldBeIgnored = true
        return false;
    end

    if not flags.cmd
    then
        if module.cmdWasPressed
       and not module.cmdShouldBeIgnored
        then
            local keyCode = e:getKeyCode()

            if keyCode == 0x37 then
                hs.keycodes.setLayout(module.leftCmdLayout)

        if module.showPopUp then
            hs.alert.show("English", 0.2)
        end

        elseif keyCode == 0x36 then
        hs.keycodes.setLayout(module.rightCmdLayout)

        if module.showPopUp then
            hs.alert.show("Russian", 0.2)
        end
        end
    end

    module.cmdWasPressed = false
    module.cmdShouldBeIgnored = false
    end

    return false;
end):start()


module.eventwatcher2 = hs.eventtap.new({"all", hs.eventtap.event.types.flagsChanged}, function(e)

    local flags = e:getFlags()

    if flags.cmd and module.cmdWasPressed then
    module.cmdShouldBeIgnored = true
    end

    return false;
end):start()
@stepango

This comment has been minimized.

Show comment
Hide comment
@stepango

stepango Jan 25, 2018

https://gist.github.com/stepango/3b7dda91c8ab82ec88a14a3ef89a296a

ctrlPressed = false
keyPressed = false

layoutWatcher = hs.eventtap.new({hs.eventtap.event.types.flagsChanged, hs.eventtap.event.types.keyUp}, function(e)
    local flags = e:getFlags()
    local keyCode = e:getKeyCode()
    if flags.cmd and keyCode == 0x36 and not (flags.alt or flags.shift or flags.ctrl or flags.fn) then
        ctrlPressed = true
        keyPressed = false
    elseif ctrlPressed and not (flags.cmd or flags.alt or flags.shift or flags.ctrl or flags.fn) and not keyPressed then
        ctrlPressed = false
        if keyCode == 0x36 then
            local lay = hs.keycodes.currentLayout()
            if lay == "U.S." then
              hs.keycodes.setLayout("Russian")
            else
              hs.keycodes.setLayout("U.S.")
            end
        end
    else
        keyPressed = true
    end
end):start()

stepango commented Jan 25, 2018

https://gist.github.com/stepango/3b7dda91c8ab82ec88a14a3ef89a296a

ctrlPressed = false
keyPressed = false

layoutWatcher = hs.eventtap.new({hs.eventtap.event.types.flagsChanged, hs.eventtap.event.types.keyUp}, function(e)
    local flags = e:getFlags()
    local keyCode = e:getKeyCode()
    if flags.cmd and keyCode == 0x36 and not (flags.alt or flags.shift or flags.ctrl or flags.fn) then
        ctrlPressed = true
        keyPressed = false
    elseif ctrlPressed and not (flags.cmd or flags.alt or flags.shift or flags.ctrl or flags.fn) and not keyPressed then
        ctrlPressed = false
        if keyCode == 0x36 then
            local lay = hs.keycodes.currentLayout()
            if lay == "U.S." then
              hs.keycodes.setLayout("Russian")
            else
              hs.keycodes.setLayout("U.S.")
            end
        end
    else
        keyPressed = true
    end
end):start()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment