snyball/hawck

Support multipurpose keys with time threshold

dit7ya opened this issue · 2 comments

Support modifying any key as a modifier as well as normal as in mooz/xkeysnail: Yet another keyboard remapping tool for X environment.

Another option that would be crucial here is to define a time threshold - when I press a key that is defined as both a modifier and a regular one, activate it as a modifier only when it is held down for longer than the threshold time. This is important otherwise you end up with wrong inputs if you are a type reasonably fast.

This has been asked before: #8

It's possible, but because of an unimplemented feature (passthrough scripts that can be pipelined,) the solution is a bit iffy for now.

-- Note: because of how this is implemented, it needs to be put in a separate script,
-- and needs to be the first script to run.
-- It also requires you to enable unsafe mode, as it needs to receive all keyboard input
-- to work.
caps_down = false
caps_as_ctrl = false
up + key "caps" => function ()
  caps_down = false
  if not caps_as_ctrl then
    kbd:press("caps")
  else
    kbd:up("control")
  end
  caps_as_ctrl = false
end

down + key "caps" => function ()
  caps_down = true
  caps_as_ctrl = false
end

-- Redefine ctrl to take our magic caps-lock key into account.
-- This is the thing pipelining of scripts would simplify.
ctrl = (ctrl / Cond.new(function ()
  return caps_down and caps_as_ctrl
end))

down => {
  -- ... put the rest of your bindings here, inside down {}, but before any{} ...

  -- This would not have worked with caps+k, if the binding was set in a
  -- different script, because there's no pipelining, the scripts always
  -- get raw unmodified input from the physical keyboards.
  ctrl + key "k" => say "something"

  -- We have to let the scripts read all keyboard input for this, not ideal for
  -- such an important feature. This should happen in a sandbox running
  -- inside hawck-inputd rather than hawck-macrod.
  any => function ()
    if caps_down and not caps_as_ctrl then
      kbd:down("control")
      caps_as_ctrl = true
    end
    kbd:echo()
  end
}

Another feature standing in the way of this being shipped with hawck by default, is inputd scripts, i.e scripts that run inside a sandbox, so that they don't need whitelisting of keys.

But it should work, also note that this solution doesn't use any timing (that's left as an exercise to the reader.)

EDIT: Should have been ctrl / Cond.new(...) (/ is OR) not ctrl + Cond.new(...).

Reopening this so you can tell me whether or not that code works, or if you were able to improve on it with the timing features you needed.