WingMan – Diff between revs 10 and 14

Subversion Repositories:
Rev:
Show entire fileRegard whitespace
Rev 10 Rev 14
Line 1... Line 1...
1 using System; 1 using System;
2 using System.Collections.Generic; 2 using System.Collections.Specialized;
3 using System.IO; 3 using System.IO;
4 using System.Linq; 4 using System.Linq;
5 using System.Threading; 5 using System.Threading;
6 using System.Threading.Tasks; 6 using System.Threading.Tasks;
-   7 using System.Threading.Tasks.Dataflow;
7 using System.Windows.Forms; 8 using System.Windows.Forms;
8 using Gma.System.MouseKeyHook; 9 using Gma.System.MouseKeyHook;
9 using WingMan.Communication; 10 using WingMan.Communication;
-   11 using WingMan.Utilities;
Line 10... Line 12...
10   12  
11 namespace WingMan.MouseKey 13 namespace WingMan.Bindings
12 { 14 {
13 public class KeyInterceptor : IDisposable 15 public class KeyInterceptor : IDisposable
14 { 16 {
Line -... Line 17...
-   17 public delegate void MouseKeyBindingMatched(object sender, KeyBindingMatchedEventArgs args);
-   18  
15 public delegate void MouseKeyBindingMatched(object sender, KeyBindingMatchedEventArgs args); 19 private volatile bool ProcessPipe;
16   20  
17 public KeyInterceptor(RemoteKeyBindings remoteKeyBindings, MqttCommunication mqttCommunication, 21 public KeyInterceptor(RemoteKeyBindings remoteKeyBindings, MqttCommunication mqttCommunication,
-   22 TaskScheduler taskScheduler, CancellationToken cancellationToken)
-   23 {
18 TaskScheduler taskScheduler, CancellationToken cancellationToken) 24 DataFlowSemaphoreSlim = new SemaphoreSlim(1, 1);
-   25  
-   26 RemoteKeyBindings = remoteKeyBindings;
19 { 27 RemoteKeyBindings.Bindings.CollectionChanged += OnRemoteKeyBindingsChanged;
20 RemoteKeyBindings = remoteKeyBindings; 28  
21 MqttCommunication = mqttCommunication; 29 MqttCommunication = mqttCommunication;
Line 22... Line -...
22 TaskScheduler = taskScheduler; -  
23 CancellationToken = cancellationToken; -  
24   30 TaskScheduler = taskScheduler;
25 KeyCombo = new List<string>(); 31 CancellationToken = cancellationToken;
26   32  
27 MouseKeyGloalHook = Hook.GlobalEvents(); 33 MouseKeyGloalHook = Hook.GlobalEvents();
Line -... Line 34...
-   34 MouseKeyGloalHook.KeyUp += MouseKeyGloalHookOnKeyUp;
-   35 MouseKeyGloalHook.KeyDown += MouseKeyGloalHookOnKeyDown;
-   36 }
-   37  
-   38 private BatchBlock<string> KeyComboBatchBlock { get; set; }
-   39  
-   40 private ActionBlock<string[]> KeyComboActionBlock { get; set; }
-   41  
28 MouseKeyGloalHook.KeyUp += MouseKeyGloalHookOnKeyUp; 42 private IDisposable KeyComboDataFlowLink { get; set; }
29 MouseKeyGloalHook.KeyDown += MouseKeyGloalHookOnKeyDown; 43  
30 } 44 private SemaphoreSlim DataFlowSemaphoreSlim { get; }
31   45  
Line 32... Line 46...
32 private RemoteKeyBindings RemoteKeyBindings { get; } 46 private RemoteKeyBindings RemoteKeyBindings { get; }
33 private MqttCommunication MqttCommunication { get; } -  
34 private TaskScheduler TaskScheduler { get; } -  
Line 35... Line 47...
35 private CancellationToken CancellationToken { get; } 47 private MqttCommunication MqttCommunication { get; }
36   48 private TaskScheduler TaskScheduler { get; }
37 private IKeyboardMouseEvents MouseKeyGloalHook { get; } 49 private CancellationToken CancellationToken { get; }
38   50  
-   51 private IKeyboardMouseEvents MouseKeyGloalHook { get; set; }
Line 39... Line 52...
39 public List<string> KeyCombo { get; set; } 52  
40   -  
41 public void Dispose() -  
42 { 53 public void Dispose()
Line 43... Line 54...
43 MouseKeyGloalHook.KeyUp -= MouseKeyGloalHookOnKeyUp; 54 {
44 MouseKeyGloalHook.KeyDown -= MouseKeyGloalHookOnKeyDown; -  
45   55 MouseKeyGloalHook.KeyUp -= MouseKeyGloalHookOnKeyUp;
46 MouseKeyGloalHook.Dispose(); -  
47 } -  
48   56 MouseKeyGloalHook.KeyDown -= MouseKeyGloalHookOnKeyDown;
Line 49... Line 57...
49 public event MouseKeyBindingMatched OnMouseKeyBindingMatched; 57 RemoteKeyBindings.Bindings.CollectionChanged -= OnRemoteKeyBindingsChanged;
50   58  
51 private void MouseKeyGloalHookOnKeyDown(object sender, KeyEventArgs e) 59 KeyComboDataFlowLink?.Dispose();
Line -... Line 60...
-   60 KeyComboDataFlowLink = null;
-   61  
-   62 MouseKeyGloalHook?.Dispose();
52 { 63 MouseKeyGloalHook = null;
-   64 }
Line 53... Line 65...
53 e.SuppressKeyPress = false; 65  
54   66 private async void OnRemoteKeyBindingsChanged(object sender, NotifyCollectionChangedEventArgs e)
55 if (KeyConversion.KeysToString.TryGetValue((byte) e.KeyCode, out var key)) KeyCombo.Add(key); -  
Line 56... Line 67...
56 } 67 {
-   68 await DataFlowSemaphoreSlim.WaitAsync(CancellationToken);
-   69  
-   70 try
-   71 {
-   72 // Break the link and dispose it.
-   73 KeyComboDataFlowLink?.Dispose();
-   74 KeyComboDataFlowLink = null;
-   75  
57   76 // Create a sliding window of size equal to the longest key combination.
-   77 var maxKeyComboLength = RemoteKeyBindings.Bindings.Max(binding => binding.Keys.Count);
-   78  
-   79 KeyComboBatchBlock =
-   80 new BatchBlock<string>(maxKeyComboLength);
-   81 KeyComboActionBlock = new ActionBlock<string[]>(ProcessKeyCombos,
Line 58... Line 82...
58 private void MouseKeyGloalHookOnKeyUp(object sender, KeyEventArgs e) 82 new ExecutionDataflowBlockOptions {CancellationToken = CancellationToken});
59 { 83 KeyComboDataFlowLink = KeyComboBatchBlock.LinkTo(KeyComboActionBlock);
-   84 }
-   85 finally
-   86 {
60 e.SuppressKeyPress = false; 87 DataFlowSemaphoreSlim.Release();
61   88 }
62 var combo = new List<string>(KeyCombo); 89 }
63   90  
Line 64... Line 91...
64 #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed 91 private async Task ProcessKeyCombos(string[] keys)
65 Task.Run(() => SimulateMouseKey(new List<string>(combo)), CancellationToken); 92 {
66 #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed 93 await DataFlowSemaphoreSlim.WaitAsync(CancellationToken);
Line 92... Line 119...
92   119  
93 await MqttCommunication.Broadcast("execute", memoryStream.ToArray()); 120 await MqttCommunication.Broadcast("execute", memoryStream.ToArray());
94 } 121 }
95 } 122 }
-   123 }
-   124 finally
-   125 {
-   126 DataFlowSemaphoreSlim.Release();
-   127 }
-   128 }
-   129  
-   130 public event MouseKeyBindingMatched OnMouseKeyBindingMatched;
-   131  
-   132 private async void MouseKeyGloalHookOnKeyDown(object sender, KeyEventArgs e)
-   133 {
-   134 ProcessPipe = true;
-   135  
-   136 if (!KeyConversion.KeysToString.TryGetValue((byte) e.KeyCode, out var key))
-   137 return;
-   138  
-   139 await DataFlowSemaphoreSlim.WaitAsync(CancellationToken);
-   140 try
-   141 {
-   142 if (KeyComboBatchBlock != null) await KeyComboBatchBlock.SendAsync(key, CancellationToken);
-   143 }
-   144 finally
-   145 {
-   146 DataFlowSemaphoreSlim.Release();
-   147 }
-   148 }
-   149  
-   150 private void MouseKeyGloalHookOnKeyUp(object sender, KeyEventArgs e)
-   151 {
-   152 ProcessPipe = false;
96 } 153 }
97 } 154 }