PowerToys icon indicating copy to clipboard operation
PowerToys copied to clipboard

[KBM] Separate function for key press vs key hold (a la dual-key-remap)

Open NeodymiumPhish opened this issue 5 years ago • 17 comments
trafficstars

I love the idea of managing key remaps via PowerToys, but there's no way (that I'm aware of) to remap a key to serve two purposed depending on whether it's pressed and released vs pressed in combination. https://github.com/ililim/dual-key-remap <- This tool is a great example. By default, it maps the CapsLock key to Escape when pressed without any other keys and Ctrl when pressed in combination with another key.

NeodymiumPhish avatar Aug 05 '20 20:08 NeodymiumPhish

@NeodymiumPhish there would be a limitation in this feature though, that the Caps->Esc behavior would work only on "press and release", since when only Caps Lock is held down there would be no way of knowing if another key is going to be pressed or not. So for Caps->Esc it works, but Caps->Shift for example when pressed alone wouldnt make much sense sense it would simulate Shift being pressed and released so it can't really be used in combination with other keys. That said, for other scenarios this looks like a cool idea.

arjunbalgovind avatar Aug 06 '20 00:08 arjunbalgovind

Totally understand the limitations issue. I meant that press and release would be one function and hold/combination presses would be another. What you're describing is how dual-key-remap works; it would be awesome if this were built into the much more user-friendly PowerToys!

NeodymiumPhish avatar Aug 06 '20 02:08 NeodymiumPhish

I desire this feature. Is there anything I can do for getting it implemented? I'm happy to help specing or coding.

masaru-iritani avatar Feb 13 '22 03:02 masaru-iritani

Because I haven't received any objection, let me share my proposal of the spec for the dual key remap feature.

Update [Remap keys] dialog

[Remap keys] dialog adds a combo box under the arrow symbol for each single key remap. It has three values, namely, "Always", "Alone", and "In Combination" (any suggestion for better names is welcome).

A screenshot of Remap keys dialog with a combo box under the arrow for each remap

I have no plan to support dual remaps for shortcuts. I'm not interested in or aware of any scenario needing it.

Update [Keyboard Manager] Settings page

Each single key remap in [Keys] section adds a label indicating the remap condition. It uses the same style with the app name of a shortcut remap in [Shortcuts] section.

A screenshot of Keyboard Manager PowerToys Settings page showing single key remaps

Process dual remap key events

"Always" keeps the current behavior as of today. "Alone" or "Combination" provides the dual key remap functionality where the remap is effective only when the key is pressed alone or in combination with other keys, respectively. When a key has dual-remaps, the remapped key press injection is delayed until the next key event to detect whether another key will be pressed during the key press.

Remaps on the same key can coexist if the condition differs. A table below shows how multiple remaps on A key will be resolved.

Always Alone Combination Key to inject
on pressing A alone
Key to inject
on pressing A in combination
Pressing A delay?
- - - A A No
A -> B - - B B No
- A -> C - C A Yes
A -> B A -> C - C B Yes
- - A -> D A D Yes
A -> B - A -> D B D Yes
- A -> C A -> D C D Yes
A -> B A -> C A -> D C D Yes

Save dual remaps in Keyboard Manager default.json

~~Add two named "alone" and "combination" in "remapKeys" object of Keyboard Manager default.json to save dual remaps in the same format with the current "inProcess" remap array.~~

Add "condition" value for each entry in "inProcess" array of Keyboard Manager default.json to save the remap condition. 0, 1, and 2 means "Always", "Alone", and "Combination" remap condition, respectively. For the backward compatibility, the value is optional and its default value is 0 ("Always").

{
    "remapKeys": {
        "inProcess": [
            {
                "originalKeys": "161",
                "newRemapKeys": "18"
            },
            {
                "originalKeys": "164",
                "newRemapKeys": "29",
                "condition": 1
            },
            {
                "originalKeys": "32",
                "newRemapKeys": "160",
                "condition": 2
            }
        ],
    },
// ...
}

masaru-iritani avatar Feb 27 '22 12:02 masaru-iritani

https://github.com/microsoft/PowerToys/compare/main...masaru-iritani:patch-1 is my ongoing work. I'm thinking of publishing a draft pull request if I get the green-light (or no objection for a while).

masaru-iritani avatar Feb 27 '22 12:02 masaru-iritani

@masaru-iritani You could create a draft PR from the branch 😄 Would you like me to tag this as In progress and assign this to you?

franky920920 avatar Mar 01 '22 07:03 franky920920

@franky920920

Would you like me to tag this as In progress and assign this to you?

Yes, please!

masaru-iritani avatar Mar 01 '22 14:03 masaru-iritani

@masaru-iritani How's progress going? :)

Jay-o-Way avatar Aug 09 '22 22:08 Jay-o-Way

@masaru-iritani How's progress going? :)

Not good :(

I didn't have enough time to understand the keyboard shortcut handling and find an appropriate design to allow tentative remap errors for both single keys and shortcuts. I'll keep updating the pull request when I make any progress.

masaru-iritani avatar Aug 12 '22 15:08 masaru-iritani

Any progress on this? I would like to setup home row mods for my windows laptop and think this would be the solution.

That being said, in the meantime, does anyone have a recommendation for setting up home row mods on a Windows laptop keyword (I can with my external keyboard through its keyboard layout software but have not figured out how to on a regular laptop keyboard). Thanks!

GitMurf avatar Jan 17 '24 17:01 GitMurf

Let me unassign me for now. I'm still hoping to make this happen by myself, but I'm not sure how long it will take to incorporate latest changes in the main branch into my current draft.

masaru-iritani avatar Jan 18 '24 03:01 masaru-iritani

I've resumed efforts to implement this feature and, based on my experiences from the previous pull request, plan to divide the work into multiple smaller refactoring pull requests. This approach should help minimize the code difference and enable easier integration with the latest code base.

My plan is:

  1. Replace std::make_pair with a RemapBufferRow initializer list to prepare for the step 2 (the pull request above).
  2. Convert RemapBufferRow from std::pair to a struct to add a field for the remap condition.
  3. Change LPINPUT (key event array) to std::vector to support the variable number of key events on the fly.
  4. (any other refactoring for reducing the amount of changes at the final step)
  5. Implement the dual key map.

Fingers crossed 🤞

masaru-iritani avatar Mar 20 '24 16:03 masaru-iritani

Very much looking forward to this! Curious if any recent progress / updates? Thanks a bunch @masaru-iritani for your hard work on this!

GitMurf avatar Aug 03 '24 07:08 GitMurf

The review on #32545 is pending. I'd like to know if there is anything I (or anyone else) can do for accelerating the review process.

masaru-iritani avatar Aug 03 '24 09:08 masaru-iritani