AHI uses new ScanCodeHelper

pull/84/head
Clive Galway 2 years ago
parent b4cd165a09
commit 8b4b092767

@ -1,6 +1,7 @@
using AutoHotInterception.Helpers;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace AutoHotInterception.DeviceHandlers
{
@ -120,9 +121,9 @@ namespace AutoHotInterception.DeviceHandlers
public abstract void DisableFilterIfNeeded();
/// <summary>
/// Process an incoming stroke
/// Process an incoming stroke, or a pair of extended keycode strokes
/// </summary>
/// <param name="stroke">The stroke to process</param>
public abstract void ProcessStroke(ManagedWrapper.Stroke stroke);
/// <param name="strokes">The stroke(s) to process</param>
public abstract void ProcessStroke(List<ManagedWrapper.Stroke> strokes);
}
}

@ -1,4 +1,5 @@
using AutoHotInterception.Helpers;
using System.Collections.Generic;
namespace AutoHotInterception.DeviceHandlers
{
@ -53,9 +54,9 @@ namespace AutoHotInterception.DeviceHandlers
void DisableFilterIfNeeded();
/// <summary>
/// Process an incoming stroke
/// Process an incoming stroke, or a pair of extended keycode strokes
/// </summary>
/// <param name="stroke">The stroke to process</param>
void ProcessStroke(ManagedWrapper.Stroke stroke);
/// <param name="strokes">The stroke(s) to process</param>
void ProcessStroke(List<ManagedWrapper.Stroke> strokes);
}
}

@ -1,6 +1,7 @@
using AutoHotInterception.Helpers;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
namespace AutoHotInterception.DeviceHandlers
@ -50,9 +51,8 @@ namespace AutoHotInterception.DeviceHandlers
#endregion
// ScanCode notes: https://www.win.tue.nl/~aeb/linux/kbd/scancodes-1.html
public override void ProcessStroke(ManagedWrapper.Stroke stroke)
public override void ProcessStroke(List<ManagedWrapper.Stroke> strokes)
{
//ManagedWrapper.Send(DeviceContext, _deviceId, ref stroke, 1);
var hasSubscription = false;
var hasContext = ContextCallback != null;
@ -62,7 +62,7 @@ namespace AutoHotInterception.DeviceHandlers
if (_isFiltered)
{
var isKeyMapping = false; // True if this is a mapping to a single key, else it would be a mapping to a whole device
var processedState = HelperFunctions.KeyboardStrokeToKeyboardState(stroke);
var processedState = ScanCodeHelper.TranslateScanCodes(strokes);
var code = processedState.Code;
var state = processedState.State;
MappingOptions mapping = null;
@ -81,41 +81,30 @@ namespace AutoHotInterception.DeviceHandlers
if (mapping != null)
{
// Begin translation of incoming key code, state, extended flag etc...
var processMappings = true;
if (processedState.Ignore)
hasSubscription = true;
if (mapping.Block) block = true;
if (mapping.Concurrent)
{
// Set flag to stop Context Mode from firing
hasSubscription = true;
// Set flag to indicate disable mapping processing
processMappings = false;
if (isKeyMapping)
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state));
}
else
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(code, state));
}
}
if (processMappings)
else
{
hasSubscription = true;
if (mapping.Block) block = true;
if (mapping.Concurrent)
//mapping.Callback(code, state);
if (isKeyMapping)
{
if (isKeyMapping)
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state));
}
else
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(code, state));
}
WorkerThreads[code]?.Actions.Add(() => mapping.Callback(state));
}
else
{
if (isKeyMapping)
{
WorkerThreads[code]?.Actions.Add(() => mapping.Callback(state));
}
else
{
DeviceWorkerThread?.Actions.Add(() => mapping.Callback(code, state));
}
DeviceWorkerThread?.Actions.Add(() => mapping.Callback(code, state));
}
}
@ -127,8 +116,12 @@ namespace AutoHotInterception.DeviceHandlers
// ... then set the Context before sending the key
if (!hasSubscription && hasContext) ContextCallback(1);
// Pass the key through to the OS.
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
// Pass the key(s) through to the OS.
for (int i = 0; i < strokes.Count; i++)
{
var stroke = strokes[i];
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
}
// If we are processing Context Mode, then Unset the context variable after sending the key
if (!hasSubscription && hasContext) ContextCallback(0);

@ -1,5 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using AutoHotInterception.Helpers;
@ -153,215 +154,220 @@ namespace AutoHotInterception.DeviceHandlers
}
#endregion
public override void ProcessStroke(ManagedWrapper.Stroke stroke)
public override void ProcessStroke(List<ManagedWrapper.Stroke> strokes)
{
var hasSubscription = false;
var hasContext = ContextCallback != null;
var moveRemoved = false;
var hasMove = false;
var x = stroke.mouse.x;
var y = stroke.mouse.y;
// Process mouse movement
var isAbsolute = (stroke.mouse.flags & (ushort)ManagedWrapper.MouseFlag.MouseMoveAbsolute) ==
(ushort)ManagedWrapper.MouseFlag.MouseMoveAbsolute;
//Determine whether or not to report mouse movement.
// For Relative mode, this is fairly simple - if x and y are both 0, no movement was reported (Since a real mouse never reports x=0/y=0)
// For Absolute mode, x=0/y=0 is reported, but we should limit this to only reporting once...
// ... so when x=0/y=0 is seen in absolute mode, set the flag _absoluteMode00Reported to true and allow it to be reported...
// then on subsequent reports of x=0/y=0 for absolute mode, if _absoluteMode00Reported is already true, then do not report movement...
// ... In absolute mode, when x!=0/y!=0 is received, clear the _absoluteMode00Reported flag
if (isAbsolute)
for (int i = 0; i < strokes.Count; i++)
{
if (x == 0 && y == 0)
var stroke = strokes[i];
var hasSubscription = false;
var hasContext = ContextCallback != null;
var moveRemoved = false;
var hasMove = false;
var x = stroke.mouse.x;
var y = stroke.mouse.y;
// Process mouse movement
var isAbsolute = (stroke.mouse.flags & (ushort)ManagedWrapper.MouseFlag.MouseMoveAbsolute) ==
(ushort)ManagedWrapper.MouseFlag.MouseMoveAbsolute;
//Determine whether or not to report mouse movement.
// For Relative mode, this is fairly simple - if x and y are both 0, no movement was reported (Since a real mouse never reports x=0/y=0)
// For Absolute mode, x=0/y=0 is reported, but we should limit this to only reporting once...
// ... so when x=0/y=0 is seen in absolute mode, set the flag _absoluteMode00Reported to true and allow it to be reported...
// then on subsequent reports of x=0/y=0 for absolute mode, if _absoluteMode00Reported is already true, then do not report movement...
// ... In absolute mode, when x!=0/y!=0 is received, clear the _absoluteMode00Reported flag
if (isAbsolute)
{
if (!_absoluteMode00Reported)
if (x == 0 && y == 0)
{
hasMove = true;
_absoluteMode00Reported = true;
if (!_absoluteMode00Reported)
{
hasMove = true;
_absoluteMode00Reported = true;
}
else
{
hasMove = false;
}
}
else
{
hasMove = false;
hasMove = true;
_absoluteMode00Reported = false;
}
}
else
{
hasMove = true;
_absoluteMode00Reported = false;
hasMove = (x != 0 || y != 0);
}
}
else
{
hasMove = (x != 0 || y != 0);
}
if (hasMove)
{
// Process Absolute Mouse Move
if (isAbsolute)
if (hasMove)
{
if (_mouseMoveAbsoluteMapping != null)
// Process Absolute Mouse Move
if (isAbsolute)
{
var mapping = _mouseMoveAbsoluteMapping;
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has absolute move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (WorkerThreads.ContainsKey(7))
WorkerThreads[7]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
if (_mouseMoveAbsoluteMapping != null)
{
moveRemoved = true;
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
var mapping = _mouseMoveAbsoluteMapping;
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has absolute move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (WorkerThreads.ContainsKey(7))
WorkerThreads[7]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
{
moveRemoved = true;
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
//Debug.WriteLine(debugStr);
//Debug.WriteLine(debugStr);
}
}
}
else
{
if (_mouseMoveRelativeMapping != null)
else
{
var mapping = _mouseMoveRelativeMapping;
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has relative move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (WorkerThreads.ContainsKey(8))
WorkerThreads[8]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
if (_mouseMoveRelativeMapping != null)
{
moveRemoved = true;
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
var mapping = _mouseMoveRelativeMapping;
hasSubscription = true;
//var debugStr = $"AHK| Mouse stroke has relative move of {x}, {y}...";
if (mapping.Concurrent)
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(x, y));
else if (WorkerThreads.ContainsKey(8))
WorkerThreads[8]?.Actions.Add(() => mapping.Callback(x, y));
if (mapping.Block)
{
moveRemoved = true;
stroke.mouse.x = 0;
stroke.mouse.y = 0;
//debugStr += "Blocking";
}
else
{
//debugStr += "Not Blocking";
}
//Debug.WriteLine(debugStr);
//Debug.WriteLine(debugStr);
}
}
}
}
}
var isMouseButtonsMapping = AllButtonsMapping != null;
var isMouseButtonsMapping = AllButtonsMapping != null;
// Process Mouse Buttons - do this AFTER mouse movement, so that absolute mode has coordinates available at the point that the button callback is fired
if (stroke.mouse.state != 0 && SingleButtonMappings.Count > 0 || isMouseButtonsMapping)
{
var btnStates = HelperFunctions.MouseStrokeToButtonStates(stroke);
foreach (var btnState in btnStates)
// Process Mouse Buttons - do this AFTER mouse movement, so that absolute mode has coordinates available at the point that the button callback is fired
if (stroke.mouse.state != 0 && SingleButtonMappings.Count > 0 || isMouseButtonsMapping)
{
if (!isMouseButtonsMapping && !SingleButtonMappings.ContainsKey(btnState.Button))
continue;
hasSubscription = true;
MappingOptions mapping = null;
if (isMouseButtonsMapping)
{
mapping = AllButtonsMapping;
}
else
var btnStates = HelperFunctions.MouseStrokeToButtonStates(stroke);
foreach (var btnState in btnStates)
{
mapping = SingleButtonMappings[btnState.Button];
}
if (!isMouseButtonsMapping && !SingleButtonMappings.ContainsKey(btnState.Button))
continue;
var state = btnState;
if (mapping.Concurrent)
{
hasSubscription = true;
MappingOptions mapping = null;
if (isMouseButtonsMapping)
{
ThreadPool.QueueUserWorkItem(threadProc =>
mapping.Callback(btnState.Button, state.State));
mapping = AllButtonsMapping;
}
else
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state.State));
mapping = SingleButtonMappings[btnState.Button];
}
}
else
{
if (isMouseButtonsMapping)
var state = btnState;
if (mapping.Concurrent)
{
DeviceWorkerThread?.Actions
.Add(() => mapping.Callback(btnState.Button, state.State));
if (isMouseButtonsMapping)
{
ThreadPool.QueueUserWorkItem(threadProc =>
mapping.Callback(btnState.Button, state.State));
}
else
{
ThreadPool.QueueUserWorkItem(threadProc => mapping.Callback(state.State));
}
}
else
{
WorkerThreads[btnState.Button]?.Actions
.Add(() => mapping.Callback(state.State));
if (isMouseButtonsMapping)
{
DeviceWorkerThread?.Actions
.Add(() => mapping.Callback(btnState.Button, state.State));
}
else
{
WorkerThreads[btnState.Button]?.Actions
.Add(() => mapping.Callback(state.State));
}
}
}
if (mapping.Block)
{
// Remove the event for this button from the stroke, leaving other button events intact
stroke.mouse.state -= btnState.Flag;
// If we are removing a mouse wheel event, then set rolling to 0 if no mouse wheel event left
if (btnState.Flag == 0x400 || btnState.Flag == 0x800)
if (mapping.Block)
{
if ((stroke.mouse.state & 0x400) != 0x400 &&
(stroke.mouse.state & 0x800) != 0x800)
// Remove the event for this button from the stroke, leaving other button events intact
stroke.mouse.state -= btnState.Flag;
// If we are removing a mouse wheel event, then set rolling to 0 if no mouse wheel event left
if (btnState.Flag == 0x400 || btnState.Flag == 0x800)
{
//Debug.WriteLine("AHK| Removing rolling flag from stroke");
stroke.mouse.rolling = 0;
if ((stroke.mouse.state & 0x400) != 0x400 &&
(stroke.mouse.state & 0x800) != 0x800)
{
//Debug.WriteLine("AHK| Removing rolling flag from stroke");
stroke.mouse.rolling = 0;
}
}
//Debug.WriteLine($"AHK| Removing flag {btnState.Flag} from stoke, leaving state {stroke.mouse.state}");
}
else
{
//Debug.WriteLine($"AHK| Leaving flag {btnState.Flag} in stroke");
}
}
}
//Debug.WriteLine($"AHK| Removing flag {btnState.Flag} from stoke, leaving state {stroke.mouse.state}");
// Forward on the stroke if required
if (hasSubscription)
{
// Subscription mode
// If the stroke has a move that was not removed, OR it has remaining button events, then forward on the stroke
if ((hasMove && !moveRemoved) || stroke.mouse.state != 0)
{
//Debug.WriteLine($"AHK| Sending stroke. State = {stroke.mouse.state}. hasMove={hasMove}, moveRemoved={moveRemoved}");
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
}
else
{
//Debug.WriteLine($"AHK| Leaving flag {btnState.Flag} in stroke");
// Everything removed from stroke, do not forward
//Debug.WriteLine("AHK| Mouse stroke now empty, not forwarding");
}
}
}
// Forward on the stroke if required
if (hasSubscription)
{
// Subscription mode
// If the stroke has a move that was not removed, OR it has remaining button events, then forward on the stroke
if ((hasMove && !moveRemoved) || stroke.mouse.state != 0)
else if (hasContext)
{
//Debug.WriteLine($"AHK| Sending stroke. State = {stroke.mouse.state}. hasMove={hasMove}, moveRemoved={moveRemoved}");
// Context Mode - forward stroke with context wrapping
ContextCallback(1);
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
ContextCallback(0);
}
else
{
// Everything removed from stroke, do not forward
//Debug.WriteLine("AHK| Mouse stroke now empty, not forwarding");
// No subscription or context mode - forward on
//Debug.WriteLine($"AHK| Sending stroke. State = {stroke.mouse.state}. hasMove={hasMove}, moveRemoved={moveRemoved}");
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
}
}
else if (hasContext)
{
// Context Mode - forward stroke with context wrapping
ContextCallback(1);
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
ContextCallback(0);
}
else
{
// No subscription or context mode - forward on
//Debug.WriteLine($"AHK| Sending stroke. State = {stroke.mouse.state}. hasMove={hasMove}, moveRemoved={moveRemoved}");
ManagedWrapper.Send(DeviceContext, DeviceId, ref stroke, 1);
}
}
}
}

@ -12,7 +12,7 @@ namespace AutoHotInterception.Helpers
Prefixed // Stroke order is Ext Modifier press, Key press, Ext Modifier release, Key release
};
public class ScanCodeHelper
public static class ScanCodeHelper
{
// Converts Interception state to AHK state
private static List<ushort> _stateConverter = new List<ushort>() { 1, 0, 1, 0, 1, 0 };
@ -20,7 +20,7 @@ namespace AutoHotInterception.Helpers
private static List<ushort> _stateToExtendedMode = new List<ushort>() { 0, 0, 1, 1, 2, 2 };
// Keys which have an E0 state, but AHK uses High (+256) code
private HashSet<ushort> _highCodeE0Keys = new HashSet<ushort>()
private static HashSet<ushort> _highCodeE0Keys = new HashSet<ushort>()
{
28, // Numpad Enter
54, // Right Shift
@ -30,6 +30,7 @@ namespace AutoHotInterception.Helpers
// List of two-stroke keys, used to build _twoStrokeKeyConverter
private static Dictionary<ushort, Order> _twoStrokeKeys = new Dictionary<ushort, Order>()
{
{ 55, Order.Wrapped }, // PrtScr
{ 69, Order.Prefixed }, // Pause
{ 71, Order.Wrapped }, // Home
{ 72, Order.Wrapped }, // Up
@ -47,7 +48,7 @@ namespace AutoHotInterception.Helpers
private static Dictionary<Tuple<ushort, ushort, ushort, ushort>, TranslatedKey>
_twoStrokeKeyConverter = new Dictionary<Tuple<ushort, ushort, ushort, ushort>, TranslatedKey>();
public ScanCodeHelper()
static ScanCodeHelper()
{
foreach (var item in _twoStrokeKeys)
{
@ -55,9 +56,10 @@ namespace AutoHotInterception.Helpers
_twoStrokeKeyConverter.Add(twoStrokeKey.PressTuple, twoStrokeKey.PressKey);
_twoStrokeKeyConverter.Add(twoStrokeKey.ReleaseTuple, twoStrokeKey.ReleaseKey);
}
//_twoStrokeKeyConverter.Add(new Tuple<ushort, ushort, ushort, ushort>(42, 298, 55, 311), new Tr
}
public TranslatedKey TranslateScanCodes(List<Stroke> strokes)
public static TranslatedKey TranslateScanCodes(List<Stroke> strokes)
{
if (strokes.Count == 2)
{
@ -94,12 +96,12 @@ namespace AutoHotInterception.Helpers
// Holds the AHK code and state equivalent of a one or two-stroke set
public class TranslatedKey
{
public ushort AhkCode { get; }
public ushort Code { get; }
public int State { get; }
public TranslatedKey(ushort code, int state)
{
AhkCode = code;
Code = code;
State = state;
}
}

@ -1,5 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using AutoHotInterception.DeviceHandlers;
@ -524,15 +525,32 @@ namespace AutoHotInterception
//Debug.WriteLine($"AHK| Poll Thread Started");
_pollThreadRunning = true;
var stroke = new ManagedWrapper.Stroke();
int i;
int deviceId;
while (!token.IsCancellationRequested)
{
//var strokes = new List<ManagedWrapper.Stroke>();
var deviceStrokes = new Dictionary<int, List<ManagedWrapper.Stroke>>();
// While no input happens, this loop will exit every 1ms to allow us to check if cancellation has been requested
// WaitWithTimeout is used with a timeout of 10ms instead of Wait, so that when we eg use SetState to turn the thread off...
// ... any input which was filtered and is waiting to be processed can be processed (eg lots of mouse moves buffered)
while (ManagedWrapper.Receive(DeviceContext, i = ManagedWrapper.WaitWithTimeout(DeviceContext, 10), ref stroke, 1) > 0)
while (ManagedWrapper.Receive(DeviceContext, deviceId = ManagedWrapper.WaitWithTimeout(DeviceContext, 0), ref stroke, 1) > 0)
{
DeviceHandlers[i].ProcessStroke(stroke);
if (!deviceStrokes.ContainsKey(deviceId))
{
deviceStrokes.Add(deviceId, new List<ManagedWrapper.Stroke>());
}
deviceStrokes[deviceId].Add(stroke);
//DeviceHandlers[i].ProcessStroke(stroke);
}
if (deviceStrokes.Count == 0) continue;
foreach (var strokes in deviceStrokes)
{
//var keyEvents = new List<KeyEvent>();
//foreach (var s in strokes.Value)
//{
// keyEvents.Add(new KeyEvent { Code = s.key.code, State = s.key.state });
//}
DeviceHandlers[strokes.Key].ProcessStroke(strokes.Value);
}
}
_pollThreadRunning = false;

@ -48,7 +48,7 @@ namespace AutoHotInterception
var keyEvents = new List<KeyEvent>();
foreach (var s in strokes)
{
keyEvents.Add(new KeyEvent { Code = stroke.key.code, State = stroke.key.state });
keyEvents.Add(new KeyEvent { Code = s.key.code, State = s.key.state });
}
_callback(keyEvents);
}

@ -150,7 +150,7 @@ namespace TestApp.Helpers
{81 /*(0x51)*/, "NumpadPgDn"},
{82 /*(0x52)*/, "NumpadIns"},
{83 /*(0x53)*/, "NumpadDel"},
{84 /*(0x54)*/, "PrintScreen"},
//{84 /*(0x54)*/, "PrintScreen"}, Use 311 instead
{86 /*(0x56)*/, "\\"},
{87 /*(0x57)*/, "F11"},
{88 /*(0x58)*/, "F12"},
@ -180,6 +180,7 @@ namespace TestApp.Helpers
{306 /*(0x132)*/, "Browser_Home"},
{309 /*(0x135)*/, "NumpadDiv"},
{310 /*(0x136)*/, "RShift"},
{311 /*(0x136)*/, "PrintScreen"}, // Note: GetKeySC("PrintScreen") yields 311, but GetKeyName("sc54") (Dec of 84) yields "PrintScreen"
{312 /*(0x138)*/, "RAlt"},
{325 /*(0x145)*/, "Numlock"},
{326 /*(0x146)*/, "CtrlBreak"},

@ -10,10 +10,10 @@ namespace TestApp
//var mmt = new MouseMoveTester(TestDevices.LogitechWheelMouse);
//var mbt = new MouseButtonTester(TestDevices.LogitechWheelMouse, MouseButtons.Left, true);
//var ambt = new MouseButtonsTester(TestDevices.LogitechWheelMouse, true);
//var kt = new KeyboardTester(TestDevices.WyseKeyboard, true);
var kt = new KeyboardTester(TestDevices.WyseKeyboard, true);
//var kkt = new KeyboardKeyTester(TestDevices.WyseKeyboard, AhkKeys.Obj("1"), true);
//var tt = new TabletTester(TestDevices.ParbloIslandA609);
var sct = new ScanCodeTester(TestDevices.WyseKeyboard, true);
//var sct = new ScanCodeTester(TestDevices.WyseKeyboard, true);
//var sst = new SetStateTester(TestDevices.WyseKeyboard, AhkKeys.Obj("1"));
Console.ReadLine();
}

@ -40,8 +40,6 @@ namespace UnitTests
[TestFixture]
class ScanCodeHelperTests
{
ScanCodeHelper sch = new ScanCodeHelper();
private static List<Stroke> Stroke(ushort code1, ushort state1, ushort code2 = 0, ushort state2 = 0)
{
var strokes = new List<Stroke>();
@ -65,12 +63,12 @@ namespace UnitTests
Debug.WriteLine($"\nTesting key {name}...");
Debug.WriteLine("Testing Press");
var expectedResult = pressResult;
var actualResult = sch.TranslateScanCodes(pressStrokes);
var actualResult = ScanCodeHelper.TranslateScanCodes(pressStrokes);
AssertResult(actualResult, expectedResult);
Debug.WriteLine("Testing Release");
expectedResult = releaseResult;
actualResult = sch.TranslateScanCodes(releaseStrokes);
actualResult = ScanCodeHelper.TranslateScanCodes(releaseStrokes);
AssertResult(actualResult, expectedResult);
Debug.WriteLine("OK!");
@ -116,7 +114,7 @@ namespace UnitTests
void AssertResult(TranslatedKey actualResult, ExpectedResult expectedResult)
{
Debug.WriteLine($"Expecting code of {expectedResult.Code}, state of {expectedResult.State}");
Assert.That(actualResult.AhkCode, Is.EqualTo(expectedResult.Code), $"Code should be {expectedResult.Code}, got {actualResult.AhkCode}");
Assert.That(actualResult.Code, Is.EqualTo(expectedResult.Code), $"Code should be {expectedResult.Code}, got {actualResult.Code}");
Assert.That(actualResult.State, Is.EqualTo(expectedResult.State), $"State should be {expectedResult.State}, got {actualResult.State}");
}
}

@ -144,7 +144,7 @@ namespace UnitTestsFoo
{
Debug.WriteLine($"Expecting code of {expectedResult.Code}, state of {expectedResult.State}");
Assert.That(actualResult != null, "Result should not be null");
Assert.That(actualResult.AhkCode, Is.EqualTo(expectedResult.Code), $"Code should be {expectedResult.Code}, got {actualResult.AhkCode}");
Assert.That(actualResult.Code, Is.EqualTo(expectedResult.Code), $"Code should be {expectedResult.Code}, got {actualResult.Code}");
Assert.That(actualResult.State, Is.EqualTo(expectedResult.State), $"State should be {expectedResult.State}, got {actualResult.State}");
}
}

Loading…
Cancel
Save