Skip to content

Commit

Permalink
Add the modifier() method.
Browse files Browse the repository at this point in the history
This includes being able to turn off the `timeout` and `doublePress`
by setting them to `-1`.
  • Loading branch information
lydell committed Sep 4, 2013
1 parent 19c495f commit 191ce66
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 15 deletions.
26 changes: 18 additions & 8 deletions dual.ahk
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class Dual {
this[keyState](keys, currentKey, lastKey)
}

comboKey(remappingKey="") {
comboKey(remappingKey=false) {
this.combo()

if (remappingKey == "") {
key := Dual.cleanKey(A_ThisHotkey)
} else {
if (remappingKey) {
key := remappingKey
} else {
key := Dual.cleanKey(A_ThisHotkey)
}
Dual.sendInternal(key)
}
Expand All @@ -52,7 +52,7 @@ class Dual {
; You want to to use just a control shortcut. So you release f. Even if the
; timout has not passed, we do not want the upKey of f to be sent now, causing
; control-f in effect (you still hold down d). That would be weird: It's like
; you've pressed the shortcut backwards, f-control, and it still works! So if
; you've pressed the shortcut backwards, f+control, and it still works! So if
; there is at least one other dual-role key that has been down for a shorter
; period of time than a just released dual-role key, return `false` to indicate
; that the upKey of the just released dual-role key shouldn't be sent.
Expand All @@ -62,7 +62,7 @@ class Dual {
; above, what if the delay of d hasn't passed yet? That means that you
; likely wanted to type fd, and typed that very quickly. You pressed down f,
; and before even releasing f you pressed d, which means that f was released
; while d was down. That usually means either control-f, or, if the delay
; while d was down. That usually means either control+f, or, if the delay
; hasn't passed, df. Therefore, in that case, we should _not_ return
; `false`. We _want_ the upKey of the just released dual-role to be sent.
}
Expand All @@ -83,6 +83,15 @@ class Dual {
return shorterTimeDownKeys
}

modifier(remappingKey=false) {
if (remappingKey) {
key := remappingKey
} else {
key := A_ThisHotkey
}
this.combine(key, key, {delay: 0, timeout: 0, doublePress: -1})
}

SendInput(string) {
this.SendAny(string, "input")
}
Expand Down Expand Up @@ -258,6 +267,7 @@ class Dual {

timeSinceLastUp := upKey.timeSinceLastUp()
if (timeSinceLastUp != false
and keys.doublePress != -1
and timeSinceLastUp <= keys.doublePress ; (*1)
and Dual.cleanKey(lastKey) == Dual.cleanKey(currentKey)) { ; (*2)
upKey.repeatMode := true
Expand All @@ -276,7 +286,7 @@ class Dual {
; Only send the actual key strokes if the timeout has passed, in order to support modifiers
; that do something when released, such as the alt and Windows keys. The comboKeys will
; force the downKey down, if they are combined before the timeout has passed.
downKey.down(downKey.timeDown() >= keys.timeout)
downKey.down(keys.timeout != -1 and downKey.timeDown() >= keys.timeout)
}

keyup(keys, currentKey, lastKey) {
Expand All @@ -289,7 +299,7 @@ class Dual {

; Determine if the upKey should be sent.
if (not downKey.combo
and (downKeyTimeDown < keys.timeout or keys.timeout == 0)
and (downKeyTimeDown < keys.timeout or keys.timeout == -1)
and not upKey.alreadySend) {
; Dual-role keys are automatically comboKeys.
shorterTimeDownKeys := this.combo(downKeyTimeDown)
Expand Down
58 changes: 51 additions & 7 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ An older version of Dual provided a method called `set()` instead of `combine()`
keys for you, using the `Hotkey` command. That was perhaps a bit more convenient (you didn't have to
write the key name twice for instance), but caused problems with other hotkeys.

`dual.comboKey(remappingKey="")`
--------------------------------
`dual.comboKey(remappingKey=false)`
-----------------------------------

The method is supposed to be called as such:

Expand Down Expand Up @@ -165,6 +165,46 @@ In fact, the `comboKey()` method (called without parameter) is roughly equivalen
dual.combo()
SendInput {Blind}%A_ThisHotkey%

`dual.modifier(remappingKey=false)`
-----------------------------------

The method is supposed to be called as such:

*ModifierName
*ModifierName UP::dual.modifier()

Let's say you want to press control+shift+a. You press down shift and then control, but then change
your mind: You only want to press control+a. So you release shift and then press a. No problems.

Now, let's say you had combined d and shift, and used that for the above. When you release d
(shift), and you do that before its timeout has passed, d will be sent, causing control+d!

You can solve this edge case by using the following:

*LCtrl::
*LCtrl UP::
*RCtrl::
*RCtrl UP::dual.modifier()

You can optionally remap just like the `comboKey()` method.

Note that if _only_ normal modifiers or _only_ dual-role keys are involved, this issue can never
occur.

This method also fixes another edge case. I don't think it's very useful, but it's there for
consistency. If you hold down for example d and then press a modifier, d will be sent, and it won't
start/continue to repeat. However, if d is a dual-role key, d would be modified. For example, if the
modifier in question is shift, D would be sent. That's like doing it backwards, d+shift, and it
still works! `dual.modifier()` takes care of this too.

Implementation note: This method actually turns things into dual-role keys with the same downKey and
upKey! The above example is actually equivalent to:

*LCtrl::
*LCtrl UP::
*RCtrl::
*RCtrl UP::dual.combine(A_ThisHotkey, A_ThisHotkey, {delay: 0, timeout: 0, doublePress: -1})

`dual.Send(string)`
-------------------

Expand All @@ -183,14 +223,16 @@ configuration.

settings := {delay: 70, timeout: 300, doublePress: 200}

`delay` is the number of milliseconds that you must hold a dual-role key in order for it to
count as a combination with another key (comboKeys only, though).
`delay` is the number of milliseconds that you must hold a dual-role key in order for it to count as
a combination with another key (comboKeys only, though). Set it to `0` to turn off the feature (of
course).

`timeout` is the number of milliseconds after which the downKey starts to be sent, and the
upKey won't be sent.
upKey won't be sent. Set it to `-1` to turn the feature off—to never timeout.

`doublePress` is the maximum number of milliseconds that can elapse between a release of a
dual-role key and its next press and still be called a doublePress.
`doublePress` is the maximum number of milliseconds that can elapse between a release of a dual-role
key and its next press and still be called a doublePress. Set it to `-1` to disable doublePress-ing,
and thus repetition.

_comboKeys_ are keys that enhance the accuracy of the dual-role keys. They can be set as such:

Expand Down Expand Up @@ -293,6 +335,8 @@ Changelog
and encourages changing the settings before setting up dual-role keys. (Backwards incompatible
change.)
- Improved: Re-factored some code.
- Added: The `modifier()` method.
- Improved: The `timeout` and `doublePress` can be turned off, by setting them to `-1`.

0.3.2 (2013-09-01)
------------------
Expand Down

0 comments on commit 191ce66

Please sign in to comment.