You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AutoHotInterception/C#/AutoHotInterception/DeviceHandlers/DeviceHandler.cs

129 lines
4.8 KiB
C#

using AutoHotInterception.Helpers;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
namespace AutoHotInterception.DeviceHandlers
{
abstract class DeviceHandler : IDeviceHandler
{
protected dynamic ContextCallback;
protected IntPtr DeviceContext;
protected int DeviceId;
protected bool _isFiltered { get; set; }
// Holds MappingOptions for individual mouse button / keyboard key subscriptions
protected ConcurrentDictionary<ushort, MappingOptions> SingleButtonMappings = new ConcurrentDictionary<ushort, MappingOptions>();
// If all mouse buttons or keyboard keys are subscribed, this holds the mapping options
protected MappingOptions AllButtonsMapping;
protected readonly ConcurrentDictionary<ushort, WorkerThread> WorkerThreads = new ConcurrentDictionary<ushort, WorkerThread>();
protected WorkerThread DeviceWorkerThread;
public DeviceHandler(IntPtr deviceContext, int deviceId)
{
DeviceContext = deviceContext;
DeviceId = deviceId;
}
/// <summary>
/// Subscribes to a single key or button of this device
/// </summary>
/// <param name="code">The ScanCode (keyboard) or Button Code (mouse) for the key or button</param>
/// <param name="mappingOptions">Options for the subscription (block, callback to fire etc)</param>
public void SubscribeSingleButton(ushort code, MappingOptions mappingOptions)
{
SingleButtonMappings.TryAdd(code, mappingOptions);
if (!mappingOptions.Concurrent && !WorkerThreads.ContainsKey(code))
{
WorkerThreads.TryAdd(code, new WorkerThread());
}
_isFiltered = true;
}
/// <summary>
/// Unsubscribes from a single key or button of this device
/// </summary>
/// <param name="code">The ScanCode (keyboard) or Button Code (mouse) for the key or button</param>
public void UnsubscribeSingleButton(ushort code)
{
if (!SingleButtonMappings.ContainsKey(code)) return;
SingleButtonMappings.TryRemove(code, out var mappingOptions);
if (!mappingOptions.Concurrent && WorkerThreads.ContainsKey(code))
{
WorkerThreads[code].Dispose();
WorkerThreads.TryRemove(code, out _);
}
DisableFilterIfNeeded();
}
/// <summary>
/// Subscribes to all keys or buttons of this device
/// </summary>
/// <param name="mappingOptions">Options for the subscription (block, callback to fire etc)</param>
public void SubscribeAllButtons(MappingOptions mappingOptions)
{
AllButtonsMapping = mappingOptions;
if (!mappingOptions.Concurrent && DeviceWorkerThread == null)
{
DeviceWorkerThread = new WorkerThread();
}
_isFiltered = true;
}
/// <summary>
/// Unsubscribes from a SubscribeAll for this device
/// </summary>
public void UnsubscribeAllButtons()
{
if (AllButtonsMapping == null) return;
// Stop DeviceWorkerThread
if (!AllButtonsMapping.Concurrent && DeviceWorkerThread != null)
{
DeviceWorkerThread.Dispose();
DeviceWorkerThread = null;
}
AllButtonsMapping = null;
DisableFilterIfNeeded();
}
/// <summary>
/// Enables Context Mode for this device
/// </summary>
/// <param name="callback">The callback to call when input happens</param>
public void SetContextCallback(dynamic callback)
{
ContextCallback = callback;
_isFiltered = true;
}
/// <summary>
/// Removes Context Mode for this device
/// </summary>
public void RemoveContextCallback()
{
ContextCallback = null;
DisableFilterIfNeeded();
}
// ToDo: Why is this IDeviceHandler.IsFiltered() and other Interface methods aren't?
public int IsFiltered()
{
return Convert.ToInt32(_isFiltered);
}
/// <summary>
/// After doing an UnsubscribeButton, UnsubscribeAll, or RemoveContext, this method will be called
/// If no more subscriptions are present, it should remove the filter for this device
/// </summary>
public abstract void DisableFilterIfNeeded();
/// <summary>
/// Process an incoming stroke, or a pair of extended keycode strokes
/// </summary>
/// <param name="strokes">The stroke(s) to process</param>
public abstract void ProcessStroke(List<ManagedWrapper.Stroke> strokes);
}
}