0aaf00dc5e
Co-authored-by: Clint Rutkas <crutkas@microsoft.com>
323 lines
11 KiB
C#
323 lines
11 KiB
C#
// 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.
|
|
|
|
using System;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Text.Json;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using Microsoft.PowerToys.Settings.UI.Library;
|
|
using NLog;
|
|
|
|
#pragma warning disable CS8602 // Dereference of a possibly null reference.
|
|
#pragma warning disable CS8603 // Possible null reference return.
|
|
|
|
namespace Awake.Core
|
|
{
|
|
internal static class TrayHelper
|
|
{
|
|
private static readonly Logger _log;
|
|
|
|
private static NotifyIcon? _trayIcon;
|
|
|
|
private static NotifyIcon TrayIcon { get => _trayIcon; set => _trayIcon = value; }
|
|
|
|
private static SettingsUtils? _moduleSettings;
|
|
|
|
private static SettingsUtils ModuleSettings { get => _moduleSettings; set => _moduleSettings = value; }
|
|
|
|
static TrayHelper()
|
|
{
|
|
_log = LogManager.GetCurrentClassLogger();
|
|
TrayIcon = new NotifyIcon();
|
|
ModuleSettings = new SettingsUtils();
|
|
}
|
|
|
|
public static void InitializeTray(string text, Icon icon, ContextMenuStrip? contextMenu = null)
|
|
{
|
|
Task.Factory.StartNew(
|
|
(tray) =>
|
|
{
|
|
((NotifyIcon?)tray).Text = text;
|
|
((NotifyIcon?)tray).Icon = icon;
|
|
((NotifyIcon?)tray).ContextMenuStrip = contextMenu;
|
|
((NotifyIcon?)tray).Visible = true;
|
|
|
|
_log.Info("Setting up the tray.");
|
|
Application.Run();
|
|
_log.Info("Tray setup complete.");
|
|
}, TrayIcon);
|
|
}
|
|
|
|
public static void ClearTray()
|
|
{
|
|
TrayIcon.Icon = null;
|
|
TrayIcon.Dispose();
|
|
}
|
|
|
|
internal static void SetTray(string text, AwakeSettings settings)
|
|
{
|
|
SetTray(
|
|
text,
|
|
settings.Properties.KeepDisplayOn,
|
|
settings.Properties.Mode,
|
|
PassiveKeepAwakeCallback(InternalConstants.AppName),
|
|
IndefiniteKeepAwakeCallback(InternalConstants.AppName),
|
|
TimedKeepAwakeCallback(InternalConstants.AppName),
|
|
KeepDisplayOnCallback(InternalConstants.AppName),
|
|
ExitCallback());
|
|
}
|
|
|
|
private static Action ExitCallback()
|
|
{
|
|
return () =>
|
|
{
|
|
Environment.Exit(Environment.ExitCode);
|
|
};
|
|
}
|
|
|
|
private static Action KeepDisplayOnCallback(string moduleName)
|
|
{
|
|
return () =>
|
|
{
|
|
AwakeSettings currentSettings;
|
|
|
|
try
|
|
{
|
|
currentSettings = ModuleSettings.GetSettings<AwakeSettings>(moduleName);
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
currentSettings = new AwakeSettings();
|
|
}
|
|
|
|
currentSettings.Properties.KeepDisplayOn = !currentSettings.Properties.KeepDisplayOn;
|
|
|
|
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
|
};
|
|
}
|
|
|
|
private static Action<uint, uint> TimedKeepAwakeCallback(string moduleName)
|
|
{
|
|
return (hours, minutes) =>
|
|
{
|
|
AwakeSettings currentSettings;
|
|
|
|
try
|
|
{
|
|
currentSettings = ModuleSettings.GetSettings<AwakeSettings>(moduleName);
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
currentSettings = new AwakeSettings();
|
|
}
|
|
|
|
currentSettings.Properties.Mode = AwakeMode.TIMED;
|
|
currentSettings.Properties.Hours = hours;
|
|
currentSettings.Properties.Minutes = minutes;
|
|
|
|
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
|
};
|
|
}
|
|
|
|
private static Action PassiveKeepAwakeCallback(string moduleName)
|
|
{
|
|
return () =>
|
|
{
|
|
AwakeSettings currentSettings;
|
|
|
|
try
|
|
{
|
|
currentSettings = ModuleSettings.GetSettings<AwakeSettings>(moduleName);
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
currentSettings = new AwakeSettings();
|
|
}
|
|
|
|
currentSettings.Properties.Mode = AwakeMode.PASSIVE;
|
|
|
|
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
|
};
|
|
}
|
|
|
|
private static Action IndefiniteKeepAwakeCallback(string moduleName)
|
|
{
|
|
return () =>
|
|
{
|
|
AwakeSettings currentSettings;
|
|
|
|
try
|
|
{
|
|
currentSettings = ModuleSettings.GetSettings<AwakeSettings>(moduleName);
|
|
}
|
|
catch (FileNotFoundException)
|
|
{
|
|
currentSettings = new AwakeSettings();
|
|
}
|
|
|
|
currentSettings.Properties.Mode = AwakeMode.INDEFINITE;
|
|
|
|
ModuleSettings.SaveSettings(JsonSerializer.Serialize(currentSettings), moduleName);
|
|
};
|
|
}
|
|
|
|
public static void SetTray(string text, bool keepDisplayOn, AwakeMode mode, Action passiveKeepAwakeCallback, Action indefiniteKeepAwakeCallback, Action<uint, uint> timedKeepAwakeCallback, Action keepDisplayOnCallback, Action exitCallback)
|
|
{
|
|
ContextMenuStrip? contextMenuStrip = new ContextMenuStrip();
|
|
|
|
// Main toolstrip.
|
|
ToolStripMenuItem? operationContextMenu = new ToolStripMenuItem
|
|
{
|
|
Text = "Mode",
|
|
};
|
|
|
|
// No keep-awake menu item.
|
|
CheckButtonToolStripMenuItem? passiveMenuItem = new CheckButtonToolStripMenuItem
|
|
{
|
|
Text = "Off (Keep using the selected power plan)",
|
|
};
|
|
|
|
passiveMenuItem.Checked = mode == AwakeMode.PASSIVE;
|
|
|
|
passiveMenuItem.Click += (e, s) =>
|
|
{
|
|
// User opted to set the mode to indefinite, so we need to write new settings.
|
|
passiveKeepAwakeCallback();
|
|
};
|
|
|
|
// Indefinite keep-awake menu item.
|
|
CheckButtonToolStripMenuItem? indefiniteMenuItem = new CheckButtonToolStripMenuItem
|
|
{
|
|
Text = "Keep awake indefinitely",
|
|
};
|
|
|
|
indefiniteMenuItem.Checked = mode == AwakeMode.INDEFINITE;
|
|
|
|
indefiniteMenuItem.Click += (e, s) =>
|
|
{
|
|
// User opted to set the mode to indefinite, so we need to write new settings.
|
|
indefiniteKeepAwakeCallback();
|
|
};
|
|
|
|
CheckButtonToolStripMenuItem? displayOnMenuItem = new CheckButtonToolStripMenuItem
|
|
{
|
|
Text = "Keep screen on",
|
|
};
|
|
|
|
displayOnMenuItem.Checked = keepDisplayOn;
|
|
|
|
displayOnMenuItem.Click += (e, s) =>
|
|
{
|
|
// User opted to set the display mode directly.
|
|
keepDisplayOnCallback();
|
|
};
|
|
|
|
// Timed keep-awake menu item
|
|
ToolStripMenuItem? timedMenuItem = new ToolStripMenuItem
|
|
{
|
|
Text = "Keep awake temporarily",
|
|
};
|
|
|
|
timedMenuItem.Checked = mode == AwakeMode.TIMED;
|
|
timedMenuItem.AccessibleName = timedMenuItem.Text + (timedMenuItem.Checked ? ". Checked. " : ". UnChecked. ");
|
|
|
|
ToolStripMenuItem? halfHourMenuItem = new ToolStripMenuItem
|
|
{
|
|
Text = "30 minutes",
|
|
};
|
|
|
|
halfHourMenuItem.Click += (e, s) =>
|
|
{
|
|
// User is setting the keep-awake to 30 minutes.
|
|
timedKeepAwakeCallback(0, 30);
|
|
};
|
|
|
|
ToolStripMenuItem? oneHourMenuItem = new ToolStripMenuItem
|
|
{
|
|
Text = "1 hour",
|
|
};
|
|
|
|
oneHourMenuItem.Click += (e, s) =>
|
|
{
|
|
// User is setting the keep-awake to 1 hour.
|
|
timedKeepAwakeCallback(1, 0);
|
|
};
|
|
|
|
ToolStripMenuItem? twoHoursMenuItem = new ToolStripMenuItem
|
|
{
|
|
Text = "2 hours",
|
|
};
|
|
|
|
twoHoursMenuItem.Click += (e, s) =>
|
|
{
|
|
// User is setting the keep-awake to 2 hours.
|
|
timedKeepAwakeCallback(2, 0);
|
|
};
|
|
|
|
// Exit menu item.
|
|
ToolStripMenuItem? exitContextMenu = new ToolStripMenuItem
|
|
{
|
|
Text = "Exit",
|
|
};
|
|
|
|
exitContextMenu.Click += (e, s) =>
|
|
{
|
|
// User is setting the keep-awake to 2 hours.
|
|
exitCallback();
|
|
};
|
|
|
|
timedMenuItem.DropDownItems.Add(halfHourMenuItem);
|
|
timedMenuItem.DropDownItems.Add(oneHourMenuItem);
|
|
timedMenuItem.DropDownItems.Add(twoHoursMenuItem);
|
|
|
|
operationContextMenu.DropDownItems.Add(passiveMenuItem);
|
|
operationContextMenu.DropDownItems.Add(indefiniteMenuItem);
|
|
operationContextMenu.DropDownItems.Add(timedMenuItem);
|
|
|
|
contextMenuStrip.Items.Add(operationContextMenu);
|
|
contextMenuStrip.Items.Add(displayOnMenuItem);
|
|
contextMenuStrip.Items.Add(new ToolStripSeparator());
|
|
contextMenuStrip.Items.Add(exitContextMenu);
|
|
|
|
TrayIcon.Text = text;
|
|
TrayIcon.ContextMenuStrip = contextMenuStrip;
|
|
}
|
|
|
|
private class CheckButtonToolStripMenuItemAccessibleObject : ToolStripItem.ToolStripItemAccessibleObject
|
|
{
|
|
private CheckButtonToolStripMenuItem _menuItem;
|
|
|
|
public CheckButtonToolStripMenuItemAccessibleObject(CheckButtonToolStripMenuItem menuItem)
|
|
: base(menuItem)
|
|
{
|
|
_menuItem = menuItem;
|
|
}
|
|
|
|
public override AccessibleRole Role
|
|
{
|
|
get
|
|
{
|
|
return AccessibleRole.CheckButton;
|
|
}
|
|
}
|
|
|
|
public override string Name => _menuItem.Text + ", " + Role + ", " + (_menuItem.Checked ? "Checked" : "Unchecked");
|
|
}
|
|
|
|
private class CheckButtonToolStripMenuItem : ToolStripMenuItem
|
|
{
|
|
public CheckButtonToolStripMenuItem()
|
|
{
|
|
}
|
|
|
|
protected override AccessibleObject CreateAccessibilityInstance()
|
|
{
|
|
return new CheckButtonToolStripMenuItemAccessibleObject(this);
|
|
}
|
|
}
|
|
}
|
|
}
|