Closed MatCyg closed 3 years ago
Wow, cool usecase :-).
Unfortunately, the stopAllMacros command doesn't stop the delayUntil action
Sounds like a bug. Therefore, let's leave this open...
Is there any other/better way of achieving the above?
Your approach requires defining a macro for each key of the keyboard, doesn't it?
It might be possible to program this using call MACRONAME
, ifInterrupted
, activateKeyPostponed
and some register signaling. But this is without a guarantee - these are pretty niche commands and therefore might contain bugs or might be removed in future...
Also, adding a macro event for onKeyPress as part of https://github.com/UltimateHackingKeyboard/firmware/issues/351 might help you.
(Also, with this level of complexity you might also consider digging straight into the firmware C code.)
Wow, cool usecase :-).
I was tired of holding MOD key all the time 😉
Your approach requires defining a macro for each key of the keyboard, doesn't it?
Yeah, that's the worrying part. Currently, it requires around 120-130 macros (2 per key).
(Also, with this level of complexity you might also consider digging straight into the firmware C code.)
I am considering this right now. I am afraid 'macro based' approach will eat too much memory. Any hint where to start looking to implement this? Had a look at the code before but felt a bit lost so I tried using this firmware.
Also, adding a macro event for onKeyPress as part of UltimateHackingKeyboard#351 might help you.
I am afraid the official smart macros feature will take months before it is completed. Would you consider accepting a PR with a feature simplifying my use case? onKeyPress
might be hard to implement, but something like $tapSameKeyFromKeymap WRT
could be much simpler. With that, I would need ~3 macros.
I am considering this right now. I am afraid 'macro based' approach will eat too much memory. Any hint where to start looking to implement this? Had a look at the code before but felt a bit lost so I tried using this firmware.
Basically all keyboard logic is implemented in usb_report_updater.c
. Specifically the top level UpdateUsbReports
function and its call to updateActiveUsbReports
. (Don't let the name fool you - the file has nothing to do with USB protocols.)
I am afraid the official smart macros feature will take months before it is completed.
I really hope not, although considering my inability to reserve time for UHK in last months, I cannot rule it out.
Would you consider accepting a PR with a feature simplifying my use case?
onKeyPress
might be hard to implement, but something like$tapSameKeyFromKeymap WRT
could be much simpler. With that, I would need ~3 macros.
That's where activateKeyPostponed
can help you - it basically enqueues a hardware key for execution in next (couple) update cycle(s), so you can switch to that layer and enqueue the key (#key
in place of a number serves as self-reference) for activation.
Regarding new command:
I definitely don't like the idea of making this thing cross-keymap, because pulling the action from memory is going to be troublesome, and executing it immediately even more so. If anything, I think cross-layer mechanism should suffice. The 12-layer feature should be implemented just as soon as I find time to finish smart macros.
Still, even if we talk cross-layer, I am not sure if anything more straightforward actually can be implemented without too much hassle and too much risk of blowing up in the future.
So consider yes, but actually accepting probably not. On the other hand, if you can come up with more intuitive naming or some sort of syntactic sugar that would simplify achieving your usecase with current features (i.e., activation via postponer queue), I will be more than happy to accept a PR or implement it.
Unfortunately, the
stopAllMacros
command doesn't stop thedelayUntil
action. I also tried with layers instead of keymaps, but the result was the same. Is there any way to clear thedelayUntil
action? Is there any other/better way of achieving the above?
I cannot reproduce this.
Using:
$delayUntil 1000
$tapKeyA
$stopAllMacros
Have a look at this UHK configuration.
There are two implementations one with ifInterrupted
and one with stopAllMacros
.
Expected behavior:
We start with Navigation (NAV) keymap. Once any letter is pressed, the keymap is changed to Writing (WRT). If we don't press any button on the WRT keymap it should change back to NAV.
ifInterrupted
implementation:
On NAV press n
and immediately after press m
. Continue pressing m
. The keyboard will stay in WRT mode for as long as you press the m
letter. If you stop, it will go back to the NAV keymap after a 1-second delay.
stopAllMacros
implementation:
On NAV press a
and immediately after press s
. Continue pressing s
. Even though the first command in the WRT_S
macro is $stopAllMacros
, your keymap will switch back to NAV.
Let me know if this is enough of an explanation. If not I can provide a better description.
Alright, found the problems. Two actually:
1) Macro stopping was done via a flag that would signal a macro to stop. The ("stopped") macro would later tidy after itself as if it stopped of its own will, except it would allow one more tick to be executed (which was not intended). This probably didn't affect your usecase, but definitely was not correct.
2) When a delay command was interrupted this way, it would not clean after itself. Original author of that code was not very defensive and did not initialize his state variables (of the delay mechanism) with each macro start - rather assumed things would work with clockwork precision. Which it did, until I came and started extending the engine :-).
Should be fixed in uhk-firmware-8.10.10.kt.2.tar.gz (E: published as prerelease, so it may not show on the main page) . (That release may be a bit unstable - I will be grateful for more bug reports if you encounter any problems.)
Thanks!
I am afraid the official smart macros feature will take months before it is completed. Would you consider accepting a PR with a feature simplifying my use case? onKeyPress might be hard to implement, but something like $tapSameKeyFromKeymap WRT could be much simpler. With that, I would need ~3 macros
I've been thinking about this, and activating a different-layer-key without leaving a layer is actually quite a strong feature, which can allow for a number of usecases which would otherwise have to be implemented in much hackier way.
I think I will implement it eventually, maybe by modification of activateKeyPostponed. But I probably won't get to that soon.
If you decide to dig into it yourself, a PR is welcome. In that case, you probably want to base it on branch common_trunk_upstream
. Also, there is an omprovement to the activateKeyPostponed
so that it works reliably even when the key in question is active - which I guess might have caused some troubles to you...
Regarding implementation - the idea is to push a new key event into postponer's queue from a macro (just like current activateKeyPostponed
, and extend postponer state to contain an optional flag denoting layer at which the key should be activated. Then, the piece of code that updates action cache will need to be updated to take the new flag into consideration. I think it should be safe to simply respect current postponer record flags if postponer is currently active.
I am trying to move my configuration from karabiner-elements to UHK. I played a bit with the commands and I thought I have found a way I could achieve it. Unfortunately, it doesn't seem to work. Wanted to ask, if it is even possible to achieve what I want. Thank you for any input.
So far I am using the following configuration with karabiner-elements: Two layers - writing_layer and navigation_layer
navigation_layer:
jkl;
buttons are mapped to arrows.jkl;
can be writtenwriting_layer:
jkl;
arrow mapping is disabled, pressing these buttons will produce their respective signsWhile in writing_layer if there's no button pressed for 600ms, it switches back to navigation_layer. This is achieved by using a delayed action on all the buttons on writing_layer. This delayed action is cleared if any other button is pressed before the 600ms timeout. I figured I could do the same with UHK macros:
On NAVigation_layer each button (besides
jkl;
) would switch to WRiTing_layer and would have a delayed action to go back to NAVigation_layerOn WRiTing_layer each button would
stopAllMacros
- disabling thedelayUntil
action to switch back to NAVigation_layerUnfortunately, the
stopAllMacros
command doesn't stop thedelayUntil
action. I also tried with layers instead of keymaps, but the result was the same. Is there any way to clear thedelayUntil
action? Is there any other/better way of achieving the above?--Edit-- My bad, I missed
ifInterrupted
command. Using that instead ofstopAllMacros
works as expected. Sorry for bothering you. Can be closed.