2424
2525extern RemapEntryContainerListItem* g_KeyTranslationTable[WIN_KEY_COUNT];
2626
27+ ULONGLONG g_KeyDownTime[WIN_KEY_COUNT];
28+
2729/*
2830Implementation of the win32 LowLevelKeyboardProc (see docs for information)
2931
@@ -33,7 +35,7 @@ created to send out the key(s) to send to the os.
3335*/
3436LRESULT CALLBACK LowLevelKeyboardProc (int nCode, WPARAM wParam, LPARAM lParam)
3537{
36- KBDLLHOOKSTRUCT *pHook = reinterpret_cast <KBDLLHOOKSTRUCT*>(lParam);
38+ KBDLLHOOKSTRUCT *pHook = reinterpret_cast <KBDLLHOOKSTRUCT*>(lParam);
3739 bool bSentInput = false ;
3840
3941 bool bAlt = 0 != (GetAsyncKeyState (VK_MENU) & 0x8000 );
@@ -51,13 +53,16 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
5153 case WM_SYSKEYDOWN:
5254 // detect a keydown that matches a remaped key (and start the input thread to respond accordingly then indicate to the OS that the key has been handled)
5355 {
54- RemapEntryContainerListItem* pKeyListItem = g_KeyTranslationTable[pHook->vkCode ];
56+ // NOTE: key down events will come in while a key is being held
57+
58+ const RemapEntryContainerListItem* pKeyListItem = g_KeyTranslationTable[pHook->vkCode ];
5559 while (NULL != pKeyListItem)
5660 {
57- InputConfig* pKeyDef = &pKeyListItem->pEntryContainer ->pEntry ->inputConfig ;
61+ const InputConfig* pKeyDef = &pKeyListItem->pEntryContainer ->pEntry ->inputConfig ;
5862 if ((bAlt == pKeyDef->inputFlag .bAlt ) &&
5963 (bControl == pKeyDef->inputFlag .bControl ) &&
60- (bShift == pKeyDef->inputFlag .bShift ))
64+ (bShift == pKeyDef->inputFlag .bShift )
65+ && !pKeyDef->inputFlag .bLongPress )
6166 {
6267#ifdef _DEBUG
6368 char * pInputConfigDescription = GetInputConfigDescription (*pKeyDef);
@@ -69,7 +74,24 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
6974 {
7075 pKeyListItem->pEntryContainer ->pEntryState ->threadHandle = CreateThread (NULL , 0 , SendInputThread, pKeyListItem->pEntryContainer , 0 , NULL );
7176 }
72- // no matter if a new SendInputThread was started or not block further processing with the inputs
77+ // block further processing with the inputs
78+ bSentInput = true ;
79+ break ;
80+ }
81+ if (!bAlt
82+ && !bControl
83+ && !bShift
84+ && pKeyDef->inputFlag .bLongPress )
85+ {
86+ if (g_KeyDownTime[pKeyDef->virtualKey ] == 0 ) // ignore all keydown events on this key after recording the initial key down time
87+ {
88+ const ULONGLONG tickCount = GetTickCount64 ();
89+ g_KeyDownTime[pKeyDef->virtualKey ] = tickCount;
90+ #ifdef _DEBUG
91+ LogDebugMessage (" Detected LONGPRESS Key Down: %d Tick: %d" , pKeyDef->virtualKey , tickCount);
92+ #endif
93+ }
94+ // block further processing with the inputs
7395 bSentInput = true ;
7496 break ;
7597 }
@@ -85,10 +107,42 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
85107 while (NULL != pKeyListItem)
86108 {
87109 InputConfig* pKeyDef = &pKeyListItem->pEntryContainer ->pEntry ->inputConfig ;
88- if ((bAlt == pKeyDef->inputFlag .bAlt ) &&
89- (bControl == pKeyDef->inputFlag .bControl ) &&
90- (bShift == pKeyDef->inputFlag .bShift ))
110+ if (bAlt == pKeyDef->inputFlag .bAlt
111+ && bControl == pKeyDef->inputFlag .bControl
112+ && bShift == pKeyDef->inputFlag .bShift
113+ && !pKeyDef->inputFlag .bLongPress )
114+ {
115+ // block further processing with the inputs
116+ bSentInput = true ;
117+ break ;
118+ }
119+ if (!bAlt
120+ && !bControl
121+ && !bShift
122+ && pKeyDef->inputFlag .bLongPress )
91123 {
124+ ULONGLONG tickCount = GetTickCount64 ();
125+ if (tickCount - g_KeyDownTime[pKeyDef->virtualKey ] > 1000 )
126+ {
127+ #ifdef _DEBUG
128+ char * pInputConfigDescription = GetInputConfigDescription (*pKeyDef);
129+ LogDebugMessage (" Detected LONGPRESS Key Up: %s Outputs: %d" , pInputConfigDescription, pKeyListItem->pEntryContainer ->pEntry ->outputCount );
130+ free (pInputConfigDescription);
131+ #endif
132+ // If there is NOT an existing thread OR the existing thread is running a repeat another key press is allowed
133+ if (NULL == pKeyListItem->pEntryContainer ->pEntryState ->threadHandle || pKeyListItem->pEntryContainer ->pEntryState ->bRepeating )
134+ {
135+ pKeyListItem->pEntryContainer ->pEntryState ->threadHandle = CreateThread (NULL , 0 , SendInputThread, pKeyListItem->pEntryContainer , 0 , NULL );
136+ }
137+ }
138+ else
139+ {
140+ LogDebugMessage (" Detected LONGPRESS Key UP (too short): %d Tick: %d (Old Tick: %d)" , pKeyDef->virtualKey , tickCount, g_KeyDownTime[pKeyDef->virtualKey ]);
141+ // when a longpress "fails" just send the normal keypress
142+ CreateThread (NULL , 0 , SendInputKeypress, pKeyDef, 0 , NULL );
143+ }
144+ g_KeyDownTime[pKeyDef->virtualKey ] = 0 ;
145+ // block further processing with the inputs
92146 bSentInput = true ;
93147 break ;
94148 }
0 commit comments