-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPointerProfile.cs
More file actions
91 lines (79 loc) · 3.86 KB
/
Copy pathPointerProfile.cs
File metadata and controls
91 lines (79 loc) · 3.86 KB
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
using SwitchifyPc.Protocol;
using SwitchifyPc.Core.Settings;
namespace SwitchifyPc.Core.Input;
public sealed record Point(double X, double Y);
public sealed record Bounds(double X, double Y, double Width, double Height);
public sealed record DisplayInfo(Bounds Bounds, double ScaleFactor);
public sealed record PointerProfileInput(Point Cursor, DisplayInfo Display, int? MaxDelta = null);
public sealed record RecommendedDeltas(int Small, int Medium, int Large);
public sealed record PointerCapabilities(bool NoAckMouseMove, IReadOnlyList<string> NoAckCommands, IReadOnlyList<string> SupportedCommands);
public sealed record PointerMovementProfile(
string DisplayId,
double ScaleFactor,
Bounds Bounds,
int MaxDelta,
RecommendedDeltas RecommendedDeltas,
PointerCapabilities Capabilities);
public static class PointerProfile
{
private const double ReferencePointerShortEdge = 1080;
private static readonly IReadOnlyDictionary<PointerMovementSizeKey, double> TargetReferenceNativeDeltas =
Enum.GetValues<PointerMovementSizeKey>().ToDictionary(
size => size,
size => ReferencePointerShortEdge * PointerMovementSettingsModel.FractionFor(PointerMovementSettingsModel.Default, size));
public static PointerMovementProfile Create(PointerProfileInput input)
{
Bounds bounds = NormalizeBounds(input.Display.Bounds);
double scaleFactor = double.IsFinite(input.Display.ScaleFactor) && input.Display.ScaleFactor > 0 ? input.Display.ScaleFactor : 1;
int maxDelta = input.MaxDelta ?? ProtocolConstants.MaxPointerDelta;
return new PointerMovementProfile(
DisplayId: $"{FormatNumber(bounds.X)}:{FormatNumber(bounds.Y)}:{FormatNumber(bounds.Width)}:{FormatNumber(bounds.Height)}:{FormatNumber(scaleFactor)}",
ScaleFactor: scaleFactor,
Bounds: bounds,
MaxDelta: maxDelta,
RecommendedDeltas: new RecommendedDeltas(
Small: ToLogicalDelta(TargetReferenceNativeDeltas[PointerMovementSizeKey.Small], scaleFactor, maxDelta),
Medium: ToLogicalDelta(TargetReferenceNativeDeltas[PointerMovementSizeKey.Medium], scaleFactor, maxDelta),
Large: ToLogicalDelta(TargetReferenceNativeDeltas[PointerMovementSizeKey.Large], scaleFactor, maxDelta)),
Capabilities: new PointerCapabilities(
NoAckMouseMove: true,
NoAckCommands: ProtocolConstants.NoAckControlCommandTypes.ToArray(),
SupportedCommands:
[
.. ProtocolConstants.NoAckControlCommandTypes,
"keyboard.textStream.open",
"keyboard.textStream.chunk",
"keyboard.textStream.close",
"connection.ping",
"pointer.profile"
]));
}
private static Bounds NormalizeBounds(Bounds bounds)
{
return new Bounds(
X: FiniteOr(bounds.X, 0),
Y: FiniteOr(bounds.Y, 0),
Width: PositiveFiniteOr(bounds.Width, 1),
Height: PositiveFiniteOr(bounds.Height, 1));
}
private static double FiniteOr(double value, double fallback)
{
return double.IsFinite(value) ? value : fallback;
}
private static double PositiveFiniteOr(double value, double fallback)
{
return double.IsFinite(value) && value > 0 ? value : fallback;
}
private static int ToLogicalDelta(double nativePixels, double scaleFactor, int maxDelta)
{
return Clamp((int)Math.Round(nativePixels / scaleFactor, MidpointRounding.AwayFromZero), 1, maxDelta);
}
private static int Clamp(int value, int min, int max)
{
return Math.Min(max, Math.Max(min, value));
}
private static string FormatNumber(double value)
{
return value.ToString("G15", System.Globalization.CultureInfo.InvariantCulture);
}
}