mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 11:48:06 +01:00
Option to toggle the system tray icon (#23220)
* Added option to toggle the system tray icon At the moment, this hides the icon making the settings window inaccessible without first modifying the general `settings.json` file. * Use IPC messages to manage the tray icon settings * Fix launching second window binds to active settings process * Added context menu option to hide tray icon * Added Exit PT button to settings ui NavigationView.PaneFooter * Moved DllImports to NativeMethods.cs * Sentence case titles * Fix whitespace * Re-add exit icon to NavView * Re-added toggle switch to new UI * Fix build * Fix build after merge main * Fix the string to display * add shut down buttons * finish polish * fix string * Styling tweaks to titlebar and settingscards * fix comment * fix unit test * fix ut --------- Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: vanzue <vanzue@outlook.com> Co-authored-by: Kayla Cinnamon <cinnamon@microsoft.com> Co-authored-by: Niels Laute <niels.laute@live.nl>
This commit is contained in:
@@ -1,5 +1,64 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
@@ -89,7 +148,7 @@
|
|||||||
<value>This setting has been disabled by your administrator.</value>
|
<value>This setting has been disabled by your administrator.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="STARTUP_DISABLED_BY_USER" xml:space="preserve">
|
<data name="STARTUP_DISABLED_BY_USER" xml:space="preserve">
|
||||||
<value>This setting has been disabled manually via <a href="https://ms_settings_startupapps" target="_blank">Startup Settings</a>.</value>
|
<value>This setting has been disabled manually via <a href="https://ms_settings_startupapps" target="_blank">Startup Settings</a>.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
|
<data name="GITHUB_NEW_VERSION_AVAILABLE" xml:space="preserve">
|
||||||
<value>An update to PowerToys is available.</value>
|
<value>An update to PowerToys is available.</value>
|
||||||
@@ -121,6 +180,9 @@
|
|||||||
<value>Exit</value>
|
<value>Exit</value>
|
||||||
<comment>Exit as a verb, as in Exit the application</comment>
|
<comment>Exit as a verb, as in Exit the application</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SHOW_TRAY_ICON_MENU_TEXT" xml:space="preserve">
|
||||||
|
<value>Show icon</value>
|
||||||
|
</data>
|
||||||
<data name="SUBMIT_BUG_TEXT" xml:space="preserve">
|
<data name="SUBMIT_BUG_TEXT" xml:space="preserve">
|
||||||
<value>Report bug</value>
|
<value>Report bug</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -134,4 +196,4 @@
|
|||||||
<data name="TRAY_ICON_ADMIN_TOOLTIP" xml:space="preserve">
|
<data name="TRAY_ICON_ADMIN_TOOLTIP" xml:space="preserve">
|
||||||
<value>Administrator</value>
|
<value>Administrator</value>
|
||||||
</data>
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "general_settings.h"
|
#include "general_settings.h"
|
||||||
#include "auto_start_helper.h"
|
#include "auto_start_helper.h"
|
||||||
|
#include "tray_icon.h"
|
||||||
#include "Generated files/resource.h"
|
#include "Generated files/resource.h"
|
||||||
|
|
||||||
#include <common/SettingsAPI/settings_helpers.h>
|
#include <common/SettingsAPI/settings_helpers.h>
|
||||||
@@ -14,6 +15,7 @@
|
|||||||
|
|
||||||
// TODO: would be nice to get rid of these globals, since they're basically cached json settings
|
// TODO: would be nice to get rid of these globals, since they're basically cached json settings
|
||||||
static std::wstring settings_theme = L"system";
|
static std::wstring settings_theme = L"system";
|
||||||
|
static bool show_tray_icon = true;
|
||||||
static bool run_as_elevated = false;
|
static bool run_as_elevated = false;
|
||||||
static bool show_new_updates_toast_notification = true;
|
static bool show_new_updates_toast_notification = true;
|
||||||
static bool download_updates_automatically = true;
|
static bool download_updates_automatically = true;
|
||||||
@@ -38,6 +40,7 @@ json::JsonObject GeneralSettings::to_json()
|
|||||||
}
|
}
|
||||||
result.SetNamedValue(L"enabled", std::move(enabled));
|
result.SetNamedValue(L"enabled", std::move(enabled));
|
||||||
|
|
||||||
|
result.SetNamedValue(L"show_tray_icon", json::value(showSystemTrayIcon));
|
||||||
result.SetNamedValue(L"is_elevated", json::value(isElevated));
|
result.SetNamedValue(L"is_elevated", json::value(isElevated));
|
||||||
result.SetNamedValue(L"run_elevated", json::value(isRunElevated));
|
result.SetNamedValue(L"run_elevated", json::value(isRunElevated));
|
||||||
result.SetNamedValue(L"show_new_updates_toast_notification", json::value(showNewUpdatesToastNotification));
|
result.SetNamedValue(L"show_new_updates_toast_notification", json::value(showNewUpdatesToastNotification));
|
||||||
@@ -74,7 +77,9 @@ json::JsonObject load_general_settings()
|
|||||||
GeneralSettings get_general_settings()
|
GeneralSettings get_general_settings()
|
||||||
{
|
{
|
||||||
const bool is_user_admin = check_user_is_admin();
|
const bool is_user_admin = check_user_is_admin();
|
||||||
GeneralSettings settings{
|
GeneralSettings settings
|
||||||
|
{
|
||||||
|
.showSystemTrayIcon = show_tray_icon,
|
||||||
.isElevated = is_process_elevated(),
|
.isElevated = is_process_elevated(),
|
||||||
.isRunElevated = run_as_elevated,
|
.isRunElevated = run_as_elevated,
|
||||||
.isAdmin = is_user_admin,
|
.isAdmin = is_user_admin,
|
||||||
@@ -214,6 +219,13 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save)
|
|||||||
settings_theme = general_configs.GetNamedString(L"theme");
|
settings_theme = general_configs.GetNamedString(L"theme");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (json::has(general_configs, L"show_tray_icon", json::JsonValueType::Boolean))
|
||||||
|
{
|
||||||
|
show_tray_icon = general_configs.GetNamedBoolean(L"show_tray_icon");
|
||||||
|
// Update tray icon visibility when setting is toggled
|
||||||
|
set_tray_icon_visible(show_tray_icon);
|
||||||
|
}
|
||||||
|
|
||||||
if (save)
|
if (save)
|
||||||
{
|
{
|
||||||
GeneralSettings save_settings = get_general_settings();
|
GeneralSettings save_settings = get_general_settings();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
struct GeneralSettings
|
struct GeneralSettings
|
||||||
{
|
{
|
||||||
bool isStartupEnabled;
|
bool isStartupEnabled;
|
||||||
|
bool showSystemTrayIcon;
|
||||||
std::wstring startupDisabledReason;
|
std::wstring startupDisabledReason;
|
||||||
std::map<std::wstring, bool> isModulesEnabledMap;
|
std::map<std::wstring, bool> isModulesEnabledMap;
|
||||||
bool isElevated;
|
bool isElevated;
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ void open_menu_from_another_instance(std::optional<std::string> settings_window)
|
|||||||
msg = static_cast<LPARAM>(ESettingsWindowNames_from_string(settings_window.value()));
|
msg = static_cast<LPARAM>(ESettingsWindowNames_from_string(settings_window.value()));
|
||||||
}
|
}
|
||||||
PostMessageW(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, msg);
|
PostMessageW(hwnd_main, WM_COMMAND, ID_SETTINGS_MENU_COMMAND, msg);
|
||||||
|
SetForegroundWindow(hwnd_main); // Bring the settings window to the front
|
||||||
}
|
}
|
||||||
|
|
||||||
int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe, bool showRestartNotificationAfterUpdate)
|
int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow, bool openOobe, bool openScoobe, bool showRestartNotificationAfterUpdate)
|
||||||
@@ -104,6 +105,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
|||||||
#endif
|
#endif
|
||||||
Trace::RegisterProvider();
|
Trace::RegisterProvider();
|
||||||
start_tray_icon(isProcessElevated);
|
start_tray_icon(isProcessElevated);
|
||||||
|
set_tray_icon_visible(get_general_settings().showSystemTrayIcon);
|
||||||
CentralizedKeyboardHook::Start();
|
CentralizedKeyboardHook::Start();
|
||||||
|
|
||||||
int result = -1;
|
int result = -1;
|
||||||
|
|||||||
@@ -20,4 +20,5 @@
|
|||||||
#define ID_ABOUT_MENU_COMMAND 40003
|
#define ID_ABOUT_MENU_COMMAND 40003
|
||||||
#define ID_REPORT_BUG_COMMAND 40004
|
#define ID_REPORT_BUG_COMMAND 40004
|
||||||
#define ID_DOCUMENTATION_MENU_COMMAND 40005
|
#define ID_DOCUMENTATION_MENU_COMMAND 40005
|
||||||
#define ID_QUICK_ACCESS_MENU_COMMAND 40006
|
#define ID_QUICK_ACCESS_MENU_COMMAND 40006
|
||||||
|
#define ID_SHOW_TRAY_ICON_MENU_COMMAND 40007
|
||||||
|
|||||||
Binary file not shown.
@@ -2,6 +2,7 @@
|
|||||||
#include "Generated files/resource.h"
|
#include "Generated files/resource.h"
|
||||||
#include "settings_window.h"
|
#include "settings_window.h"
|
||||||
#include "tray_icon.h"
|
#include "tray_icon.h"
|
||||||
|
#include "general_settings.h"
|
||||||
#include "centralized_hotkeys.h"
|
#include "centralized_hotkeys.h"
|
||||||
#include "centralized_kb_hook.h"
|
#include "centralized_kb_hook.h"
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
@@ -90,6 +91,13 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
|
|||||||
}
|
}
|
||||||
DestroyWindow(window);
|
DestroyWindow(window);
|
||||||
break;
|
break;
|
||||||
|
case ID_SHOW_TRAY_ICON_MENU_COMMAND:
|
||||||
|
{
|
||||||
|
GeneralSettings settings = get_general_settings();
|
||||||
|
settings.showSystemTrayIcon = true;
|
||||||
|
apply_general_settings(settings.to_json(), true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ID_ABOUT_MENU_COMMAND:
|
case ID_ABOUT_MENU_COMMAND:
|
||||||
if (!about_box_shown)
|
if (!about_box_shown)
|
||||||
{
|
{
|
||||||
@@ -191,11 +199,13 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
|||||||
{
|
{
|
||||||
static std::wstring settings_menuitem_label = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT);
|
static std::wstring settings_menuitem_label = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT);
|
||||||
static std::wstring exit_menuitem_label = GET_RESOURCE_STRING(IDS_EXIT_MENU_TEXT);
|
static std::wstring exit_menuitem_label = GET_RESOURCE_STRING(IDS_EXIT_MENU_TEXT);
|
||||||
|
static std::wstring show_tray_icon_menuitem_label = GET_RESOURCE_STRING(IDS_SHOW_TRAY_ICON_MENU_TEXT);
|
||||||
static std::wstring submit_bug_menuitem_label = GET_RESOURCE_STRING(IDS_SUBMIT_BUG_TEXT);
|
static std::wstring submit_bug_menuitem_label = GET_RESOURCE_STRING(IDS_SUBMIT_BUG_TEXT);
|
||||||
static std::wstring documentation_menuitem_label = GET_RESOURCE_STRING(IDS_DOCUMENTATION_MENU_TEXT);
|
static std::wstring documentation_menuitem_label = GET_RESOURCE_STRING(IDS_DOCUMENTATION_MENU_TEXT);
|
||||||
static std::wstring quick_access_menuitem_label = GET_RESOURCE_STRING(IDS_QUICK_ACCESS_MENU_TEXT);
|
static std::wstring quick_access_menuitem_label = GET_RESOURCE_STRING(IDS_QUICK_ACCESS_MENU_TEXT);
|
||||||
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
|
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
|
||||||
change_menu_item_text(ID_EXIT_MENU_COMMAND, exit_menuitem_label.data());
|
change_menu_item_text(ID_EXIT_MENU_COMMAND, exit_menuitem_label.data());
|
||||||
|
change_menu_item_text(ID_SHOW_TRAY_ICON_MENU_COMMAND, show_tray_icon_menuitem_label.data());
|
||||||
change_menu_item_text(ID_REPORT_BUG_COMMAND, submit_bug_menuitem_label.data());
|
change_menu_item_text(ID_REPORT_BUG_COMMAND, submit_bug_menuitem_label.data());
|
||||||
change_menu_item_text(ID_DOCUMENTATION_MENU_COMMAND, documentation_menuitem_label.data());
|
change_menu_item_text(ID_DOCUMENTATION_MENU_COMMAND, documentation_menuitem_label.data());
|
||||||
change_menu_item_text(ID_QUICK_ACCESS_MENU_COMMAND, quick_access_menuitem_label.data());
|
change_menu_item_text(ID_QUICK_ACCESS_MENU_COMMAND, quick_access_menuitem_label.data());
|
||||||
@@ -312,6 +322,14 @@ void start_tray_icon(bool isProcessElevated)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_tray_icon_visible(bool shouldIconBeVisible)
|
||||||
|
{
|
||||||
|
tray_icon_data.uFlags |= NIF_STATE;
|
||||||
|
tray_icon_data.dwStateMask = NIS_HIDDEN;
|
||||||
|
tray_icon_data.dwState = shouldIconBeVisible ? 0 : NIS_HIDDEN;
|
||||||
|
Shell_NotifyIcon(NIM_MODIFY, &tray_icon_data);
|
||||||
|
}
|
||||||
|
|
||||||
void stop_tray_icon()
|
void stop_tray_icon()
|
||||||
{
|
{
|
||||||
if (tray_icon_created)
|
if (tray_icon_created)
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
// Start the Tray Icon
|
// Start the Tray Icon
|
||||||
void start_tray_icon(bool isProcessElevated);
|
void start_tray_icon(bool isProcessElevated);
|
||||||
|
// Change the Tray Icon visibility
|
||||||
|
void set_tray_icon_visible(bool shouldIconBeVisible);
|
||||||
// Stop the Tray Icon
|
// Stop the Tray Icon
|
||||||
void stop_tray_icon();
|
void stop_tray_icon();
|
||||||
// Open the Settings Window
|
// Open the Settings Window
|
||||||
@@ -13,4 +15,5 @@ typedef void (*main_loop_callback_function)(PVOID);
|
|||||||
// Calls a callback in _callback
|
// Calls a callback in _callback
|
||||||
bool dispatch_run_on_main_ui_thread(main_loop_callback_function _callback, PVOID data);
|
bool dispatch_run_on_main_ui_thread(main_loop_callback_function _callback, PVOID data);
|
||||||
|
|
||||||
|
// Must be the same as: settings-ui/Settings.UI/Views/ShellPage.xaml.cs -> ExitPTItem_Tapped() -> const string ptTrayIconWindowClass
|
||||||
const inline wchar_t* pt_tray_icon_window_class = L"PToyTrayIconWindow";
|
const inline wchar_t* pt_tray_icon_window_class = L"PToyTrayIconWindow";
|
||||||
@@ -19,6 +19,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
[JsonPropertyName("startup")]
|
[JsonPropertyName("startup")]
|
||||||
public bool Startup { get; set; }
|
public bool Startup { get; set; }
|
||||||
|
|
||||||
|
// Gets or sets a value indicating whether the powertoys system tray icon should be hidden.
|
||||||
|
[JsonPropertyName("show_tray_icon")]
|
||||||
|
public bool ShowSysTrayIcon { get; set; }
|
||||||
|
|
||||||
// Gets or sets a value indicating whether the powertoy elevated.
|
// Gets or sets a value indicating whether the powertoy elevated.
|
||||||
[CmdConfigureIgnoreAttribute]
|
[CmdConfigureIgnoreAttribute]
|
||||||
[JsonPropertyName("is_elevated")]
|
[JsonPropertyName("is_elevated")]
|
||||||
@@ -75,6 +79,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
|||||||
public GeneralSettings()
|
public GeneralSettings()
|
||||||
{
|
{
|
||||||
Startup = false;
|
Startup = false;
|
||||||
|
ShowSysTrayIcon = true;
|
||||||
IsAdmin = false;
|
IsAdmin = false;
|
||||||
EnableWarningsElevatedApps = true;
|
EnableWarningsElevatedApps = true;
|
||||||
IsElevated = false;
|
IsElevated = false;
|
||||||
|
|||||||
@@ -224,6 +224,36 @@ namespace ViewModelTests
|
|||||||
viewModel.ThemeIndex = 0;
|
viewModel.ThemeIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void IsShowSysTrayIconEnabledByDefaultShouldDisableWhenSuccessful()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
// Assert
|
||||||
|
Func<string, int> sendMockIPCConfigMSG = msg =>
|
||||||
|
{
|
||||||
|
OutGoingGeneralSettings snd = JsonSerializer.Deserialize<OutGoingGeneralSettings>(msg);
|
||||||
|
Assert.IsFalse(snd.GeneralSettings.ShowSysTrayIcon);
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Func<string, int> sendRestartAdminIPCMessage = msg => { return 0; };
|
||||||
|
Func<string, int> sendCheckForUpdatesIPCMessage = msg => { return 0; };
|
||||||
|
GeneralViewModel viewModel = new(
|
||||||
|
settingsRepository: SettingsRepository<GeneralSettings>.GetInstance(mockGeneralSettingsUtils.Object),
|
||||||
|
"GeneralSettings_RunningAsAdminText",
|
||||||
|
"GeneralSettings_RunningAsUserText",
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
sendMockIPCConfigMSG,
|
||||||
|
sendRestartAdminIPCMessage,
|
||||||
|
sendCheckForUpdatesIPCMessage,
|
||||||
|
GeneralSettingsFileName);
|
||||||
|
Assert.IsTrue(viewModel.ShowSysTrayIcon);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
viewModel.ShowSysTrayIcon = false;
|
||||||
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
public void AllModulesAreEnabledByDefault()
|
public void AllModulesAreEnabledByDefault()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
|||||||
internal const int SW_SHOWNORMAL = 1;
|
internal const int SW_SHOWNORMAL = 1;
|
||||||
internal const int SW_SHOWMAXIMIZED = 3;
|
internal const int SW_SHOWMAXIMIZED = 3;
|
||||||
internal const int SW_HIDE = 0;
|
internal const int SW_HIDE = 0;
|
||||||
|
internal const int WM_COMMAND = 0x0111; // https://learn.microsoft.com/en-us/windows/win32/menurc/wm-command
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
internal static extern IntPtr GetActiveWindow();
|
internal static extern IntPtr GetActiveWindow();
|
||||||
@@ -48,6 +49,12 @@ namespace Microsoft.PowerToys.Settings.UI.Helpers
|
|||||||
[DllImport("Comdlg32.dll", CharSet = CharSet.Unicode)]
|
[DllImport("Comdlg32.dll", CharSet = CharSet.Unicode)]
|
||||||
internal static extern bool GetOpenFileName([In, Out] OpenFileName openFileName);
|
internal static extern bool GetOpenFileName([In, Out] OpenFileName openFileName);
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||||
|
internal static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
internal static extern IntPtr SendMessage(IntPtr hWnd, IntPtr msg, UIntPtr wParam, UIntPtr lParam);
|
||||||
|
|
||||||
[DllImport("comdlg32.dll", CharSet = CharSet.Auto, EntryPoint = "ChooseFont", SetLastError = true)]
|
[DllImport("comdlg32.dll", CharSet = CharSet.Auto, EntryPoint = "ChooseFont", SetLastError = true)]
|
||||||
internal static extern bool ChooseFont(IntPtr lpChooseFont);
|
internal static extern bool ChooseFont(IntPtr lpChooseFont);
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
<tkconverters:StringFormatConverter x:Key="StringFormatConverter" />
|
<tkconverters:StringFormatConverter x:Key="StringFormatConverter" />
|
||||||
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||||
|
<x:Double x:Key="SettingsCardSpacing">2</x:Double>
|
||||||
|
|
||||||
<!-- Overrides -->
|
<!-- Overrides -->
|
||||||
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>
|
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<StackPanel
|
<StackPanel
|
||||||
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
|
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
|
||||||
Orientation="Vertical"
|
Orientation="Vertical"
|
||||||
Spacing="2" />
|
Spacing="{StaticResource SettingsCardSpacing}" />
|
||||||
</ItemsPanelTemplate>
|
</ItemsPanelTemplate>
|
||||||
</Setter.Value>
|
</Setter.Value>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ namespace Microsoft.PowerToys.Settings.UI.Flyout
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ReportBugBtn_Click(object sender, RoutedEventArgs e)
|
internal void ReportBugBtn_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
ViewModel.StartBugReport();
|
ViewModel.StartBugReport();
|
||||||
|
|
||||||
|
|||||||
@@ -266,6 +266,10 @@
|
|||||||
<tkcontrols:SettingsCard x:Uid="GeneralPage_RunAtStartUp" IsEnabled="{x:Bind ViewModel.IsRunAtStartupGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
<tkcontrols:SettingsCard x:Uid="GeneralPage_RunAtStartUp" IsEnabled="{x:Bind ViewModel.IsRunAtStartupGPOManaged, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||||
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.Startup, Mode=TwoWay}" />
|
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.Startup, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
|
|
||||||
|
<tkcontrols:SettingsCard x:Uid="ShowSystemTrayIcon">
|
||||||
|
<ToggleSwitch x:Uid="ShowSystemTrayIcon_ToggleSwitch" IsOn="{x:Bind ViewModel.ShowSysTrayIcon, Mode=TwoWay}" />
|
||||||
|
</tkcontrols:SettingsCard>
|
||||||
<InfoBar
|
<InfoBar
|
||||||
x:Uid="GPO_SettingIsManaged"
|
x:Uid="GPO_SettingIsManaged"
|
||||||
BorderThickness="0"
|
BorderThickness="0"
|
||||||
@@ -402,10 +406,11 @@
|
|||||||
</InfoBar>
|
</InfoBar>
|
||||||
</controls:SettingsGroup>
|
</controls:SettingsGroup>
|
||||||
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback" Visibility="Visible">
|
<controls:SettingsGroup x:Uid="General_DiagnosticsAndFeedback" Visibility="Visible">
|
||||||
<StackPanel>
|
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||||
<HyperlinkButton
|
<HyperlinkButton
|
||||||
x:Uid="GeneralPage_DiagnosticsAndFeedback_Link"
|
x:Uid="GeneralPage_DiagnosticsAndFeedback_Link"
|
||||||
Margin="-8,0,0,0"
|
Margin="0,0,0,8"
|
||||||
|
Padding="0"
|
||||||
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
|
NavigateUri="https://aka.ms/powertoys-data-and-privacy-documentation" />
|
||||||
<tkcontrols:SettingsCard
|
<tkcontrols:SettingsCard
|
||||||
x:Uid="GeneralPage_EnableDataDiagnostics"
|
x:Uid="GeneralPage_EnableDataDiagnostics"
|
||||||
@@ -449,7 +454,12 @@
|
|||||||
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
|
<Button x:Uid="GeneralPage_ViewDiagnosticDataViewerInfoButton" Click="Click_ViewDiagnosticDataViewerRestart" />
|
||||||
</InfoBar.ActionButton>
|
</InfoBar.ActionButton>
|
||||||
</InfoBar>
|
</InfoBar>
|
||||||
|
<tkcontrols:SettingsCard x:Uid="GeneralPage_ReportBugPackage" HeaderIcon="{ui:FontIcon Glyph=}">
|
||||||
|
<Button
|
||||||
|
x:Uid="GeneralPageReportBugPackage"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Click="BugReportToolClicked" />
|
||||||
|
</tkcontrols:SettingsCard>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</controls:SettingsGroup>
|
</controls:SettingsGroup>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
|
using Microsoft.PowerToys.Settings.UI.Flyout;
|
||||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||||
@@ -165,5 +166,24 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
{
|
{
|
||||||
await Task.Run(ViewModel.ViewDiagnosticData);
|
await Task.Run(ViewModel.ViewDiagnosticData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExitPTItem_Tapped(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
const string ptTrayIconWindowClass = "PToyTrayIconWindow"; // Defined in runner/tray_icon.h
|
||||||
|
const nuint ID_EXIT_MENU_COMMAND = 40001; // Generated resource from runner/runner.base.rc
|
||||||
|
|
||||||
|
// Exit the XAML application
|
||||||
|
Application.Current.Exit();
|
||||||
|
|
||||||
|
// Invoke the exit command from the tray icon
|
||||||
|
IntPtr hWnd = NativeMethods.FindWindow(ptTrayIconWindowClass, ptTrayIconWindowClass);
|
||||||
|
NativeMethods.SendMessage(hWnd, NativeMethods.WM_COMMAND, ID_EXIT_MENU_COMMAND, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BugReportToolClicked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
var launchPage = new LaunchPage();
|
||||||
|
launchPage.ReportBugBtn_Click(sender, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,10 +39,17 @@
|
|||||||
Margin="48,0,0,0"
|
Margin="48,0,0,0"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
IsHitTestVisible="True">
|
IsHitTestVisible="True">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="LeftTitleBarColumn" Width="*" />
|
||||||
|
<ColumnDefinition x:Name="RightTitleBarColumn" Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
<animations:Implicit.Animations>
|
<animations:Implicit.Animations>
|
||||||
<animations:OffsetAnimation Duration="0:0:0.3" />
|
<animations:OffsetAnimation Duration="0:0:0.3" />
|
||||||
</animations:Implicit.Animations>
|
</animations:Implicit.Animations>
|
||||||
<StackPanel Orientation="Horizontal">
|
<StackPanel
|
||||||
|
Grid.Column="0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Orientation="Horizontal">
|
||||||
<Image
|
<Image
|
||||||
Width="16"
|
Width="16"
|
||||||
Height="16"
|
Height="16"
|
||||||
@@ -64,6 +71,24 @@
|
|||||||
TextWrapping="NoWrap"
|
TextWrapping="NoWrap"
|
||||||
Visibility="Collapsed" />
|
Visibility="Collapsed" />
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
<StackPanel
|
||||||
|
Grid.Column="1"
|
||||||
|
Margin="0,0,148,0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<Button
|
||||||
|
x:Name="ShutDownBtn"
|
||||||
|
Height="48"
|
||||||
|
Click="ExitPTItem_Tapped"
|
||||||
|
Style="{StaticResource SubtleButtonStyle}">
|
||||||
|
<FontIcon FontSize="16" Glyph="" />
|
||||||
|
<ToolTipService.ToolTip>
|
||||||
|
<ToolTip>
|
||||||
|
<TextBlock x:Uid="AppTitleBarShutDown_Tooltip" />
|
||||||
|
</ToolTip>
|
||||||
|
</ToolTipService.ToolTip>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
<NavigationView
|
<NavigationView
|
||||||
x:Name="navigationView"
|
x:Name="navigationView"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using ManagedCommon;
|
|||||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||||
using Microsoft.PowerToys.Settings.UI.Services;
|
using Microsoft.PowerToys.Settings.UI.Services;
|
||||||
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||||
|
using Microsoft.UI.Windowing;
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Automation.Peers;
|
using Microsoft.UI.Xaml.Automation.Peers;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
@@ -422,6 +423,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
// A custom title bar is required for full window theme and Mica support.
|
// A custom title bar is required for full window theme and Mica support.
|
||||||
// https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization
|
// https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization
|
||||||
u.ExtendsContentIntoTitleBar = true;
|
u.ExtendsContentIntoTitleBar = true;
|
||||||
|
u.AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
|
||||||
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(u));
|
WindowHelpers.ForceTopBorder1PixelInsetOnWindows10(WindowNative.GetWindowHandle(u));
|
||||||
u.SetTitleBar(AppTitleBar);
|
u.SetTitleBar(AppTitleBar);
|
||||||
var loader = ResourceLoaderInstance.ResourceLoader;
|
var loader = ResourceLoaderInstance.ResourceLoader;
|
||||||
@@ -457,5 +459,18 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
{
|
{
|
||||||
navigationView.IsPaneOpen = !navigationView.IsPaneOpen;
|
navigationView.IsPaneOpen = !navigationView.IsPaneOpen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ExitPTItem_Tapped(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
const string ptTrayIconWindowClass = "PToyTrayIconWindow"; // Defined in runner/tray_icon.h
|
||||||
|
const nuint ID_EXIT_MENU_COMMAND = 40001; // Generated resource from runner/runner.base.rc
|
||||||
|
|
||||||
|
// Exit the XAML application
|
||||||
|
Application.Current.Exit();
|
||||||
|
|
||||||
|
// Invoke the exit command from the tray icon
|
||||||
|
IntPtr hWnd = NativeMethods.FindWindow(ptTrayIconWindowClass, ptTrayIconWindowClass);
|
||||||
|
NativeMethods.SendMessage(hWnd, NativeMethods.WM_COMMAND, ID_EXIT_MENU_COMMAND, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4299,6 +4299,12 @@ Activate by holding the key for the character you want to add an accent to, then
|
|||||||
<data name="GeneralPage_ShowWhatsNewAfterUpdates.Content" xml:space="preserve">
|
<data name="GeneralPage_ShowWhatsNewAfterUpdates.Content" xml:space="preserve">
|
||||||
<value>Show the release notes after an update</value>
|
<value>Show the release notes after an update</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ShowSystemTrayIcon.Description" xml:space="preserve">
|
||||||
|
<value>This settings page is accessible by running the PowerToys executable again</value>
|
||||||
|
</data>
|
||||||
|
<data name="ShowSystemTrayIcon.Header" xml:space="preserve">
|
||||||
|
<value>Show system tray icon</value>
|
||||||
|
</data>
|
||||||
<data name="QuickAccent_Prevent_Activation_On_Game_Mode.Content" xml:space="preserve">
|
<data name="QuickAccent_Prevent_Activation_On_Game_Mode.Content" xml:space="preserve">
|
||||||
<value>Do not activate when Game Mode is on</value>
|
<value>Do not activate when Game Mode is on</value>
|
||||||
<comment>"Game mode" is the Windows feature to prevent notification when playing a game.</comment>
|
<comment>"Game mode" is the Windows feature to prevent notification when playing a game.</comment>
|
||||||
@@ -5020,4 +5026,25 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
|||||||
<data name="Help_hueOklch" xml:space="preserve">
|
<data name="Help_hueOklch" xml:space="preserve">
|
||||||
<value>hue (Oklch)</value>
|
<value>hue (Oklch)</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="ExitPT_NavViewItem.Content" xml:space="preserve">
|
||||||
|
<value>Exit PowerToys</value>
|
||||||
|
</data>
|
||||||
|
<data name="General_System.Header" xml:space="preserve">
|
||||||
|
<value>System</value>
|
||||||
|
</data>
|
||||||
|
<data name="GeneralPage_ReportBugPackage.Header" xml:space="preserve">
|
||||||
|
<value>Generate bug report package</value>
|
||||||
|
</data>
|
||||||
|
<data name="GeneralPage_ReportBugPackage.Description" xml:space="preserve">
|
||||||
|
<value>Create zip folder with logs on the Desktop</value>
|
||||||
|
</data>
|
||||||
|
<data name="GeneralPageReportBugPackage.Content" xml:space="preserve">
|
||||||
|
<value>Generate package</value>
|
||||||
|
</data>
|
||||||
|
<data name="AppTitleBarShutDown_Tooltip.Text" xml:space="preserve">
|
||||||
|
<value>Shut down</value>
|
||||||
|
</data>
|
||||||
|
<data name="BugReportUnderConstruction" xml:space="preserve">
|
||||||
|
<value>Bug report package is being created</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -146,6 +146,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
_startup = GeneralSettingsConfig.Startup;
|
_startup = GeneralSettingsConfig.Startup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_showSysTrayIcon = GeneralSettingsConfig.ShowSysTrayIcon;
|
||||||
_showNewUpdatesToastNotification = GeneralSettingsConfig.ShowNewUpdatesToastNotification;
|
_showNewUpdatesToastNotification = GeneralSettingsConfig.ShowNewUpdatesToastNotification;
|
||||||
_autoDownloadUpdates = GeneralSettingsConfig.AutoDownloadUpdates;
|
_autoDownloadUpdates = GeneralSettingsConfig.AutoDownloadUpdates;
|
||||||
_showWhatsNewAfterUpdates = GeneralSettingsConfig.ShowWhatsNewAfterUpdates;
|
_showWhatsNewAfterUpdates = GeneralSettingsConfig.ShowWhatsNewAfterUpdates;
|
||||||
@@ -228,6 +229,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
|
|
||||||
private static bool _isDevBuild;
|
private static bool _isDevBuild;
|
||||||
private bool _startup;
|
private bool _startup;
|
||||||
|
private bool _showSysTrayIcon;
|
||||||
private GpoRuleConfigured _runAtStartupGpoRuleConfiguration;
|
private GpoRuleConfigured _runAtStartupGpoRuleConfiguration;
|
||||||
private bool _runAtStartupIsGPOConfigured;
|
private bool _runAtStartupIsGPOConfigured;
|
||||||
private bool _isElevated;
|
private bool _isElevated;
|
||||||
@@ -359,6 +361,25 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets or sets a value indicating whether the PowerToys icon should be shown in the system tray.
|
||||||
|
public bool ShowSysTrayIcon
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _showSysTrayIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (_showSysTrayIcon != value)
|
||||||
|
{
|
||||||
|
_showSysTrayIcon = value;
|
||||||
|
GeneralSettingsConfig.ShowSysTrayIcon = value;
|
||||||
|
NotifyPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string RunningAsText
|
public string RunningAsText
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|||||||
Reference in New Issue
Block a user