Remap CapsLock+ijkl to arrows Topic is solved

Get help with using AutoHotkey (v2 or newer) and its commands and hotkeys
kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Remap CapsLock+ijkl to arrows

Post by kaspar » 15 Nov 2023, 20:24

Hello,
I would like to write a script which disables CapsLock and does some remapings on it. There is a v1 script, but I cannot convert it to v2.
v1 - works, but not in an RDP session

Code: Select all

SetCapsLockState, AlwaysOff

#If GetKeyState("CapsLock", "P")
i::Up
j::Left
k::Down
l::Right
u::PgUp
o::PgDn
Backspace::Del
#If

*CapsLock::
KeyWait, CapsLock
Return
v2 - disables CapsLock, but remap ijkl to arrows all the time despite the CapsLock state

Code: Select all

SetCapsLockState "AlwaysOff"

if GetKeyState("CapsLock", "P")
{
i::Up
j::Left
k::Down
l::Right
u::PgUp
o::PgDn
Backspace::Del
}

Return
Can you please help me correct the v2 version and make it work in an RDP session? Thank you in advance!

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows

Post by DuckingQuack » 15 Nov 2023, 21:15

Looks like you need to use #HotIf instead of just If... something like:

Code: Select all

SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
{
i::Up
j::Left
k::Down
l::Right
u::PgUp
o::PgDn
Backspace::Del
}
#HotIf
Return
Test that to see if it fixes your issue.
Best of Luck,
The Duck

kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Re: Remap CapsLock+ijkl to arrows

Post by kaspar » 16 Nov 2023, 03:24

DuckingQuack wrote:
15 Nov 2023, 21:15
Looks like you need to use #HotIf instead of just If... something like:

Code: Select all

SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
{
i::Up
j::Left
k::Down
l::Right
u::PgUp
o::PgDn
Backspace::Del
}
#HotIf
Return
Test that to see if it fixes your issue.
Many thanks! It works as the v1 now, but still doesn't in an RDP session. Any chance to make the remap work everywhere, similar to the hardware re-assignment?

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows

Post by DuckingQuack » 16 Nov 2023, 05:47

Sorry for my ignorance, but I’m unfamiliar with RDP. Tell me about it and we can determine if we want to use a different send mode or change key delay settings.
SetKeyDelay: https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm
SendMode: https://www.autohotkey.com/docs/v2/lib/SendMode.htm

P.S.
We may need to send to a control in RDP for it to accept the key presses, in which case we’ll have to use ControlSend.
ControlSend: https://www.autohotkey.com/docs/v2/lib/ControlSend.htm
Best of Luck,
The Duck

kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Re: Remap CapsLock+ijkl to arrows

Post by kaspar » 16 Nov 2023, 12:27

DuckingQuack wrote:
16 Nov 2023, 05:47
Sorry for my ignorance, but I’m unfamiliar with RDP. Tell me about it and we can determine if we want to use a different send mode or change key delay settings.
SetKeyDelay: https://www.autohotkey.com/docs/v2/lib/SetKeyDelay.htm
SendMode: https://www.autohotkey.com/docs/v2/lib/SendMode.htm

P.S.
We may need to send to a control in RDP for it to accept the key presses, in which case we’ll have to use ControlSend.
ControlSend: https://www.autohotkey.com/docs/v2/lib/ControlSend.htm
Sorry, RDP is a Microsoft tool to work on a remote terminal. What makes the situation even worse - it can be nested, i.e. from a remote desktop you connect to another remote desktop.
https://learn.microsoft.com/en-us/troubleshoot/windows-server/remote/understanding-remote-desktop-protocol

The remapping doesn't work there, CapsLock is not disabled and switches its states: uppercase and lowercase. When I go back to my desktop it works again.
I made a few more tests today and see that it works unstable:
1. It may work even in the remote desktop if I don't type too fast.
2. Even on my desktop it sometimes misses the remap and type one of the letters: ijkl, especially if I type fast holding CapsLock, maybe I press multiple buttons at the same time.
3. I can even break the remap completely if I keep doing the actions from item 2. To fix it I have to reload the script.

I can provide some debug logs if needed. Is there a technical description on how AHK works?
Attachments
ahk_rdp.png
ahk_rdp.png (142.58 KiB) Viewed 992 times

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows

Post by DuckingQuack » 16 Nov 2023, 16:59

Everything I've read suggests no issues sending keystrokes to RDP, so perhaps the issue is the key reassignment?
This script uses the send command to send to the keystrokes, test this and let me know if it works for you and we can go from there... like further improvements.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
{
i::Send("{Up}")
j::Send("{Left}")
k::Send("{Down}")
l::Send("{Right}")
u::Send("{PgUp}")
o::Send("{PgDn}")
Backspace::Send("{Del}")
}
#HotIf
Best of Luck,
The Duck

kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Re: Remap CapsLock+ijkl to arrows

Post by kaspar » 16 Nov 2023, 19:04

DuckingQuack wrote:
16 Nov 2023, 16:59
Everything I've read suggests no issues sending keystrokes to RDP, so perhaps the issue is the key reassignment?
This script uses the send command to send to the keystrokes, test this and let me know if it works for you and we can go from there... like further improvements.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
{
i::Send("{Up}")
j::Send("{Left}")
k::Send("{Down}")
l::Send("{Right}")
u::Send("{PgUp}")
o::Send("{PgDn}")
Backspace::Send("{Del}")
}
#HotIf
Wow, it is a great improvement: I cannot break it now by typing fast, thank you so much! More information on the behavior in RDP session:
1. Right after connection, CapsLock in the remote session toggles case (not good). The toggle also starts working after minimizing-maximizing RDP screen. So, I have feeling that the AHK script somehow gets suspended or by-passed on switching/focusing to a maximized RDP session.
2. To make the script work again I exit full screen mode (restore down), hit the re-mapped combination (clicking CapsLock only doesn't help!) in RDP window mode, and then can maximize RDP window and the remap will work flawless, even in an inner RDP session!
image.png
image.png (9.81 KiB) Viewed 957 times
image.png
image.png (31.71 KiB) Viewed 957 times
3. When working with 2 screens where one of them shows full-screen RDP, changing focus (mouse click) from full screen RDP "suspends" the script again on the return to the full-screen RDP.

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows

Post by DuckingQuack » 16 Nov 2023, 20:59

Well, if you're dead set on using CapsLock to #HotIf your hotkeys, then I can look into a way to prevent it from inadvertently toggling when changing focus and swapping active windows. However...
There are a plethora of other methods for making these keys active, my preferred is to simply toggle them.

This makes the keys active or inactive by simply clicking F1, no need to hold down a modifier key. It can be set to work with any key or mouse button.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

on := False
F1:: Global on := !on

#HotIf on
{
i::Send("{Up}")
j::Send("{Left}")
k::Send("{Down}")
l::Send("{Right}")
u::Send("{PgUp}")
o::Send("{PgDn}")
Backspace::Send("{Del}")
}
#HotIf
Best of Luck,
The Duck

kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Re: Remap CapsLock+ijkl to arrows

Post by kaspar » 17 Nov 2023, 11:47

DuckingQuack wrote:
16 Nov 2023, 20:59
Well, if you're dead set on using CapsLock to #HotIf your hotkeys, then I can look into a way to prevent it from inadvertently toggling when changing focus and swapping active windows. However...
There are a plethora of other methods for making these keys active, my preferred is to simply toggle them.

This makes the keys active or inactive by simply clicking F1, no need to hold down a modifier key. It can be set to work with any key or mouse button.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

on := False
F1:: Global on := !on

#HotIf on
{
i::Send("{Up}")
j::Send("{Left}")
k::Send("{Down}")
l::Send("{Right}")
u::Send("{PgUp}")
o::Send("{PgDn}")
Backspace::Send("{Del}")
}
#HotIf
Thank you for the script! Indeed there could be alternative ways to do this, though I'm not sure if toggling arrows is the fastest one. Are there other best practices? :)
CapsLock is a big useless key, which is right under the left pinky, so it looks perfect for this case. But I don't want to trouble you much with this RDP CapsLock glitch, moreover I have a workaround.
I've noticed one issue with the latest CapsLock script: the remap doesn't work with key combinations. E.g. if I press CapsLock+Shift+k it gives me uppercase 'K' instead of down text selection. I'm using arrows in combination with Left Shift, Alt, and Ctrl for different kinds of selection, in the worst case (column selection in Visual Studio Code) it will be all of them at once, now plus CapsLock :D

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows

Post by DuckingQuack » 17 Nov 2023, 16:08

Made some adjustments based on your needs. This should better meet your requirements, but I still need to look into the CapsLock toggling issue when changing focus.
I'll probably need to add some kind of check and correction.

Test this and let me know what you think.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
{
*i::Send("{Blind}{Up}")
*j::Send("{Blind}{Left}")
*k::Send("{Blind}{Down}")
*l::Send("{Blind}{Right}")
*u::Send("{Blind}{PgUp}")
*o::Send("{Blind}{PgDn}")
*Backspace::Send("{Blind}{Del}")
}
#HotIf

Edit:
Here is a version that might solve the CapsLock toggling issue. Test and let me know what you think.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

SetTimer () => NoCaps(), 10
NoCaps(){
If GetKeyState("CapsLock", "T")
    SetCapsLockState "AlwaysOff"
}

#HotIf GetKeyState("CapsLock", "P")
{
*i::Send("{Blind}{Up}")
*j::Send("{Blind}{Left}")
*k::Send("{Blind}{Down}")
*l::Send("{Blind}{Right}")
*u::Send("{Blind}{PgUp}")
*o::Send("{Blind}{PgDn}")
*Backspace::Send("{Blind}{Del}")
}
#HotIf
Best of Luck,
The Duck

kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Re: Remap CapsLock+ijkl to arrows

Post by kaspar » 17 Nov 2023, 18:08

DuckingQuack wrote:
17 Nov 2023, 16:08
Made some adjustments based on your needs. This should better meet your requirements, but I still need to look into the CapsLock toggling issue when changing focus.
I'll probably need to add some kind of check and correction.

Test this and let me know what you think.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
{
*i::Send("{Blind}{Up}")
*j::Send("{Blind}{Left}")
*k::Send("{Blind}{Down}")
*l::Send("{Blind}{Right}")
*u::Send("{Blind}{PgUp}")
*o::Send("{Blind}{PgDn}")
*Backspace::Send("{Blind}{Del}")
}
#HotIf

Edit:
Here is a version that might solve the CapsLock toggling issue. Test and let me know what you think.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
Esc::ExitApp

SetTimer () => NoCaps(), 10
NoCaps(){
If GetKeyState("CapsLock", "T")
    SetCapsLockState "AlwaysOff"
}

#HotIf GetKeyState("CapsLock", "P")
{
*i::Send("{Blind}{Up}")
*j::Send("{Blind}{Left}")
*k::Send("{Blind}{Down}")
*l::Send("{Blind}{Right}")
*u::Send("{Blind}{PgUp}")
*o::Send("{Blind}{PgDn}")
*Backspace::Send("{Blind}{Del}")
}
#HotIf
The first version works fine, I can select text now! The RDP issue still persists for both versions of the scrips.
I've recorded a short video for demonstration, the storyline:
- The AHK script is always running during the video. The lower on-screen keyboard is local, the upper - from RDP session
- 00:00-00:13 - the script works perfectly locally
- 00:13-00:30 - same in windowed and full-screen RDP session
- 00:30-00:43 - minimize-maximize the RDP session, the script is broken, CapsLock toggles
- 00:43-00:59 - the fix via restore-down and maximize again

https://drive.google.com/file/d/1eQS9wla8ScCx-eNDfswRudA5GJ0sFcdf/view?usp=sharing

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows

Post by DuckingQuack » 17 Nov 2023, 18:59

I just found out that my "Home Edition" prevents me from using RDP in any capacity, so I am powerless to run any tests to resolve this bug.
What method are you using to min/max and restore/max? The shortcut key combos or clicking the buttons?
Test 1: Please add this hotkey to the script, recreate the bug, then use this hotkey to see if this method can resolve it. (Place it outside of the HotIf section.)
(Just need to find a way to "turn the script back on" then I can write the code to prevent it from breaking/auto-fix it when it does)

Code: Select all

F1::SetCapsLockState "AlwaysOff"
Best of Luck,
The Duck

kaspar
Posts: 7
Joined: 15 Nov 2023, 20:11

Re: Remap CapsLock+ijkl to arrows

Post by kaspar » 18 Nov 2023, 06:12

DuckingQuack wrote:
17 Nov 2023, 18:59
I just found out that my "Home Edition" prevents me from using RDP in any capacity, so I am powerless to run any tests to resolve this bug.
What method are you using to min/max and restore/max? The shortcut key combos or clicking the buttons?
Test 1: Please add this hotkey to the script, recreate the bug, then use this hotkey to see if this method can resolve it. (Place it outside of the HotIf section.)
(Just need to find a way to "turn the script back on" then I can write the code to prevent it from breaking/auto-fix it when it does)

Code: Select all

F1::SetCapsLockState "AlwaysOff"
I'm using the buttons in the RDP window header to min/max/restore or Alt+Tab.
The F1 remap doesn't work either. When the script is broken it just opens "how to get help in windows" in browser, when active it does nothing visible (SetCapsLockState).

I found this topic viewtopic.php?t=19419
The guys are talking about 'artificial vkFF keystroke when the RDP client becomes active' and 'reinstall our keyboard hook'. It looks relevant, but it is for v1 and doesn't work without adjustments.

I saw your PM and made the requested actions, I'm too new on this forum to reply there.

User avatar
DuckingQuack
Posts: 221
Joined: 20 Jan 2023, 18:20

Re: Remap CapsLock+ijkl to arrows  Topic is solved

Post by DuckingQuack » 18 Nov 2023, 08:46

Alright, that link had loads of useful information and I implemented the advice but now it needs testing.

EDIT: Fully tested and fully functional script.

Code: Select all

#Requires AutoHotkey v2.0
#SingleInstance Force
DetectHiddenWindows True
InstallMouseHook
InstallKeybdHook
SetCapsLockState "AlwaysOff"

#HotIf GetKeyState("CapsLock", "P")
*i::Send("{Blind}{Up}")
*j::Send("{Blind}{Left}")
*k::Send("{Blind}{Down}")
*l::Send("{Blind}{Right}")
*u::Send("{Blind}{PgUp}")
*o::Send("{Blind}{PgDn}")
*Backspace::Send("{Blind}{Del}")
#HotIf

#HotIf WinActive("ahk_class TscShellContainerClass")
~vkFF:: {
    if (A_TimeIdlePhysical > A_TimeSinceThisHotkey)
        Sleep(100)
        InstallKeybdHook(1,1)
        SetCapsLockState "AlwaysOff"
}
#HotIf

Best of Luck,
The Duck

Post Reply

Return to “Ask for Help (v2)”