LenovoLegionToolkit
135 строк · 4.4 Кб
1using System;
2using System.Linq;
3using System.Threading.Tasks;
4using LenovoLegionToolkit.Lib.Extensions;
5using LenovoLegionToolkit.Lib.System;
6using LenovoLegionToolkit.Lib.Utils;
7using WindowsDisplayAPI;
8using WindowsDisplayAPI.Native.DeviceContext;
9
10namespace LenovoLegionToolkit.Lib.Features;
11
12public class RefreshRateFeature : IFeature<RefreshRate>
13{
14public Task<bool> IsSupportedAsync() => Task.FromResult(true);
15
16public Task<RefreshRate[]> GetAllStatesAsync()
17{
18if (Log.Instance.IsTraceEnabled)
19Log.Instance.Trace($"Getting all refresh rates...");
20
21var display = InternalDisplay.Get();
22if (display is null)
23{
24if (Log.Instance.IsTraceEnabled)
25Log.Instance.Trace($"Built in display not found");
26
27return Task.FromResult(Array.Empty<RefreshRate>());
28}
29
30if (Log.Instance.IsTraceEnabled)
31Log.Instance.Trace($"Built in display found: {display}");
32
33var currentSettings = display.CurrentSetting;
34
35if (Log.Instance.IsTraceEnabled)
36Log.Instance.Trace($"Current built in display settings: {currentSettings.ToExtendedString()}");
37
38var result = display.GetPossibleSettings()
39.Where(dps => Match(dps, currentSettings))
40.Select(dps => dps.Frequency)
41.Distinct()
42.OrderBy(freq => freq)
43.Select(freq => new RefreshRate(freq))
44.ToArray();
45
46if (Log.Instance.IsTraceEnabled)
47Log.Instance.Trace($"Possible refresh rates are {string.Join(", ", result)}");
48
49return Task.FromResult(result);
50}
51
52public Task<RefreshRate> GetStateAsync()
53{
54if (Log.Instance.IsTraceEnabled)
55Log.Instance.Trace($"Getting current refresh rate...");
56
57var display = InternalDisplay.Get();
58if (display is null)
59{
60if (Log.Instance.IsTraceEnabled)
61Log.Instance.Trace($"Built in display not found");
62
63return Task.FromResult(default(RefreshRate));
64}
65
66var currentSettings = display.CurrentSetting;
67var result = new RefreshRate(currentSettings.Frequency);
68
69if (Log.Instance.IsTraceEnabled)
70Log.Instance.Trace($"Current refresh rate is {result} [currentSettings={currentSettings.ToExtendedString()}]");
71
72return Task.FromResult(result);
73}
74
75public Task SetStateAsync(RefreshRate state)
76{
77var display = InternalDisplay.Get();
78if (display is null)
79{
80if (Log.Instance.IsTraceEnabled)
81Log.Instance.Trace($"Built in display not found");
82throw new InvalidOperationException("Built in display not found");
83}
84
85var currentSettings = display.CurrentSetting;
86
87if (Log.Instance.IsTraceEnabled)
88Log.Instance.Trace($"Current built in display settings: {currentSettings.ToExtendedString()}");
89
90if (currentSettings.Frequency == state.Frequency)
91{
92if (Log.Instance.IsTraceEnabled)
93Log.Instance.Trace($"Frequency already set to {state.Frequency}");
94
95return Task.CompletedTask;
96}
97
98var possibleSettings = display.GetPossibleSettings();
99var newSettings = possibleSettings
100.Where(dps => Match(dps, currentSettings))
101.Where(dps => dps.Frequency == state.Frequency)
102.Select(dps => new DisplaySetting(dps, currentSettings.Position, currentSettings.Orientation, DisplayFixedOutput.Default))
103.FirstOrDefault();
104
105if (newSettings is not null)
106{
107if (Log.Instance.IsTraceEnabled)
108Log.Instance.Trace($"Setting display to {newSettings.ToExtendedString()}...");
109
110display.SetSettings(newSettings, true);
111
112if (Log.Instance.IsTraceEnabled)
113Log.Instance.Trace($"Display set to {newSettings.ToExtendedString()}");
114}
115else
116{
117if (Log.Instance.IsTraceEnabled)
118Log.Instance.Trace($"Could not find matching settings for frequency {state}");
119}
120
121return Task.CompletedTask;
122}
123
124private static bool Match(DisplayPossibleSetting dps, DisplayPossibleSetting ds)
125{
126if (dps.IsTooSmall())
127return false;
128
129var result = true;
130result &= dps.Resolution == ds.Resolution;
131result &= dps.ColorDepth == ds.ColorDepth;
132result &= dps.IsInterlaced == ds.IsInterlaced;
133return result;
134}
135}
136