forked from kmcnaught/SmoothMousePlugin
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMouseInput.cs
157 lines (127 loc) · 4.13 KB
/
MouseInput.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
using System;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Net.Sockets;
using System.Text;
using System.Text.Json;
using System.Windows;
using System.ComponentModel;
using System.Threading;
using JuliusSweetland.OptiKey.Contracts;
using JuliusSweetland.OptiKey.Static;
using System.Runtime.InteropServices;
namespace EyeGestures
{
public class MousePosition
{
public double x { get; set; }
public double y { get; set; }
public bool blink { get; set; }
public bool fixation { get; set; }
}
public class EyeGesturesInput : IPointService, IDisposable
{
#region Fields
private event EventHandler<Timestamped<Point>> pointEvent;
private BackgroundWorker pollWorker;
private TcpClient tcpClient;
private NetworkStream networkStream;
#endregion
#region Ctor
private const string ServerIp = "127.0.0.1"; // Replace with your server IP
private const int ServerPort = 65432; // Replace with your server port
public EyeGesturesInput()
{
try
{
pollWorker = new BackgroundWorker();
pollWorker.DoWork += pollMouse;
pollWorker.WorkerSupportsCancellation = true;
tcpClient = new TcpClient();
tcpClient.Connect(ServerIp, ServerPort);
networkStream = tcpClient.GetStream();
}
catch (Exception ex)
{
PublishError(this, ex);
}
}
public void Dispose()
{
pollWorker.CancelAsync();
networkStream.Close();
tcpClient.Close();
pollWorker.Dispose();
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
#endregion
#region Events
public event EventHandler<Exception> Error;
public event EventHandler<Timestamped<Point>> Point
{
add
{
if (pointEvent == null)
{
// Start polling the mouse
pollWorker.RunWorkerAsync();
}
pointEvent += value;
}
remove
{
pointEvent -= value;
if (pointEvent?.GetInvocationList().Length == 0)
{
pollWorker.CancelAsync();
}
}
}
#endregion
#region Private methods
private void pollMouse(object sender, DoWorkEventArgs e)
{
while (!pollWorker.CancellationPending)
{
try{
// Get latest mouse position from the socket
var timeStamp = Time.HighResolutionUtcNow.ToUniversalTime();
// Read JSON data from the socket
byte[] buffer = new byte[1024];
int bytesRead = networkStream.Read(buffer, 0, buffer.Length);
string jsonData = Encoding.UTF8.GetString(buffer, 0, bytesRead);
// Parse JSON data
var mousePosition = JsonSerializer.Deserialize<MousePosition>(jsonData);
// Gets the absolute mouse position, relative to screen
double x = mousePosition.x;
double y = mousePosition.y;
// Emit a point event
pointEvent?.Invoke(this, new Timestamped<Point>(new Point((int)x, (int)y), timeStamp));
}
catch (Exception ex)
{
PublishError(this, ex);
}
// Sleep thread to avoid hot loop
int delay = 30; // ms
Thread.Sleep(delay);
}
}
#endregion
#region Publish Error
private void PublishError(object sender, Exception ex)
{
if (Error != null)
{
Error(sender, ex);
}
}
#endregion
}
}