tons of nits and todos

This commit is contained in:
Mike Griese
2026-02-19 10:27:47 -06:00
parent faa4bf7b50
commit 672b0213a7
19 changed files with 214 additions and 74 deletions

View File

@@ -325,6 +325,14 @@ REGSTR
# Misc Win32 APIs and PInvokes
INVOKEIDLIST
MEMORYSTATUSEX
ABE
HTCAPTION
POSCHANGED
QUERYPOS
SETAUTOHIDEBAR
WINDOWPOS
WINEVENTPROC
WORKERW
# PowerRename metadata pattern abbreviations (used in tests and regex patterns)
DDDD
@@ -349,3 +357,6 @@ nostdin
# Performance counter keys
engtype
Nonpaged
# XAML
Untargeted

View File

@@ -37,6 +37,7 @@
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.Calc\\Microsoft.CmdPal.Ext.Calc.csproj",
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.ClipboardHistory\\Microsoft.CmdPal.Ext.ClipboardHistory.csproj",
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.Indexer\\Microsoft.CmdPal.Ext.Indexer.csproj",
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.PerformanceMonitor\\Microsoft.CmdPal.Ext.PerformanceMonitor.csproj",
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.Registry\\Microsoft.CmdPal.Ext.Registry.csproj",
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.RemoteDesktop\\Microsoft.CmdPal.Ext.RemoteDesktop.csproj",
"src\\modules\\cmdpal\\ext\\Microsoft.CmdPal.Ext.Shell\\Microsoft.CmdPal.Ext.Shell.csproj",

View File

@@ -4,5 +4,11 @@
namespace Microsoft.CmdPal.Core.ViewModels;
internal sealed partial class NullPageViewModel(TaskScheduler scheduler, AppExtensionHost extensionHost)
: PageViewModel(null, scheduler, extensionHost);
internal sealed partial class NullPageViewModel : PageViewModel
{
internal NullPageViewModel(TaskScheduler scheduler, AppExtensionHost extensionHost)
: base(null, scheduler, extensionHost)
{
HasBackButton = false;
}
}

View File

@@ -98,7 +98,6 @@ public partial class ShellViewModel : ObservableObject,
_appHostService = appHostService;
NullPage = new NullPageViewModel(_scheduler, appHostService.GetDefaultHost());
NullPage.HasBackButton = false;
_currentPage = new LoadingPageViewModel(null, _scheduler, appHostService.GetDefaultHost());
// Register to receive messages
@@ -278,9 +277,9 @@ public partial class ShellViewModel : ObservableObject,
// Telemetry: Track extension page navigation for session metrics
if (host is not null)
{
string extensionId = host.GetExtensionDisplayName() ?? "builtin";
string commandId = command?.Id ?? "unknown";
string commandName = command?.Name ?? "unknown";
var extensionId = host.GetExtensionDisplayName() ?? "builtin";
var commandId = command?.Id ?? "unknown";
var commandName = command?.Name ?? "unknown";
WeakReferenceMessenger.Default.Send<TelemetryExtensionInvokedMessage>(
new(extensionId, commandId, commandName, true, 0));
}
@@ -361,10 +360,10 @@ public partial class ShellViewModel : ObservableObject,
// Telemetry: Track command execution time and success
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
var command = message.Command.Unsafe;
string extensionId = host?.GetExtensionDisplayName() ?? "builtin";
string commandId = command?.Id ?? "unknown";
string commandName = command?.Name ?? "unknown";
bool success = false;
var extensionId = host?.GetExtensionDisplayName() ?? "builtin";
var commandId = command?.Id ?? "unknown";
var commandName = command?.Name ?? "unknown";
var success = false;
try
{

View File

@@ -151,12 +151,16 @@ public sealed partial class DockBandViewModel : ExtensionObjectViewModel
newViewModels.Add(newItemVm);
}
List<DockItemViewModel> removed = new();
DoOnUiThread(() =>
{
ListHelpers.InPlaceUpdateList(Items, newViewModels, out var removed);
ListHelpers.InPlaceUpdateList(Items, newViewModels, out removed);
});
// TODO! dispose removed VMs
foreach (var removedItem in removed)
{
removedItem.SafeCleanup();
}
}
public override void InitializeProperties()
@@ -186,6 +190,22 @@ public sealed partial class DockBandViewModel : ExtensionObjectViewModel
InitializeFromList(p);
}
}
protected override void UnsafeCleanup()
{
base.UnsafeCleanup();
var command = _rootItem.Command;
if (command.Model.Unsafe is IListPage list)
{
list.ItemsChanged -= HandleItemsChanged;
}
foreach (var item in Items)
{
item.SafeCleanup();
}
}
}
public partial class DockItemViewModel : CommandItemViewModel

View File

@@ -58,6 +58,12 @@ public sealed partial class DockViewModel : IDisposable,
SetupBands(_settings.StartBands, StartItems);
SetupBands(_settings.CenterBands, CenterItems);
SetupBands(_settings.EndBands, EndItems);
// Initialize properties on BG thread
Task.Run(() =>
{
InitializeAllBands();
});
}
private void SetupBands(
@@ -77,6 +83,9 @@ public sealed partial class DockViewModel : IDisposable,
if (topLevelCommand is not null)
{
// note: CreateBandItem doesn't actually initialize the band, it
// just creates the VM. Callers need to make sure to call
// InitializeProperties() on a BG thread elsewhere
var bandVm = CreateBandItem(band, topLevelCommand.ItemViewModel);
newBands.Add(bandVm);
}
@@ -96,6 +105,7 @@ public sealed partial class DockViewModel : IDisposable,
public void Dispose()
{
WeakReferenceMessenger.Default.Unregister<CommandsReloadedMessage>(this);
}
public void Receive(CommandsReloadedMessage message)
@@ -515,6 +525,11 @@ public sealed partial class DockViewModel : IDisposable,
// Snapshot the new band so it can be removed on discard
bandVm.SnapshotShowLabels();
Task.Run(() =>
{
bandVm.SafeInitializePropertiesSynchronous();
});
Logger.LogDebug($"Added band {bandId} to {targetSide} (not saved yet)");
}
@@ -597,6 +612,24 @@ public sealed partial class DockViewModel : IDisposable,
};
}
}
private void InitializeAllBands()
{
foreach (var band in StartItems)
{
band.SafeInitializePropertiesSynchronous();
}
foreach (var band in CenterItems)
{
band.SafeInitializePropertiesSynchronous();
}
foreach (var band in EndItems)
{
band.SafeInitializePropertiesSynchronous();
}
}
}
#pragma warning restore SA1402 // File may only contain a single type

View File

@@ -291,5 +291,5 @@
<data name="dock_settings_name" xml:space="preserve">
<value>Dock settings</value>
<comment>Command name for opening dock settings</comment>
</data>
</data>
</root>

View File

@@ -21,7 +21,7 @@ public class DockSettings
public DockSize DockIconsSize { get; set; } = DockSize.Small;
// Theme settings
// <Theme settings>
public DockBackdrop Backdrop { get; set; } = DockBackdrop.Acrylic;
public UserTheme Theme { get; set; } = UserTheme.Default;
@@ -42,7 +42,7 @@ public class DockSettings
public string? BackgroundImagePath { get; set; }
// /Theme settings
// </Theme settings>
public List<string> PinnedCommands { get; set; } = [];
public List<DockBandSettings> StartBands { get; set; } = [];
@@ -64,7 +64,7 @@ public class DockSettings
StartBands.Add(new DockBandSettings { Id = "com.microsoft.cmdpal.winget", ShowLabels = false });
EndBands.Add(new DockBandSettings { Id = "com.microsoft.cmdpal.performanceWidget" });
EndBands.Add(new DockBandSettings { Id = "com.microsoft.cmdpal.timedate.dockband" });
EndBands.Add(new DockBandSettings { Id = "com.microsoft.cmdpal.timedate.dockBand" });
}
}

View File

@@ -32,6 +32,7 @@ public partial class TopLevelCommandManager : ObservableObject,
private readonly List<CommandProviderWrapper> _builtInCommands = [];
private readonly List<CommandProviderWrapper> _extensionCommandProviders = [];
private readonly Lock _commandProvidersLock = new();
private readonly Lock _dockBandsLock = new();
private readonly SupersedingAsyncGate _reloadCommandsGate;
TaskScheduler IPageContext.Scheduler => _taskScheduler;
@@ -94,7 +95,10 @@ public partial class TopLevelCommandManager : ObservableObject,
TopLevelCommands.Add(c);
}
}
}
lock (_dockBandsLock)
{
if (objects.DockBands is IEnumerable<TopLevelViewModel> bands)
{
foreach (var c in bands)
@@ -203,7 +207,10 @@ public partial class TopLevelCommandManager : ObservableObject,
clone.InsertRange(startIndex, newItems);
ListHelpers.InPlaceUpdateList(TopLevelCommands, clone);
}
lock (_dockBandsLock)
{
// same idea for DockBands
List<TopLevelViewModel> dockClone = [.. DockBands];
var dockStartIndex = FindIndexForFirstProviderItem(dockClone, sender.ProviderId);
@@ -256,6 +263,10 @@ public partial class TopLevelCommandManager : ObservableObject,
lock (TopLevelCommands)
{
TopLevelCommands.Clear();
}
lock (_dockBandsLock)
{
DockBands.Clear();
}
@@ -333,14 +344,14 @@ public partial class TopLevelCommandManager : ObservableObject,
var commandSets = (await Task.WhenAll(loadTasks)).Where(results => results is not null).Select(r => r!).ToList();
lock (TopLevelCommands)
foreach (var providerObjects in commandSets)
{
foreach (var providerObjects in commandSets)
{
var commandsCount = providerObjects.Commands?.Count() ?? 0;
var bandsCount = providerObjects.DockBands?.Count() ?? 0;
Logger.LogDebug($"(some provider) Loaded {commandsCount} commands and {bandsCount} bands");
var commandsCount = providerObjects.Commands?.Count() ?? 0;
var bandsCount = providerObjects.DockBands?.Count() ?? 0;
Logger.LogDebug($"(some provider) Loaded {commandsCount} commands and {bandsCount} bands");
lock (TopLevelCommands)
{
if (providerObjects.Commands is IEnumerable<TopLevelViewModel> commands)
{
foreach (var c in commands)
@@ -348,7 +359,10 @@ public partial class TopLevelCommandManager : ObservableObject,
TopLevelCommands.Add(c);
}
}
}
lock (_dockBandsLock)
{
if (providerObjects.DockBands is IEnumerable<TopLevelViewModel> bands)
{
foreach (var c in bands)
@@ -408,6 +422,7 @@ public partial class TopLevelCommandManager : ObservableObject,
{
// Then find all the top-level commands that belonged to that extension
List<TopLevelViewModel> commandsToRemove = [];
List<TopLevelViewModel> bandsToRemove = [];
lock (TopLevelCommands)
{
foreach (var extension in extensions)
@@ -420,6 +435,15 @@ public partial class TopLevelCommandManager : ObservableObject,
commandsToRemove.Add(command);
}
}
foreach (var band in DockBands)
{
var host = band.ExtensionHost;
if (host?.Extension == extension)
{
bandsToRemove.Add(band);
}
}
}
}
@@ -439,6 +463,17 @@ public partial class TopLevelCommandManager : ObservableObject,
}
}
}
lock (_dockBandsLock)
{
if (bandsToRemove.Count != 0)
{
foreach (var deleted in bandsToRemove)
{
DockBands.Remove(deleted);
}
}
}
},
CancellationToken.None,
TaskCreationOptions.None,
@@ -464,8 +499,7 @@ public partial class TopLevelCommandManager : ObservableObject,
public TopLevelViewModel? LookupDockBand(string id)
{
// TODO! bad that we're using TopLevelCommands as the object to lock, even for bands
lock (TopLevelCommands)
lock (_dockBandsLock)
{
foreach (var command in DockBands)
{
@@ -499,7 +533,7 @@ public partial class TopLevelCommandManager : ObservableObject,
internal void PinDockBand(TopLevelViewModel bandVm)
{
lock (DockBands)
lock (_dockBandsLock)
{
foreach (var existing in DockBands)
{

View File

@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -494,8 +494,9 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem, IEx
contextItems.Add(new Separator());
var inStartBands = _settings.DockSettings.StartBands.Any(band => band.Id == this.Id);
var inCenterBands = _settings.DockSettings.CenterBands.Any(band => band.Id == this.Id);
var inEndBands = _settings.DockSettings.EndBands.Any(band => band.Id == this.Id);
var alreadyPinned = (inStartBands || inEndBands) &&
var alreadyPinned = (inStartBands || inCenterBands || inEndBands) &&
_settings.DockSettings.PinnedCommands.Contains(this.Id);
var pinCommand = new PinToDockCommand(
@@ -608,9 +609,9 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem, IEx
ShowLabels = true,
});
// Create a new band VM from our current TLVM. This will allow us to
// update the bands in the CommandProviderWrapper and the TLCM,
// without forcing a whole reload
// Create a new band VM from our current TopLevelViewModel. This
// will allow us to update the bands in the CommandProviderWrapper
// and the TopLevelCommandManager, without forcing a whole reload
var bandVm = _topLevelViewModel.CloneAsBand();
_topLevelCommandManager.PinDockBand(bandVm);
@@ -621,6 +622,7 @@ public sealed partial class TopLevelViewModel : ObservableObject, IListItem, IEx
{
_settings.DockSettings.PinnedCommands.Remove(_topLevelViewModel.Id);
_settings.DockSettings.StartBands.RemoveAll(band => band.Id == _topLevelViewModel.Id);
_settings.DockSettings.CenterBands.RemoveAll(band => band.Id == _topLevelViewModel.Id);
_settings.DockSettings.EndBands.RemoveAll(band => band.Id == _topLevelViewModel.Id);
_topLevelViewModel.Save();

View File

@@ -48,7 +48,7 @@ internal static class DockSettingsToViews
return backdrop switch
{
DockBackdrop.Transparent => new TransparentTintBackdrop(),
DockBackdrop.Acrylic => null, // new DesktopAcrylicBackdrop(),
DockBackdrop.Acrylic => null,
_ => throw new NotImplementedException(),
};
}
@@ -65,4 +65,3 @@ internal static class DockSettingsToViews
};
}
}
#pragma warning restore SA1402 // File may only contain a single type

View File

@@ -108,7 +108,7 @@ public sealed partial class DockWindow : WindowEx,
// TaskbarCreated is the message that's broadcast when explorer.exe
// restarts. We need to know when that happens to be able to bring our
// appbar back
// app bar back
// And this apparently happens on lock screens / hibernates, too
WM_TASKBAR_RESTART = PInvoke.RegisterWindowMessage("TaskbarCreated");
@@ -259,7 +259,7 @@ public sealed partial class DockWindow : WindowEx,
uCallbackMessage = _callbackMessageId,
};
// Register this window as an appbar
// Register this window as an app bar
PInvoke.SHAppBarMessage(PInvoke.ABM_NEW, ref _appBarData);
// Stash the last size we created the bar at, so we know when to hot-
@@ -294,12 +294,12 @@ public sealed partial class DockWindow : WindowEx,
PInvoke.SHAppBarMessage(PInvoke.ABM_QUERYPOS, ref _appBarData);
PInvoke.SHAppBarMessage(PInvoke.ABM_SETPOS, ref _appBarData);
// TODO: investigate ABS_AUTOHIDE and autohide bars.
// TODO: investigate ABS_AUTOHIDE and auto hide bars.
// I think it's something like this, but I don't totally know
// // _appBarData.lParam = ABS_ALWAYSONTOP;
// _appBarData.lParam = (LPARAM)(int)PInvoke.ABS_AUTOHIDE;
// PInvoke.SHAppBarMessage(ABM_SETSTATE, ref _appBarData);
// PInvoke.SHAppBarMessage(PInvoke.ABM_SETAUTOHIDEBAR, ref _appBarData);
// _appBarData.lParam = ABS_ALWAYSONTOP;
// _appBarData.lParam = (LPARAM)(int)PInvoke.ABS_AUTOHIDE;
// PInvoke.SHAppBarMessage(ABM_SETSTATE, ref _appBarData);
// PInvoke.SHAppBarMessage(PInvoke.ABM_SETAUTOHIDEBAR, ref _appBarData);
// Account for system borders when moving the window
// Adjust position to account for window frame/border
@@ -630,7 +630,7 @@ public sealed partial class DockWindow : WindowEx,
_themeService.ThemeChanged -= ThemeService_ThemeChanged;
DisposeAcrylic();
// Remove our appbar registration
// Remove our app bar registration
DestroyAppBar(_hwnd);
// Unhook the window procedure

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8" ?>
<?xml version="1.0" encoding="utf-8" ?>
<Page
x:Class="Microsoft.CmdPal.UI.Settings.DockSettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
@@ -47,8 +47,7 @@
<!-- Dock Position -->
<controls:SettingsExpander
Description="Choose where the dock appears on your screen"
Header="Dock position and appearance"
x:Uid="DockAppearance_DockPosition_SettingsExpander"
IsExpanded="True">
<controls:SettingsExpander.HeaderIcon>
<SymbolIcon Symbol="MoveToFolder" />
@@ -57,18 +56,17 @@
x:Name="DockPositionComboBox"
MinWidth="120"
SelectedIndex="{x:Bind SelectedSideIndex, Mode=TwoWay}">
<ComboBoxItem Content="Left" />
<ComboBoxItem Content="Top" />
<ComboBoxItem Content="Right" />
<ComboBoxItem Content="Bottom" />
<ComboBoxItem x:Uid="DockAppearance_DockPosition_Left" />
<ComboBoxItem x:Uid="DockAppearance_DockPosition_Top" />
<ComboBoxItem x:Uid="DockAppearance_DockPosition_Right" />
<ComboBoxItem x:Uid="DockAppearance_DockPosition_Bottom" />
</ComboBox>
<controls:SettingsExpander.Items>
<!-- Show Labels -->
<controls:SettingsCard ContentAlignment="Left">
<ptcontrols:CheckBoxWithDescriptionControl
Description="Choose whether to show labels for dock items by default"
Header="Show labels"
x:Uid="DockAppearance_ShowLabels_CheckBox"
IsChecked="{x:Bind ShowLabels, Mode=TwoWay}" />
</controls:SettingsCard>
</controls:SettingsExpander.Items>

View File

@@ -888,4 +888,28 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
<data name="ConfigureShortcutText.Text" xml:space="preserve">
<value>Assign shortcut</value>
</data>
<data name="DockAppearance_DockPosition_SettingsExpander.Header" xml:space="preserve">
<value>Dock position and appearance</value>
</data>
<data name="DockAppearance_DockPosition_SettingsExpander.Description" xml:space="preserve">
<value>Choose where the dock appears on your screen</value>
</data>
<data name="DockAppearance_DockPosition_Left.Content" xml:space="preserve">
<value>Left</value>
</data>
<data name="DockAppearance_DockPosition_Top.Content" xml:space="preserve">
<value>Top</value>
</data>
<data name="DockAppearance_DockPosition_Right.Content" xml:space="preserve">
<value>Right</value>
</data>
<data name="DockAppearance_DockPosition_Bottom.Content" xml:space="preserve">
<value>Bottom</value>
</data>
<data name="DockAppearance_ShowLabels_CheckBox.Header" xml:space="preserve">
<value>Show labels</value>
</data>
<data name="DockAppearance_ShowLabels_CheckBox.Description" xml:space="preserve">
<value>Choose whether to show labels for dock items by default</value>
</data>
</root>

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\Common.Dotnet.CsWinRT.props" />
<Import Project="..\..\..\..\Common.Dotnet.AotCompatibility.props" />
<Import Project="..\Common.ExtDependencies.props" />
<Import Project="$(RepoRoot)src\Common.Dotnet.CsWinRT.props" />
<Import Project="$(RepoRoot)src\Common.Dotnet.AotCompatibility.props" />
<Import Project="..\Common.ExtDependencies.props" />
<PropertyGroup>
<RootNamespace>Microsoft.CmdPal.Ext.PerformanceMonitor</RootNamespace>
<OutputPath>$(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\CmdPal</OutputPath>
@@ -9,7 +9,7 @@
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<!-- MRT from windows app sdk will search for a pri file with the same name of the module before defaulting to resources.pri -->
<ProjectPriFileName>Microsoft.CmdPal.Ext.PerformanceMonitor.pri</ProjectPriFileName>
<nullable>enable</nullable>
<nullable>enable</nullable>
<LangVersion>preview</LangVersion>
</PropertyGroup>

View File

@@ -941,5 +941,23 @@ namespace Microsoft.CmdPal.Ext.TimeDate {
return ResourceManager.GetString("Microsoft_plugin_timedate_Year", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Copy date.
/// </summary>
public static string timedate_copy_date_command_name {
get {
return ResourceManager.GetString("timedate_copy_date_command_name", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Copy time.
/// </summary>
public static string timedate_copy_time_command_name {
get {
return ResourceManager.GetString("timedate_copy_time_command_name", resourceCulture);
}
}
}
}

View File

@@ -436,4 +436,12 @@
<value>Clock</value>
<comment>Title for the time and date dock band</comment>
</data>
<data name="timedate_copy_time_command_name" xml:space="preserve">
<value>Copy time</value>
<comment>Name of a command to copy the current time to the clipboard</comment>
</data>
<data name="timedate_copy_date_command_name" xml:space="preserve">
<value>Copy date</value>
<comment>Name of a command to copy the current date to the clipboard</comment>
</data>
</root>

View File

@@ -56,7 +56,7 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider
{
var wrappedBand = new WrappedDockItem(
[_bandItem],
"com.microsoft.cmdpal.timedate.dockband",
"com.microsoft.cmdpal.timedate.dockBand",
Resources.Microsoft_plugin_timedate_dock_band_title);
return new ICommandItem[] { wrappedBand };
@@ -66,14 +66,15 @@ public sealed partial class TimeDateCommandsProvider : CommandProvider
internal sealed partial class NowDockBand : ListItem
{
private static readonly TimeSpan UpdateInterval = TimeSpan.FromSeconds(60);
private CopyTextCommand _copyTimeCommand;
private CopyTextCommand _copyDateCommand;
public NowDockBand()
{
Command = new NoOpCommand() { Id = "com.microsoft.cmdpal.timedate.dockband" };
_copyTimeCommand = new CopyTextCommand(string.Empty) { Name = "Copy Time" };
_copyDateCommand = new CopyTextCommand(string.Empty) { Name = "Copy Date" };
Command = new NoOpCommand() { Id = "com.microsoft.cmdpal.timedate.dockBand" };
_copyTimeCommand = new CopyTextCommand(string.Empty) { Name = Resources.timedate_copy_time_command_name };
_copyDateCommand = new CopyTextCommand(string.Empty) { Name = Resources.timedate_copy_date_command_name };
MoreCommands = [
new CommandContextItem(_copyTimeCommand),
new CommandContextItem(_copyDateCommand)
@@ -81,11 +82,11 @@ internal sealed partial class NowDockBand : ListItem
UpdateText();
// Create a timer to update the time every minute
System.Timers.Timer timer = new(60000); // 60000 ms = 1 minute
System.Timers.Timer timer = new(UpdateInterval.TotalMilliseconds);
// but we want it to tick on the minute, so calculate the initial delay
var now = DateTime.Now;
timer.Interval = 60000 - ((now.Second * 1000) + now.Millisecond);
timer.Interval = UpdateInterval.TotalMilliseconds - ((now.Second * 1000) + now.Millisecond);
// then after the first tick, set it to 60 seconds
timer.Elapsed += Timer_ElapsedFirst;
@@ -97,7 +98,7 @@ internal sealed partial class NowDockBand : ListItem
// After the first tick, set the interval to 60 seconds
if (sender is System.Timers.Timer timer)
{
timer.Interval = 60000;
timer.Interval = UpdateInterval.TotalMilliseconds;
timer.Elapsed -= Timer_ElapsedFirst;
timer.Elapsed += Timer_Elapsed;

View File

@@ -1,14 +0,0 @@
GetCurrentThreadId
SetWinEventHook
SetWindowsHookEx
UnhookWindowsHookEx
CallNextHookEx
EVENT_OBJECT_CREATE
EVENT_OBJECT_NAMECHANGE
EVENT_OBJECT_SHOW
EVENT_OBJECT_DESTROY
EVENT_OBJECT_HIDE
WINEVENT_OUTOFCONTEXT
WINEVENT_SKIPOWNPROCESS
OBJECT_IDENTIFIER