Skip to content

Commit 6cdd2ea

Browse files
Merge pull request #369 from raisingthefloor/christopher/atusecounter
Add initial atusecounter functionality to Morphic
2 parents 99e7643 + 245d10f commit 6cdd2ea

40 files changed

+2294
-518
lines changed

Morphic.Client/App.xaml.cs

+49-233
Large diffs are not rendered by default.

Morphic.Client/AtUseCounter/AtUseCounterEngine.cs

+1,141
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2020-2023 Raising the Floor - US, Inc.
2+
//
3+
// Licensed under the New BSD license. You may not use this file except in
4+
// compliance with this License.
5+
//
6+
// You may obtain a copy of the License at
7+
// https://github.com/raisingthefloor/morphic-windows/blob/master/LICENSE.txt
8+
//
9+
// The R&D leading to these results received funding from the:
10+
// * Rehabilitation Services Administration, US Dept. of Education under
11+
// grant H421A150006 (APCP)
12+
// * National Institute on Disability, Independent Living, and
13+
// Rehabilitation Research (NIDILRR)
14+
// * Administration for Independent Living & Dept. of Education under grants
15+
// H133E080022 (RERC-IT) and H133E130028/90RE5003-01-00 (UIITA-RERC)
16+
// * European Union's Seventh Framework Programme (FP7/2007-2013) grant
17+
// agreement nos. 289016 (Cloud4all) and 610510 (Prosperity4All)
18+
// * William and Flora Hewlett Foundation
19+
// * Ontario Ministry of Research and Innovation
20+
// * Canadian Foundation for Innovation
21+
// * Adobe Foundation
22+
// * Consumer Electronics Association Foundation
23+
24+
using System;
25+
using System.Collections.Generic;
26+
using System.Linq;
27+
using System.Text;
28+
using System.Threading.Tasks;
29+
30+
namespace Morphic.Client.AtUseCounter;
31+
32+
internal struct DarkThemeState
33+
{
34+
public bool? AppsUseDarkTheme;
35+
public bool? SystemUsesDarkTheme;
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2020-2023 Raising the Floor - US, Inc.
2+
//
3+
// Licensed under the New BSD license. You may not use this file except in
4+
// compliance with this License.
5+
//
6+
// You may obtain a copy of the License at
7+
// https://github.com/raisingthefloor/morphic-windows/blob/master/LICENSE.txt
8+
//
9+
// The R&D leading to these results received funding from the:
10+
// * Rehabilitation Services Administration, US Dept. of Education under
11+
// grant H421A150006 (APCP)
12+
// * National Institute on Disability, Independent Living, and
13+
// Rehabilitation Research (NIDILRR)
14+
// * Administration for Independent Living & Dept. of Education under grants
15+
// H133E080022 (RERC-IT) and H133E130028/90RE5003-01-00 (UIITA-RERC)
16+
// * European Union's Seventh Framework Programme (FP7/2007-2013) grant
17+
// agreement nos. 289016 (Cloud4all) and 610510 (Prosperity4All)
18+
// * William and Flora Hewlett Foundation
19+
// * Ontario Ministry of Research and Innovation
20+
// * Canadian Foundation for Innovation
21+
// * Adobe Foundation
22+
// * Consumer Electronics Association Foundation
23+
24+
using System;
25+
using System.Collections.Generic;
26+
using System.Linq;
27+
using System.Text;
28+
using System.Threading.Tasks;
29+
30+
namespace Morphic.Client.AtUseCounter;
31+
32+
internal struct DisplayState
33+
{
34+
public Morphic.WindowsNative.Display.Display Display;
35+
public double ScalePercentage;
36+
}

Morphic.Client/Bar/Data/Actions/Functions.cs

+4-84
Original file line numberDiff line numberDiff line change
@@ -1112,48 +1112,7 @@ private static async Task<MorphicResult<GetRemovableDisksAndDrivesResult, Morphi
11121112
internal async static Task<MorphicResult<bool, MorphicUnit>> GetDarkModeStateAsync()
11131113
{
11141114
var osVersion = Morphic.WindowsNative.OsVersion.OsVersion.GetWindowsVersion();
1115-
if (osVersion == Morphic.WindowsNative.OsVersion.WindowsVersion.Win10_v1809)
1116-
{
1117-
// Windows 10 v1809
1118-
1119-
// NOTE: this is hard-coded, as a patch, because the solutions registry does not yet understand how to capture/apply settings across incompatible handlers
1120-
// [and trying to call the Windows 10 v1903+ handlers for apps/system "light theme" will result in a memory access exception under v1809]
1121-
// [also: only "AppsUseLightTheme" (and not "SystemUsesLightTheme") existed properly under Windows 10 v1809]
1122-
1123-
var openPersonalizeKeyResult = Morphic.WindowsNative.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize", true);
1124-
if (openPersonalizeKeyResult.IsError == true)
1125-
{
1126-
return MorphicResult.ErrorResult();
1127-
}
1128-
var personalizeKey = openPersonalizeKeyResult.Value!;
1129-
1130-
// get the current setting
1131-
bool appsUseLightThemeAsBool;
1132-
var getAppsUseLightThemeResult = personalizeKey.GetValueData<uint>("AppsUseLightTheme");
1133-
if (getAppsUseLightThemeResult.IsError == true)
1134-
{
1135-
switch (getAppsUseLightThemeResult.Error!.Value)
1136-
{
1137-
case WindowsNative.Registry.RegistryKey.RegistryGetValueError.Values.ValueDoesNotExist:
1138-
// default AppsUseLightTheme (inverse of dark mode state) on Windows 10 v1809 is true
1139-
appsUseLightThemeAsBool = true;
1140-
break;
1141-
default:
1142-
return MorphicResult.ErrorResult();
1143-
}
1144-
}
1145-
else
1146-
{
1147-
var appsUseLightThemeAsUInt32 = getAppsUseLightThemeResult.Value!;
1148-
appsUseLightThemeAsBool = (appsUseLightThemeAsUInt32 != 0) ? true : false;
1149-
}
1150-
1151-
// dark theme state is the inverse of AppsUseLightTheme
1152-
var darkThemeState = !appsUseLightThemeAsBool;
1153-
1154-
return MorphicResult.OkResult(darkThemeState);
1155-
}
1156-
else if (osVersion is null)
1115+
if (osVersion is null)
11571116
{
11581117
// error
11591118
return MorphicResult.ErrorResult();
@@ -1191,47 +1150,7 @@ internal async static Task<MorphicResult<bool, MorphicUnit>> GetDarkModeStateAsy
11911150
internal async static Task<MorphicResult<MorphicUnit, MorphicUnit>> SetDarkModeStateAsync(bool state)
11921151
{
11931152
var osVersion = Morphic.WindowsNative.OsVersion.OsVersion.GetWindowsVersion();
1194-
if (osVersion == Morphic.WindowsNative.OsVersion.WindowsVersion.Win10_v1809)
1195-
{
1196-
// Windows 10 v1809
1197-
1198-
// NOTE: this is hard-coded, as a patch, because the solutions registry does not yet understand how to capture/apply settings across incompatible handlers
1199-
// [and trying to call the Windows 10 v1903+ handlers for apps/system "light theme" will result in a memory access exception under v1809]
1200-
// [also: only "AppsUseLightTheme" (and not "SystemUsesLightTheme") existed properly under Windows 10 v1809]
1201-
1202-
var openPersonalizeKeyResult = Morphic.WindowsNative.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize", true);
1203-
if (openPersonalizeKeyResult.IsError == true)
1204-
{
1205-
return MorphicResult.ErrorResult();
1206-
}
1207-
var personalizeKey = openPersonalizeKeyResult.Value!;
1208-
1209-
// set apps dark/light theme
1210-
//
1211-
uint newAppsUseLightThemeAsUInt32 = state ? (uint)0 : (uint)1; // NOTE: these are inverted (because we are setting "light state" using the inverse of the "dark state" parameter
1212-
//
1213-
// set the setting to the inverted state
1214-
var setAppsUseLightThemeResult = personalizeKey.SetValue<uint>("AppsUseLightTheme", newAppsUseLightThemeAsUInt32);
1215-
if (setAppsUseLightThemeResult.IsError == true)
1216-
{
1217-
return MorphicResult.ErrorResult();
1218-
}
1219-
1220-
// see: https://docs.microsoft.com/en-us/windows/win32/winmsg/wm-wininichange
1221-
var pointerToImmersiveColorSetString = Marshal.StringToHGlobalUni("ImmersiveColorSet");
1222-
try
1223-
{
1224-
// notify all windows that we have changed a setting in the "win ini" settings
1225-
// NOTE: we use SendNotifyMessage instead of SendMessage since we are broadcasting the message and we want to avoid any chance that a locked-up top-level window would lock up our app (since SendMessage does not return until all windows have processed a broadcast message)
1226-
// [in the future, we may want to consider using SendMessageCallback so that we can wait some time for the action to complete as a UI optimization]
1227-
_ = WinApi.SendNotifyMessage(WinApi.HWND_BROADCAST, WinApi.WM_WININICHANGE, UIntPtr.Zero, pointerToImmersiveColorSetString);
1228-
}
1229-
finally
1230-
{
1231-
Marshal.FreeHGlobal(pointerToImmersiveColorSetString);
1232-
}
1233-
}
1234-
else if (osVersion is null)
1153+
if (osVersion is null)
12351154
{
12361155
// error
12371156
return MorphicResult.ErrorResult();
@@ -1242,7 +1161,8 @@ internal async static Task<MorphicResult<MorphicUnit, MorphicUnit>> SetDarkModeS
12421161

12431162
/*
12441163
* NOTE: in addition to the SPI implementation (in code, below), we could also turn on/off the dark theme (via powershell...or possibly via direct registry access); here are the corresponding PowerShell commands
1245-
* NOTE: we use registry access to get/set dark mode under Windows 10 <=v1809 (see code above); the "system dark theme" was introduced in Windows 10 v1903
1164+
* NOTE: we used registry access to get/set dark mode prior to Windows 10 v1903
1165+
* NOTE: the "system dark theme" was introduced in Windows 10 v1903
12461166
*
12471167
* SWITCH TO LIGHT MODE:
12481168
* New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize -Name SystemUsesLightTheme -Value 1 -Type Dword -Force

Morphic.Client/Bar/UI/BarControls/MultiButtonBarControl.xaml.cs

+1-53
Original file line numberDiff line numberDiff line change
@@ -332,59 +332,7 @@ public async Task SetControlAsync(ButtonBase control)
332332
var darkModeState = getDarkModeStateResult.Value!;
333333

334334
var osVersion = Morphic.WindowsNative.OsVersion.OsVersion.GetWindowsVersion();
335-
if (osVersion == Morphic.WindowsNative.OsVersion.WindowsVersion.Win10_v1809)
336-
{
337-
// Windows 10 v1809
338-
339-
// NOTE: this is hard-coded, as a patch, because the solutions registry does not yet understand how to capture/apply settings across incompatible handlers
340-
// [and trying to call the Windows 10 v1903+ handlers for apps/system "light theme" will result in a memory access exception under v1809]
341-
// [also: only "AppsUseLightTheme" (and not "SystemUsesLightTheme") existed properly under Windows 10 v1809]
342-
343-
var openPersonalizeKeyResult = Morphic.WindowsNative.Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize", true);
344-
if (openPersonalizeKeyResult.IsError == true)
345-
{
346-
Debug.Assert(false, "Could not get Personalize key from registry (so we cannot watch the dark mode state)");
347-
}
348-
else
349-
{
350-
var personalizeKey = openPersonalizeKeyResult.Value!;
351-
352-
var registerForChangesEvent = new Morphic.WindowsNative.Registry.RegistryKey.RegistryKeyChangedEventHandler(async (sender, e) =>
353-
{
354-
await Application.Current.Dispatcher.InvokeAsync(async () =>
355-
{
356-
var getDarkModeStateResult = await Morphic.Client.Bar.Data.Actions.Functions.GetDarkModeStateAsync();
357-
if (getDarkModeStateResult.IsError == true)
358-
{
359-
Debug.Assert(false, "Could not get dark mode state");
360-
return;
361-
}
362-
var darkModeState = getDarkModeStateResult.Value!;
363-
364-
Setting appsThemeSetting = App.Current.MorphicSession.Solutions.GetSetting(Settings.SolutionsRegistry.SettingId.LightThemeApps);
365-
Application.Current.Dispatcher.Invoke(new Action(() =>
366-
{
367-
this.InverseSettingOnChanged(sender, new SettingEventArgs(appsThemeSetting, !darkModeState));
368-
}));
369-
});
370-
});
371-
personalizeKey.RegistryKeyChangedEvent += registerForChangesEvent;
372-
373-
this.Control.Unloaded += (sender, SettingEventArgs) =>
374-
{
375-
// dispose of the RegistryKey; this should terminate the notification registration as well
376-
personalizeKey.Dispose();
377-
};
378-
}
379-
380-
// TODO: add a registry hook which watches for the value to change (and which calls "this.InverseSettingOnChanged")
381-
// [and unwire the handler when our control is unloaded]
382-
// TODO: we need to make sure that we wire this up in a way that the registry key doesn't get GC'd prematurely
383-
//appsThemeRegistryKey.Changed += this.InverseSettingOnChanged;
384-
////
385-
//this.Control.Unloaded += (sender, args) => appsThemeRegistryKey.Changed -= this.InverseSettingOnChanged;
386-
}
387-
else if (osVersion is null)
335+
if (osVersion is null)
388336
{
389337
// error
390338
//break;

Morphic.Client/Config/ConfigurableFeatures.cs

+4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public enum MorphicBarVisibilityAfterLoginOption
2222

2323
public static bool AtOnDemandIsEnabled = true;
2424
//
25+
public static bool AtUseCounterIsEnabled = false;
26+
//
2527
public static AutorunConfigOption? AutorunConfig = null;
2628
//
2729
public static bool CheckForUpdatesIsEnabled = false;
@@ -40,6 +42,7 @@ public enum MorphicBarVisibilityAfterLoginOption
4042

4143
public static void SetFeatures(
4244
bool atOnDemandIsEnabled,
45+
bool atUseCounterIsEnabled,
4346
AutorunConfigOption? autorunConfig,
4447
bool checkForUpdatesIsEnabled,
4548
bool cloudSettingsTransferIsEnabled,
@@ -51,6 +54,7 @@ public static void SetFeatures(
5154
)
5255
{
5356
ConfigurableFeatures.AtOnDemandIsEnabled = atOnDemandIsEnabled;
57+
ConfigurableFeatures.AtUseCounterIsEnabled = atUseCounterIsEnabled;
5458
ConfigurableFeatures.AutorunConfig = autorunConfig;
5559
ConfigurableFeatures.CheckForUpdatesIsEnabled = checkForUpdatesIsEnabled;
5660
ConfigurableFeatures.CloudSettingsTransferIsEnabled = cloudSettingsTransferIsEnabled;

Morphic.Client/Menu/MorphicMenu.xaml.cs

+3-10
Original file line numberDiff line numberDiff line change
@@ -154,15 +154,12 @@ private async void WindowsSettingsAllAccessibilityOptionsClicked(object sender,
154154
{
155155
switch (windowsVersion)
156156
{
157-
case WindowsVersion.Win10_v1809:
158-
case WindowsVersion.Win10_v1903:
159-
case WindowsVersion.Win10_v1909:
160157
case WindowsVersion.Win10_v2004:
161158
case WindowsVersion.Win10_v20H2:
162159
case WindowsVersion.Win10_v21H1:
163160
case WindowsVersion.Win10_v21H2:
164161
case WindowsVersion.Win10_v22H2:
165-
// Windows 10 1809, 1903, 1909, 2004, 20H2, 21H1, 21H2
162+
// Windows 10 2004, 20H2, 21H1, 21H2
166163
// NOTE: we should re-evaluate this path in all versions of Windows (to verify that it shouldn't be simply "ms-settings:easeofaccess" instead)
167164
settingsUrlAsPath = "ms-settings:easeofaccess-display";
168165
break;
@@ -172,6 +169,7 @@ private async void WindowsSettingsAllAccessibilityOptionsClicked(object sender,
172169
break;
173170
case WindowsVersion.Win11_v21H2:
174171
case WindowsVersion.Win11_v22H2:
172+
case WindowsVersion.Win11_v23H2:
175173
case WindowsVersion.Win11_vFuture:
176174
// Windows 11 21H2 (and assumed for the future)
177175
settingsUrlAsPath = "ms-settings:easeofaccess";
@@ -202,12 +200,6 @@ private async void WindowsSettingsPointerSizeClicked(object sender, RoutedEventA
202200
{
203201
switch (windowsVersion)
204202
{
205-
case WindowsVersion.Win10_v1809:
206-
case WindowsVersion.Win10_v1903:
207-
case WindowsVersion.Win10_v1909:
208-
// Windows 10 1809, 1903, 1909
209-
settingsUrlAsPath = "ms-settings:easeofaccess-cursorandpointersize";
210-
break;
211203
case WindowsVersion.Win10_v2004:
212204
// Windows 10 2004
213205
settingsUrlAsPath = "ms-settings:easeofaccess-MousePointer";
@@ -248,6 +240,7 @@ private async void WindowsSettingsPointerSizeClicked(object sender, RoutedEventA
248240
break;
249241
case WindowsVersion.Win11_v21H2:
250242
case WindowsVersion.Win11_v22H2:
243+
case WindowsVersion.Win11_v23H2:
251244
case WindowsVersion.Win11_vFuture:
252245
// Windows 11 21H2 (and assumed for the future)
253246
settingsUrlAsPath = "ms-settings:easeofaccess-mousepointer";

Morphic.Client/Morphic.Client.csproj

+5-5
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686

8787
<ItemGroup>
8888
<PackageReference Include="AToD.Deployment.MSI" Version="0.9.0" />
89-
<PackageReference Include="Autoupdater.NET.Official" Version="1.7.6" />
89+
<PackageReference Include="Autoupdater.NET.Official" Version="1.8.4" />
9090
<PackageReference Include="CommandLineParser" Version="2.9.1" />
9191
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="7.0.0" />
9292
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="7.0.0" />
@@ -95,13 +95,13 @@
9595
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="7.0.0" />
9696
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="7.0.0" />
9797
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="7.0.0" />
98-
<PackageReference Include="Morphic.Core" Version="1.2.0" />
98+
<PackageReference Include="Morphic.Core" Version="1.3.1" />
9999
<PackageReference Include="Morphic.OAuth.Client" Version="0.3.0" />
100-
<PackageReference Include="Morphic.OAuth.Core" Version="1.2.0" />
100+
<PackageReference Include="Morphic.OAuth.Core" Version="1.3.0" />
101101
<PackageReference Include="Morphic.TelemetryClient" Version="2.0.2" />
102102
<!-- <PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" /> -->
103-
<PackageReference Include="NHotkey.Wpf" Version="2.1.0" />
104-
<PackageReference Include="NReco.Logging.File" Version="1.1.5" />
103+
<PackageReference Include="NHotkey.Wpf" Version="2.1.1" />
104+
<PackageReference Include="NReco.Logging.File" Version="1.1.7" />
105105
</ItemGroup>
106106

107107
<ItemGroup>

0 commit comments

Comments
 (0)