diff --git a/C#/AutoHotInterception/InterceptionWrapper.cs b/C#/AutoHotInterception/InterceptionWrapper.cs index 05881e3..ea3d80e 100644 --- a/C#/AutoHotInterception/InterceptionWrapper.cs +++ b/C#/AutoHotInterception/InterceptionWrapper.cs @@ -11,13 +11,8 @@ using System.Threading.Tasks; public class InterceptionWrapper { private readonly IntPtr _deviceContext; - private Thread _subscriptionThread; - private bool _subscriptionThreadRunning = false; - private bool _subscriptionsEnabled = false; - - private Thread _contextSwitcherThread; - private bool _contextSwitcherThreadRunning = false; - private bool _contextSwitchingEnabled = false; + private Thread _pollThread; + private bool _pollThreadRunning = false; private readonly bool _filterState = false; @@ -57,10 +52,6 @@ public class InterceptionWrapper public bool SubscribeKey(uint code, bool block, dynamic callback, int vid = 0, int pid = 0) { - if (_contextSwitchingEnabled) - { - throw new Exception("Cannot enable Subscription mode once Context mode has been enabled"); - } SetFilterState(false); var id = 0; if (vid != 0 && pid != 0) @@ -78,23 +69,29 @@ public class InterceptionWrapper _filteredDevices[id] = true; SetFilterState(true); - if (!_subscriptionThreadRunning) - { - _subscriptionThreadRunning = true; - _subscriptionThread = new Thread(SubscriptionThread); - _subscriptionThread.Start(); - } - - _subscriptionsEnabled = true; + SetThreadState(true); return true; } - public bool SetContextCallback(int vid, int pid, dynamic callback) + private void SetThreadState(bool state) { - if (_subscriptionsEnabled) + if (state) + { + if (!_pollThreadRunning) + { + _pollThreadRunning = true; + _pollThread = new Thread(PollThread); + _pollThread.Start(); + } + } + else { - throw new Exception("Cannot enable Context mode once Subscription mode has been enabled"); + throw new NotImplementedException(); } + } + + public bool SetContextCallback(int vid, int pid, dynamic callback) + { SetFilterState(false); var id = 0; if (vid != 0 && pid != 0) @@ -107,14 +104,7 @@ public class InterceptionWrapper _filteredDevices[id] = true; SetFilterState(true); - if (!_contextSwitcherThreadRunning) - { - _contextSwitcherThreadRunning = true; - _contextSwitcherThread = new Thread(ContextSwitcherThread); - _contextSwitcherThread.Start(); - } - - _contextSwitchingEnabled = true; + SetThreadState(true); return true; } @@ -151,7 +141,6 @@ public class InterceptionWrapper private int IsMonitoredKeyboard(int device) { - //return Convert.ToInt32(_mappings.ContainsKey(device)); return Convert.ToInt32(_filteredDevices.ContainsKey(device)); } @@ -167,7 +156,7 @@ public class InterceptionWrapper } } - private void ContextSwitcherThread() + private void PollThread() { Stroke stroke = new Stroke(); @@ -175,44 +164,20 @@ public class InterceptionWrapper { for (var i = 1; i < 11; i++) { - var isMonitoredKeyboard = _contextCallbacks.ContainsKey(i); - - while (Receive(_deviceContext, i, ref stroke, 1) > 0) - { - if (isMonitoredKeyboard) - { - _contextCallbacks[i](1); - } - Send(_deviceContext, i, ref stroke, 1); - if (isMonitoredKeyboard) - { - _contextCallbacks[i](0); - } - } - } - Thread.Sleep(10); - } - - } - - private void SubscriptionThread() - { - Stroke stroke = new Stroke(); - - while (true) - { - for (var i = 1; i < 11; i++) - { - var isMonitoredKeyboard = _mappings.ContainsKey(i); + var isMonitoredKeyboard = IsMonitoredKeyboard(i) == 1; + var hasSubscription = false; + var hasContext = _contextCallbacks.ContainsKey(i); while (Receive(_deviceContext, i, ref stroke, 1) > 0) { var block = false; if (isMonitoredKeyboard) { + // Process Subscription Mode foreach (var mapping in _mappings[i]) { if (stroke.key.code != mapping.code) continue; + hasSubscription = true; if (mapping.block) { block = true; @@ -220,11 +185,25 @@ public class InterceptionWrapper mapping.callback(1 - stroke.key.state); break; } + // If this key had no subscriptions, but Context Mode is set for this keyboard... + // ... then set the Context before sending the key + if (!hasSubscription && hasContext) + { + // Set Context + _contextCallbacks[i](1); + } } + // If the key was not blocked by Subscription Mode, then send it now if (!block) { Send(_deviceContext, i, ref stroke, 1); } + // If we are processing Context Mode, then Unset the context variable after sending the key + if (!hasSubscription && hasContext) + { + // Unset Context + _contextCallbacks[i](0); + } } } Thread.Sleep(10); diff --git a/C#/TestApp/Program.cs b/C#/TestApp/Program.cs index 3100a10..f3a1111 100644 --- a/C#/TestApp/Program.cs +++ b/C#/TestApp/Program.cs @@ -13,11 +13,18 @@ class TestApp { var iw = new InterceptionWrapper(); var str = iw.GetDeviceList(); - iw.SubscribeKey(0x2D, true, new Action((value) => { - Console.WriteLine("Value: " + value); - //}), 0x413C, 0x2107); + // 0x2D = X key + iw.SubscribeKey(0x2D, true, new Action((value) => + { + Console.WriteLine("Subscription Value: " + value); + //}), 0x413C, 0x2107); }), 0x04F2, 0x0112); //}), 0x046D, 0xC531); + + iw.SetContextCallback(0x04F2, 0x0112, new Action((value) => + { + Console.WriteLine("Context Value: " + value); + })); while (true) { Thread.Sleep(100); diff --git a/Context Example - Copy.ahk b/Context Example - Copy.ahk new file mode 100644 index 0000000..e9eebe0 --- /dev/null +++ b/Context Example - Copy.ahk @@ -0,0 +1,43 @@ +#SingleInstance force +#Persistent +#include Lib\AutoHotInterception.ahk + +VID := 0x04F2, PID := 0x0112 + +global Interception := AutoHotInterception_Init() + +devices := Interception.GetDeviceList() +if (!devices){ + msgbox Device List Check failed + ExitApp +} + +;~ clipboard := devices +;~ MsgBox % devices + +result := Interception.SetContextCallback(VID, PID, Func("SetKb1Context")) +if (result != -1){ + msgbox Subscribe failed + ExitApp +} +return + +SetKb1Context(state){ + global isKeyboard1Active + Sleep 0 ; We seem to need this for hotstrings to work, not sure why + isKeyboard1Active := state +} +#if isKeyboard1Active +1::ctrl +;~ ::aaa::JACKPOT +;~ 1:: + ;~ ToolTip % "KEY DOWN EVENT @ " A_TickCount + ;~ return + +;~ 1 up:: + ;~ ToolTip % "KEY UP EVENT @ " A_TickCount + ;~ return +#if + +^Esc:: + ExitApp \ No newline at end of file