Created
May 7, 2016 02:07
-
-
Save galvesribeiro/33675d6e707df8639f6ca3cbaae8c8c0 to your computer and use it in GitHub Desktop.
Input providers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public abstract class GenericInputProvider : ITouchProvider, IKeyboardInputProvider | |
{ | |
public event Action<TouchData> Touch; | |
public event Action<Keys> KeyPressed; | |
public event Action<Keys> KeyReleased; | |
private string _keyboardDevice; | |
private string _touchDevice; | |
private int _touchFd = -1; | |
private int _keyboardFd = -1; | |
private bool _isListeningToTouch; | |
public bool IsListeningToTouch | |
{ | |
get { return _isListeningToTouch; } | |
set | |
{ | |
if (!string.IsNullOrWhiteSpace(_touchDevice) && _isListeningToTouch != value) | |
{ | |
_isListeningToTouch = value; | |
if (_isListeningToTouch) | |
{ | |
_touchFd = NativeOpen(_touchDevice, 2); | |
if (_touchFd < 0) | |
throw new InvalidOperationException($"Unable to open touch device {_touchDevice}. Return code {_touchFd}."); | |
ListenToTouch(); | |
} | |
else | |
{ | |
NativeClose(_touchFd); | |
} | |
} | |
} | |
} | |
private bool _isListeningToKeys; | |
public bool IsListeningToKeys | |
{ | |
get { return _isListeningToKeys; } | |
set | |
{ | |
if (!string.IsNullOrWhiteSpace(_keyboardDevice) && _isListeningToKeys != value) | |
{ | |
_isListeningToKeys = value; | |
if (_isListeningToKeys) | |
{ | |
_keyboardFd = NativeOpen(_keyboardDevice, 2); | |
if (_keyboardFd < 0) | |
throw new InvalidOperationException($"Unable to open keyboard device {_keyboardDevice}. Return code {_keyboardFd}."); | |
ListenToKeyboard(); | |
} | |
else | |
{ | |
NativeClose(_keyboardFd); | |
} | |
} | |
} | |
} | |
public GenericInputProvider(string keyboardDevice, string touchDevice = "") | |
{ | |
if (string.IsNullOrWhiteSpace(keyboardDevice)) | |
throw new ArgumentNullException("keyboardDevice"); | |
_keyboardDevice = keyboardDevice; | |
_touchDevice = touchDevice; | |
} | |
private void ListenToTouch() | |
{ | |
new Thread(new ThreadStart(() => | |
{ | |
var ev = new InputEvent[64]; | |
var size = Marshal.SizeOf(typeof(InputEvent)); | |
var totalSize = size * 64; | |
var buffer_ptr = Marshal.AllocHGlobal(totalSize); | |
while (_isListeningToTouch) | |
{ | |
var rd = NativeRead(_touchFd, buffer_ptr, totalSize); | |
if (rd > size) | |
{ | |
var eventNum = rd / size; | |
var event_ptr = buffer_ptr; | |
var touchData = new TouchData(); | |
for (int i = 0; i < eventNum; i++) | |
{ | |
var entry = new InputEvent(); | |
Marshal.PtrToStructure(event_ptr, entry); | |
event_ptr = IntPtr.Add(event_ptr, size); | |
if (entry.type == 0x00) //EV_SYN | |
continue; | |
if (entry.type == 0x01 && entry.code == 0x14A) //EV_TOUCH | |
{ | |
if (entry.value == 1) | |
{ | |
touchData.Type = TouchEventType.Down; | |
} | |
else if (entry.value == 0) | |
{ | |
touchData.Type = TouchEventType.Up; | |
} | |
} | |
else if (entry.type == 0x03) //EV_ABS | |
{ | |
if (touchData.Type == TouchEventType.None) | |
{ | |
touchData.Type = TouchEventType.Move; | |
} | |
if (entry.code == 0x00) | |
{ | |
touchData.X = entry.value; | |
} | |
else if (entry.code == 0x01) | |
{ | |
touchData.Y = entry.value; | |
} | |
} | |
//Console.WriteLine($"[Touch] code {entry.code} | type {entry.type} | value {entry.value}"); | |
} | |
if (Touch != null && Touch.GetInvocationList().Length > 0) | |
Touch(touchData); | |
} | |
//Thread.Sleep(300); | |
} | |
//Marshal.FreeHGlobal(buffer_ptr); | |
})).Start(); | |
} | |
private void ListenToKeyboard() | |
{ | |
new Thread(new ThreadStart(() => { | |
var ev = new InputEvent[64]; | |
var size = Marshal.SizeOf(typeof(InputEvent)); | |
var totalSize = size * 64; | |
var buffer_ptr = Marshal.AllocHGlobal(totalSize); | |
while (_isListeningToKeys) | |
{ | |
var rd = NativeRead(_keyboardFd, buffer_ptr, totalSize); | |
if (rd > size) | |
{ | |
var eventNum = rd / size; | |
var event_ptr = buffer_ptr; | |
for (int i = 0; i < eventNum; i++) | |
{ | |
var entry = new InputEvent(); | |
Marshal.PtrToStructure(event_ptr, entry); | |
event_ptr = IntPtr.Add(event_ptr, size); | |
if (entry.type == 0x00) //EV_SYN | |
continue; | |
if (entry.type == 1) | |
{ | |
if (entry.value == 1 && KeyPressed != null && | |
KeyPressed.GetInvocationList().Length > 0) | |
{ | |
KeyPressed(GetKey(entry.code)); | |
} | |
else | |
if (entry.value == 0 && KeyReleased != null && | |
KeyReleased.GetInvocationList().Length > 0) | |
{ | |
KeyReleased(GetKey(entry.code)); | |
} | |
} | |
} | |
} | |
//Thread.Sleep(300); | |
} | |
})).Start(); | |
} | |
protected abstract Keys GetKey(int nativeKeyValue); | |
#region Native | |
private const string LIBC = "libc"; | |
[DllImport(LIBC, EntryPoint = "open")] | |
private static extern int NativeOpen([In()] [MarshalAs(UnmanagedType.LPStr)] string file, int oflag); | |
[DllImport(LIBC, EntryPoint = "close")] | |
private static extern int NativeClose(int fd); | |
[DllImport(LIBC, EntryPoint = "read", CallingConvention = CallingConvention.Cdecl)] | |
private static extern int NativeRead(int fd, IntPtr buf, int nbytes); | |
[StructLayout(LayoutKind.Sequential)] | |
private struct InputEvent | |
{ | |
public int Seconds; | |
public int Microseconds; | |
public ushort type; | |
public ushort code; | |
public int value; | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment