2022-11-24 22:37:24 +01:00
|
|
|
using WindowsInput;
|
|
|
|
|
using static CommonHelpers.Log;
|
|
|
|
|
|
|
|
|
|
namespace SteamController.Devices
|
|
|
|
|
{
|
|
|
|
|
public class MouseController : IDisposable
|
|
|
|
|
{
|
|
|
|
|
private struct Accum
|
|
|
|
|
{
|
|
|
|
|
double? last, now;
|
|
|
|
|
|
|
|
|
|
public bool Used
|
|
|
|
|
{
|
|
|
|
|
get { return now is not null; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Tick()
|
|
|
|
|
{
|
|
|
|
|
last = now;
|
|
|
|
|
now = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Add(double delta)
|
|
|
|
|
{
|
|
|
|
|
now = (now ?? 0.0) + delta;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public int Consume()
|
|
|
|
|
{
|
|
|
|
|
double accum = ((now ?? 0.0) + (last ?? 0.0));
|
|
|
|
|
now = accum - (int)accum;
|
|
|
|
|
last = null;
|
|
|
|
|
return (int)accum;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO: Unsure what it is
|
|
|
|
|
public const int XButtonID = 0;
|
|
|
|
|
public const int YButtonID = 1;
|
2022-11-27 19:45:14 +01:00
|
|
|
public const int UpdateValidInterval = 100;
|
2022-11-24 22:37:24 +01:00
|
|
|
|
|
|
|
|
InputSimulator simulator = new InputSimulator();
|
|
|
|
|
|
|
|
|
|
HashSet<Button> mouseButtons = new HashSet<Button>();
|
|
|
|
|
HashSet<Button> lastMouseButtons = new HashSet<Button>();
|
|
|
|
|
|
|
|
|
|
Accum movedX, movedY, verticalScroll, horizontalScroll;
|
|
|
|
|
|
|
|
|
|
bool? valid = null;
|
|
|
|
|
DateTime lastValid = DateTime.Now;
|
|
|
|
|
|
|
|
|
|
public enum Button
|
|
|
|
|
{
|
|
|
|
|
Left,
|
|
|
|
|
Right,
|
|
|
|
|
Middle,
|
|
|
|
|
X,
|
|
|
|
|
Y
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool this[Button button]
|
|
|
|
|
{
|
|
|
|
|
get { return mouseButtons.Contains(button); }
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (value)
|
|
|
|
|
mouseButtons.Add(button);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool Valid
|
|
|
|
|
{
|
|
|
|
|
get { return valid ?? true; }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Button[] DownButtons
|
|
|
|
|
{
|
|
|
|
|
get { return mouseButtons.ToArray(); }
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-27 09:19:34 +01:00
|
|
|
internal MouseController()
|
2022-11-24 22:37:24 +01:00
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Safe(Func<bool> action)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (action())
|
|
|
|
|
{
|
|
|
|
|
valid = true;
|
|
|
|
|
lastValid = DateTime.Now;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
catch (InvalidOperationException)
|
|
|
|
|
{
|
|
|
|
|
valid = false;
|
|
|
|
|
lastValid = DateTime.Now;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateValid()
|
|
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
if (valid is null || lastValid.AddMilliseconds(UpdateValidInterval) < DateTime.Now)
|
2022-11-24 22:37:24 +01:00
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
Safe(() =>
|
2022-11-24 22:37:24 +01:00
|
|
|
{
|
|
|
|
|
simulator.Mouse.MoveMouseBy(0, 0);
|
|
|
|
|
return true;
|
2022-11-28 10:44:01 +01:00
|
|
|
});
|
|
|
|
|
}
|
2022-11-24 22:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void BeforeUpdate()
|
|
|
|
|
{
|
|
|
|
|
lastMouseButtons = mouseButtons;
|
|
|
|
|
mouseButtons = new HashSet<Button>();
|
|
|
|
|
movedX.Tick();
|
|
|
|
|
movedY.Tick();
|
|
|
|
|
verticalScroll.Tick();
|
|
|
|
|
horizontalScroll.Tick();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void Update()
|
|
|
|
|
{
|
|
|
|
|
// Mouse Up: it is missing now
|
|
|
|
|
foreach (var button in lastMouseButtons.Except(mouseButtons))
|
|
|
|
|
{
|
|
|
|
|
Safe(() =>
|
|
|
|
|
{
|
|
|
|
|
switch (button)
|
|
|
|
|
{
|
|
|
|
|
case Button.Left:
|
|
|
|
|
simulator.Mouse.LeftButtonUp();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Right:
|
|
|
|
|
simulator.Mouse.RightButtonUp();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Middle:
|
|
|
|
|
simulator.Mouse.MiddleButtonUp();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.X:
|
|
|
|
|
simulator.Mouse.XButtonUp(XButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Y:
|
|
|
|
|
simulator.Mouse.XButtonUp(YButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Key Down: new keys being down
|
|
|
|
|
foreach (var button in mouseButtons.Except(lastMouseButtons))
|
|
|
|
|
{
|
|
|
|
|
Safe(() =>
|
|
|
|
|
{
|
|
|
|
|
switch (button)
|
|
|
|
|
{
|
|
|
|
|
case Button.Left:
|
|
|
|
|
simulator.Mouse.LeftButtonDown();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Right:
|
|
|
|
|
simulator.Mouse.RightButtonDown();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Middle:
|
|
|
|
|
simulator.Mouse.MiddleButtonDown();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.X:
|
|
|
|
|
simulator.Mouse.XButtonDown(XButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Y:
|
|
|
|
|
simulator.Mouse.XButtonDown(YButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Move cursor
|
|
|
|
|
if (movedX.Used || movedY.Used)
|
|
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
int x = movedX.Consume();
|
|
|
|
|
int y = movedY.Consume();
|
|
|
|
|
if (x != 0 || y != 0)
|
2022-11-24 22:37:24 +01:00
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
Safe(() =>
|
|
|
|
|
{
|
|
|
|
|
simulator.Mouse.MoveMouseBy(x, y);
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-11-24 22:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Scroll
|
|
|
|
|
if (verticalScroll.Used)
|
|
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
int value = verticalScroll.Consume();
|
|
|
|
|
if (value != 0)
|
2022-11-24 22:37:24 +01:00
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
Safe(() =>
|
2022-11-27 19:45:14 +01:00
|
|
|
{
|
2022-11-24 22:37:24 +01:00
|
|
|
simulator.Mouse.VerticalScroll(value);
|
2022-11-27 19:45:14 +01:00
|
|
|
return true;
|
2022-11-28 10:44:01 +01:00
|
|
|
});
|
|
|
|
|
}
|
2022-11-24 22:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (horizontalScroll.Used)
|
|
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
int value = horizontalScroll.Consume();
|
|
|
|
|
if (value != 0)
|
2022-11-24 22:37:24 +01:00
|
|
|
{
|
2022-11-28 10:44:01 +01:00
|
|
|
Safe(() =>
|
2022-11-27 19:45:14 +01:00
|
|
|
{
|
2022-11-24 22:37:24 +01:00
|
|
|
simulator.Mouse.HorizontalScroll(value);
|
2022-11-27 19:45:14 +01:00
|
|
|
return true;
|
2022-11-28 10:44:01 +01:00
|
|
|
});
|
|
|
|
|
}
|
2022-11-24 22:37:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
UpdateValid();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void MouseClick(Button button)
|
|
|
|
|
{
|
|
|
|
|
Safe(() =>
|
|
|
|
|
{
|
|
|
|
|
switch (button)
|
|
|
|
|
{
|
|
|
|
|
case Button.Left:
|
|
|
|
|
simulator.Mouse.LeftButtonClick();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Right:
|
|
|
|
|
simulator.Mouse.RightButtonClick();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Middle:
|
|
|
|
|
simulator.Mouse.MiddleButtonClick();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.X:
|
|
|
|
|
simulator.Mouse.XButtonClick(XButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Y:
|
|
|
|
|
simulator.Mouse.XButtonClick(YButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void MouseDoubleClick(Button button)
|
|
|
|
|
{
|
|
|
|
|
Safe(() =>
|
|
|
|
|
{
|
|
|
|
|
switch (button)
|
|
|
|
|
{
|
|
|
|
|
case Button.Left:
|
|
|
|
|
simulator.Mouse.LeftButtonDoubleClick();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Right:
|
|
|
|
|
simulator.Mouse.RightButtonDoubleClick();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Middle:
|
|
|
|
|
simulator.Mouse.MiddleButtonDoubleClick();
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.X:
|
|
|
|
|
simulator.Mouse.XButtonDoubleClick(XButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
case Button.Y:
|
|
|
|
|
simulator.Mouse.XButtonDoubleClick(YButtonID);
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void MoveBy(double pixelDeltaX, double pixelDeltaY)
|
|
|
|
|
{
|
|
|
|
|
movedX.Add(pixelDeltaX);
|
|
|
|
|
movedY.Add(pixelDeltaY);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void MoveTo(double absoluteX, double absoluteY)
|
|
|
|
|
{
|
|
|
|
|
Safe(() =>
|
|
|
|
|
{
|
|
|
|
|
simulator.Mouse.MoveMouseTo(absoluteX, absoluteY);
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void VerticalScroll(double scrollAmountInClicks)
|
|
|
|
|
{
|
|
|
|
|
verticalScroll.Add(scrollAmountInClicks);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void HorizontalScroll(double scrollAmountInClicks)
|
|
|
|
|
{
|
|
|
|
|
horizontalScroll.Add(scrollAmountInClicks);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|