7

I have a Windows 10 laptop with a keyboard designed by idiots. They tried to cram the arrow keys where they don't belong, with the result that the up arrow key is between the right shift key and the / key (US keyboard layout). This is one of the stupidest things the designers could have done, because it means that when I go to hit the right shift key (which is most of the time), I end up hitting up arrow instead. This is incredibly annoying.

I found a program called Sharp Keys which allows me to remap the keys such that the up arrow behaves as shift and the right shift behaves as up arrow. Now, at least I can type. However, I've now lost important functionality for the up arrow key. Up arrow (now labeled "shift" on my keyboard) doesn't repeat. So, I can't just hold the key down to move up. Instead, I have to hit the key repeatedly. How can I fix this, so my right shift key behaves like up arrow and my up arrow key behaves like right shift ?

EDIT

Following a suggestion from the comments, I installed AutoHotkey. I have the following script:

RShift::Up
Up::RShift

I have the same problem as earlier. But, since AHK is a scripting language, is it possible to use it to change the repeat behavior?

phuclv
  • 30,396
  • 15
  • 136
  • 260

3 Answers3

2

I tried the hotkeys you listed... they worked fine for me and repeated automatically just fine when held down...

#Persistent
Return

#IfWinActive    ; Make replacement operate globally
RShift::Up
Up::RShift

You may be able to try a different SendMode...

RShift::SendInput {Up}
Up::SendInput {RShift}

or...

RShift::SendPlay {Up}
Up::SendPlay {RShift}

Do you have any other programs that are intercepting these or anything like that? Does the key repeat work normally when the script isn't running?

Setting up a custom loop might look something like this...

RShift::
    While GetKeyState("RShift", "P") {
        Send {Up}
        Sleep 50    ; Set delay to taste
    }
Return

EDIT

To address the need for other modifiers to work, a '*' may be used with the hotkey, although in the case of having two shift keys it may not work correctly by default. I've added a special case for the shift key detection but I don't know how that would work if you were to throw other modifiers into the mix... in that case you could look at adding the {blind} modifier to the Send statements to see if you could get it to work properly.

To address the 'race condition' another pre-repeat delay can also be added before the repeat loop along with an initial send statement (see below).

*Up::SendInput {blind}{RShift Down}
*Up Up::SendInput {blind}{RShift Up}

*RShift::
    Send % GetKeyState("LShift", "P") ? "+{Up}" : "{Up}"
    Sleep 250           ; Initial delay before repeat
    While GetKeyState("RShift", "P") {
        Send % GetKeyState("LShift", "P") ? "+{Up}" : "{Up}"
        Sleep 100    ; Repeat delay
    }
Return
JJohnston2
  • 1,929
2

The problem with all of the other answers is that repeated shift presses will be ignored because the previous hotkey subroutine is still being executed. By defualt, #MaxThreadsPerHotkey is 1, and #MaxThreads is 10.

Below are two possible solutions. Both works well for me.

Increase #MaxThreadsPerHotkey (and #MaxThreads)

SendMode Input
#MaxThreads 150
#MaxThreadsPerHotkey 150

; return the send command including any pressed modifier keys
getSendCommand() {
    sendCmd = {Up}
    sendCmd = % GetKeyState("LAlt", "P") ? "!" . sendCmd : sendCmd
    sendCmd = % GetKeyState("LCtrl", "P") ? "^" . sendCmd : sendCmd
    sendCmd = % GetKeyState("LShift", "P") ? "+" . sendCmd : sendCmd
    sendCmd = % GetKeyState("Win", "P") ? "#" . sendCmd : sendCmd
    return sendCmd
}

*$RShift::
    ; Immediately send an up key
    Send % getSendCommand()
    Sleep, 450

    While GetKeyState("RShift", "P") {  ; while key remains pressed
        Send % getSendCommand()  ; keep sending up keys
        Sleep, 30
    }
    Return

Immediately abort execution when shift key is released

SendMode Input

; return the send command including any pressed modifier keys
getSendCommand() {
    sendCmd = {Up}
    sendCmd = % GetKeyState("LAlt", "P") ? "!" . sendCmd : sendCmd
    sendCmd = % GetKeyState("LCtrl", "P") ? "^" . sendCmd : sendCmd
    sendCmd = % GetKeyState("LShift", "P") ? "+" . sendCmd : sendCmd
    sendCmd = % GetKeyState("Win", "P") ? "#" . sendCmd : sendCmd
    return sendCmd
}

*$RShift::
    ; Immediately send an up key
    Send % getSendCommand()

    ; Initial wait period (sleep time = 350 ms, execution time ~450 ms)
    Loop 35 {  ; Check keystate every 10 ms, abort execution as soon as shift is released
        Sleep, 10  ; 10 ms is the shortest possible sleep interval
        if not GetKeyState("RShift", "P") {
            return
        }
    }

    ; Start repeating if and while key is still pressed. Stop execution as soon as shift is released
    While GetKeyState("RShift", "P") {
        Send % getSendCommand()

        Loop 2 {
            if not GetKeyState("RShift", "P") {
                return
            }
            Sleep, 10
        }
    }
    Return
Joakim
  • 381
0

While JJohnston2's answer gave me part of the solution, I wound up asking several other places and doing a lot of experimentation myself. Here's what I eventually wound up with:

Up::RShift
*RShift::
    delay=400
    While GetKeyState("RShift", "P") {
        Send {Blind}{Up}
        Sleep %delay%    ; Set delay to taste
        delay=30
    }
    Return

This solves the problems of key repeat and allowing shift+up to work as expected. There are two outstanding issues that I haven't solved, but which are low enough in priority that I'm going to consider this question solved anyway:

  1. The race condition isn't solved. I tried to put the first iteration outside of the loop, as JJohnston2 did, but it had no observable effect for me.
  2. The root cause of all this trouble is that the system doesn't seem to repeat the shift, Ctrl, or Alt keys, even though the others repeat. So, AHK can't repeat what it never sees. Since everyone I've asked for help hasn't had this issue, there must be something funky with my setup, but I don't have the foggiest idea what that might be.