-
Notifications
You must be signed in to change notification settings - Fork 435
/
Copy pathTouchpadHandler.cs
112 lines (92 loc) · 3.71 KB
/
TouchpadHandler.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
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System;
using osu.Framework.Bindables;
using osu.Framework.Input.StateChanges;
using osu.Framework.Platform;
using osu.Framework.Statistics;
using osuTK;
using osuTK.Input;
namespace osu.Framework.Input.Handlers.Touchpad
{
/// <summary>
/// For <see cref="IWindow"/> implementing <see cref="IHasTouchpadInput"/>. Translate the touchpad events to mouse events.
/// </summary>
public class TouchpadHandler : InputHandler, IHasCursorSensitivity
{
private static readonly GlobalStatistic<ulong> statistic_total_events = GlobalStatistics.Get<ulong>(StatisticGroupFor<TouchpadHandler>(), "Total events");
public override string Description => "Touchpad";
public override bool IsActive => true;
public BindableDouble Sensitivity { get; } = new BindableDouble(1)
{
MinValue = 1,
MaxValue = 10,
Precision = 0.01
};
private IHasTouchpadInput? window;
public override bool Initialize(GameHost host)
{
if (!base.Initialize(host))
return false;
if (host.Window is not IHasTouchpadInput hasTouchpadInput)
return false;
window = hasTouchpadInput;
Enabled.BindValueChanged(enabled =>
{
if (enabled.NewValue)
{
window!.TouchpadDataUpdate += handleTouchpadUpdate;
}
else
{
window!.TouchpadDataUpdate -= handleTouchpadUpdate;
}
}, true);
return true;
}
public override void Reset()
{
Sensitivity.SetDefault();
base.Reset();
}
private void handleTouchpadUpdate(TouchpadData data)
{
// We just use the first reported point (For PoC).
// This might not be the first finger touched.
foreach (var point in data.Points)
{
if (!point.Valid || !point.Confidence) continue;
var position = mapToWindow(data.Info, point);
enqueueInput(new MousePositionAbsoluteInput { Position = position });
break;
}
// TODO Real mouse button event should be suppressed (???) otherwise tapping can be converted to clicks by the OS
// TODO only enqueue when state changed
enqueueInput(new MouseButtonInput(MouseButton.Left, data.ButtonDown));
}
private Vector2 mapToWindow(TouchpadInfo info, TouchpadPoint point)
{
var center = window!.Size / 2;
// centered (-range/2 ~ range/2)
int x = point.X - info.XMin - info.XRange / 2;
int y = point.Y - info.YMin - info.YRange / 2;
// Minimum ratio to cover the whole window
float minimumRatio = Math.Max(
(float)window.Size.Width / info.XRange,
(float)window.Size.Height / info.YRange);
var toWindow = new Vector2(
center.Width + x * minimumRatio * (float)Sensitivity.Value,
center.Height + y * minimumRatio * (float)Sensitivity.Value);
return Vector2.Clamp(
toWindow,
Vector2.Zero,
new Vector2(window.Size.Width - 1, window.Size.Height - 1));
}
private void enqueueInput(IInput input)
{
PendingInputs.Enqueue(input);
FrameStatistics.Increment(StatisticsCounterType.MouseEvents);
statistic_total_events.Value++;
}
}
}