Should I give up on this idea of trying to use kanata as a layering system with tap-dance functionalities through kanata_passthrough.dll in ahk? #1578
-
Much more context. My purpose is to turn a numpad into a multilayer macropad with tap-dance functionalities. This is already feasible through kanata alone and works great as expected. Though this way I am sending normal windows keys which in my case are bothersome as my purpose is to assign them to scripts through AHK and if I do that, then I am binding keys that windows recognize making my normal keyboard useless. I know I also have the option of F-keys but I kinda use them already. and f13-f24 are not enough. So this is where interceptor driver comes with ahk. Interceptor gives me back raw code that windows dont understand but ahk does! and I can map those without affecting my main keyboard functionality which is exactly what I need. AHk through interceptor alone works great but I dont have any layer functionalities. If I wanted I could integrate interceptionTapHold which also gives me tap dance functionalities but really what I am missing is layers functionality which kanata does great and also support tap-dance. So all toys in one package! I have setup an AHK script that intercept just my keypad and send codes to kanata and kanata sends back and this works as expected so far. this is the script for reference #SingleInstance force
Persistent
#include Lib\AutoHotInterception.ahk
#Requires AutoHotkey v2.0
F9::Reload
libPath := "./"
kanata_cfg := "./kanata_dll.kbd"
log_lvl := 0
; Load Kanata DLL and bind functions
libNm := "kanata_passthru"
hModule := DllCall("LoadLibrary", "Str", libPath libNm ".dll", "Ptr")
fnKanata_main := DllCall.Bind(libNm "\lib_kanata_passthru", "Ptr", unset, "Str", unset, "Int", unset, "Str", unset)
fnKanata_in_ev := DllCall.Bind(libNm "\input_ev_listener", "Int", unset, "Int", unset, "Int", unset)
K_output_ev_check:= DllCall.Bind(libNm "\output_ev_check")
AHI := AutoHotInterception()
keyboardId := AHI.GetDeviceIdFromHandle(false, "HID\VID_276D&PID_FFE3&REV_0100&MI_00")
AHI.SubscribeKeyboard(keyboardId, true, KeyEvent)
addr_cbKanataOut := CallbackCreate(cbKanataOut)
fnKanata_main(addr_cbKanataOut, kanata_cfg, log_lvl, "9999") ; Start Kanata
return
KeyEvent(code, state) {
scancode := Format("{:X}", code)
vk := GetKeyVK("SC" scancode)
if state == 0 {
state := 1
} else {
state := 0
}
FileAppend("In: SC " scancode " VK " vk " State " state " Time " A_TickCount "`n", "debug.txt")
fnKanata_in_ev(vk, code, state)
if (state == 1) {
Sleep(20)
}
loop 10 {
isOut := K_output_ev_check()
if (isOut < 0) {
break
}
}
}
cbKanataOut(kvk, ksc, up) {
vk_hex := Format("vk{:x}", kvk)
if up {
SendEvent('{' vk_hex ' up}')
} else {
SendEvent('{' vk_hex ' down}')
}
} Everything is great but my problems start the moment I start to use anything that has a delay. e.g tap-dance/tap-hold. The issue is when I press and release a key, interceptor sends to kanata both pressed and released state and the event finishes at that moment. So anything that kanata sends back is not arriving. When I increase sleep to about 200 things start to work (not always as expected cause I guess it gets way too complicated with the in kanata timers at that point) but at that time everything feels so slow. this just an example code I have for kanata. its not a final result but its the stage I am trying to figure it all out
I was hoping that maybe there is a better way to go about it that can synchronize both ahk and kanata through the intercepion driver? or I don't know, I should just give up on it. Or If there is way for kanata to send back codes that windows dont understand but ahk does, this still will work for my puprose. |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 9 replies
-
For some other ideas, you can try calling ahk via |
Beta Was this translation helpful? Give feedback.
-
So in other words give up! 😂 Damn ahk. Nothing works with it except ahk! |
Beta Was this translation helpful? Give feedback.
-
Your problem is partly you run out of keys or key combo's? When you are using windows you could create your own keyboard layout with kbdedit, where you can assign combo's not used somewhere else. You can also use the Kana, Roya and Loya modifier, which does not clash with something else (assuming you do not type Japanese). I think that can be done, but guess it will require a lot of time to get everything running. So I do not recommended that as best, but merely mention an option you can have a look into. |
Beta Was this translation helpful? Give feedback.
-
Never tried the dll Kanata, but I too use AHK+AHI in concert with Kanata (the wintercept version). FWIW, what worked for me as a reliable enough crutch is to have an AHK script deal with some specific keyboard/numpad first, binding key presses to function calls that signal a certain Kanata instance over TCP with an "ActOnFakeKey" message, at which point the control is transferred to Kanata and you can do layers and everything. So in essense AHK talks to Kanata through TCP using fakekeys. It's NOT easy to maintain tho.. Also I found it tricky to make Kanata talk back to AHK/trigger AHK functions. What I'm using at the moment is having Kanata send some obscure unicode symbols which are handled by AHK as hotstrings, and that's not pretty at all.. |
Beta Was this translation helpful? Give feedback.
-
So I found a way after all! when @GrewHair said about Unicode characters I had the biggest flash of my life! At first after I mapped some of them to kanata I tried mapping them to AHK and thats when all problems started as unicode are not directly mapped to ahk. But after back and forth with grok and ahk documentation and millions of failed experiments I found a way to map them effectively without letting windows get a hold of them! I will never need them anyway so it wont annoy my normal keyboard functionality so its amazing! I used some arabic and chinese characters or whatever and I used wintercept to map the numpad keys of my specific numpad so it wouldnt affect the numpad that is build in in my keyboard. The only thing I found little annoying from kanata side was unicode characters are not repeated like normal characters if you hold them so I used macro-repeat functions to make them repeatable in conjunction with tap-hold-press to make them behave like windows and to my surprise it was working exactly like windows as in ahk I could use all the normal while loops and all! so all in all now I get all the amazing functionalities of kanata 100% natively, no back and forth with ahk, no states, holds no passthrough driver and all the mess and also I get easy scripting in AHK as I dont have to think about states 0 and state 1 and tap and hold and all that stuff just normal key bindings! for reference to anyone else going through the same issue here is an example of my kanata code
its a mess of course but its just in its experimental phase! #Requires AutoHotkey v2.0
#SingleInstance force
#include Lib\AutoHotInterception.ahk
#include Lib\TapHoldManager.ahk
#include Lib\InterceptionTapHold.ahk
#include Lib\FindText.ahk
Persistent
F9::Reload
ih := InputHook("V L0") ; V = Visible, let unmapped keys pass
ih.KeyOpt("{vkE7}", "S") ; Suppress Unicode events
ih.OnChar := OnChar
ih.Start()
OnChar(ih, char) {
static dragging := false ; Track drag state
static xposP := "", yposP := "" ; Initialize coordinates
static X, Y ; For FindText results
static lastTimeDrag := 0 ; Track time for dragging (ا)
static lastTimePremiere := 0 ; Track time for Premiere (ب)
if (char == "ا") {
currentTime := A_TickCount
if (WinActive("ahk_exe Memento.exe")) {
if (!dragging) { ; Not already dragging
dragging := true
Click("Left") ; Activate window
CoordMode "Mouse", "Screen"
MouseGetPos(&xposP, &yposP)
; Concatenate patterns for FindText
Text := "|<>**50$23.Tzzxk70T0C0SzzyxU0Bv0Dvq0nrg1bjM3DSk3yzU0Dz70TqTQrhrxjT7TSw0Sxk0RvzzvrzzrU70DUC0vzzzc"
Text .= "|<>*101$20.U60E1U0zzwDzz3zzkzyQDz73ztkzzwzzzzzzwzzwDbz3knks0QC033zzkzzw06081U2"
Text .= "|<>*146$20.U60E1U0zzwDzz3zzkzwQDz73zlkzzwzzzzzzwzzwDbz3knks0QA033zzkzzw06081U6"
if (ok := FindText(&X, &Y, 313, 93, 2141, 1135, 0, 0, Text)) {
MouseMove(X, Y, 0) ; Move to pattern instantly
Click("Down Left") ; Start dragging
while (A_TickCount - lastTimeDrag < 100) { ; Loop while held
MouseMove(-1, 0, 0, "R") ; Move left 1 pixel
Sleep(10) ; Drag speed
currentTime := A_TickCount
}
dragging := false
Click("Up Left") ; Release mouse
if (xposP != "" && yposP != "") {
MouseMove(xposP, yposP, 0) ; Return to original position
}
}
}
lastTimeDrag := currentTime ; Update drag timer
} else {
Send("=")
lastTimeDrag := currentTime
}
} else if (char == "ب") {
currentTime := A_TickCount
if (WinActive("ahk_exe Adobe Premiere Pro.exe")) {
; Throttle to 500ms for Premiere
elapsed := currentTime - lastTimePremiere
if (elapsed >= 200) {
lastTimePremiere := currentTime ; Update before sequence
SendInput("x")
SendInput("^!l") ; Ctrl + Alt + L
Sleep(180)
SendInput("{Down}")
Sleep(1)
ToolTip("Elapsed: " elapsed) ; Debug timing
SetTimer(() => ToolTip(), -1000) ; Clear after 1s
}
} else {
; No throttle for type4, runs at Kanata’s speed
Send("type4")
}
} else if (char == "⠼") {
Send("type2")
} else if (char == "你") {
Send("type3")
} else if (char == "好") {
Send("type5")
} else if (char == "ث") {
Send("type6")
} else if (char == "ج") {
Send("type7")
} else if (char == "⠵") {
Send("type8")
}
} in the premiere loop I used an internal ahk timer to throttle it as I didnt want to mess with the timer in kanata cause that feels very natural for normal staff! Hopefully this is the end (of that certain journey at least!) its been 3 or 4 days now. Thanks guys for all the ideas and help! |
Beta Was this translation helpful? Give feedback.
-
I made it! It's unbelievable! I finally ended up using the inputhook option as It could handle my more complicated scripts with mouse drags and loops. Inputhook makes the Unicode characters behave - just like normal characters, coding for that though is a little more complicated but it's possible! I managed to make my small keypad of 20 keys to have 152 functions for macros without annoying a single window key! 4 actions per key 2 taps and 2 taps-hold. And all of those again on 2nd layer while holding keypadEnter! I can share the script if anyone wants |
Beta Was this translation helpful? Give feedback.
So I found a way after all! when @GrewHair said about Unicode characters I had the biggest flash of my life! At first after I mapped some of them to kanata I tried mapping them to AHK and thats when all problems started as unicode are not directly mapped to ahk. But after back and forth with grok and ahk documentation and millions of failed experiments I found a way to map them effectively without letting windows get a hold of them! I will never need them anyway so it wont annoy my normal keyboard functionality so its amazing!
I used some arabic and chinese characters or whatever and I used wintercept to map the numpad keys of my specific numpad so it wouldnt affect the numpad that is bui…