Skip to content

Commit e188459

Browse files
committed
Another pass on long press
Added ability to configure the milliseconds. Unfortunately the Windows operating system provides keyboard events based on the Windows Keyboard control panel configuration. Precision appears to be 250ms at the minimum.
1 parent 112cce6 commit e188459

File tree

6 files changed

+90
-21
lines changed

6 files changed

+90
-21
lines changed

Format/InputConfig.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
// SOFTWARE.
2323
////////////////////////////////////////////////////////////////////////////////
2424

25+
using Support.UI;
2526
using System.IO;
2627
using System.Windows.Forms;
2728

@@ -70,7 +71,7 @@ public override string GetDescription()
7071
(IsFlaggedAs(InputFlag.Shift) ? "+Shift" : string.Empty) +
7172
(IsFlaggedAs(InputFlag.Alt) ? "+Alt" : string.Empty) +
7273
(IsFlaggedAs(InputFlag.Control) ? "+Control" : string.Empty) +
73-
(IsFlaggedAs(InputFlag.LongPress) ? "+LongPress" : string.Empty) +
74+
(IsFlaggedAs(InputFlag.LongPress) ? "+LongPress[{0}ms]".FormatString(Parameter.ToString()) : string.Empty) +
7475
"]";
7576
}
7677
}

Forms/KeyCaptureConfig.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,12 @@ private InputConfig UpdateInputFlags(InputConfig zInputConfig)
653653
nFlags = BitUtil.UpdateFlag(nFlags, bShift, InputConfig.InputFlag.Shift);
654654
nFlags = BitUtil.UpdateFlag(nFlags, bLongPress, InputConfig.InputFlag.LongPress);
655655
zInputConfig.Flags = nFlags;
656+
657+
if (bLongPress)
658+
{
659+
zInputConfig.Parameter = (int)numericUpDownInputParameter.Value;
660+
}
661+
656662
return zInputConfig;
657663
}
658664

@@ -713,7 +719,7 @@ private void ConfigureToolTips()
713719
{
714720
var zToolTip = new ToolTip()
715721
{
716-
AutoPopDelay = 5000,
722+
AutoPopDelay = 10000,
717723
InitialDelay = 500,
718724
ReshowDelay = 250,
719725
ShowAlways = false,
@@ -722,6 +728,8 @@ private void ConfigureToolTips()
722728
zToolTip.SetToolTip(checkInputAlt, "Requires Alt to be pressed");
723729
zToolTip.SetToolTip(checkInputControl, "Requires Ctrl to be pressed");
724730
zToolTip.SetToolTip(checkInputShift, "Requires Shift to be pressed");
731+
zToolTip.SetToolTip(checkInputLongPress, "Require the key to be held for a minimum amount of time");
732+
zToolTip.SetToolTip(numericUpDownInputParameter, "The minimum duration of the long press (milliseconds). \n\nNOTE: The 'Repeat Delay' setting in the Windows Keyboard control panel has a direct impact on how low this can be.");
725733

726734
zToolTip.SetToolTip(checkOutputAlt, "Generates Alt event");
727735
zToolTip.SetToolTip(checkOutputControl, "Generates Ctrl event");

Forms/KeyCaptureConfig.designer.cs

Lines changed: 33 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

KeyCapLib/keyboardproc.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
extern RemapEntryContainerListItem* g_KeyTranslationTable[WIN_KEY_COUNT];
2626

27+
const int LONG_PRESS_MIN = 100;
28+
const int KEY_DOWN_UNSET = 0; // key not being held
29+
const int KEY_DOWN_EVENT_FIRED = 1; // key is held and already sent output
30+
// other values stored in g_KeyDownTime are the original key down time as returned by GetTickCount64
2731
ULONGLONG g_KeyDownTime[WIN_KEY_COUNT];
2832

2933
/*
@@ -83,13 +87,49 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
8387
&& !bShift
8488
&& pKeyDef->inputFlag.bLongPress)
8589
{
86-
if (g_KeyDownTime[pKeyDef->virtualKey] == 0) // ignore all keydown events on this key after recording the initial key down time
90+
switch(g_KeyDownTime[pKeyDef->virtualKey])
91+
{
92+
case KEY_DOWN_UNSET:
8793
{
8894
const ULONGLONG tickCount = GetTickCount64();
8995
g_KeyDownTime[pKeyDef->virtualKey] = tickCount;
9096
#ifdef _DEBUG
9197
LogDebugMessage("Detected LONGPRESS Key Down: %d Tick: %d", pKeyDef->virtualKey, tickCount);
9298
#endif
99+
}
100+
break;
101+
102+
case KEY_DOWN_EVENT_FIRED:
103+
// nothing for now
104+
break;
105+
default:
106+
{
107+
const ULONGLONG tickCount = GetTickCount64();
108+
const unsigned int longPressMinimum = max(LONG_PRESS_MIN, pKeyDef->parameter);
109+
#if false
110+
// windows has a built repeat rate limiter so the shortest time is 250ms
111+
const ULONGLONG diff = tickCount - g_KeyDownTime[pKeyDef->virtualKey];
112+
LogDebugMessage("diff: %d", diff);
113+
#endif
114+
if (tickCount - g_KeyDownTime[pKeyDef->virtualKey] >= longPressMinimum)
115+
{
116+
#ifdef _DEBUG
117+
char* pInputConfigDescription = GetInputConfigDescription(*pKeyDef);
118+
LogDebugMessage("Detected LONGPRESS [Key Down: %s] [Outputs: %d][longPressMinimum: %d]",
119+
pInputConfigDescription,
120+
pKeyListItem->pEntryContainer->pEntry->outputCount,
121+
longPressMinimum);
122+
free(pInputConfigDescription);
123+
#endif
124+
// If there is NOT an existing thread OR the existing thread is running a repeat another key press is allowed
125+
if (NULL == pKeyListItem->pEntryContainer->pEntryState->threadHandle || pKeyListItem->pEntryContainer->pEntryState->bRepeating)
126+
{
127+
pKeyListItem->pEntryContainer->pEntryState->threadHandle = CreateThread(NULL, 0, SendInputThread, pKeyListItem->pEntryContainer, 0, NULL);
128+
}
129+
g_KeyDownTime[pKeyDef->virtualKey] = KEY_DOWN_EVENT_FIRED;
130+
}
131+
}
132+
break;
93133
}
94134
// block further processing with the inputs
95135
bSentInput = true;
@@ -121,27 +161,14 @@ LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
121161
&& !bShift
122162
&& pKeyDef->inputFlag.bLongPress)
123163
{
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
164+
if (g_KeyDownTime[pKeyDef->virtualKey] != KEY_DOWN_EVENT_FIRED)
139165
{
166+
const ULONGLONG tickCount = GetTickCount64();
140167
LogDebugMessage("Detected LONGPRESS Key UP (too short): %d Tick: %d (Old Tick: %d)", pKeyDef->virtualKey, tickCount, g_KeyDownTime[pKeyDef->virtualKey]);
141168
// when a longpress "fails" just send the normal keypress
142169
CreateThread(NULL, 0, SendInputKeypress, pKeyDef, 0, NULL);
143170
}
144-
g_KeyDownTime[pKeyDef->virtualKey] = 0;
171+
g_KeyDownTime[pKeyDef->virtualKey] = KEY_DOWN_UNSET;
145172
// block further processing with the inputs
146173
bSentInput = true;
147174
break;

Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@
5555
// You can specify all the values or you can default the Build and Revision Numbers
5656
// by using the '*' as shown below:
5757
// [assembly: AssemblyVersion("1.0.*")]
58-
[assembly: AssemblyVersion("2.0.0.5")]
59-
[assembly: AssemblyFileVersion("2.0.0.5")]
58+
[assembly: AssemblyVersion("2.1.0.0")]
59+
[assembly: AssemblyFileVersion("2.1.0.0")]

bin/Release/KeyCap.odt

171 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)