mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-08 05:17:03 +01:00
Compare commits
64 Commits
niels9001/
...
shawn/quic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41c42ae835 | ||
|
|
97dae3a79b | ||
|
|
224db0094c | ||
|
|
e20dc19abc | ||
|
|
1b6b446915 | ||
|
|
78b0139bc3 | ||
|
|
709c4bbf6b | ||
|
|
bb3435322f | ||
|
|
d43e1d8cb2 | ||
|
|
1a145fd136 | ||
|
|
aa262cdf20 | ||
|
|
bb3dee489b | ||
|
|
01aa491962 | ||
|
|
ee0d931f39 | ||
|
|
eceb55ca9f | ||
|
|
e941ea4ebf | ||
|
|
b1cf7fa9da | ||
|
|
346c99543a | ||
|
|
1211e2c92f | ||
|
|
9f99727bf5 | ||
|
|
fee146b084 | ||
|
|
91cceb70d5 | ||
|
|
b73908c413 | ||
|
|
062589b9f7 | ||
|
|
ff21b77b7b | ||
|
|
d6ae07c040 | ||
|
|
e038a09357 | ||
|
|
f6e6fe676a | ||
|
|
debf4322df | ||
|
|
4a823320c4 | ||
|
|
e89d6d8f5a | ||
|
|
2ca7531ae7 | ||
|
|
6ba33b0d91 | ||
|
|
273eebda25 | ||
|
|
fdd34bca09 | ||
|
|
dd9643dd38 | ||
|
|
eb69549320 | ||
|
|
8f6bd72679 | ||
|
|
4865b44de1 | ||
|
|
3381e82fc1 | ||
|
|
a40be6f9be | ||
|
|
90e4f1ca41 | ||
|
|
1fcb8e7515 | ||
|
|
3ed9641072 | ||
|
|
0428cf45af | ||
|
|
5fc0ae7e42 | ||
|
|
8cdd8574d6 | ||
|
|
f564cf9189 | ||
|
|
e826cfb491 | ||
|
|
45e94f2ce0 | ||
|
|
b3b99d6d11 | ||
|
|
bb180a166a | ||
|
|
7e62c76c18 | ||
|
|
68dd7a46f0 | ||
|
|
a67326d86d | ||
|
|
16733718c3 | ||
|
|
5bf797d9f6 | ||
|
|
8de7110918 | ||
|
|
ed254b60cc | ||
|
|
ea0a13be3a | ||
|
|
8e6f40ffe9 | ||
|
|
891dd41cc2 | ||
|
|
d7e727fa1a | ||
|
|
709ceed137 |
7
.github/actions/spell-check/expect.txt
vendored
7
.github/actions/spell-check/expect.txt
vendored
@@ -365,6 +365,7 @@ DEFAULTICON
|
||||
defaultlib
|
||||
DEFAULTONLY
|
||||
DEFAULTTONEAREST
|
||||
Defaulttonearest
|
||||
DEFAULTTONULL
|
||||
DEFAULTTOPRIMARY
|
||||
DEFERERASE
|
||||
@@ -865,6 +866,7 @@ lastcodeanalysissucceeded
|
||||
LASTEXITCODE
|
||||
LAYOUTRTL
|
||||
lbl
|
||||
Lbuttondown
|
||||
LCh
|
||||
lcid
|
||||
LCIDTo
|
||||
@@ -987,6 +989,7 @@ maxversiontested
|
||||
mber
|
||||
MBM
|
||||
MBR
|
||||
Mbuttondown
|
||||
MDICHILD
|
||||
MDL
|
||||
mdtext
|
||||
@@ -1445,6 +1448,7 @@ RAWINPUTHEADER
|
||||
RAWMODE
|
||||
RAWPATH
|
||||
rbhid
|
||||
Rbuttondown
|
||||
rclsid
|
||||
RCZOOMIT
|
||||
remotedesktop
|
||||
@@ -1746,6 +1750,7 @@ svgz
|
||||
SVSI
|
||||
SWFO
|
||||
SWP
|
||||
Swp
|
||||
SWPNOSIZE
|
||||
SWPNOZORDER
|
||||
SWRESTORE
|
||||
@@ -1765,6 +1770,7 @@ syskeydown
|
||||
SYSKEYUP
|
||||
SYSLIB
|
||||
SYSMENU
|
||||
Sysmenu
|
||||
systemai
|
||||
SYSTEMAPPS
|
||||
SYSTEMMODAL
|
||||
@@ -2090,6 +2096,7 @@ Wwanpp
|
||||
xap
|
||||
XAxis
|
||||
XButton
|
||||
Xbuttondown
|
||||
xclip
|
||||
xcopy
|
||||
XDeployment
|
||||
|
||||
@@ -1001,6 +1001,14 @@
|
||||
<Project Path="src/modules/ZoomIt/ZoomItSettingsInterop/ZoomItSettingsInterop.vcxproj" Id="ca7d8106-30b9-4aec-9d05-b69b31b8c461" />
|
||||
</Folder>
|
||||
<Folder Name="/settings-ui/">
|
||||
<Project Path="src/settings-ui/QuickAccess.UI/PowerToys.QuickAccess.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/settings-ui/Settings.UI.Controls/Settings.UI.Controls.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
</Project>
|
||||
<Project Path="src/settings-ui/Settings.UI.Library/Settings.UI.Library.csproj">
|
||||
<Platform Solution="*|ARM64" Project="ARM64" />
|
||||
<Platform Solution="*|x64" Project="x64" />
|
||||
|
||||
@@ -58,8 +58,8 @@ string validUIDisplayString = Resources.ValidUIDisplayString;
|
||||
## More On Coding Guidance
|
||||
Please review these brief docs below relating to our coding standards, etc.
|
||||
|
||||
* [Coding Style](./style.md)
|
||||
* [Code Organization](./readme.md)
|
||||
* [Coding Style](development/style.md)
|
||||
* [Code Organization](readme.md)
|
||||
|
||||
|
||||
[VS Resource Editor]: https://learn.microsoft.com/cpp/windows/resource-editors?view=vs-2019
|
||||
|
||||
@@ -57,7 +57,7 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and an
|
||||
## Rules
|
||||
|
||||
- **Follow the pattern of what you already see in the code.**
|
||||
- [Coding style](style.md).
|
||||
- [Coding style](development/style.md).
|
||||
- Try to package new functionality/components into libraries that have nicely defined interfaces.
|
||||
- Package new functionality into classes or refactor existing functionality into a class as you extend the code.
|
||||
- When adding new classes/methods/changing existing code, add new unit tests or update the existing tests.
|
||||
|
||||
@@ -50,6 +50,7 @@ Contact the developers of a plugin directly for assistance with a specific plugi
|
||||
| [Hotkeys](https://github.com/ruslanlap/PowerToysRun-Hotkeys) | [ruslanlap](https://github.com/ruslanlap) | Create, manage, and trigger custom keyboard shortcuts directly from PowerToys Run. |
|
||||
| [RandomGen](https://github.com/ruslanlap/PowerToysRun-RandomGen) | [ruslanlap](https://github.com/ruslanlap) | 🎲 Generate random data instantly with a single keystroke. Perfect for developers, testers, designers, and anyone who needs quick access to random data. Features include secure passwords, PINs, names, business data, dates, numbers, GUIDs, color codes, and more. Especially useful for designers who need random color codes and placeholder content. |
|
||||
| [Open With Cursor](https://github.com/VictorNoxx/PowerToys-Run-Cursor/) | [VictorNoxx](https://github.com/VictorNoxx) | Open Visual Studio, VS Code recents with Cursor AI |
|
||||
| [Open With Antygravity](https://github.com/artickc/PowerToys-Run-Antygravity) | [artickc](https://github.com/artickc) | Open Visual Studio, VS Code recents with Cursor AI |
|
||||
| [CheatSheets](https://github.com/ruslanlap/PowerToysRun-CheatSheets) | [ruslanlap](https://github.com/ruslanlap) | 📚 Find cheat sheets and command examples instantly from tldr pages, cheat.sh, and devhints.io. Features include favorites system, categories, offline mode, and smart caching. |
|
||||
| [QuickAI](https://github.com/ruslanlap/PowerToysRun-QuickAi) | [ruslanlap](https://github.com/ruslanlap) | AI-powered assistance with instant, smart responses from multiple providers (Groq, Together, Fireworks, OpenRouter, Cohere) |
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Microsoft.PowerToys.FilePreviewCommon
|
||||
var softlineBreak = new Markdig.Extensions.Hardlines.SoftlineBreakAsHardlineExtension();
|
||||
|
||||
MarkdownPipelineBuilder pipelineBuilder;
|
||||
pipelineBuilder = new MarkdownPipelineBuilder().UseAdvancedExtensions().UseEmojiAndSmiley().UseYamlFrontMatter().UseMathematics();
|
||||
pipelineBuilder = new MarkdownPipelineBuilder().UseAdvancedExtensions().UseEmojiAndSmiley().UseYamlFrontMatter().UseMathematics().DisableHtml();
|
||||
pipelineBuilder.Extensions.Add(extension);
|
||||
pipelineBuilder.Extensions.Add(softlineBreak);
|
||||
|
||||
|
||||
@@ -36,5 +36,6 @@ namespace ManagedCommon
|
||||
PowerOCR,
|
||||
Workspaces,
|
||||
ZoomIt,
|
||||
GeneralSettings,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,16 @@ namespace PowerToysSettings
|
||||
class HotkeyObject
|
||||
{
|
||||
public:
|
||||
HotkeyObject() :
|
||||
m_json(json::JsonObject())
|
||||
{
|
||||
m_json.SetNamedValue(L"win", json::value(false));
|
||||
m_json.SetNamedValue(L"ctrl", json::value(false));
|
||||
m_json.SetNamedValue(L"alt", json::value(false));
|
||||
m_json.SetNamedValue(L"shift", json::value(false));
|
||||
m_json.SetNamedValue(L"code", json::value(0));
|
||||
m_json.SetNamedValue(L"key", json::value(L""));
|
||||
}
|
||||
static HotkeyObject from_json(json::JsonObject json)
|
||||
{
|
||||
return HotkeyObject(std::move(json));
|
||||
|
||||
@@ -466,27 +466,39 @@
|
||||
TextChanged="EditVariableDialogValueTxtBox_TextChanged"
|
||||
TextWrapping="Wrap" />
|
||||
<MenuFlyoutSeparator Visibility="{Binding ShowAsList, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<ItemsControl
|
||||
<ListView
|
||||
x:Name="EditVariableValuesList"
|
||||
Margin="0,-8,0,12"
|
||||
HorizontalAlignment="Stretch"
|
||||
AllowDrop="True"
|
||||
CanDragItems="True"
|
||||
CanReorderItems="True"
|
||||
DragItemsCompleted="EditVariableValuesList_DragItemsCompleted"
|
||||
ItemsSource="{Binding ValuesList, Mode=TwoWay}"
|
||||
Visibility="{Binding ShowAsList, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="32" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="40" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<FontIcon
|
||||
Grid.Column="0"
|
||||
Margin="0,0,8,0"
|
||||
FontSize="16"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Glyph="" />
|
||||
<TextBox
|
||||
Grid.Column="1"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
LostFocus="EditVariableValuesListTextBox_LostFocus"
|
||||
Text="{Binding Text}" />
|
||||
<Button
|
||||
x:Uid="More_Options_Button"
|
||||
Grid.Column="1"
|
||||
Grid.Column="2"
|
||||
VerticalAlignment="Center"
|
||||
Content=""
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
@@ -523,8 +535,8 @@
|
||||
</Button>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</ContentDialog>
|
||||
|
||||
@@ -16,6 +16,8 @@ namespace EnvironmentVariablesUILib
|
||||
{
|
||||
public sealed partial class EnvironmentVariablesMainPage : Page
|
||||
{
|
||||
private const string ValueListSeparator = ";";
|
||||
|
||||
private sealed class RelayCommandParameter
|
||||
{
|
||||
public RelayCommandParameter(Variable variable, VariablesSet set)
|
||||
@@ -440,7 +442,7 @@ namespace EnvironmentVariablesUILib
|
||||
variable.ValuesList.Move(index, index - 1);
|
||||
}
|
||||
|
||||
var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
}
|
||||
|
||||
@@ -461,7 +463,7 @@ namespace EnvironmentVariablesUILib
|
||||
variable.ValuesList.Move(index, index + 1);
|
||||
}
|
||||
|
||||
var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
}
|
||||
|
||||
@@ -476,7 +478,7 @@ namespace EnvironmentVariablesUILib
|
||||
var variable = EditVariableDialog.DataContext as Variable;
|
||||
variable.ValuesList.Remove(listItem);
|
||||
|
||||
var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
}
|
||||
|
||||
@@ -492,7 +494,7 @@ namespace EnvironmentVariablesUILib
|
||||
var index = variable.ValuesList.IndexOf(listItem);
|
||||
variable.ValuesList.Insert(index, new Variable.ValuesListItem { Text = string.Empty });
|
||||
|
||||
var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
|
||||
@@ -510,7 +512,7 @@ namespace EnvironmentVariablesUILib
|
||||
var index = variable.ValuesList.IndexOf(listItem);
|
||||
variable.ValuesList.Insert(index + 1, new Variable.ValuesListItem { Text = string.Empty });
|
||||
|
||||
var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
|
||||
@@ -532,7 +534,7 @@ namespace EnvironmentVariablesUILib
|
||||
listItem.Text = (sender as TextBox)?.Text;
|
||||
var variable = EditVariableDialog.DataContext as Variable;
|
||||
|
||||
var newValues = string.Join(";", variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList?.Select(x => x.Text).ToArray());
|
||||
EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
|
||||
@@ -548,5 +550,16 @@ namespace EnvironmentVariablesUILib
|
||||
CancelAddVariable();
|
||||
ConfirmAddVariableBtn.IsEnabled = false;
|
||||
}
|
||||
|
||||
private void EditVariableValuesList_DragItemsCompleted(ListViewBase sender, DragItemsCompletedEventArgs args)
|
||||
{
|
||||
if (EditVariableDialog.DataContext is Variable variable && variable.ValuesList != null)
|
||||
{
|
||||
var newValues = string.Join(ValueListSeparator, variable.ValuesList.Select(x => x.Text));
|
||||
EditVariableDialogValueTxtBox.TextChanged -= EditVariableDialogValueTxtBox_TextChanged;
|
||||
EditVariableDialogValueTxtBox.Text = newValues;
|
||||
EditVariableDialogValueTxtBox.TextChanged += EditVariableDialogValueTxtBox_TextChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Pages;
|
||||
|
||||
@@ -24,15 +25,15 @@ internal sealed partial class FancyZonesMonitorListItem : ListItem
|
||||
|
||||
var pickerPage = new FancyZonesMonitorLayoutPickerPage(monitor)
|
||||
{
|
||||
Name = "Set active layout",
|
||||
Name = Resources.FancyZones_SetActiveLayout,
|
||||
};
|
||||
|
||||
MoreCommands =
|
||||
[
|
||||
new CommandContextItem(pickerPage)
|
||||
{
|
||||
Title = "Set active layout",
|
||||
Subtitle = "Pick a layout for this monitor",
|
||||
Title = Resources.FancyZones_SetActiveLayout,
|
||||
Subtitle = Resources.FancyZones_PickLayoutForMonitor,
|
||||
},
|
||||
];
|
||||
}
|
||||
@@ -42,14 +43,14 @@ internal sealed partial class FancyZonesMonitorListItem : ListItem
|
||||
var currentVirtualDesktop = FancyZonesVirtualDesktop.GetCurrentVirtualDesktopIdString();
|
||||
var tags = new List<IDetailsElement>
|
||||
{
|
||||
DetailTag("Monitor", monitor.Data.Monitor),
|
||||
DetailTag("Instance", monitor.Data.MonitorInstanceId),
|
||||
DetailTag("Serial", monitor.Data.MonitorSerialNumber),
|
||||
DetailTag("Number", monitor.Data.MonitorNumber.ToString(CultureInfo.InvariantCulture)),
|
||||
DetailTag("Virtual desktop", currentVirtualDesktop),
|
||||
DetailTag("Work area", $"{monitor.Data.LeftCoordinate},{monitor.Data.TopCoordinate} {monitor.Data.WorkAreaWidth}\u00D7{monitor.Data.WorkAreaHeight}"),
|
||||
DetailTag("Resolution", $"{monitor.Data.MonitorWidth}\u00D7{monitor.Data.MonitorHeight}"),
|
||||
DetailTag("DPI", monitor.Data.Dpi.ToString(CultureInfo.InvariantCulture)),
|
||||
DetailTag(Resources.FancyZones_Monitor, monitor.Data.Monitor),
|
||||
DetailTag(Resources.FancyZones_Instance, monitor.Data.MonitorInstanceId),
|
||||
DetailTag(Resources.FancyZones_Serial, monitor.Data.MonitorSerialNumber),
|
||||
DetailTag(Resources.FancyZones_Number, monitor.Data.MonitorNumber.ToString(CultureInfo.InvariantCulture)),
|
||||
DetailTag(Resources.FancyZones_VirtualDesktop, currentVirtualDesktop),
|
||||
DetailTag(Resources.FancyZones_WorkArea, $"{monitor.Data.LeftCoordinate},{monitor.Data.TopCoordinate} {monitor.Data.WorkAreaWidth}\u00D7{monitor.Data.WorkAreaHeight}"),
|
||||
DetailTag(Resources.FancyZones_Resolution, $"{monitor.Data.MonitorWidth}\u00D7{monitor.Data.MonitorHeight}"),
|
||||
DetailTag(Resources.FancyZones_DPI, monitor.Data.Dpi.ToString(CultureInfo.InvariantCulture)),
|
||||
};
|
||||
|
||||
return new Details
|
||||
@@ -68,7 +69,7 @@ internal sealed partial class FancyZonesMonitorListItem : ListItem
|
||||
Key = key,
|
||||
Data = new DetailsTags
|
||||
{
|
||||
Tags = [new Tag(string.IsNullOrWhiteSpace(value) ? "n/a" : value)],
|
||||
Tags = [new Tag(string.IsNullOrWhiteSpace(value) ? Resources.Common_NotAvailable : value)],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -5,15 +5,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using WorkspacesCsharpLibrary.Data;
|
||||
|
||||
namespace PowerToysExtension.Commands;
|
||||
|
||||
internal sealed partial class WorkspaceListItem : ListItem
|
||||
{
|
||||
private static readonly CompositeFormat ApplicationsFormat = CompositeFormat.Parse(Resources.Workspaces_Applications_Format);
|
||||
private static readonly CompositeFormat LastLaunchedFormat = CompositeFormat.Parse(Resources.Workspaces_LastLaunched_Format);
|
||||
private static readonly CompositeFormat ApplicationsCountFormat = CompositeFormat.Parse(Resources.Workspaces_ApplicationsCount_Format);
|
||||
private static readonly CompositeFormat MinAgoFormat = CompositeFormat.Parse(Resources.Workspaces_MinAgo_Format);
|
||||
private static readonly CompositeFormat HrAgoFormat = CompositeFormat.Parse(Resources.Workspaces_HrAgo_Format);
|
||||
private static readonly CompositeFormat DaysAgoFormat = CompositeFormat.Parse(Resources.Workspaces_DaysAgo_Format);
|
||||
|
||||
public WorkspaceListItem(ProjectWrapper workspace, IconInfo icon)
|
||||
: base(new LaunchWorkspaceCommand(workspace.Id))
|
||||
{
|
||||
@@ -28,13 +37,13 @@ internal sealed partial class WorkspaceListItem : ListItem
|
||||
var appCount = workspace.Applications?.Count ?? 0;
|
||||
var appsText = appCount switch
|
||||
{
|
||||
0 => "No applications",
|
||||
_ => string.Format(CultureInfo.CurrentCulture, "{0} applications", appCount),
|
||||
0 => Resources.Workspaces_NoApplications,
|
||||
_ => string.Format(CultureInfo.CurrentCulture, ApplicationsFormat, appCount),
|
||||
};
|
||||
|
||||
var lastLaunched = workspace.LastLaunchedTime > 0
|
||||
? $"Last launched {FormatRelativeTime(workspace.LastLaunchedTime)}"
|
||||
: "Never launched";
|
||||
? string.Format(CultureInfo.CurrentCulture, LastLaunchedFormat, FormatRelativeTime(workspace.LastLaunchedTime))
|
||||
: Resources.Workspaces_NeverLaunched;
|
||||
|
||||
return $"{appsText} \u2022 {lastLaunched}";
|
||||
}
|
||||
@@ -44,15 +53,15 @@ internal sealed partial class WorkspaceListItem : ListItem
|
||||
var appCount = workspace.Applications?.Count ?? 0;
|
||||
var body = appCount switch
|
||||
{
|
||||
0 => "No applications in this workspace",
|
||||
1 => "1 application",
|
||||
_ => $"{appCount} applications",
|
||||
0 => Resources.Workspaces_NoApplicationsInWorkspace,
|
||||
1 => Resources.Workspaces_OneApplication,
|
||||
_ => string.Format(CultureInfo.CurrentCulture, ApplicationsCountFormat, appCount),
|
||||
};
|
||||
|
||||
return new Details
|
||||
{
|
||||
HeroImage = icon,
|
||||
Title = workspace.Name ?? "Workspace",
|
||||
Title = workspace.Name ?? Resources.Workspaces_Workspace,
|
||||
Body = body,
|
||||
Metadata = BuildAppMetadata(workspace),
|
||||
};
|
||||
@@ -68,7 +77,7 @@ internal sealed partial class WorkspaceListItem : ListItem
|
||||
var elements = new List<IDetailsElement>();
|
||||
foreach (var app in workspace.Applications)
|
||||
{
|
||||
var appName = string.IsNullOrWhiteSpace(app.Application) ? "App" : app.Application;
|
||||
var appName = string.IsNullOrWhiteSpace(app.Application) ? Resources.Workspaces_App : app.Application;
|
||||
var title = string.IsNullOrWhiteSpace(app.Title) ? appName : app.Title;
|
||||
|
||||
var tags = new List<ITag>();
|
||||
@@ -99,19 +108,19 @@ internal sealed partial class WorkspaceListItem : ListItem
|
||||
|
||||
if (delta.TotalMinutes < 1)
|
||||
{
|
||||
return "just now";
|
||||
return Resources.Workspaces_JustNow;
|
||||
}
|
||||
|
||||
if (delta.TotalMinutes < 60)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0} min ago", (int)delta.TotalMinutes);
|
||||
return string.Format(CultureInfo.CurrentCulture, MinAgoFormat, (int)delta.TotalMinutes);
|
||||
}
|
||||
|
||||
if (delta.TotalHours < 24)
|
||||
{
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0} hr ago", (int)delta.TotalHours);
|
||||
return string.Format(CultureInfo.CurrentCulture, HrAgoFormat, (int)delta.TotalHours);
|
||||
}
|
||||
|
||||
return string.Format(CultureInfo.CurrentCulture, "{0} days ago", (int)delta.TotalDays);
|
||||
return string.Format(CultureInfo.CurrentCulture, DaysAgoFormat, (int)delta.TotalDays);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
using FancyZonesEditorCommon.Data;
|
||||
using FancyZonesEditorCommon.Utils;
|
||||
using ManagedCommon;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
using FZPaths = FancyZonesEditorCommon.Data.FancyZonesPaths;
|
||||
|
||||
@@ -20,6 +23,15 @@ internal static class FancyZonesDataService
|
||||
{
|
||||
private const string ZeroUuid = "{00000000-0000-0000-0000-000000000000}";
|
||||
|
||||
private static readonly CompositeFormat ReadMonitorDataFailedFormat = CompositeFormat.Parse(Resources.FancyZones_ReadMonitorDataFailed_Format);
|
||||
private static readonly CompositeFormat WriteAppliedLayoutsFailedFormat = CompositeFormat.Parse(Resources.FancyZones_WriteAppliedLayoutsFailed_Format);
|
||||
private static readonly CompositeFormat LayoutAppliedNotifyFailedFormat = CompositeFormat.Parse(Resources.FancyZones_LayoutAppliedNotifyFailed_Format);
|
||||
private static readonly CompositeFormat TemplateFormat = CompositeFormat.Parse(Resources.FancyZones_Template_Format);
|
||||
private static readonly CompositeFormat ZonesFormat = CompositeFormat.Parse(Resources.FancyZones_Zones_Format);
|
||||
private static readonly CompositeFormat CustomGridZonesFormat = CompositeFormat.Parse(Resources.FancyZones_CustomGrid_Zones_Format);
|
||||
private static readonly CompositeFormat CustomCanvasZonesFormat = CompositeFormat.Parse(Resources.FancyZones_CustomCanvas_Zones_Format);
|
||||
private static readonly CompositeFormat CustomZonesFormat = CompositeFormat.Parse(Resources.FancyZones_Custom_Zones_Format);
|
||||
|
||||
public static bool TryGetMonitors(out IReadOnlyList<FancyZonesMonitorDescriptor> monitors, out string error)
|
||||
{
|
||||
monitors = Array.Empty<FancyZonesMonitorDescriptor>();
|
||||
@@ -31,7 +43,7 @@ internal static class FancyZonesDataService
|
||||
{
|
||||
if (!File.Exists(FZPaths.EditorParameters))
|
||||
{
|
||||
error = "FancyZones monitor data not found. Open FancyZones Editor once to initialize.";
|
||||
error = Resources.FancyZones_MonitorDataNotFound;
|
||||
Logger.LogWarning($"TryGetMonitors: File not found. Path={FZPaths.EditorParameters}");
|
||||
return false;
|
||||
}
|
||||
@@ -43,7 +55,7 @@ internal static class FancyZonesDataService
|
||||
var editorMonitors = editorParams.Monitors;
|
||||
if (editorMonitors is null || editorMonitors.Count == 0)
|
||||
{
|
||||
error = "No FancyZones monitors found.";
|
||||
error = Resources.FancyZones_NoFancyZonesMonitorsFound;
|
||||
Logger.LogWarning($"TryGetMonitors: No monitors in file.");
|
||||
return false;
|
||||
}
|
||||
@@ -56,7 +68,7 @@ internal static class FancyZonesDataService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
error = $"Failed to read FancyZones monitor data: {ex.Message}";
|
||||
error = string.Format(CultureInfo.CurrentCulture, ReadMonitorDataFailedFormat, ex.Message);
|
||||
Logger.LogError($"TryGetMonitors: Exception. Message={ex.Message} Stack={ex.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
@@ -204,7 +216,7 @@ internal static class FancyZonesDataService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (false, $"Failed to write applied layouts: {ex.Message}");
|
||||
return (false, string.Format(CultureInfo.CurrentCulture, WriteAppliedLayoutsFailedFormat, ex.Message));
|
||||
}
|
||||
|
||||
try
|
||||
@@ -213,10 +225,10 @@ internal static class FancyZonesDataService
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (true, $"Layout applied, but FancyZones could not be notified: {ex.Message}");
|
||||
return (true, string.Format(CultureInfo.CurrentCulture, LayoutAppliedNotifyFailedFormat, ex.Message));
|
||||
}
|
||||
|
||||
return (true, "Layout applied.");
|
||||
return (true, Resources.FancyZones_LayoutApplied);
|
||||
}
|
||||
|
||||
private static AppliedLayouts.AppliedLayoutWrapper? FindAppliedLayoutEntry(AppliedLayouts.AppliedLayoutsListWrapper file, EditorParameters.NativeMonitorDataWrapper monitor, string virtualDesktopId)
|
||||
@@ -293,8 +305,8 @@ internal static class FancyZonesDataService
|
||||
var zoneCount = type.Equals("blank", StringComparison.OrdinalIgnoreCase)
|
||||
? 0
|
||||
: template.ZoneCount > 0 ? template.ZoneCount : 3;
|
||||
var title = $"Template: {type}";
|
||||
var subtitle = $"{zoneCount} zones";
|
||||
var title = string.Format(CultureInfo.CurrentCulture, TemplateFormat, type);
|
||||
var subtitle = string.Format(CultureInfo.CurrentCulture, ZonesFormat, zoneCount);
|
||||
|
||||
yield return new FancyZonesLayoutDescriptor
|
||||
{
|
||||
@@ -357,9 +369,9 @@ internal static class FancyZonesDataService
|
||||
var title = custom.Name.Trim();
|
||||
var subtitle = customType switch
|
||||
{
|
||||
"grid" => $"Custom grid \u2022 {applied.ZoneCount} zones",
|
||||
"canvas" => $"Custom canvas \u2022 {applied.ZoneCount} zones",
|
||||
_ => $"Custom \u2022 {applied.ZoneCount} zones",
|
||||
"grid" => string.Format(CultureInfo.CurrentCulture, CustomGridZonesFormat, applied.ZoneCount),
|
||||
"canvas" => string.Format(CultureInfo.CurrentCulture, CustomCanvasZonesFormat, applied.ZoneCount),
|
||||
_ => string.Format(CultureInfo.CurrentCulture, CustomZonesFormat, applied.ZoneCount),
|
||||
};
|
||||
|
||||
yield return new FancyZonesLayoutDescriptor
|
||||
|
||||
@@ -61,6 +61,21 @@
|
||||
<ProjectReference Include="..\..\..\Workspaces\Workspaces.ModuleServices\Workspaces.ModuleServices.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- Always build/publish AOT so the extension ships as native code -->
|
||||
<SelfContained>true</SelfContained>
|
||||
|
||||
@@ -7,6 +7,7 @@ using Common.UI;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
|
||||
@@ -22,8 +23,8 @@ internal sealed class AdvancedPasteModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new OpenAdvancedPasteCommand())
|
||||
{
|
||||
Title = "Open Advanced Paste",
|
||||
Subtitle = "Launch the Advanced Paste UI",
|
||||
Title = Resources.AdvancedPaste_Open_Title,
|
||||
Subtitle = Resources.AdvancedPaste_Open_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -31,7 +32,7 @@ internal sealed class AdvancedPasteModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Advanced Paste settings",
|
||||
Subtitle = Resources.AdvancedPaste_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class AlwaysOnTopModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.AlwaysOnTop, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Always On Top settings",
|
||||
Subtitle = Resources.AlwaysOnTop_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Pages;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
|
||||
@@ -26,7 +27,7 @@ internal sealed class AwakeModuleCommandProvider : ModuleCommandProvider
|
||||
items.Add(new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Awake settings",
|
||||
Subtitle = Resources.Awake_Settings_Subtitle,
|
||||
Icon = moduleIcon,
|
||||
});
|
||||
|
||||
@@ -49,40 +50,40 @@ internal sealed class AwakeModuleCommandProvider : ModuleCommandProvider
|
||||
|
||||
statusItem = new ListItem(new CommandItem(refreshCommand))
|
||||
{
|
||||
Title = "Awake: Current status",
|
||||
Title = Resources.Awake_Status_Title,
|
||||
Subtitle = AwakeStatusService.GetStatusSubtitle(),
|
||||
Icon = icon,
|
||||
};
|
||||
items.Add(statusItem);
|
||||
|
||||
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake indefinitely", () => AwakeService.Instance.SetIndefiniteAsync(), "Awake set to indefinite", refreshStatus))
|
||||
items.Add(new ListItem(new StartAwakeCommand(Resources.Awake_KeepIndefinite_Title, () => AwakeService.Instance.SetIndefiniteAsync(), Resources.Awake_SetIndefinite_Toast, refreshStatus))
|
||||
{
|
||||
Title = "Awake: Keep awake indefinitely",
|
||||
Subtitle = "Run Awake in indefinite mode",
|
||||
Title = Resources.Awake_KeepIndefinite_Title,
|
||||
Subtitle = Resources.Awake_KeepIndefinite_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake for 30 minutes", () => AwakeService.Instance.SetTimedAsync(30), "Awake set for 30 minutes", refreshStatus))
|
||||
items.Add(new ListItem(new StartAwakeCommand(Resources.Awake_Keep30Min_Title, () => AwakeService.Instance.SetTimedAsync(30), Resources.Awake_Set30Min_Toast, refreshStatus))
|
||||
{
|
||||
Title = "Awake: Keep awake for 30 minutes",
|
||||
Subtitle = "Run Awake timed for 30 minutes",
|
||||
Title = Resources.Awake_Keep30Min_Title,
|
||||
Subtitle = Resources.Awake_Keep30Min_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake for 1 hour", () => AwakeService.Instance.SetTimedAsync(60), "Awake set for 1 hour", refreshStatus))
|
||||
items.Add(new ListItem(new StartAwakeCommand(Resources.Awake_Keep1Hour_Title, () => AwakeService.Instance.SetTimedAsync(60), Resources.Awake_Set1Hour_Toast, refreshStatus))
|
||||
{
|
||||
Title = "Awake: Keep awake for 1 hour",
|
||||
Subtitle = "Run Awake timed for 1 hour",
|
||||
Title = Resources.Awake_Keep1Hour_Title,
|
||||
Subtitle = Resources.Awake_Keep1Hour_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
items.Add(new ListItem(new StartAwakeCommand("Awake: Keep awake for 2 hours", () => AwakeService.Instance.SetTimedAsync(120), "Awake set for 2 hours", refreshStatus))
|
||||
items.Add(new ListItem(new StartAwakeCommand(Resources.Awake_Keep2Hours_Title, () => AwakeService.Instance.SetTimedAsync(120), Resources.Awake_Set2Hours_Toast, refreshStatus))
|
||||
{
|
||||
Title = "Awake: Keep awake for 2 hours",
|
||||
Subtitle = "Run Awake timed for 2 hours",
|
||||
Title = Resources.Awake_Keep2Hours_Title,
|
||||
Subtitle = Resources.Awake_Keep2Hours_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
items.Add(new ListItem(new StopAwakeCommand(refreshStatus))
|
||||
{
|
||||
Title = "Awake: Turn off",
|
||||
Subtitle = "Switch Awake back to Off",
|
||||
Title = Resources.Awake_TurnOff_Title,
|
||||
Subtitle = Resources.Awake_TurnOff_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Pages;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
|
||||
@@ -24,7 +25,7 @@ internal sealed class ColorPickerModuleCommandProvider : ModuleCommandProvider
|
||||
commands.Add(new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Color Picker settings",
|
||||
Subtitle = Resources.ColorPicker_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
|
||||
@@ -36,15 +37,15 @@ internal sealed class ColorPickerModuleCommandProvider : ModuleCommandProvider
|
||||
// Direct entries in the module list.
|
||||
commands.Add(new ListItem(new OpenColorPickerCommand())
|
||||
{
|
||||
Title = "Open Color Picker",
|
||||
Subtitle = "Start a color pick session",
|
||||
Title = Resources.ColorPicker_Open_Title,
|
||||
Subtitle = Resources.ColorPicker_Open_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
|
||||
commands.Add(new ListItem(new CommandItem(new ColorPickerSavedColorsPage()))
|
||||
{
|
||||
Title = "Saved colors",
|
||||
Subtitle = "Browse and copy saved colors",
|
||||
Title = Resources.ColorPicker_SavedColors_Title,
|
||||
Subtitle = Resources.ColorPicker_SavedColors_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class CommandNotFoundModuleCommandProvider : ModuleCommandProvid
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.CmdNotFound, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Command Not Found settings",
|
||||
Subtitle = Resources.CommandNotFound_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,15 +23,15 @@ internal sealed class CropAndLockModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new CropAndLockReparentCommand())
|
||||
{
|
||||
Title = "Crop and Lock (Reparent)",
|
||||
Subtitle = "Create a cropped reparented window",
|
||||
Title = Resources.CropAndLock_Reparent_Title,
|
||||
Subtitle = Resources.CropAndLock_Reparent_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new CropAndLockThumbnailCommand())
|
||||
{
|
||||
Title = "Crop and Lock (Thumbnail)",
|
||||
Subtitle = "Create a cropped thumbnail window",
|
||||
Title = Resources.CropAndLock_Thumbnail_Title,
|
||||
Subtitle = Resources.CropAndLock_Thumbnail_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -38,7 +39,7 @@ internal sealed class CropAndLockModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Crop and Lock settings",
|
||||
Subtitle = Resources.CropAndLock_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,15 +23,15 @@ internal sealed class EnvironmentVariablesModuleCommandProvider : ModuleCommandP
|
||||
{
|
||||
yield return new ListItem(new OpenEnvironmentVariablesCommand())
|
||||
{
|
||||
Title = "Open Environment Variables",
|
||||
Subtitle = "Launch Environment Variables editor",
|
||||
Title = Resources.EnvironmentVariables_Open_Title,
|
||||
Subtitle = Resources.EnvironmentVariables_Open_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new OpenEnvironmentVariablesAdminCommand())
|
||||
{
|
||||
Title = "Open Environment Variables (Admin)",
|
||||
Subtitle = "Launch Environment Variables editor as admin",
|
||||
Title = Resources.EnvironmentVariables_OpenAdmin_Title,
|
||||
Subtitle = Resources.EnvironmentVariables_OpenAdmin_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -38,7 +39,7 @@ internal sealed class EnvironmentVariablesModuleCommandProvider : ModuleCommandP
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Environment Variables settings",
|
||||
Subtitle = Resources.EnvironmentVariables_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Pages;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -23,22 +24,22 @@ internal sealed class FancyZonesModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new CommandItem(new FancyZonesLayoutsPage()))
|
||||
{
|
||||
Title = "FancyZones: Layouts",
|
||||
Subtitle = "Apply a layout to all monitors or a specific monitor",
|
||||
Title = Resources.FancyZones_Layouts_Title,
|
||||
Subtitle = Resources.FancyZones_Layouts_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new CommandItem(new FancyZonesMonitorsPage()))
|
||||
{
|
||||
Title = "FancyZones: Monitors",
|
||||
Subtitle = "Identify monitors and apply layouts",
|
||||
Title = Resources.FancyZones_Monitors_Title,
|
||||
Subtitle = Resources.FancyZones_Monitors_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new OpenFancyZonesEditorCommand())
|
||||
{
|
||||
Title = "Open FancyZones Editor",
|
||||
Subtitle = "Launch layout editor",
|
||||
Title = Resources.FancyZones_OpenEditor_Title,
|
||||
Subtitle = Resources.FancyZones_OpenEditor_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -46,7 +47,7 @@ internal sealed class FancyZonesModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open FancyZones settings",
|
||||
Subtitle = Resources.FancyZones_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class FileExplorerAddonsModuleCommandProvider : ModuleCommandPro
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.FileExplorer, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open File Explorer add-ons settings",
|
||||
Subtitle = Resources.FileExplorerAddons_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class FileLocksmithModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.FileLocksmith, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open File Locksmith settings",
|
||||
Subtitle = Resources.FileLocksmith_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,15 +23,15 @@ internal sealed class HostsModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new OpenHostsEditorCommand())
|
||||
{
|
||||
Title = "Open Hosts File Editor",
|
||||
Subtitle = "Launch Hosts File Editor",
|
||||
Title = Resources.Hosts_Open_Title,
|
||||
Subtitle = Resources.Hosts_Open_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
|
||||
yield return new ListItem(new OpenHostsEditorAdminCommand())
|
||||
{
|
||||
Title = "Open Hosts File Editor (Admin)",
|
||||
Subtitle = "Launch Hosts File Editor as admin",
|
||||
Title = Resources.Hosts_OpenAdmin_Title,
|
||||
Subtitle = Resources.Hosts_OpenAdmin_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -38,7 +39,7 @@ internal sealed class HostsModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Hosts File Editor settings",
|
||||
Subtitle = Resources.Hosts_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class ImageResizerModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.ImageResizer, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Image Resizer settings",
|
||||
Subtitle = Resources.ImageResizer_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class KeyboardManagerModuleCommandProvider : ModuleCommandProvid
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.KBM, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Keyboard Manager settings",
|
||||
Subtitle = Resources.KeyboardManager_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -24,8 +25,8 @@ internal sealed class LightSwitchModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
items.Add(new ListItem(new ToggleLightSwitchCommand())
|
||||
{
|
||||
Title = "Toggle Light Switch",
|
||||
Subtitle = "Toggle system/apps theme immediately",
|
||||
Title = Resources.LightSwitch_Toggle_Title,
|
||||
Subtitle = Resources.LightSwitch_Toggle_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
}
|
||||
@@ -33,7 +34,7 @@ internal sealed class LightSwitchModuleCommandProvider : ModuleCommandProvider
|
||||
items.Add(new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Light Switch settings",
|
||||
Subtitle = Resources.LightSwitch_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,8 +23,8 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleFindMyMouseCommand())
|
||||
{
|
||||
Title = "Trigger Find My Mouse",
|
||||
Subtitle = "Focus the mouse pointer",
|
||||
Title = Resources.MouseUtils_FindMyMouse_Title,
|
||||
Subtitle = Resources.MouseUtils_FindMyMouse_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -32,8 +33,8 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleMouseHighlighterCommand())
|
||||
{
|
||||
Title = "Toggle Mouse Highlighter",
|
||||
Subtitle = "Highlight mouse clicks",
|
||||
Title = Resources.MouseUtils_Highlighter_Title,
|
||||
Subtitle = Resources.MouseUtils_Highlighter_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -42,8 +43,8 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleMouseCrosshairsCommand())
|
||||
{
|
||||
Title = "Toggle Mouse Crosshairs",
|
||||
Subtitle = "Enable or disable pointer crosshairs",
|
||||
Title = Resources.MouseUtils_Crosshairs_Title,
|
||||
Subtitle = Resources.MouseUtils_Crosshairs_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -52,8 +53,8 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleCursorWrapCommand())
|
||||
{
|
||||
Title = "Toggle Cursor Wrap",
|
||||
Subtitle = "Wrap the cursor across monitor edges",
|
||||
Title = Resources.MouseUtils_CursorWrap_Title,
|
||||
Subtitle = Resources.MouseUtils_CursorWrap_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -62,8 +63,8 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ShowMouseJumpPreviewCommand())
|
||||
{
|
||||
Title = "Show Mouse Jump Preview",
|
||||
Subtitle = "Jump the pointer to a target",
|
||||
Title = Resources.MouseUtils_MouseJump_Title,
|
||||
Subtitle = Resources.MouseUtils_MouseJump_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -71,7 +72,7 @@ internal sealed class MouseUtilsModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Mouse Utilities settings",
|
||||
Subtitle = Resources.MouseUtils_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class MouseWithoutBordersModuleCommandProvider : ModuleCommandPr
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.MouseWithoutBorders, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Mouse Without Borders settings",
|
||||
Subtitle = Resources.MouseWithoutBorders_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class NewPlusModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.NewPlus, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open New+ settings",
|
||||
Subtitle = Resources.NewPlus_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class PeekModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.Peek, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Peek settings",
|
||||
Subtitle = Resources.Peek_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class PowerRenameModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.PowerRename, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open PowerRename settings",
|
||||
Subtitle = Resources.PowerRename_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class PowerToysRunModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.PowerLauncher, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open PowerToys Run settings",
|
||||
Subtitle = Resources.PowerToysRun_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -20,7 +21,7 @@ internal sealed class QuickAccentModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(SettingsWindow.PowerAccent, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Quick Accent settings",
|
||||
Subtitle = Resources.QuickAccent_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,8 +23,8 @@ internal sealed class RegistryPreviewModuleCommandProvider : ModuleCommandProvid
|
||||
{
|
||||
yield return new ListItem(new OpenRegistryPreviewCommand())
|
||||
{
|
||||
Title = "Open Registry Preview",
|
||||
Subtitle = "Launch Registry Preview",
|
||||
Title = Resources.RegistryPreview_Open_Title,
|
||||
Subtitle = Resources.RegistryPreview_Open_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -31,7 +32,7 @@ internal sealed class RegistryPreviewModuleCommandProvider : ModuleCommandProvid
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Registry Preview settings",
|
||||
Subtitle = Resources.RegistryPreview_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,8 +23,8 @@ internal sealed class ScreenRulerModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleScreenRulerCommand())
|
||||
{
|
||||
Title = "Toggle Screen Ruler",
|
||||
Subtitle = "Start or close Screen Ruler",
|
||||
Title = Resources.ScreenRuler_Toggle_Title,
|
||||
Subtitle = Resources.ScreenRuler_Toggle_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -31,7 +32,7 @@ internal sealed class ScreenRulerModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Screen Ruler settings",
|
||||
Subtitle = Resources.ScreenRuler_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,8 +23,8 @@ internal sealed class ShortcutGuideModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleShortcutGuideCommand())
|
||||
{
|
||||
Title = "Toggle Shortcut Guide",
|
||||
Subtitle = "Show or hide Shortcut Guide",
|
||||
Title = Resources.ShortcutGuide_Toggle_Title,
|
||||
Subtitle = Resources.ShortcutGuide_Toggle_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -31,7 +32,7 @@ internal sealed class ShortcutGuideModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Shortcut Guide settings",
|
||||
Subtitle = Resources.ShortcutGuide_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -22,8 +23,8 @@ internal sealed class TextExtractorModuleCommandProvider : ModuleCommandProvider
|
||||
{
|
||||
yield return new ListItem(new ToggleTextExtractorCommand())
|
||||
{
|
||||
Title = "Toggle Text Extractor",
|
||||
Subtitle = "Start or close Text Extractor",
|
||||
Title = Resources.TextExtractor_Toggle_Title,
|
||||
Subtitle = Resources.TextExtractor_Toggle_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -31,7 +32,7 @@ internal sealed class TextExtractorModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Text Extractor settings",
|
||||
Subtitle = Resources.TextExtractor_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using Common.UI;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using Workspaces.ModuleServices;
|
||||
using WorkspacesCsharpLibrary.Data;
|
||||
|
||||
@@ -25,7 +26,7 @@ internal sealed class WorkspacesModuleCommandProvider : ModuleCommandProvider
|
||||
items.Add(new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open Workspaces settings",
|
||||
Subtitle = Resources.Workspaces_Settings_Subtitle,
|
||||
Icon = moduleIcon,
|
||||
});
|
||||
|
||||
@@ -37,8 +38,8 @@ internal sealed class WorkspacesModuleCommandProvider : ModuleCommandProvider
|
||||
// Settings entry plus common actions.
|
||||
items.Add(new ListItem(new OpenWorkspaceEditorCommand())
|
||||
{
|
||||
Title = "Workspaces: Open editor",
|
||||
Subtitle = "Create or edit workspaces",
|
||||
Title = Resources.Workspaces_OpenEditor_Title,
|
||||
Subtitle = Resources.Workspaces_OpenEditor_Subtitle,
|
||||
Icon = icon,
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
using static Common.UI.SettingsDeepLink;
|
||||
|
||||
namespace PowerToysExtension.Modules;
|
||||
@@ -21,40 +22,40 @@ internal sealed class ZoomItModuleCommandProvider : ModuleCommandProvider
|
||||
if (ModuleEnablementService.IsModuleEnabled(module))
|
||||
{
|
||||
// Action commands via ZoomIt IPC
|
||||
yield return new ListItem(new ZoomItActionCommand("zoom", "ZoomIt: Zoom"))
|
||||
yield return new ListItem(new ZoomItActionCommand("zoom", Resources.ZoomIt_Zoom_Title))
|
||||
{
|
||||
Title = "ZoomIt: Zoom",
|
||||
Subtitle = "Enter zoom mode",
|
||||
Title = Resources.ZoomIt_Zoom_Title,
|
||||
Subtitle = Resources.ZoomIt_Zoom_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
yield return new ListItem(new ZoomItActionCommand("draw", "ZoomIt: Draw"))
|
||||
yield return new ListItem(new ZoomItActionCommand("draw", Resources.ZoomIt_Draw_Title))
|
||||
{
|
||||
Title = "ZoomIt: Draw",
|
||||
Subtitle = "Enter drawing mode",
|
||||
Title = Resources.ZoomIt_Draw_Title,
|
||||
Subtitle = Resources.ZoomIt_Draw_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
yield return new ListItem(new ZoomItActionCommand("break", "ZoomIt: Break"))
|
||||
yield return new ListItem(new ZoomItActionCommand("break", Resources.ZoomIt_Break_Title))
|
||||
{
|
||||
Title = "ZoomIt: Break",
|
||||
Subtitle = "Enter break timer",
|
||||
Title = Resources.ZoomIt_Break_Title,
|
||||
Subtitle = Resources.ZoomIt_Break_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
yield return new ListItem(new ZoomItActionCommand("liveZoom", "ZoomIt: Live Zoom"))
|
||||
yield return new ListItem(new ZoomItActionCommand("liveZoom", Resources.ZoomIt_LiveZoom_Title))
|
||||
{
|
||||
Title = "ZoomIt: Live Zoom",
|
||||
Subtitle = "Toggle live zoom",
|
||||
Title = Resources.ZoomIt_LiveZoom_Title,
|
||||
Subtitle = Resources.ZoomIt_LiveZoom_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
yield return new ListItem(new ZoomItActionCommand("snip", "ZoomIt: Snip"))
|
||||
yield return new ListItem(new ZoomItActionCommand("snip", Resources.ZoomIt_Snip_Title))
|
||||
{
|
||||
Title = "ZoomIt: Snip",
|
||||
Subtitle = "Enter snip mode",
|
||||
Title = Resources.ZoomIt_Snip_Title,
|
||||
Subtitle = Resources.ZoomIt_Snip_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
yield return new ListItem(new ZoomItActionCommand("record", "ZoomIt: Record"))
|
||||
yield return new ListItem(new ZoomItActionCommand("record", Resources.ZoomIt_Record_Title))
|
||||
{
|
||||
Title = "ZoomIt: Record",
|
||||
Subtitle = "Start recording",
|
||||
Title = Resources.ZoomIt_Record_Title,
|
||||
Subtitle = Resources.ZoomIt_Record_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
@@ -62,7 +63,7 @@ internal sealed class ZoomItModuleCommandProvider : ModuleCommandProvider
|
||||
yield return new ListItem(new OpenInSettingsCommand(module, title))
|
||||
{
|
||||
Title = title,
|
||||
Subtitle = "Open ZoomIt settings",
|
||||
Subtitle = Resources.ZoomIt_Settings_Subtitle,
|
||||
Icon = icon,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using ColorPicker.ModuleServices;
|
||||
@@ -10,24 +11,27 @@ using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Pages;
|
||||
|
||||
internal sealed partial class ColorPickerSavedColorsPage : DynamicListPage
|
||||
{
|
||||
private static readonly CompositeFormat NoMatchingSavedColorsFormat = CompositeFormat.Parse(Resources.ColorPicker_NoMatchingSavedColors_Subtitle);
|
||||
|
||||
private readonly CommandItem _emptyContent;
|
||||
|
||||
public ColorPickerSavedColorsPage()
|
||||
{
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("ColorPicker.png");
|
||||
Title = "Saved colors";
|
||||
Title = Resources.ColorPicker_SavedColors_Title;
|
||||
Name = "ColorPickerSavedColors";
|
||||
Id = "com.microsoft.powertoys.colorpicker.savedColors";
|
||||
|
||||
_emptyContent = new CommandItem()
|
||||
{
|
||||
Title = "No saved colors",
|
||||
Subtitle = "Pick a color first, then try again.",
|
||||
Title = Resources.ColorPicker_NoSavedColors_Title,
|
||||
Subtitle = Resources.ColorPicker_NoSavedColors_Subtitle,
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("ColorPicker.png"),
|
||||
};
|
||||
|
||||
@@ -70,8 +74,8 @@ internal sealed partial class ColorPickerSavedColorsPage : DynamicListPage
|
||||
public override void UpdateSearchText(string oldSearch, string newSearch)
|
||||
{
|
||||
_emptyContent.Subtitle = string.IsNullOrWhiteSpace(newSearch)
|
||||
? "Pick a color first, then try again."
|
||||
: $"No saved colors matching '{newSearch}'";
|
||||
? Resources.ColorPicker_NoSavedColors_Subtitle
|
||||
: string.Format(CultureInfo.CurrentCulture, NoMatchingSavedColorsFormat, newSearch);
|
||||
|
||||
RaiseItemsChanged(0);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Pages;
|
||||
|
||||
@@ -21,13 +22,13 @@ internal sealed partial class FancyZonesLayoutsPage : DynamicListPage
|
||||
public FancyZonesLayoutsPage()
|
||||
{
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("FancyZones.png");
|
||||
Name = Title = "FancyZones Layouts";
|
||||
Name = Title = Resources.FancyZones_Layouts_Title;
|
||||
Id = "com.microsoft.cmdpal.powertoys.fancyzones.layouts";
|
||||
|
||||
_emptyMessage = new CommandItem()
|
||||
{
|
||||
Title = "No layouts found",
|
||||
Subtitle = "Open FancyZones Editor once to initialize layouts.",
|
||||
Title = Resources.FancyZones_NoLayoutsFound_Title,
|
||||
Subtitle = Resources.FancyZones_NoLayoutsFound_Subtitle,
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("FancyZones.png"),
|
||||
};
|
||||
EmptyContent = _emptyMessage;
|
||||
|
||||
@@ -4,16 +4,21 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Pages;
|
||||
|
||||
internal sealed partial class FancyZonesMonitorLayoutPickerPage : DynamicListPage
|
||||
{
|
||||
private static readonly CompositeFormat SetActiveLayoutForFormat = CompositeFormat.Parse(Resources.FancyZones_SetActiveLayoutFor_Format);
|
||||
|
||||
private readonly FancyZonesMonitorDescriptor _monitor;
|
||||
private readonly CommandItem _emptyMessage;
|
||||
|
||||
@@ -21,13 +26,13 @@ internal sealed partial class FancyZonesMonitorLayoutPickerPage : DynamicListPag
|
||||
{
|
||||
_monitor = monitor;
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("FancyZones.png");
|
||||
Name = Title = $"Set active layout for {_monitor.Title}";
|
||||
Name = Title = string.Format(CultureInfo.CurrentCulture, SetActiveLayoutForFormat, _monitor.Title);
|
||||
Id = $"com.microsoft.cmdpal.powertoys.fancyzones.monitor.{_monitor.Index}.layouts";
|
||||
|
||||
_emptyMessage = new CommandItem()
|
||||
{
|
||||
Title = "No layouts found",
|
||||
Subtitle = "Open FancyZones Editor once to initialize layouts.",
|
||||
Title = Resources.FancyZones_NoLayoutsFound_Title,
|
||||
Subtitle = Resources.FancyZones_NoLayoutsFound_Subtitle,
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("FancyZones.png"),
|
||||
};
|
||||
EmptyContent = _emptyMessage;
|
||||
|
||||
@@ -4,26 +4,31 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Pages;
|
||||
|
||||
internal sealed partial class FancyZonesMonitorsPage : DynamicListPage
|
||||
{
|
||||
private static readonly CompositeFormat CurrentLayoutFormat = CompositeFormat.Parse(Resources.FancyZones_CurrentLayout_Format);
|
||||
|
||||
private readonly CommandItem _emptyMessage;
|
||||
|
||||
public FancyZonesMonitorsPage()
|
||||
{
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("FancyZones.png");
|
||||
Name = Title = "FancyZones Monitors";
|
||||
Name = Title = Resources.FancyZones_Monitors_Title;
|
||||
Id = "com.microsoft.cmdpal.powertoys.fancyzones.monitors";
|
||||
|
||||
_emptyMessage = new CommandItem()
|
||||
{
|
||||
Title = "No monitors found",
|
||||
Subtitle = "Open FancyZones Editor once to initialize monitor data.",
|
||||
Title = Resources.FancyZones_NoMonitorsFound_Title,
|
||||
Subtitle = Resources.FancyZones_NoMonitorsFound_Subtitle,
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("FancyZones.png"),
|
||||
};
|
||||
EmptyContent = _emptyMessage;
|
||||
@@ -55,8 +60,8 @@ internal sealed partial class FancyZonesMonitorsPage : DynamicListPage
|
||||
}
|
||||
|
||||
var layoutDescription = FancyZonesDataService.TryGetAppliedLayoutForMonitor(monitor.Data, out var applied) && applied is not null
|
||||
? $"Current layout: {applied.Value.Type}"
|
||||
: "Current layout: unknown";
|
||||
? string.Format(CultureInfo.CurrentCulture, CurrentLayoutFormat, applied.Value.Type)
|
||||
: Resources.FancyZones_CurrentLayout_Unknown;
|
||||
|
||||
var item = new FancyZonesMonitorListItem(monitor, layoutDescription, monitorIcon);
|
||||
items.Add(item);
|
||||
|
||||
@@ -6,6 +6,7 @@ using Awake.ModuleServices;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Commands;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension;
|
||||
|
||||
@@ -14,32 +15,32 @@ internal sealed partial class PowerToysExtensionPage : ListPage
|
||||
public PowerToysExtensionPage()
|
||||
{
|
||||
Icon = Helpers.PowerToysResourcesHelper.IconFromSettingsIcon("PowerToys.png");
|
||||
Title = "PowerToys";
|
||||
Name = "PowerToys commands";
|
||||
Title = Resources.PowerToys_DisplayName;
|
||||
Name = Resources.PowerToysExtension_CommandsName;
|
||||
}
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
return [
|
||||
new ListItem(new LaunchModuleCommand("PowerToys", executableName: "PowerToys.exe", displayName: "Open PowerToys"))
|
||||
new ListItem(new LaunchModuleCommand("PowerToys", executableName: "PowerToys.exe", displayName: Resources.PowerToysExtension_OpenPowerToys_Title))
|
||||
{
|
||||
Title = "Open PowerToys",
|
||||
Subtitle = "Launch the PowerToys shell",
|
||||
Title = Resources.PowerToysExtension_OpenPowerToys_Title,
|
||||
Subtitle = Resources.PowerToysExtension_OpenPowerToys_Subtitle,
|
||||
},
|
||||
new ListItem(new OpenPowerToysSettingsCommand("PowerToys", "General"))
|
||||
{
|
||||
Title = "Open PowerToys settings",
|
||||
Subtitle = "Open the main PowerToys settings window",
|
||||
Title = Resources.PowerToysExtension_OpenSettings_Title,
|
||||
Subtitle = Resources.PowerToysExtension_OpenSettings_Subtitle,
|
||||
},
|
||||
new ListItem(new OpenPowerToysSettingsCommand("Workspaces", "Workspaces"))
|
||||
{
|
||||
Title = "Open Workspaces settings",
|
||||
Subtitle = "Jump directly to Workspaces settings",
|
||||
Title = Resources.PowerToysExtension_OpenWorkspacesSettings_Title,
|
||||
Subtitle = Resources.PowerToysExtension_OpenWorkspacesSettings_Subtitle,
|
||||
},
|
||||
new ListItem(new OpenWorkspaceEditorCommand())
|
||||
{
|
||||
Title = "Open Workspaces editor",
|
||||
Subtitle = "Launch the Workspaces editor",
|
||||
Title = Resources.PowerToysExtension_OpenWorkspacesEditor_Title,
|
||||
Subtitle = Resources.PowerToysExtension_OpenWorkspacesEditor_Subtitle,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension.Pages;
|
||||
|
||||
@@ -15,13 +16,13 @@ internal sealed partial class PowerToysListPage : ListPage
|
||||
public PowerToysListPage()
|
||||
{
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("PowerToys.png");
|
||||
Name = Title = "PowerToys";
|
||||
Name = Title = Resources.PowerToys_DisplayName;
|
||||
Id = "com.microsoft.cmdpal.powertoys";
|
||||
SettingsChangeNotifier.SettingsChanged += OnSettingsChanged;
|
||||
_empty = new CommandItem()
|
||||
{
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("PowerToys.png"),
|
||||
Title = "No matching module found",
|
||||
Title = Resources.PowerToys_NoMatchingModule,
|
||||
Subtitle = SearchText,
|
||||
};
|
||||
EmptyContent = _empty;
|
||||
|
||||
@@ -7,6 +7,7 @@ using ManagedCommon;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension;
|
||||
|
||||
@@ -14,7 +15,7 @@ public sealed partial class PowerToysCommandsProvider : CommandProvider
|
||||
{
|
||||
public PowerToysCommandsProvider()
|
||||
{
|
||||
DisplayName = "PowerToys";
|
||||
DisplayName = Resources.PowerToys_DisplayName;
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("PowerToys.png");
|
||||
}
|
||||
|
||||
@@ -22,8 +23,8 @@ public sealed partial class PowerToysCommandsProvider : CommandProvider
|
||||
[
|
||||
new CommandItem(new Pages.PowerToysListPage())
|
||||
{
|
||||
Title = "PowerToys",
|
||||
Subtitle = "PowerToys commands and settings",
|
||||
Title = Resources.PowerToys_DisplayName,
|
||||
Subtitle = Resources.PowerToys_Subtitle,
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using PowerToysExtension.Helpers;
|
||||
using PowerToysExtension.Properties;
|
||||
|
||||
namespace PowerToysExtension;
|
||||
|
||||
@@ -15,13 +16,13 @@ public partial class PowerToysExtensionCommandsProvider : CommandProvider
|
||||
|
||||
public PowerToysExtensionCommandsProvider()
|
||||
{
|
||||
DisplayName = "PowerToys";
|
||||
DisplayName = Resources.PowerToys_DisplayName;
|
||||
Icon = PowerToysResourcesHelper.IconFromSettingsIcon("PowerToys.png");
|
||||
_commands = [
|
||||
new CommandItem(new Pages.PowerToysListPage())
|
||||
{
|
||||
Title = "PowerToys",
|
||||
Subtitle = "PowerToys commands and settings",
|
||||
Title = Resources.PowerToys_DisplayName,
|
||||
Subtitle = Resources.PowerToys_Subtitle,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
1503
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Properties/Resources.Designer.cs
generated
Normal file
1503
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Properties/Resources.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,630 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<!-- PowerToys CommandsProvider -->
|
||||
<data name="PowerToys_DisplayName" xml:space="preserve">
|
||||
<value>PowerToys</value>
|
||||
</data>
|
||||
<data name="PowerToys_Subtitle" xml:space="preserve">
|
||||
<value>PowerToys commands and settings</value>
|
||||
</data>
|
||||
<data name="PowerToys_NoMatchingModule" xml:space="preserve">
|
||||
<value>No matching module found</value>
|
||||
</data>
|
||||
<!-- PowerToys Extension Page -->
|
||||
<data name="PowerToysExtension_CommandsName" xml:space="preserve">
|
||||
<value>PowerToys commands</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenPowerToys_Title" xml:space="preserve">
|
||||
<value>Open PowerToys</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenPowerToys_Subtitle" xml:space="preserve">
|
||||
<value>Launch the PowerToys shell</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenSettings_Title" xml:space="preserve">
|
||||
<value>Open PowerToys settings</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenSettings_Subtitle" xml:space="preserve">
|
||||
<value>Open the main PowerToys settings window</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenWorkspacesSettings_Title" xml:space="preserve">
|
||||
<value>Open Workspaces settings</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenWorkspacesSettings_Subtitle" xml:space="preserve">
|
||||
<value>Jump directly to Workspaces settings</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenWorkspacesEditor_Title" xml:space="preserve">
|
||||
<value>Open Workspaces editor</value>
|
||||
</data>
|
||||
<data name="PowerToysExtension_OpenWorkspacesEditor_Subtitle" xml:space="preserve">
|
||||
<value>Launch the Workspaces editor</value>
|
||||
</data>
|
||||
<!-- Advanced Paste Module -->
|
||||
<data name="AdvancedPaste_Open_Title" xml:space="preserve">
|
||||
<value>Open Advanced Paste</value>
|
||||
</data>
|
||||
<data name="AdvancedPaste_Open_Subtitle" xml:space="preserve">
|
||||
<value>Launch the Advanced Paste UI</value>
|
||||
</data>
|
||||
<data name="AdvancedPaste_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Advanced Paste settings</value>
|
||||
</data>
|
||||
<!-- Always On Top Module -->
|
||||
<data name="AlwaysOnTop_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Always On Top settings</value>
|
||||
</data>
|
||||
<!-- Awake Module -->
|
||||
<data name="Awake_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Awake settings</value>
|
||||
</data>
|
||||
<data name="Awake_Status_Title" xml:space="preserve">
|
||||
<value>Awake: Current status</value>
|
||||
</data>
|
||||
<data name="Awake_KeepIndefinite_Title" xml:space="preserve">
|
||||
<value>Awake: Keep awake indefinitely</value>
|
||||
</data>
|
||||
<data name="Awake_KeepIndefinite_Subtitle" xml:space="preserve">
|
||||
<value>Run Awake in indefinite mode</value>
|
||||
</data>
|
||||
<data name="Awake_Keep30Min_Title" xml:space="preserve">
|
||||
<value>Awake: Keep awake for 30 minutes</value>
|
||||
</data>
|
||||
<data name="Awake_Keep30Min_Subtitle" xml:space="preserve">
|
||||
<value>Run Awake timed for 30 minutes</value>
|
||||
</data>
|
||||
<data name="Awake_Keep1Hour_Title" xml:space="preserve">
|
||||
<value>Awake: Keep awake for 1 hour</value>
|
||||
</data>
|
||||
<data name="Awake_Keep1Hour_Subtitle" xml:space="preserve">
|
||||
<value>Run Awake timed for 1 hour</value>
|
||||
</data>
|
||||
<data name="Awake_Keep2Hours_Title" xml:space="preserve">
|
||||
<value>Awake: Keep awake for 2 hours</value>
|
||||
</data>
|
||||
<data name="Awake_Keep2Hours_Subtitle" xml:space="preserve">
|
||||
<value>Run Awake timed for 2 hours</value>
|
||||
</data>
|
||||
<data name="Awake_TurnOff_Title" xml:space="preserve">
|
||||
<value>Awake: Turn off</value>
|
||||
</data>
|
||||
<data name="Awake_TurnOff_Subtitle" xml:space="preserve">
|
||||
<value>Switch Awake back to Off</value>
|
||||
</data>
|
||||
<data name="Awake_SetIndefinite_Toast" xml:space="preserve">
|
||||
<value>Awake set to indefinite</value>
|
||||
</data>
|
||||
<data name="Awake_Set30Min_Toast" xml:space="preserve">
|
||||
<value>Awake set for 30 minutes</value>
|
||||
</data>
|
||||
<data name="Awake_Set1Hour_Toast" xml:space="preserve">
|
||||
<value>Awake set for 1 hour</value>
|
||||
</data>
|
||||
<data name="Awake_Set2Hours_Toast" xml:space="preserve">
|
||||
<value>Awake set for 2 hours</value>
|
||||
</data>
|
||||
<!-- Color Picker Module -->
|
||||
<data name="ColorPicker_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Color Picker settings</value>
|
||||
</data>
|
||||
<data name="ColorPicker_Open_Title" xml:space="preserve">
|
||||
<value>Open Color Picker</value>
|
||||
</data>
|
||||
<data name="ColorPicker_Open_Subtitle" xml:space="preserve">
|
||||
<value>Start a color pick session</value>
|
||||
</data>
|
||||
<data name="ColorPicker_SavedColors_Title" xml:space="preserve">
|
||||
<value>Saved colors</value>
|
||||
</data>
|
||||
<data name="ColorPicker_SavedColors_Subtitle" xml:space="preserve">
|
||||
<value>Browse and copy saved colors</value>
|
||||
</data>
|
||||
<data name="ColorPicker_NoSavedColors_Title" xml:space="preserve">
|
||||
<value>No saved colors</value>
|
||||
</data>
|
||||
<data name="ColorPicker_NoSavedColors_Subtitle" xml:space="preserve">
|
||||
<value>Pick a color first, then try again.</value>
|
||||
</data>
|
||||
<data name="ColorPicker_NoMatchingSavedColors_Subtitle" xml:space="preserve">
|
||||
<value>No saved colors matching '{0}'</value>
|
||||
</data>
|
||||
<!-- Command Not Found Module -->
|
||||
<data name="CommandNotFound_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Command Not Found settings</value>
|
||||
</data>
|
||||
<!-- Crop And Lock Module -->
|
||||
<data name="CropAndLock_Reparent_Title" xml:space="preserve">
|
||||
<value>Crop and Lock (Reparent)</value>
|
||||
</data>
|
||||
<data name="CropAndLock_Reparent_Subtitle" xml:space="preserve">
|
||||
<value>Create a cropped reparented window</value>
|
||||
</data>
|
||||
<data name="CropAndLock_Thumbnail_Title" xml:space="preserve">
|
||||
<value>Crop and Lock (Thumbnail)</value>
|
||||
</data>
|
||||
<data name="CropAndLock_Thumbnail_Subtitle" xml:space="preserve">
|
||||
<value>Create a cropped thumbnail window</value>
|
||||
</data>
|
||||
<data name="CropAndLock_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Crop and Lock settings</value>
|
||||
</data>
|
||||
<!-- Environment Variables Module -->
|
||||
<data name="EnvironmentVariables_Open_Title" xml:space="preserve">
|
||||
<value>Open Environment Variables</value>
|
||||
</data>
|
||||
<data name="EnvironmentVariables_Open_Subtitle" xml:space="preserve">
|
||||
<value>Launch Environment Variables editor</value>
|
||||
</data>
|
||||
<data name="EnvironmentVariables_OpenAdmin_Title" xml:space="preserve">
|
||||
<value>Open Environment Variables (Admin)</value>
|
||||
</data>
|
||||
<data name="EnvironmentVariables_OpenAdmin_Subtitle" xml:space="preserve">
|
||||
<value>Launch Environment Variables editor as admin</value>
|
||||
</data>
|
||||
<data name="EnvironmentVariables_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Environment Variables settings</value>
|
||||
</data>
|
||||
<!-- FancyZones Module -->
|
||||
<data name="FancyZones_Layouts_Title" xml:space="preserve">
|
||||
<value>FancyZones: Layouts</value>
|
||||
</data>
|
||||
<data name="FancyZones_Layouts_Subtitle" xml:space="preserve">
|
||||
<value>Apply a layout to all monitors or a specific monitor</value>
|
||||
</data>
|
||||
<data name="FancyZones_Monitors_Title" xml:space="preserve">
|
||||
<value>FancyZones: Monitors</value>
|
||||
</data>
|
||||
<data name="FancyZones_Monitors_Subtitle" xml:space="preserve">
|
||||
<value>Identify monitors and apply layouts</value>
|
||||
</data>
|
||||
<data name="FancyZones_OpenEditor_Title" xml:space="preserve">
|
||||
<value>Open FancyZones Editor</value>
|
||||
</data>
|
||||
<data name="FancyZones_OpenEditor_Subtitle" xml:space="preserve">
|
||||
<value>Launch layout editor</value>
|
||||
</data>
|
||||
<data name="FancyZones_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open FancyZones settings</value>
|
||||
</data>
|
||||
<data name="FancyZones_LayoutsPage_Title" xml:space="preserve">
|
||||
<value>FancyZones Layouts</value>
|
||||
</data>
|
||||
<data name="FancyZones_NoLayoutsFound_Title" xml:space="preserve">
|
||||
<value>No layouts found</value>
|
||||
</data>
|
||||
<data name="FancyZones_NoLayoutsFound_Subtitle" xml:space="preserve">
|
||||
<value>Open FancyZones Editor once to initialize layouts.</value>
|
||||
</data>
|
||||
<data name="FancyZones_ApplyTo_Format" xml:space="preserve">
|
||||
<value>Apply to {0}</value>
|
||||
</data>
|
||||
<data name="FancyZones_MonitorsPage_Title" xml:space="preserve">
|
||||
<value>FancyZones Monitors</value>
|
||||
</data>
|
||||
<data name="FancyZones_NoMonitorsFound_Title" xml:space="preserve">
|
||||
<value>No monitors found</value>
|
||||
</data>
|
||||
<data name="FancyZones_NoMonitorsFound_Subtitle" xml:space="preserve">
|
||||
<value>Open FancyZones Editor once to initialize monitor data.</value>
|
||||
</data>
|
||||
<data name="FancyZones_SetActiveLayout" xml:space="preserve">
|
||||
<value>Set active layout</value>
|
||||
</data>
|
||||
<data name="FancyZones_PickLayoutForMonitor" xml:space="preserve">
|
||||
<value>Pick a layout for this monitor</value>
|
||||
</data>
|
||||
<data name="FancyZones_SetActiveLayoutFor_Format" xml:space="preserve">
|
||||
<value>Set active layout for {0}</value>
|
||||
</data>
|
||||
<data name="FancyZones_CurrentLayout_Format" xml:space="preserve">
|
||||
<value>Current layout: {0}</value>
|
||||
</data>
|
||||
<data name="FancyZones_CurrentLayout_Unknown" xml:space="preserve">
|
||||
<value>Current layout: unknown</value>
|
||||
</data>
|
||||
<data name="FancyZones_Template_Format" xml:space="preserve">
|
||||
<value>Template: {0}</value>
|
||||
</data>
|
||||
<data name="FancyZones_Zones_Format" xml:space="preserve">
|
||||
<value>{0} zones</value>
|
||||
</data>
|
||||
<data name="FancyZones_CustomGrid_Zones_Format" xml:space="preserve">
|
||||
<value>Custom grid • {0} zones</value>
|
||||
</data>
|
||||
<data name="FancyZones_CustomCanvas_Zones_Format" xml:space="preserve">
|
||||
<value>Custom canvas • {0} zones</value>
|
||||
</data>
|
||||
<data name="FancyZones_Custom_Zones_Format" xml:space="preserve">
|
||||
<value>Custom • {0} zones</value>
|
||||
</data>
|
||||
<data name="FancyZones_LayoutApplied" xml:space="preserve">
|
||||
<value>Layout applied.</value>
|
||||
</data>
|
||||
<data name="FancyZones_LayoutAppliedNotifyFailed_Format" xml:space="preserve">
|
||||
<value>Layout applied, but FancyZones could not be notified: {0}</value>
|
||||
</data>
|
||||
<data name="FancyZones_WriteAppliedLayoutsFailed_Format" xml:space="preserve">
|
||||
<value>Failed to write applied layouts: {0}</value>
|
||||
</data>
|
||||
<data name="FancyZones_MonitorDataNotFound" xml:space="preserve">
|
||||
<value>FancyZones monitor data not found. Open FancyZones Editor once to initialize.</value>
|
||||
</data>
|
||||
<data name="FancyZones_NoFancyZonesMonitorsFound" xml:space="preserve">
|
||||
<value>No FancyZones monitors found.</value>
|
||||
</data>
|
||||
<data name="FancyZones_ReadMonitorDataFailed_Format" xml:space="preserve">
|
||||
<value>Failed to read FancyZones monitor data: {0}</value>
|
||||
</data>
|
||||
<!-- File Explorer Addons Module -->
|
||||
<data name="FileExplorerAddons_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open File Explorer add-ons settings</value>
|
||||
</data>
|
||||
<!-- File Locksmith Module -->
|
||||
<data name="FileLocksmith_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open File Locksmith settings</value>
|
||||
</data>
|
||||
<!-- Hosts Module -->
|
||||
<data name="Hosts_Open_Title" xml:space="preserve">
|
||||
<value>Open Hosts File Editor</value>
|
||||
</data>
|
||||
<data name="Hosts_Open_Subtitle" xml:space="preserve">
|
||||
<value>Launch Hosts File Editor</value>
|
||||
</data>
|
||||
<data name="Hosts_OpenAdmin_Title" xml:space="preserve">
|
||||
<value>Open Hosts File Editor (Admin)</value>
|
||||
</data>
|
||||
<data name="Hosts_OpenAdmin_Subtitle" xml:space="preserve">
|
||||
<value>Launch Hosts File Editor as admin</value>
|
||||
</data>
|
||||
<data name="Hosts_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Hosts File Editor settings</value>
|
||||
</data>
|
||||
<!-- Image Resizer Module -->
|
||||
<data name="ImageResizer_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Image Resizer settings</value>
|
||||
</data>
|
||||
<!-- Keyboard Manager Module -->
|
||||
<data name="KeyboardManager_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Keyboard Manager settings</value>
|
||||
</data>
|
||||
<!-- Light Switch Module -->
|
||||
<data name="LightSwitch_Toggle_Title" xml:space="preserve">
|
||||
<value>Light Switch: Toggle theme</value>
|
||||
</data>
|
||||
<data name="LightSwitch_Toggle_Subtitle" xml:space="preserve">
|
||||
<value>Toggle system/apps theme immediately</value>
|
||||
</data>
|
||||
<data name="LightSwitch_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Light Switch settings</value>
|
||||
</data>
|
||||
<!-- Mouse Utils Module -->
|
||||
<data name="MouseUtils_FindMyMouse_Title" xml:space="preserve">
|
||||
<value>Trigger Find My Mouse</value>
|
||||
</data>
|
||||
<data name="MouseUtils_FindMyMouse_Subtitle" xml:space="preserve">
|
||||
<value>Focus the mouse pointer</value>
|
||||
</data>
|
||||
<data name="MouseUtils_Highlighter_Title" xml:space="preserve">
|
||||
<value>Toggle Mouse Highlighter</value>
|
||||
</data>
|
||||
<data name="MouseUtils_Highlighter_Subtitle" xml:space="preserve">
|
||||
<value>Highlight mouse clicks</value>
|
||||
</data>
|
||||
<data name="MouseUtils_Crosshairs_Title" xml:space="preserve">
|
||||
<value>Toggle Mouse Crosshairs</value>
|
||||
</data>
|
||||
<data name="MouseUtils_Crosshairs_Subtitle" xml:space="preserve">
|
||||
<value>Enable or disable pointer crosshairs</value>
|
||||
</data>
|
||||
<data name="MouseUtils_CursorWrap_Title" xml:space="preserve">
|
||||
<value>Toggle Cursor Wrap</value>
|
||||
</data>
|
||||
<data name="MouseUtils_CursorWrap_Subtitle" xml:space="preserve">
|
||||
<value>Wrap the cursor across monitor edges</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump_Title" xml:space="preserve">
|
||||
<value>Show Mouse Jump Preview</value>
|
||||
</data>
|
||||
<data name="MouseUtils_MouseJump_Subtitle" xml:space="preserve">
|
||||
<value>Jump the pointer to a target</value>
|
||||
</data>
|
||||
<data name="MouseUtils_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Mouse Utilities settings</value>
|
||||
</data>
|
||||
<!-- Mouse Without Borders Module -->
|
||||
<data name="MouseWithoutBorders_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Mouse Without Borders settings</value>
|
||||
</data>
|
||||
<!-- New+ Module -->
|
||||
<data name="NewPlus_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open New+ settings</value>
|
||||
</data>
|
||||
<!-- Peek Module -->
|
||||
<data name="Peek_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Peek settings</value>
|
||||
</data>
|
||||
<!-- PowerRename Module -->
|
||||
<data name="PowerRename_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open PowerRename settings</value>
|
||||
</data>
|
||||
<!-- PowerToys Run Module -->
|
||||
<data name="PowerToysRun_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open PowerToys Run settings</value>
|
||||
</data>
|
||||
<!-- Quick Accent Module -->
|
||||
<data name="QuickAccent_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Quick Accent settings</value>
|
||||
</data>
|
||||
<!-- Registry Preview Module -->
|
||||
<data name="RegistryPreview_Open_Title" xml:space="preserve">
|
||||
<value>Open Registry Preview</value>
|
||||
</data>
|
||||
<data name="RegistryPreview_Open_Subtitle" xml:space="preserve">
|
||||
<value>Launch Registry Preview</value>
|
||||
</data>
|
||||
<data name="RegistryPreview_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Registry Preview settings</value>
|
||||
</data>
|
||||
<!-- Screen Ruler Module -->
|
||||
<data name="ScreenRuler_Toggle_Title" xml:space="preserve">
|
||||
<value>Toggle Screen Ruler</value>
|
||||
</data>
|
||||
<data name="ScreenRuler_Toggle_Subtitle" xml:space="preserve">
|
||||
<value>Start or close Screen Ruler</value>
|
||||
</data>
|
||||
<data name="ScreenRuler_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Screen Ruler settings</value>
|
||||
</data>
|
||||
<!-- Shortcut Guide Module -->
|
||||
<data name="ShortcutGuide_Toggle_Title" xml:space="preserve">
|
||||
<value>Toggle Shortcut Guide</value>
|
||||
</data>
|
||||
<data name="ShortcutGuide_Toggle_Subtitle" xml:space="preserve">
|
||||
<value>Show or hide Shortcut Guide</value>
|
||||
</data>
|
||||
<data name="ShortcutGuide_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Shortcut Guide settings</value>
|
||||
</data>
|
||||
<!-- Text Extractor Module -->
|
||||
<data name="TextExtractor_Toggle_Title" xml:space="preserve">
|
||||
<value>Toggle Text Extractor</value>
|
||||
</data>
|
||||
<data name="TextExtractor_Toggle_Subtitle" xml:space="preserve">
|
||||
<value>Start or close Text Extractor</value>
|
||||
</data>
|
||||
<data name="TextExtractor_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Text Extractor settings</value>
|
||||
</data>
|
||||
<!-- Workspaces Module -->
|
||||
<data name="Workspaces_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open Workspaces settings</value>
|
||||
</data>
|
||||
<data name="Workspaces_OpenEditor_Title" xml:space="preserve">
|
||||
<value>Workspaces: Open editor</value>
|
||||
</data>
|
||||
<data name="Workspaces_OpenEditor_Subtitle" xml:space="preserve">
|
||||
<value>Create or edit workspaces</value>
|
||||
</data>
|
||||
<data name="Workspaces_NoApplications" xml:space="preserve">
|
||||
<value>No applications</value>
|
||||
</data>
|
||||
<data name="Workspaces_Applications_Format" xml:space="preserve">
|
||||
<value>{0} applications</value>
|
||||
</data>
|
||||
<data name="Workspaces_LastLaunched_Format" xml:space="preserve">
|
||||
<value>Last launched {0}</value>
|
||||
</data>
|
||||
<data name="Workspaces_NeverLaunched" xml:space="preserve">
|
||||
<value>Never launched</value>
|
||||
</data>
|
||||
<data name="Workspaces_NoApplicationsInWorkspace" xml:space="preserve">
|
||||
<value>No applications in this workspace</value>
|
||||
</data>
|
||||
<data name="Workspaces_OneApplication" xml:space="preserve">
|
||||
<value>1 application</value>
|
||||
</data>
|
||||
<data name="Workspaces_ApplicationsCount_Format" xml:space="preserve">
|
||||
<value>{0} applications</value>
|
||||
</data>
|
||||
<data name="Workspaces_Workspace" xml:space="preserve">
|
||||
<value>Workspace</value>
|
||||
</data>
|
||||
<data name="Workspaces_App" xml:space="preserve">
|
||||
<value>App</value>
|
||||
</data>
|
||||
<data name="Workspaces_JustNow" xml:space="preserve">
|
||||
<value>just now</value>
|
||||
</data>
|
||||
<data name="Workspaces_MinAgo_Format" xml:space="preserve">
|
||||
<value>{0} min ago</value>
|
||||
</data>
|
||||
<data name="Workspaces_HrAgo_Format" xml:space="preserve">
|
||||
<value>{0} hr ago</value>
|
||||
</data>
|
||||
<data name="Workspaces_DaysAgo_Format" xml:space="preserve">
|
||||
<value>{0} days ago</value>
|
||||
</data>
|
||||
<!-- ZoomIt Module -->
|
||||
<data name="ZoomIt_Zoom_Title" xml:space="preserve">
|
||||
<value>ZoomIt: Zoom</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Zoom_Subtitle" xml:space="preserve">
|
||||
<value>Enter zoom mode</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Draw_Title" xml:space="preserve">
|
||||
<value>ZoomIt: Draw</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Draw_Subtitle" xml:space="preserve">
|
||||
<value>Enter drawing mode</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Break_Title" xml:space="preserve">
|
||||
<value>ZoomIt: Break</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Break_Subtitle" xml:space="preserve">
|
||||
<value>Enter break timer</value>
|
||||
</data>
|
||||
<data name="ZoomIt_LiveZoom_Title" xml:space="preserve">
|
||||
<value>ZoomIt: Live Zoom</value>
|
||||
</data>
|
||||
<data name="ZoomIt_LiveZoom_Subtitle" xml:space="preserve">
|
||||
<value>Toggle live zoom</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Snip_Title" xml:space="preserve">
|
||||
<value>ZoomIt: Snip</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Snip_Subtitle" xml:space="preserve">
|
||||
<value>Enter snip mode</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Record_Title" xml:space="preserve">
|
||||
<value>ZoomIt: Record</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Record_Subtitle" xml:space="preserve">
|
||||
<value>Start recording</value>
|
||||
</data>
|
||||
<data name="ZoomIt_Settings_Subtitle" xml:space="preserve">
|
||||
<value>Open ZoomIt settings</value>
|
||||
</data>
|
||||
<!-- FancyZones Monitor Details -->
|
||||
<data name="FancyZones_Monitor" xml:space="preserve">
|
||||
<value>Monitor</value>
|
||||
</data>
|
||||
<data name="FancyZones_Instance" xml:space="preserve">
|
||||
<value>Instance</value>
|
||||
</data>
|
||||
<data name="FancyZones_Serial" xml:space="preserve">
|
||||
<value>Serial</value>
|
||||
</data>
|
||||
<data name="FancyZones_Number" xml:space="preserve">
|
||||
<value>Number</value>
|
||||
</data>
|
||||
<data name="FancyZones_VirtualDesktop" xml:space="preserve">
|
||||
<value>Virtual desktop</value>
|
||||
</data>
|
||||
<data name="FancyZones_WorkArea" xml:space="preserve">
|
||||
<value>Work area</value>
|
||||
</data>
|
||||
<data name="FancyZones_Resolution" xml:space="preserve">
|
||||
<value>Resolution</value>
|
||||
</data>
|
||||
<data name="FancyZones_DPI" xml:space="preserve">
|
||||
<value>DPI</value>
|
||||
</data>
|
||||
<data name="Common_NotAvailable" xml:space="preserve">
|
||||
<value>N/A</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -130,6 +130,7 @@ namespace Peek.FilePreviewer.Previewers
|
||||
}
|
||||
else if (isMarkdown)
|
||||
{
|
||||
IsDevFilePreview = false;
|
||||
var raw = await ReadHelper.Read(File.Path.ToString());
|
||||
Preview = new Uri(MarkdownHelper.PreviewTempFile(raw, File.Path, TempFolderPath.Path));
|
||||
}
|
||||
|
||||
@@ -344,19 +344,13 @@ IFACEMETHODIMP CPowerRenameRegEx::PutFlags(_In_ DWORD flags)
|
||||
|
||||
IFACEMETHODIMP CPowerRenameRegEx::PutFileTime(_In_ SYSTEMTIME fileTime)
|
||||
{
|
||||
union timeunion
|
||||
{
|
||||
FILETIME fileTime;
|
||||
ULARGE_INTEGER ul;
|
||||
};
|
||||
FILETIME ft1;
|
||||
FILETIME ft2;
|
||||
|
||||
timeunion ft1;
|
||||
timeunion ft2;
|
||||
SystemTimeToFileTime(&m_fileTime, &ft1);
|
||||
SystemTimeToFileTime(&fileTime, &ft2);
|
||||
|
||||
SystemTimeToFileTime(&m_fileTime, &ft1.fileTime);
|
||||
SystemTimeToFileTime(&fileTime, &ft2.fileTime);
|
||||
|
||||
if (ft2.ul.QuadPart != ft1.ul.QuadPart)
|
||||
if (ft2.dwLowDateTime != ft1.dwLowDateTime || ft2.dwHighDateTime != ft1.dwHighDateTime)
|
||||
{
|
||||
m_fileTime = fileTime;
|
||||
m_useFileTime = true;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "general_settings.h"
|
||||
#include "auto_start_helper.h"
|
||||
#include "tray_icon.h"
|
||||
#include "quick_access_host.h"
|
||||
#include "Generated files/resource.h"
|
||||
#include "hotkey_conflict_detector.h"
|
||||
|
||||
@@ -72,6 +73,8 @@ static bool download_updates_automatically = true;
|
||||
static bool show_whats_new_after_updates = true;
|
||||
static bool enable_experimentation = true;
|
||||
static bool enable_warnings_elevated_apps = true;
|
||||
static bool enable_quick_access = true;
|
||||
static PowerToysSettings::HotkeyObject quick_access_shortcut;
|
||||
static DashboardSortOrder dashboard_sort_order = DashboardSortOrder::Alphabetical;
|
||||
static json::JsonObject ignored_conflict_properties = create_default_ignored_conflict_properties();
|
||||
|
||||
@@ -105,6 +108,8 @@ json::JsonObject GeneralSettings::to_json()
|
||||
result.SetNamedValue(L"dashboard_sort_order", json::value(static_cast<int>(dashboardSortOrder)));
|
||||
result.SetNamedValue(L"is_admin", json::value(isAdmin));
|
||||
result.SetNamedValue(L"enable_warnings_elevated_apps", json::value(enableWarningsElevatedApps));
|
||||
result.SetNamedValue(L"enable_quick_access", json::value(enableQuickAccess));
|
||||
result.SetNamedValue(L"quick_access_shortcut", quickAccessShortcut.get_json());
|
||||
result.SetNamedValue(L"theme", json::value(theme));
|
||||
result.SetNamedValue(L"system_theme", json::value(systemTheme));
|
||||
result.SetNamedValue(L"powertoys_version", json::value(powerToysVersion));
|
||||
@@ -127,6 +132,11 @@ json::JsonObject load_general_settings()
|
||||
show_whats_new_after_updates = loaded.GetNamedBoolean(L"show_whats_new_after_updates", true);
|
||||
enable_experimentation = loaded.GetNamedBoolean(L"enable_experimentation", true);
|
||||
enable_warnings_elevated_apps = loaded.GetNamedBoolean(L"enable_warnings_elevated_apps", true);
|
||||
enable_quick_access = loaded.GetNamedBoolean(L"enable_quick_access", true);
|
||||
if (json::has(loaded, L"quick_access_shortcut", json::JsonValueType::Object))
|
||||
{
|
||||
quick_access_shortcut = PowerToysSettings::HotkeyObject::from_json(loaded.GetNamedObject(L"quick_access_shortcut"));
|
||||
}
|
||||
dashboard_sort_order = parse_dashboard_sort_order(loaded, dashboard_sort_order);
|
||||
|
||||
if (json::has(loaded, L"ignored_conflict_properties", json::JsonValueType::Object))
|
||||
@@ -153,6 +163,8 @@ GeneralSettings get_general_settings()
|
||||
.isRunElevated = run_as_elevated,
|
||||
.isAdmin = is_user_admin,
|
||||
.enableWarningsElevatedApps = enable_warnings_elevated_apps,
|
||||
.enableQuickAccess = enable_quick_access,
|
||||
.quickAccessShortcut = quick_access_shortcut,
|
||||
.showNewUpdatesToastNotification = show_new_updates_toast_notification,
|
||||
.downloadUpdatesAutomatically = download_updates_automatically && is_user_admin,
|
||||
.showWhatsNewAfterUpdates = show_whats_new_after_updates,
|
||||
@@ -178,11 +190,47 @@ GeneralSettings get_general_settings()
|
||||
|
||||
void apply_general_settings(const json::JsonObject& general_configs, bool save)
|
||||
{
|
||||
std::wstring old_settings_json_string;
|
||||
if (save)
|
||||
{
|
||||
old_settings_json_string = get_general_settings().to_json().Stringify().c_str();
|
||||
}
|
||||
|
||||
Logger::info(L"apply_general_settings: {}", std::wstring{ general_configs.ToString() });
|
||||
run_as_elevated = general_configs.GetNamedBoolean(L"run_elevated", false);
|
||||
|
||||
enable_warnings_elevated_apps = general_configs.GetNamedBoolean(L"enable_warnings_elevated_apps", true);
|
||||
|
||||
bool new_enable_quick_access = general_configs.GetNamedBoolean(L"enable_quick_access", true);
|
||||
Logger::info(L"apply_general_settings: enable_quick_access={}, new_enable_quick_access={}", enable_quick_access, new_enable_quick_access);
|
||||
|
||||
PowerToysSettings::HotkeyObject new_quick_access_shortcut;
|
||||
if (json::has(general_configs, L"quick_access_shortcut", json::JsonValueType::Object))
|
||||
{
|
||||
new_quick_access_shortcut = PowerToysSettings::HotkeyObject::from_json(general_configs.GetNamedObject(L"quick_access_shortcut"));
|
||||
}
|
||||
|
||||
auto hotkey_equals = [](const PowerToysSettings::HotkeyObject& a, const PowerToysSettings::HotkeyObject& b) {
|
||||
return a.get_code() == b.get_code() &&
|
||||
a.get_modifiers() == b.get_modifiers();
|
||||
};
|
||||
|
||||
if (enable_quick_access != new_enable_quick_access || !hotkey_equals(quick_access_shortcut, new_quick_access_shortcut))
|
||||
{
|
||||
enable_quick_access = new_enable_quick_access;
|
||||
quick_access_shortcut = new_quick_access_shortcut;
|
||||
|
||||
if (enable_quick_access)
|
||||
{
|
||||
QuickAccessHost::start();
|
||||
}
|
||||
else
|
||||
{
|
||||
QuickAccessHost::stop();
|
||||
}
|
||||
update_quick_access_hotkey(enable_quick_access, quick_access_shortcut);
|
||||
}
|
||||
|
||||
show_new_updates_toast_notification = general_configs.GetNamedBoolean(L"show_new_updates_toast_notification", true);
|
||||
|
||||
download_updates_automatically = general_configs.GetNamedBoolean(L"download_updates_automatically", true);
|
||||
@@ -321,8 +369,12 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save)
|
||||
if (save)
|
||||
{
|
||||
GeneralSettings save_settings = get_general_settings();
|
||||
PTSettingsHelper::save_general_settings(save_settings.to_json());
|
||||
Trace::SettingsChanged(save_settings);
|
||||
std::wstring new_settings_json_string = save_settings.to_json().Stringify().c_str();
|
||||
if (old_settings_json_string != new_settings_json_string)
|
||||
{
|
||||
PTSettingsHelper::save_general_settings(save_settings.to_json());
|
||||
Trace::SettingsChanged(save_settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,3 +464,5 @@ void start_enabled_powertoys()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <common/utils/json.h>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
|
||||
enum class DashboardSortOrder
|
||||
{
|
||||
@@ -18,6 +19,8 @@ struct GeneralSettings
|
||||
bool isRunElevated;
|
||||
bool isAdmin;
|
||||
bool enableWarningsElevatedApps;
|
||||
bool enableQuickAccess;
|
||||
PowerToysSettings::HotkeyObject quickAccessShortcut;
|
||||
bool showNewUpdatesToastNotification;
|
||||
bool downloadUpdatesAutomatically;
|
||||
bool showWhatsNewAfterUpdates;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <shellapi.h>
|
||||
#include "centralized_kb_hook.h"
|
||||
#include "centralized_hotkeys.h"
|
||||
#include "quick_access_host.h"
|
||||
#include "ai_detection.h"
|
||||
#include <common/utils/package.h>
|
||||
|
||||
@@ -189,6 +190,11 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
#endif
|
||||
Trace::RegisterProvider();
|
||||
start_tray_icon(isProcessElevated);
|
||||
if (get_general_settings().enableQuickAccess)
|
||||
{
|
||||
QuickAccessHost::start();
|
||||
}
|
||||
update_quick_access_hotkey(get_general_settings().enableQuickAccess, get_general_settings().quickAccessShortcut);
|
||||
set_tray_icon_visible(get_general_settings().showSystemTrayIcon);
|
||||
CentralizedKeyboardHook::Start();
|
||||
|
||||
@@ -316,7 +322,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
{
|
||||
window = winrt::to_hstring(settingsWindow);
|
||||
}
|
||||
open_settings_window(window, false);
|
||||
open_settings_window(window);
|
||||
}
|
||||
|
||||
if (openOobe)
|
||||
@@ -339,6 +345,7 @@ int runner(bool isProcessElevated, bool openSettings, std::string settingsWindow
|
||||
result = -1;
|
||||
}
|
||||
Trace::UnregisterProvider();
|
||||
QuickAccessHost::stop();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
269
src/runner/quick_access_host.cpp
Normal file
269
src/runner/quick_access_host.cpp
Normal file
@@ -0,0 +1,269 @@
|
||||
#include "pch.h"
|
||||
#include "quick_access_host.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <rpc.h>
|
||||
#include <new>
|
||||
#include <memory>
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
#include <common/utils/process_path.h>
|
||||
#include <common/interop/two_way_pipe_message_ipc.h>
|
||||
#include <wil/resource.h>
|
||||
|
||||
extern void receive_json_send_to_main_thread(const std::wstring& msg);
|
||||
|
||||
namespace
|
||||
{
|
||||
wil::unique_handle quick_access_process;
|
||||
wil::unique_handle show_event;
|
||||
wil::unique_handle exit_event;
|
||||
std::wstring show_event_name;
|
||||
std::wstring exit_event_name;
|
||||
std::wstring runner_pipe_name;
|
||||
std::wstring app_pipe_name;
|
||||
std::unique_ptr<TwoWayPipeMessageIPC> quick_access_ipc;
|
||||
std::mutex quick_access_mutex;
|
||||
|
||||
bool is_process_active_locked()
|
||||
{
|
||||
if (!quick_access_process)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD exit_code = 0;
|
||||
if (!GetExitCodeProcess(quick_access_process.get(), &exit_code))
|
||||
{
|
||||
Logger::warn(L"QuickAccessHost: failed to read Quick Access process exit code. error={}.", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return exit_code == STILL_ACTIVE;
|
||||
}
|
||||
|
||||
void reset_state_locked()
|
||||
{
|
||||
if (quick_access_ipc)
|
||||
{
|
||||
quick_access_ipc->end();
|
||||
quick_access_ipc.reset();
|
||||
}
|
||||
|
||||
quick_access_process.reset();
|
||||
show_event.reset();
|
||||
exit_event.reset();
|
||||
show_event_name.clear();
|
||||
exit_event_name.clear();
|
||||
runner_pipe_name.clear();
|
||||
app_pipe_name.clear();
|
||||
}
|
||||
|
||||
std::wstring build_event_name(const wchar_t* suffix)
|
||||
{
|
||||
std::wstring name = L"Local\\PowerToysQuickAccess_";
|
||||
name += std::to_wstring(GetCurrentProcessId());
|
||||
if (suffix)
|
||||
{
|
||||
name += suffix;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
std::wstring build_command_line(const std::wstring& exe_path)
|
||||
{
|
||||
std::wstring command_line = L"\"";
|
||||
command_line += exe_path;
|
||||
command_line += L"\" --show-event=\"";
|
||||
command_line += show_event_name;
|
||||
command_line += L"\" --exit-event=\"";
|
||||
command_line += exit_event_name;
|
||||
command_line += L"\"";
|
||||
if (!runner_pipe_name.empty())
|
||||
{
|
||||
command_line.append(L" --runner-pipe=\"");
|
||||
command_line += runner_pipe_name;
|
||||
command_line += L"\"";
|
||||
}
|
||||
if (!app_pipe_name.empty())
|
||||
{
|
||||
command_line.append(L" --app-pipe=\"");
|
||||
command_line += app_pipe_name;
|
||||
command_line += L"\"";
|
||||
}
|
||||
return command_line;
|
||||
}
|
||||
}
|
||||
|
||||
namespace QuickAccessHost
|
||||
{
|
||||
bool is_running()
|
||||
{
|
||||
std::scoped_lock lock(quick_access_mutex);
|
||||
return is_process_active_locked();
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
Logger::info(L"QuickAccessHost::start() called");
|
||||
std::scoped_lock lock(quick_access_mutex);
|
||||
if (is_process_active_locked())
|
||||
{
|
||||
Logger::info(L"QuickAccessHost::start: process already active");
|
||||
return;
|
||||
}
|
||||
|
||||
reset_state_locked();
|
||||
|
||||
show_event_name = build_event_name(L"_Show");
|
||||
exit_event_name = build_event_name(L"_Exit");
|
||||
|
||||
show_event.reset(CreateEventW(nullptr, FALSE, FALSE, show_event_name.c_str()));
|
||||
if (!show_event)
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to create show event. error={}.", GetLastError());
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
exit_event.reset(CreateEventW(nullptr, FALSE, FALSE, exit_event_name.c_str()));
|
||||
if (!exit_event)
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to create exit event. error={}.", GetLastError());
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
runner_pipe_name = L"\\\\.\\pipe\\powertoys_quick_access_runner_";
|
||||
app_pipe_name = L"\\\\.\\pipe\\powertoys_quick_access_ui_";
|
||||
UUID temp_uuid;
|
||||
wchar_t* uuid_chars = nullptr;
|
||||
if (UuidCreate(&temp_uuid) == RPC_S_UUID_NO_ADDRESS)
|
||||
{
|
||||
Logger::warn(L"QuickAccessHost: failed to create UUID for pipe names. error={}.", GetLastError());
|
||||
}
|
||||
else if (UuidToString(&temp_uuid, reinterpret_cast<RPC_WSTR*>(&uuid_chars)) != RPC_S_OK)
|
||||
{
|
||||
Logger::warn(L"QuickAccessHost: failed to convert UUID to string. error={}.", GetLastError());
|
||||
}
|
||||
|
||||
if (uuid_chars != nullptr)
|
||||
{
|
||||
runner_pipe_name += std::wstring(uuid_chars);
|
||||
app_pipe_name += std::wstring(uuid_chars);
|
||||
RpcStringFree(reinterpret_cast<RPC_WSTR*>(&uuid_chars));
|
||||
uuid_chars = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::wstring fallback_suffix = std::to_wstring(GetTickCount64());
|
||||
runner_pipe_name += fallback_suffix;
|
||||
app_pipe_name += fallback_suffix;
|
||||
}
|
||||
|
||||
HANDLE token_handle = nullptr;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token_handle))
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to open process token. error={}.", GetLastError());
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
wil::unique_handle token(token_handle);
|
||||
quick_access_ipc.reset(new (std::nothrow) TwoWayPipeMessageIPC(runner_pipe_name, app_pipe_name, receive_json_send_to_main_thread));
|
||||
if (!quick_access_ipc)
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to allocate IPC instance.");
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
quick_access_ipc->start(token.get());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to start IPC server for Quick Access.");
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
const std::wstring exe_path = get_module_folderpath() + L"\\WinUI3Apps\\PowerToys.QuickAccess.exe";
|
||||
if (GetFileAttributesW(exe_path.c_str()) == INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
Logger::warn(L"QuickAccessHost: missing Quick Access executable at {}", exe_path);
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
const std::wstring command_line = build_command_line(exe_path);
|
||||
std::vector<wchar_t> command_line_buffer(command_line.begin(), command_line.end());
|
||||
command_line_buffer.push_back(L'\0');
|
||||
STARTUPINFOW startup_info{};
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
PROCESS_INFORMATION process_info{};
|
||||
|
||||
BOOL created = CreateProcessW(exe_path.c_str(), command_line_buffer.data(), nullptr, nullptr, FALSE, 0, nullptr, nullptr, &startup_info, &process_info);
|
||||
if (!created)
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to launch Quick Access host. error={}.", GetLastError());
|
||||
reset_state_locked();
|
||||
return;
|
||||
}
|
||||
|
||||
quick_access_process.reset(process_info.hProcess);
|
||||
CloseHandle(process_info.hThread);
|
||||
}
|
||||
|
||||
void show()
|
||||
{
|
||||
start();
|
||||
std::scoped_lock lock(quick_access_mutex);
|
||||
|
||||
if (show_event)
|
||||
{
|
||||
if (!SetEvent(show_event.get()))
|
||||
{
|
||||
Logger::warn(L"QuickAccessHost: failed to signal show event. error={}.", GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
Logger::info(L"QuickAccessHost::stop() called");
|
||||
std::unique_lock lock(quick_access_mutex);
|
||||
if (exit_event)
|
||||
{
|
||||
SetEvent(exit_event.get());
|
||||
}
|
||||
|
||||
if (quick_access_process)
|
||||
{
|
||||
const DWORD wait_result = WaitForSingleObject(quick_access_process.get(), 2000);
|
||||
Logger::info(L"QuickAccessHost::stop: WaitForSingleObject result={}", wait_result);
|
||||
if (wait_result == WAIT_TIMEOUT)
|
||||
{
|
||||
Logger::warn(L"QuickAccessHost: Quick Access process did not exit in time, terminating.");
|
||||
if (!TerminateProcess(quick_access_process.get(), 0))
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed to terminate Quick Access process. error={}.", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info(L"QuickAccessHost: TerminateProcess succeeded.");
|
||||
WaitForSingleObject(quick_access_process.get(), 5000);
|
||||
}
|
||||
}
|
||||
else if (wait_result == WAIT_FAILED)
|
||||
{
|
||||
Logger::error(L"QuickAccessHost: failed while waiting for Quick Access process. error={}.", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
reset_state_locked();
|
||||
}
|
||||
}
|
||||
12
src/runner/quick_access_host.h
Normal file
12
src/runner/quick_access_host.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <optional>
|
||||
|
||||
namespace QuickAccessHost
|
||||
{
|
||||
void start();
|
||||
void show();
|
||||
void stop();
|
||||
bool is_running();
|
||||
}
|
||||
@@ -70,6 +70,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="powertoy_module.cpp" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClCompile Include="quick_access_host.cpp" />
|
||||
<ClCompile Include="restart_elevated.cpp" />
|
||||
<ClCompile Include="centralized_kb_hook.cpp" />
|
||||
<ClCompile Include="settings_telemetry.cpp" />
|
||||
@@ -85,6 +86,7 @@
|
||||
<ClInclude Include="auto_start_helper.h" />
|
||||
<ClInclude Include="bug_report.h" />
|
||||
<ClInclude Include="centralized_hotkeys.h" />
|
||||
<ClInclude Include="quick_access_host.h" />
|
||||
<ClInclude Include="general_settings.h" />
|
||||
<ClInclude Include="hotkey_conflict_detector.h" />
|
||||
<ClInclude Include="pch.h" />
|
||||
|
||||
@@ -48,6 +48,9 @@
|
||||
<ClCompile Include="hotkey_conflict_detector.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="quick_access_host.cpp">
|
||||
<Filter>Utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="pch.h" />
|
||||
@@ -102,6 +105,9 @@
|
||||
<ClInclude Include="hotkey_conflict_detector.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="quick_access_host.h">
|
||||
<Filter>Utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Utils">
|
||||
|
||||
@@ -180,6 +180,8 @@ void dispatch_received_json(const std::wstring& json_to_parse)
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::info(L"dispatch_received_json: {}", json_to_parse);
|
||||
|
||||
for (const auto& base_element : j)
|
||||
{
|
||||
const auto name = base_element.Key();
|
||||
@@ -188,12 +190,12 @@ void dispatch_received_json(const std::wstring& json_to_parse)
|
||||
if (name == L"general")
|
||||
{
|
||||
apply_general_settings(value.GetObjectW());
|
||||
const std::wstring settings_string{ get_all_settings().Stringify().c_str() };
|
||||
{
|
||||
std::unique_lock lock{ ipc_mutex };
|
||||
if (current_settings_ipc)
|
||||
current_settings_ipc->send(settings_string);
|
||||
}
|
||||
// const std::wstring settings_string{ get_all_settings().Stringify().c_str() };
|
||||
// {
|
||||
// std::unique_lock lock{ ipc_mutex };
|
||||
// if (current_settings_ipc)
|
||||
// current_settings_ipc->send(settings_string);
|
||||
// }
|
||||
}
|
||||
else if (name == L"powertoys")
|
||||
{
|
||||
@@ -403,7 +405,7 @@ BOOL run_settings_non_elevated(LPCWSTR executable_path, LPWSTR executable_args,
|
||||
|
||||
DWORD g_settings_process_id = 0;
|
||||
|
||||
void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::optional<std::wstring> settings_window, bool show_flyout = false, const std::optional<POINT>& flyout_position = std::nullopt)
|
||||
void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::optional<std::wstring> settings_window)
|
||||
{
|
||||
g_isLaunchInProgress = true;
|
||||
|
||||
@@ -473,22 +475,16 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op
|
||||
// Arg 9: should scoobe window be shown
|
||||
std::wstring settings_showScoobe = show_scoobe_window ? L"true" : L"false";
|
||||
|
||||
// Arg 10: should flyout be shown
|
||||
std::wstring settings_showFlyout = show_flyout ? L"true" : L"false";
|
||||
|
||||
// Arg 11: contains if there's a settings window argument. If true, will add one extra argument with the value to the call.
|
||||
// Arg 10: contains if there's a settings window argument. If true, will add one extra argument with the value to the call.
|
||||
std::wstring settings_containsSettingsWindow = settings_window.has_value() ? L"true" : L"false";
|
||||
|
||||
// Arg 12: contains if there's flyout coordinates. If true, will add two extra arguments to the call containing the x and y coordinates.
|
||||
std::wstring settings_containsFlyoutPosition = flyout_position.has_value() ? L"true" : L"false";
|
||||
|
||||
// Args 13, .... : Optional arguments depending on the options presented before. All by the same value.
|
||||
// Args 11, .... : Optional arguments depending on the options presented before. All by the same value.
|
||||
|
||||
// create general settings file to initialize the settings file with installation configurations like :
|
||||
// 1. Run on start up.
|
||||
PTSettingsHelper::save_general_settings(save_settings.to_json());
|
||||
|
||||
std::wstring executable_args = fmt::format(L"\"{}\" {} {} {} {} {} {} {} {} {} {} {}",
|
||||
std::wstring executable_args = fmt::format(L"\"{}\" {} {} {} {} {} {} {} {} {}",
|
||||
executable_path,
|
||||
powertoys_pipe_name,
|
||||
settings_pipe_name,
|
||||
@@ -498,9 +494,7 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op
|
||||
settings_isUserAnAdmin,
|
||||
settings_showOobe,
|
||||
settings_showScoobe,
|
||||
settings_showFlyout,
|
||||
settings_containsSettingsWindow,
|
||||
settings_containsFlyoutPosition);
|
||||
settings_containsSettingsWindow);
|
||||
|
||||
if (settings_window.has_value())
|
||||
{
|
||||
@@ -508,14 +502,6 @@ void run_settings_window(bool show_oobe_window, bool show_scoobe_window, std::op
|
||||
executable_args.append(settings_window.value());
|
||||
}
|
||||
|
||||
if (flyout_position)
|
||||
{
|
||||
executable_args.append(L" ");
|
||||
executable_args.append(std::to_wstring(flyout_position.value().x));
|
||||
executable_args.append(L" ");
|
||||
executable_args.append(std::to_wstring(flyout_position.value().y));
|
||||
}
|
||||
|
||||
BOOL process_created = false;
|
||||
|
||||
// Commented out to fix #22659
|
||||
@@ -666,39 +652,22 @@ void bring_settings_to_front()
|
||||
EnumWindows(callback, 0);
|
||||
}
|
||||
|
||||
void open_settings_window(std::optional<std::wstring> settings_window, bool show_flyout = false, const std::optional<POINT>& flyout_position)
|
||||
void open_settings_window(std::optional<std::wstring> settings_window)
|
||||
{
|
||||
if (g_settings_process_id != 0)
|
||||
{
|
||||
if (show_flyout)
|
||||
// nl instead of showing the window, send message to it (flyout might need to be hidden, main setting window activated)
|
||||
// bring_settings_to_front();
|
||||
if (current_settings_ipc)
|
||||
{
|
||||
if (current_settings_ipc)
|
||||
if (settings_window.has_value())
|
||||
{
|
||||
if (!flyout_position.has_value())
|
||||
{
|
||||
current_settings_ipc->send(L"{\"ShowYourself\":\"flyout\"}");
|
||||
}
|
||||
else
|
||||
{
|
||||
current_settings_ipc->send(fmt::format(L"{{\"ShowYourself\":\"flyout\", \"x_position\":{}, \"y_position\":{} }}", std::to_wstring(flyout_position.value().x), std::to_wstring(flyout_position.value().y)));
|
||||
}
|
||||
std::wstring msg = L"{\"ShowYourself\":\"" + settings_window.value() + L"\"}";
|
||||
current_settings_ipc->send(msg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// nl instead of showing the window, send message to it (flyout might need to be hidden, main setting window activated)
|
||||
// bring_settings_to_front();
|
||||
if (current_settings_ipc)
|
||||
else
|
||||
{
|
||||
if (settings_window.has_value())
|
||||
{
|
||||
std::wstring msg = L"{\"ShowYourself\":\"" + settings_window.value() + L"\"}";
|
||||
current_settings_ipc->send(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_settings_ipc->send(L"{\"ShowYourself\":\"Dashboard\"}");
|
||||
}
|
||||
current_settings_ipc->send(L"{\"ShowYourself\":\"Dashboard\"}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -706,8 +675,8 @@ void open_settings_window(std::optional<std::wstring> settings_window, bool show
|
||||
{
|
||||
if (!g_isLaunchInProgress)
|
||||
{
|
||||
std::thread([settings_window, show_flyout, flyout_position]() {
|
||||
run_settings_window(false, false, settings_window, show_flyout, flyout_position);
|
||||
std::thread([settings_window]() {
|
||||
run_settings_window(false, false, settings_window);
|
||||
}).detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,9 +41,8 @@ enum class ESettingsWindowNames
|
||||
std::string ESettingsWindowNames_to_string(ESettingsWindowNames value);
|
||||
ESettingsWindowNames ESettingsWindowNames_from_string(std::string value);
|
||||
|
||||
void open_settings_window(std::optional<std::wstring> settings_window, bool show_flyout, const std::optional<POINT>& flyout_position);
|
||||
void open_settings_window(std::optional<std::wstring> settings_window);
|
||||
void close_settings_window();
|
||||
|
||||
void open_oobe_window();
|
||||
void open_scoobe_window();
|
||||
void open_flyout();
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "general_settings.h"
|
||||
#include "centralized_hotkeys.h"
|
||||
#include "centralized_kb_hook.h"
|
||||
#include "quick_access_host.h"
|
||||
#include "hotkey_conflict_detector.h"
|
||||
#include <Windows.h>
|
||||
|
||||
#include <common/utils/resources.h>
|
||||
@@ -69,9 +71,9 @@ void change_menu_item_text(const UINT item_id, wchar_t* new_text)
|
||||
SetMenuItemInfoW(h_menu, item_id, false, &menuitem);
|
||||
}
|
||||
|
||||
void open_quick_access_flyout_window(const POINT flyout_position)
|
||||
void open_quick_access_flyout_window()
|
||||
{
|
||||
open_settings_window(std::nullopt, true, flyout_position);
|
||||
QuickAccessHost::show();
|
||||
}
|
||||
|
||||
void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
|
||||
@@ -81,7 +83,7 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
|
||||
case ID_SETTINGS_MENU_COMMAND:
|
||||
{
|
||||
std::wstring settings_window{ winrt::to_hstring(ESettingsWindowNames_to_string(static_cast<ESettingsWindowNames>(lparam))) };
|
||||
open_settings_window(settings_window, false);
|
||||
open_settings_window(settings_window);
|
||||
}
|
||||
break;
|
||||
case ID_CLOSE_MENU_COMMAND:
|
||||
@@ -113,9 +115,7 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
|
||||
}
|
||||
case ID_QUICK_ACCESS_MENU_COMMAND:
|
||||
{
|
||||
POINT mouse_pointer;
|
||||
GetCursorPos(&mouse_pointer);
|
||||
open_quick_access_flyout_window(mouse_pointer);
|
||||
open_quick_access_flyout_window();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -126,7 +126,14 @@ void click_timer_elapsed()
|
||||
double_click_timer_running = false;
|
||||
if (!double_clicked)
|
||||
{
|
||||
open_quick_access_flyout_window(tray_icon_click_point);
|
||||
if (get_general_settings().enableQuickAccess)
|
||||
{
|
||||
open_quick_access_flyout_window();
|
||||
}
|
||||
else
|
||||
{
|
||||
open_settings_window(std::nullopt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,9 +225,6 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
// ignore event if this is the second click of a double click
|
||||
if (!double_click_timer_running)
|
||||
{
|
||||
// save the cursor position for sending where to show the popup.
|
||||
GetCursorPos(&tray_icon_click_point);
|
||||
|
||||
// start timer for detecting single or double click
|
||||
double_click_timer_running = true;
|
||||
double_clicked = false;
|
||||
@@ -236,7 +240,7 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
double_clicked = true;
|
||||
open_settings_window(std::nullopt, false);
|
||||
open_settings_window(std::nullopt);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -349,4 +353,37 @@ void stop_tray_icon()
|
||||
BugReportManager::instance().clear_callbacks();
|
||||
SendMessage(tray_icon_hwnd, WM_CLOSE, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
void update_quick_access_hotkey(bool enabled, PowerToysSettings::HotkeyObject hotkey)
|
||||
{
|
||||
static PowerToysSettings::HotkeyObject current_hotkey;
|
||||
static bool is_registered = false;
|
||||
auto& hkmng = HotkeyConflictDetector::HotkeyConflictManager::GetInstance();
|
||||
|
||||
if (is_registered)
|
||||
{
|
||||
CentralizedKeyboardHook::ClearModuleHotkeys(L"QuickAccess");
|
||||
hkmng.RemoveHotkeyByModule(L"GeneralSettings");
|
||||
is_registered = false;
|
||||
}
|
||||
|
||||
if (enabled && hotkey.get_code() != 0)
|
||||
{
|
||||
HotkeyConflictDetector::Hotkey hk = {
|
||||
hotkey.win_pressed(),
|
||||
hotkey.ctrl_pressed(),
|
||||
hotkey.shift_pressed(),
|
||||
hotkey.alt_pressed(),
|
||||
static_cast<unsigned char>(hotkey.get_code())
|
||||
};
|
||||
|
||||
hkmng.AddHotkey(hk, L"GeneralSettings", 0, true);
|
||||
CentralizedKeyboardHook::SetHotkeyAction(L"QuickAccess", hk, []() {
|
||||
open_quick_access_flyout_window();
|
||||
return true;
|
||||
});
|
||||
|
||||
current_hotkey = hotkey;
|
||||
is_registered = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <common/SettingsAPI/settings_objects.h>
|
||||
|
||||
// Start the Tray Icon
|
||||
void start_tray_icon(bool isProcessElevated);
|
||||
@@ -9,7 +10,9 @@ void set_tray_icon_visible(bool shouldIconBeVisible);
|
||||
// Stop the Tray Icon
|
||||
void stop_tray_icon();
|
||||
// Open the Settings Window
|
||||
void open_settings_window(std::optional<std::wstring> settings_window, bool show_flyout, const std::optional<POINT>& flyout_position = std::nullopt);
|
||||
void open_settings_window(std::optional<std::wstring> settings_window);
|
||||
// Update Quick Access Hotkey
|
||||
void update_quick_access_hotkey(bool enabled, PowerToysSettings::HotkeyObject hotkey);
|
||||
// Callback type to be called by the tray icon loop
|
||||
typedef void (*main_loop_callback_function)(PVOID);
|
||||
// Calls a callback in _callback
|
||||
|
||||
49
src/settings-ui/QuickAccess.UI/Helpers/ModuleGpoHelper.cs
Normal file
49
src/settings-ui/QuickAccess.UI/Helpers/ModuleGpoHelper.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// 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 global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Helpers;
|
||||
|
||||
internal static class ModuleGpoHelper
|
||||
{
|
||||
public static GpoRuleConfigured GetModuleGpoConfiguration(ModuleType moduleType)
|
||||
{
|
||||
return moduleType switch
|
||||
{
|
||||
ModuleType.AdvancedPaste => GPOWrapper.GetConfiguredAdvancedPasteEnabledValue(),
|
||||
ModuleType.AlwaysOnTop => GPOWrapper.GetConfiguredAlwaysOnTopEnabledValue(),
|
||||
ModuleType.Awake => GPOWrapper.GetConfiguredAwakeEnabledValue(),
|
||||
ModuleType.CmdPal => GPOWrapper.GetConfiguredCmdPalEnabledValue(),
|
||||
ModuleType.ColorPicker => GPOWrapper.GetConfiguredColorPickerEnabledValue(),
|
||||
ModuleType.CropAndLock => GPOWrapper.GetConfiguredCropAndLockEnabledValue(),
|
||||
ModuleType.CursorWrap => GPOWrapper.GetConfiguredCursorWrapEnabledValue(),
|
||||
ModuleType.EnvironmentVariables => GPOWrapper.GetConfiguredEnvironmentVariablesEnabledValue(),
|
||||
ModuleType.FancyZones => GPOWrapper.GetConfiguredFancyZonesEnabledValue(),
|
||||
ModuleType.FileLocksmith => GPOWrapper.GetConfiguredFileLocksmithEnabledValue(),
|
||||
ModuleType.FindMyMouse => GPOWrapper.GetConfiguredFindMyMouseEnabledValue(),
|
||||
ModuleType.Hosts => GPOWrapper.GetConfiguredHostsFileEditorEnabledValue(),
|
||||
ModuleType.ImageResizer => GPOWrapper.GetConfiguredImageResizerEnabledValue(),
|
||||
ModuleType.KeyboardManager => GPOWrapper.GetConfiguredKeyboardManagerEnabledValue(),
|
||||
ModuleType.MouseHighlighter => GPOWrapper.GetConfiguredMouseHighlighterEnabledValue(),
|
||||
ModuleType.MouseJump => GPOWrapper.GetConfiguredMouseJumpEnabledValue(),
|
||||
ModuleType.MousePointerCrosshairs => GPOWrapper.GetConfiguredMousePointerCrosshairsEnabledValue(),
|
||||
ModuleType.MouseWithoutBorders => GPOWrapper.GetConfiguredMouseWithoutBordersEnabledValue(),
|
||||
ModuleType.NewPlus => GPOWrapper.GetConfiguredNewPlusEnabledValue(),
|
||||
ModuleType.Peek => GPOWrapper.GetConfiguredPeekEnabledValue(),
|
||||
ModuleType.PowerRename => GPOWrapper.GetConfiguredPowerRenameEnabledValue(),
|
||||
ModuleType.PowerLauncher => GPOWrapper.GetConfiguredPowerLauncherEnabledValue(),
|
||||
ModuleType.PowerAccent => GPOWrapper.GetConfiguredQuickAccentEnabledValue(),
|
||||
ModuleType.Workspaces => GPOWrapper.GetConfiguredWorkspacesEnabledValue(),
|
||||
ModuleType.RegistryPreview => GPOWrapper.GetConfiguredRegistryPreviewEnabledValue(),
|
||||
ModuleType.MeasureTool => GPOWrapper.GetConfiguredScreenRulerEnabledValue(),
|
||||
ModuleType.ShortcutGuide => GPOWrapper.GetConfiguredShortcutGuideEnabledValue(),
|
||||
ModuleType.PowerOCR => GPOWrapper.GetConfiguredTextExtractorEnabledValue(),
|
||||
ModuleType.ZoomIt => GPOWrapper.GetConfiguredZoomItEnabledValue(),
|
||||
_ => GpoRuleConfigured.Unavailable,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// 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 Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Helpers;
|
||||
|
||||
internal static class ResourceLoaderInstance
|
||||
{
|
||||
internal static ResourceLoader ResourceLoader { get; } = new("PowerToys.QuickAccess.pri");
|
||||
}
|
||||
89
src/settings-ui/QuickAccess.UI/PowerToys.QuickAccess.csproj
Normal file
89
src/settings-ui/QuickAccess.UI/PowerToys.QuickAccess.csproj
Normal file
@@ -0,0 +1,89 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\..\Common.Dotnet.CsWinRT.props" />
|
||||
<Import Project="..\..\Common.SelfContained.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net9.0-windows10.0.26100.0</TargetFramework>
|
||||
<RootNamespace>Microsoft.PowerToys.QuickAccess</RootNamespace>
|
||||
<AssemblyName>PowerToys.QuickAccess</AssemblyName>
|
||||
<UseWinUI>true</UseWinUI>
|
||||
<WindowsPackageType>None</WindowsPackageType>
|
||||
<WindowsAppSDKSelfContained>true</WindowsAppSDKSelfContained>
|
||||
<EnablePreviewMsixTooling>true</EnablePreviewMsixTooling>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<OutputPath>..\..\..\$(Platform)\$(Configuration)\WinUI3Apps</OutputPath>
|
||||
<EnableDefaultPageItems>false</EnableDefaultPageItems>
|
||||
<EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>
|
||||
<Nullable>enable</Nullable>
|
||||
<ProjectPriFileName>PowerToys.QuickAccess.pri</ProjectPriFileName>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<CsWinRTIncludes>PowerToys.GPOWrapper</CsWinRTIncludes>
|
||||
<CsWinRTGeneratedFilesDir>$(OutDir)</CsWinRTGeneratedFilesDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="QuickAccessXaml\App.xaml" />
|
||||
<Page Include="QuickAccessXaml\MainWindow.xaml" />
|
||||
<Page Include="QuickAccessXaml\Flyout\ShellPage.xaml" />
|
||||
<Page Include="QuickAccessXaml\Flyout\LaunchPage.xaml" />
|
||||
<Page Include="QuickAccessXaml\Flyout\AppsListPage.xaml" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Include="..\Settings.UI\SettingsXAML\Styles\Button.xaml">
|
||||
<Link>Resources\Styles\Button.xaml</Link>
|
||||
</Page>
|
||||
<Page Include="..\Settings.UI\SettingsXAML\Styles\TextBlock.xaml">
|
||||
<Link>Resources\Styles\TextBlock.xaml</Link>
|
||||
</Page>
|
||||
<Page Include="..\Settings.UI\SettingsXAML\Themes\Colors.xaml">
|
||||
<Link>Resources\Themes\Colors.xaml</Link>
|
||||
</Page>
|
||||
<Page Include="..\Settings.UI\SettingsXAML\Themes\Generic.xaml">
|
||||
<Link>Resources\Themes\Generic.xaml</Link>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PRIResource Include="..\Settings.UI\Strings\en-us\Resources.resw">
|
||||
<Link>Strings\en-us\Resources.resw</Link>
|
||||
</PRIResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Settings.UI\Assets\Settings\Icons\**\*">
|
||||
<Link>Assets\Settings\Icons\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Animations" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Primitives" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.Segmented" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="Microsoft.WindowsAppSDK" />
|
||||
<PackageReference Include="WinUIEx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\GPOWrapper\GPOWrapper.vcxproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedCommon\ManagedCommon.csproj" />
|
||||
<ProjectReference Include="..\..\common\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
|
||||
<ProjectReference Include="..\..\common\interop\PowerToys.Interop.vcxproj" />
|
||||
<ProjectReference Include="..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
<ProjectReference Include="..\Settings.UI.Controls\Settings.UI.Controls.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Manifest Include="$(ApplicationManifest)" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
62
src/settings-ui/QuickAccess.UI/QuickAccessLaunchContext.cs
Normal file
62
src/settings-ui/QuickAccess.UI/QuickAccessLaunchContext.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
// 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.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess;
|
||||
|
||||
public sealed record QuickAccessLaunchContext(string? ShowEventName, string? ExitEventName, string? RunnerPipeName, string? AppPipeName)
|
||||
{
|
||||
public static QuickAccessLaunchContext Parse(string[] args)
|
||||
{
|
||||
string? showEvent = null;
|
||||
string? exitEvent = null;
|
||||
string? runnerPipe = null;
|
||||
string? appPipe = null;
|
||||
|
||||
foreach (var arg in args)
|
||||
{
|
||||
if (TryReadValue(arg, "--show-event", out var value))
|
||||
{
|
||||
showEvent = value;
|
||||
}
|
||||
else if (TryReadValue(arg, "--exit-event", out value))
|
||||
{
|
||||
exitEvent = value;
|
||||
}
|
||||
else if (TryReadValue(arg, "--runner-pipe", out value))
|
||||
{
|
||||
runnerPipe = value;
|
||||
}
|
||||
else if (TryReadValue(arg, "--app-pipe", out value))
|
||||
{
|
||||
appPipe = value;
|
||||
}
|
||||
}
|
||||
|
||||
return new QuickAccessLaunchContext(showEvent, exitEvent, runnerPipe, appPipe);
|
||||
}
|
||||
|
||||
private static bool TryReadValue(string candidate, string key, [NotNullWhen(true)] out string? value)
|
||||
{
|
||||
if (candidate.StartsWith(key, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (candidate.Length == key.Length)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate[key.Length] == '=')
|
||||
{
|
||||
value = candidate[(key.Length + 1)..].Trim('"');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
60
src/settings-ui/QuickAccess.UI/QuickAccessXAML/App.xaml
Normal file
60
src/settings-ui/QuickAccess.UI/QuickAccessXAML/App.xaml
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application
|
||||
x:Class="Microsoft.PowerToys.QuickAccess.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters">
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||
<ResourceDictionary Source="/Resources/Styles/Button.xaml" />
|
||||
<ResourceDictionary Source="/Resources/Styles/TextBlock.xaml" />
|
||||
<ResourceDictionary Source="/Resources/Themes/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<SolidColorBrush
|
||||
x:Key="LayerOnAcrylicFillColorDefaultBrush"
|
||||
Opacity="0.7"
|
||||
Color="#FFFFFFFF" />
|
||||
<SolidColorBrush x:Key="CardStrokeColorDefaultBrush" Color="#0F000000" />
|
||||
<SolidColorBrush x:Key="CardBackgroundFillColorDefaultBrush" Color="#B3FFFFFF" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<SolidColorBrush
|
||||
x:Key="LayerOnAcrylicFillColorDefaultBrush"
|
||||
Opacity="0.7"
|
||||
Color="#FFFFFFFF" />
|
||||
<SolidColorBrush x:Key="CardStrokeColorDefaultBrush" Color="#0F000000" />
|
||||
<SolidColorBrush x:Key="CardBackgroundFillColorDefaultBrush" Color="#B3FFFFFF" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
<SolidColorBrush
|
||||
x:Key="LayerOnAcrylicFillColorDefaultBrush"
|
||||
Opacity="0.6"
|
||||
Color="#FF000000" />
|
||||
<SolidColorBrush x:Key="CardStrokeColorDefaultBrush" Color="#0FFFFFFF" />
|
||||
<SolidColorBrush x:Key="CardBackgroundFillColorDefaultBrush" Color="#0DFFFFFF" />
|
||||
</ResourceDictionary>
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<SolidColorBrush x:Key="LayerOnAcrylicFillColorDefaultBrush" Color="{ThemeResource SystemColorWindowColor}" />
|
||||
<SolidColorBrush x:Key="CardStrokeColorDefaultBrush" Color="{ThemeResource SystemColorWindowTextColor}" />
|
||||
<SolidColorBrush x:Key="CardBackgroundFillColorDefaultBrush" Color="{ThemeResource SystemColorWindowColor}" />
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<tkconverters:BoolToVisibilityConverter
|
||||
x:Key="ReverseBoolToVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
TrueValue="Collapsed" />
|
||||
<tkconverters:BoolToVisibilityConverter
|
||||
x:Key="BoolToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
TrueValue="Visible" />
|
||||
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
<tkconverters:StringVisibilityConverter x:Key="StringVisibilityConverter" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
36
src/settings-ui/QuickAccess.UI/QuickAccessXAML/App.xaml.cs
Normal file
36
src/settings-ui/QuickAccess.UI/QuickAccessXAML/App.xaml.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// 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 Microsoft.UI.Xaml;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
private static MainWindow? _window;
|
||||
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnLaunched(LaunchActivatedEventArgs args)
|
||||
{
|
||||
var launchContext = QuickAccessLaunchContext.Parse(Environment.GetCommandLineArgs());
|
||||
_window = new MainWindow(launchContext);
|
||||
_window.Closed += OnWindowClosed;
|
||||
_window.Activate();
|
||||
}
|
||||
|
||||
private static void OnWindowClosed(object sender, WindowEventArgs args)
|
||||
{
|
||||
if (sender is MainWindow window)
|
||||
{
|
||||
window.Closed -= OnWindowClosed;
|
||||
}
|
||||
|
||||
_window = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.QuickAccess.Flyout.AppsListPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Controls.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="using:Microsoft.PowerToys.QuickAccess.Flyout"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:viewModels="using:Microsoft.PowerToys.QuickAccess.ViewModels"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<converters:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
|
||||
</Page.Resources>
|
||||
<Grid Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Padding="24,32,24,0">
|
||||
<TextBlock
|
||||
x:Uid="AllAppsTxt"
|
||||
VerticalAlignment="Center"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}" />
|
||||
<StackPanel
|
||||
HorizontalAlignment="Right"
|
||||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Button
|
||||
x:Uid="Dashboard_SortBy"
|
||||
VerticalAlignment="Center"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="Dashboard_SortBy_ToolTip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<Button.Content>
|
||||
<FontIcon FontSize="14" Glyph="" />
|
||||
</Button.Content>
|
||||
<Button.Flyout>
|
||||
<MenuFlyout Placement="BottomEdgeAlignedRight">
|
||||
<ToggleMenuFlyoutItem
|
||||
x:Uid="Dashboard_SortAlphabetical"
|
||||
Click="SortAlphabetical_Click"
|
||||
IsChecked="{x:Bind ViewModel.DashboardSortOrder, Mode=OneWay, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=Alphabetical}" />
|
||||
<ToggleMenuFlyoutItem
|
||||
x:Uid="Dashboard_SortByStatus"
|
||||
Click="SortByStatus_Click"
|
||||
IsChecked="{x:Bind ViewModel.DashboardSortOrder, Mode=OneWay, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter=ByStatus}" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<Button
|
||||
x:Uid="BackBtn"
|
||||
Padding="8,4,8,4"
|
||||
VerticalAlignment="Center"
|
||||
Click="BackButton_Click">
|
||||
<Button.Content>
|
||||
<StackPanel
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="12">
|
||||
<FontIcon
|
||||
Margin="0,2,0,0"
|
||||
FontSize="12"
|
||||
Glyph="" />
|
||||
<TextBlock x:Uid="BackLabel" Style="{StaticResource CaptionTextBlockStyle}" />
|
||||
</StackPanel>
|
||||
</Button.Content>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||
<controls:ModuleList
|
||||
Margin="8,12,12,12"
|
||||
DividerThickness="0,0,0,0"
|
||||
IsItemClickable="False"
|
||||
ItemsSource="{x:Bind ViewModel.FlyoutMenuItems, Mode=OneWay}" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Page>
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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 Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Flyout;
|
||||
|
||||
public sealed partial class AppsListPage : Page
|
||||
{
|
||||
private FlyoutNavigationContext? _context;
|
||||
|
||||
public AppsListPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public AllAppsViewModel ViewModel { get; private set; } = default!;
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
if (e.Parameter is FlyoutNavigationContext context)
|
||||
{
|
||||
_context = context;
|
||||
ViewModel = context.AllAppsViewModel;
|
||||
DataContext = ViewModel;
|
||||
ViewModel.RefreshSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private void BackButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_context == null || Frame == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Frame.Navigate(typeof(LaunchPage), _context, new SlideNavigationTransitionInfo { Effect = SlideNavigationTransitionEffect.FromLeft });
|
||||
}
|
||||
|
||||
private void SortAlphabetical_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ViewModel != null)
|
||||
{
|
||||
ViewModel.DashboardSortOrder = DashboardSortOrder.Alphabetical;
|
||||
}
|
||||
}
|
||||
|
||||
private void SortByStatus_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (ViewModel != null)
|
||||
{
|
||||
ViewModel.DashboardSortOrder = DashboardSortOrder.ByStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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 Microsoft.PowerToys.QuickAccess.Services;
|
||||
using Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Flyout;
|
||||
|
||||
internal sealed record FlyoutNavigationContext(
|
||||
LauncherViewModel LauncherViewModel,
|
||||
AllAppsViewModel AllAppsViewModel,
|
||||
IQuickAccessCoordinator Coordinator);
|
||||
@@ -1,5 +1,5 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.LaunchPage"
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.QuickAccess.Flyout.LaunchPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||
@@ -9,7 +9,7 @@
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||
xmlns:viewModels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
|
||||
xmlns:viewModels="using:Microsoft.PowerToys.QuickAccess.ViewModels"
|
||||
mc:Ignorable="d">
|
||||
<Page.Resources>
|
||||
<Style
|
||||
@@ -52,7 +52,6 @@
|
||||
VerticalAlignment="Center"
|
||||
Orientation="Horizontal"
|
||||
Spacing="12">
|
||||
|
||||
<TextBlock x:Uid="MoreLabel" Style="{StaticResource CaptionTextBlockStyle}" />
|
||||
<FontIcon
|
||||
Margin="0,2,0,0"
|
||||
@@ -64,45 +63,12 @@
|
||||
</Grid>
|
||||
<Grid Grid.Row="1">
|
||||
<ScrollViewer>
|
||||
<ItemsControl
|
||||
<controls:QuickAccessList
|
||||
Margin="12,26,12,24"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Top"
|
||||
ItemsSource="{x:Bind ViewModel.FlyoutMenuItems}"
|
||||
TabNavigation="Local">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<tkcontrols:WrapPanel HorizontalAlignment="Stretch" VerticalSpacing="12" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewModels:FlyoutMenuItem">
|
||||
<controls:FlyoutMenuButton
|
||||
AutomationProperties.Name="{x:Bind Label}"
|
||||
Click="ModuleButton_Click"
|
||||
Tag="{x:Bind Tag}"
|
||||
Visibility="{x:Bind Visible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<controls:FlyoutMenuButton.Content>
|
||||
<TextBlock
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Label}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
</controls:FlyoutMenuButton.Content>
|
||||
<controls:FlyoutMenuButton.Icon>
|
||||
<Image>
|
||||
<Image.Source>
|
||||
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</controls:FlyoutMenuButton.Icon>
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip Content="{x:Bind ToolTip}" Visibility="{x:Bind ToolTip, Converter={StaticResource StringVisibilityConverter}}" />
|
||||
</ToolTipService.ToolTip>
|
||||
</controls:FlyoutMenuButton>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
TabNavigation="Local" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -150,7 +116,7 @@
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="SettingsTooltip" />
|
||||
</ToolTipService.ToolTip>
|
||||
<AnimatedIcon x:Name="SearchAnimatedIcon">
|
||||
<AnimatedIcon x:Name="SettingsAnimatedIcon">
|
||||
<AnimatedIcon.Source>
|
||||
<animatedVisuals:AnimatedSettingsVisualSource />
|
||||
</AnimatedIcon.Source>
|
||||
@@ -159,14 +125,6 @@
|
||||
</AnimatedIcon.FallbackIconSource>
|
||||
</AnimatedIcon>
|
||||
</Button>
|
||||
<!--<AppBarSeparator />
|
||||
<Button
|
||||
x:Name="QuitBtn"
|
||||
Style="{StaticResource FlyoutButtonStyle}"
|
||||
ToolTipService.ToolTip="Quit"
|
||||
Click="QuitButton_Click">
|
||||
<FontIcon FontSize="16" Glyph="" />
|
||||
</Button>-->
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
@@ -0,0 +1,80 @@
|
||||
// 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.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.QuickAccess.Services;
|
||||
using Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
using Microsoft.PowerToys.Settings.UI.Controls;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using PowerToys.Interop;
|
||||
using Windows.System;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Flyout;
|
||||
|
||||
public sealed partial class LaunchPage : Page
|
||||
{
|
||||
private AllAppsViewModel? _allAppsViewModel;
|
||||
private IQuickAccessCoordinator? _coordinator;
|
||||
|
||||
public LaunchPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public LauncherViewModel ViewModel { get; private set; } = default!;
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
if (e.Parameter is FlyoutNavigationContext context)
|
||||
{
|
||||
ViewModel = context.LauncherViewModel;
|
||||
_allAppsViewModel = context.AllAppsViewModel;
|
||||
_coordinator = context.Coordinator;
|
||||
DataContext = ViewModel;
|
||||
}
|
||||
}
|
||||
|
||||
private void SettingsBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_coordinator?.OpenSettings();
|
||||
}
|
||||
|
||||
private async void DocsBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_coordinator == null || !await _coordinator.ShowDocumentationAsync())
|
||||
{
|
||||
await Launcher.LaunchUriAsync(new Uri("https://aka.ms/PowerToysOverview"));
|
||||
}
|
||||
}
|
||||
|
||||
private void AllAppButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (Frame == null || _allAppsViewModel == null || ViewModel == null || _coordinator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var context = new FlyoutNavigationContext(ViewModel, _allAppsViewModel, _coordinator);
|
||||
Frame.Navigate(typeof(AppsListPage), context, new SlideNavigationTransitionInfo { Effect = SlideNavigationTransitionEffect.FromRight });
|
||||
}
|
||||
|
||||
public void ReportBugBtn_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_coordinator?.ReportBug();
|
||||
}
|
||||
|
||||
private void UpdateInfoBar_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
_coordinator?.OpenGeneralSettingsForUpdates();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.ShellPage"
|
||||
<Page
|
||||
x:Class="Microsoft.PowerToys.QuickAccess.Flyout.ShellPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
@@ -0,0 +1,68 @@
|
||||
// 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 Microsoft.PowerToys.QuickAccess.Services;
|
||||
using Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Media.Animation;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Flyout;
|
||||
|
||||
/// <summary>
|
||||
/// Hosts the flyout navigation frame.
|
||||
/// </summary>
|
||||
public sealed partial class ShellPage : Page
|
||||
{
|
||||
private LauncherViewModel? _launcherViewModel;
|
||||
private AllAppsViewModel? _allAppsViewModel;
|
||||
private IQuickAccessCoordinator? _coordinator;
|
||||
|
||||
public ShellPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void Initialize(IQuickAccessCoordinator coordinator, LauncherViewModel launcherViewModel, AllAppsViewModel allAppsViewModel)
|
||||
{
|
||||
_coordinator = coordinator;
|
||||
_launcherViewModel = launcherViewModel;
|
||||
_allAppsViewModel = allAppsViewModel;
|
||||
}
|
||||
|
||||
private void Page_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_launcherViewModel == null || _allAppsViewModel == null || _coordinator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (ContentFrame.Content is LaunchPage)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var context = new FlyoutNavigationContext(_launcherViewModel, _allAppsViewModel, _coordinator);
|
||||
ContentFrame.Navigate(typeof(LaunchPage), context, new SuppressNavigationTransitionInfo());
|
||||
}
|
||||
|
||||
internal void NavigateToLaunch()
|
||||
{
|
||||
if (_launcherViewModel == null || _allAppsViewModel == null || _coordinator == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var context = new FlyoutNavigationContext(_launcherViewModel, _allAppsViewModel, _coordinator);
|
||||
ContentFrame.Navigate(typeof(LaunchPage), context, new SlideNavigationTransitionInfo { Effect = SlideNavigationTransitionEffect.FromLeft });
|
||||
}
|
||||
|
||||
internal void RefreshIfAppsList()
|
||||
{
|
||||
if (ContentFrame.Content is AppsListPage appsListPage)
|
||||
{
|
||||
appsListPage.ViewModel?.RefreshSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
<winuiex:WindowEx
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.FlyoutWindow"
|
||||
<winuiEx:WindowEx
|
||||
x:Class="Microsoft.PowerToys.QuickAccess.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:flyout="using:Microsoft.PowerToys.Settings.UI.Flyout"
|
||||
xmlns:local="using:Microsoft.PowerToys.Settings.UI"
|
||||
xmlns:flyout="using:Microsoft.PowerToys.QuickAccess.Flyout"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:winuiex="using:WinUIEx"
|
||||
Title="PowerToys Settings"
|
||||
xmlns:winuiEx="using:WinUIEx"
|
||||
Title="PowerToys Quick Access (Preview)"
|
||||
Width="400"
|
||||
Height="516"
|
||||
MinWidth="400"
|
||||
MinHeight="516"
|
||||
IsAlwaysOnTop="True"
|
||||
IsMaximizable="False"
|
||||
IsMinimizable="False"
|
||||
@@ -15,8 +18,8 @@
|
||||
IsShownInSwitchers="False"
|
||||
IsTitleBarVisible="False"
|
||||
mc:Ignorable="d">
|
||||
<winuiex:WindowEx.Backdrop>
|
||||
<winuiex:AcrylicSystemBackdrop
|
||||
<winuiEx:WindowEx.Backdrop>
|
||||
<winuiEx:AcrylicSystemBackdrop
|
||||
DarkFallbackColor="#1c1c1c"
|
||||
DarkLuminosityOpacity="0.96"
|
||||
DarkTintColor="#202020"
|
||||
@@ -25,8 +28,9 @@
|
||||
LightLuminosityOpacity="0.90"
|
||||
LightTintColor="#F3F3F3"
|
||||
LightTintOpacity="0" />
|
||||
</winuiex:WindowEx.Backdrop>
|
||||
</winuiEx:WindowEx.Backdrop>
|
||||
|
||||
<Grid>
|
||||
<flyout:ShellPage x:Name="FlyoutShellPage" />
|
||||
<flyout:ShellPage x:Name="ShellHost" />
|
||||
</Grid>
|
||||
</winuiex:WindowEx>
|
||||
</winuiEx:WindowEx>
|
||||
@@ -0,0 +1,732 @@
|
||||
// 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.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.QuickAccess.Services;
|
||||
using Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Windows.Graphics;
|
||||
using WinRT.Interop;
|
||||
using WinUIEx;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess;
|
||||
|
||||
public sealed partial class MainWindow : WindowEx, IDisposable
|
||||
{
|
||||
private readonly QuickAccessLaunchContext _launchContext;
|
||||
private readonly DispatcherQueue _dispatcherQueue;
|
||||
private readonly IntPtr _hwnd;
|
||||
private readonly AppWindow? _appWindow;
|
||||
private readonly LauncherViewModel _launcherViewModel;
|
||||
private readonly AllAppsViewModel _allAppsViewModel;
|
||||
private readonly QuickAccessCoordinator _coordinator;
|
||||
private bool _disposed;
|
||||
private EventWaitHandle? _showEvent;
|
||||
private EventWaitHandle? _exitEvent;
|
||||
private ManualResetEventSlim? _listenerShutdownEvent;
|
||||
private Thread? _showListenerThread;
|
||||
private Thread? _exitListenerThread;
|
||||
private bool _isWindowCloaked;
|
||||
private bool _initialActivationHandled;
|
||||
private bool _isPrimed;
|
||||
|
||||
// Prevent auto-hide until the window actually gained focus once.
|
||||
private bool _hasSeenInteractiveActivation;
|
||||
private bool _isVisible;
|
||||
private IntPtr _mouseHook;
|
||||
private LowLevelMouseProc? _mouseHookDelegate;
|
||||
private CancellationTokenSource? _trimCts;
|
||||
|
||||
private const int DefaultWidth = 320;
|
||||
private const int DefaultHeight = 480;
|
||||
private const int DwmWaCloak = 13;
|
||||
private const int GwlStyle = -16;
|
||||
private const int GwlExStyle = -20;
|
||||
private const int SwHide = 0;
|
||||
private const int SwShow = 5;
|
||||
private const int SwShowNoActivate = 8;
|
||||
private const uint SwpShowWindow = 0x0040;
|
||||
private const uint SwpNoZorder = 0x0004;
|
||||
private const uint SwpNoSize = 0x0001;
|
||||
private const uint SwpNoMove = 0x0002;
|
||||
private const uint SwpNoActivate = 0x0010;
|
||||
private const uint SwpFrameChanged = 0x0020;
|
||||
private const long WsSysmenu = 0x00080000L;
|
||||
private const long WsMinimizeBox = 0x00020000L;
|
||||
private const long WsMaximizeBox = 0x00010000L;
|
||||
private const long WsExToolWindow = 0x00000080L;
|
||||
private const uint MonitorDefaulttonearest = 0x00000002;
|
||||
private static readonly IntPtr HwndTopmost = new(-1);
|
||||
private static readonly IntPtr HwndBottom = new(1);
|
||||
|
||||
public MainWindow(QuickAccessLaunchContext launchContext)
|
||||
{
|
||||
InitializeComponent();
|
||||
_launchContext = launchContext;
|
||||
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
_hwnd = WindowNative.GetWindowHandle(this);
|
||||
_appWindow = InitializeAppWindow(_hwnd);
|
||||
Title = "PowerToys Quick Access (Preview)";
|
||||
|
||||
_coordinator = new QuickAccessCoordinator(this, _launchContext);
|
||||
_launcherViewModel = new LauncherViewModel(_coordinator);
|
||||
_allAppsViewModel = new AllAppsViewModel(_coordinator);
|
||||
ShellHost.Initialize(_coordinator, _launcherViewModel, _allAppsViewModel);
|
||||
|
||||
CustomizeWindowChrome();
|
||||
HideFromTaskbar();
|
||||
HideWindow();
|
||||
InitializeEventListeners();
|
||||
Closed += OnClosed;
|
||||
Activated += OnActivated;
|
||||
}
|
||||
|
||||
private AppWindow? InitializeAppWindow(IntPtr hwnd)
|
||||
{
|
||||
var windowId = Microsoft.UI.Win32Interop.GetWindowIdFromWindow(hwnd);
|
||||
return AppWindow.GetFromWindowId(windowId);
|
||||
}
|
||||
|
||||
private void HideWindow()
|
||||
{
|
||||
if (_hwnd != IntPtr.Zero)
|
||||
{
|
||||
var cloaked = CloakWindow();
|
||||
|
||||
if (!ShowWindowNative(_hwnd, SwHide) && _appWindow != null)
|
||||
{
|
||||
_appWindow.Hide();
|
||||
}
|
||||
|
||||
if (cloaked)
|
||||
{
|
||||
ShowWindowNative(_hwnd, SwShowNoActivate);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowPosNative(_hwnd, HwndBottom, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpNoActivate);
|
||||
}
|
||||
}
|
||||
else if (_appWindow != null)
|
||||
{
|
||||
_appWindow.Hide();
|
||||
}
|
||||
|
||||
_isVisible = false;
|
||||
RemoveGlobalMouseHook();
|
||||
|
||||
ScheduleMemoryTrim();
|
||||
}
|
||||
|
||||
internal void RequestHide()
|
||||
{
|
||||
if (_dispatcherQueue.HasThreadAccess)
|
||||
{
|
||||
HideWindow();
|
||||
}
|
||||
else
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(HideWindow);
|
||||
}
|
||||
}
|
||||
|
||||
private void ScheduleMemoryTrim()
|
||||
{
|
||||
CancelMemoryTrim();
|
||||
_trimCts = new CancellationTokenSource();
|
||||
var token = _trimCts.Token;
|
||||
|
||||
// Delay the trim to avoid aggressive GC during quick toggles
|
||||
Task.Delay(2000, token).ContinueWith(
|
||||
_ =>
|
||||
{
|
||||
if (token.IsCancellationRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
TrimMemory();
|
||||
},
|
||||
token,
|
||||
TaskContinuationOptions.None,
|
||||
TaskScheduler.Default);
|
||||
}
|
||||
|
||||
private void CancelMemoryTrim()
|
||||
{
|
||||
_trimCts?.Cancel();
|
||||
_trimCts?.Dispose();
|
||||
_trimCts = null;
|
||||
}
|
||||
|
||||
private void TrimMemory()
|
||||
{
|
||||
GC.Collect();
|
||||
GC.WaitForPendingFinalizers();
|
||||
GC.Collect();
|
||||
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
|
||||
}
|
||||
|
||||
private void InitializeEventListeners()
|
||||
{
|
||||
if (!string.IsNullOrEmpty(_launchContext.ShowEventName))
|
||||
{
|
||||
try
|
||||
{
|
||||
_showEvent = EventWaitHandle.OpenExisting(_launchContext.ShowEventName!);
|
||||
EnsureListenerInfrastructure();
|
||||
StartShowListenerThread();
|
||||
}
|
||||
catch (WaitHandleCannotBeOpenedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(_launchContext.ExitEventName))
|
||||
{
|
||||
try
|
||||
{
|
||||
_exitEvent = EventWaitHandle.OpenExisting(_launchContext.ExitEventName!);
|
||||
EnsureListenerInfrastructure();
|
||||
StartExitListenerThread();
|
||||
}
|
||||
catch (WaitHandleCannotBeOpenedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowWindow()
|
||||
{
|
||||
CancelMemoryTrim();
|
||||
|
||||
if (_hwnd != IntPtr.Zero)
|
||||
{
|
||||
UncloakWindow();
|
||||
|
||||
ShowWindowNative(_hwnd, SwShow);
|
||||
|
||||
var flags = SwpNoSize | SwpShowWindow;
|
||||
var targetX = 0;
|
||||
var targetY = 0;
|
||||
|
||||
var windowSize = _appWindow?.Size;
|
||||
var windowWidth = windowSize?.Width ?? DefaultWidth;
|
||||
var windowHeight = windowSize?.Height ?? DefaultHeight;
|
||||
|
||||
GetCursorPos(out var cursorPosition);
|
||||
var monitorHandle = MonitorFromPointNative(cursorPosition, MonitorDefaulttonearest);
|
||||
if (monitorHandle != IntPtr.Zero)
|
||||
{
|
||||
var monitorInfo = new MonitorInfo { CbSize = Marshal.SizeOf<MonitorInfo>() };
|
||||
if (GetMonitorInfoNative(monitorHandle, ref monitorInfo))
|
||||
{
|
||||
targetX = monitorInfo.RcWork.Right - windowWidth;
|
||||
targetY = monitorInfo.RcWork.Bottom - windowHeight;
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowPosNative(_hwnd, HwndTopmost, targetX, targetY, 0, 0, flags);
|
||||
WindowHelpers.BringToForeground(_hwnd);
|
||||
}
|
||||
|
||||
_hasSeenInteractiveActivation = true;
|
||||
_initialActivationHandled = true;
|
||||
Activate();
|
||||
_isVisible = true;
|
||||
EnsureGlobalMouseHook();
|
||||
ShellHost.RefreshIfAppsList();
|
||||
}
|
||||
|
||||
private void OnActivated(object sender, WindowActivatedEventArgs args)
|
||||
{
|
||||
if (args.WindowActivationState == WindowActivationState.Deactivated)
|
||||
{
|
||||
if (!_hasSeenInteractiveActivation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HideWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
_hasSeenInteractiveActivation = true;
|
||||
|
||||
if (_initialActivationHandled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_initialActivationHandled = true;
|
||||
PrimeWindow();
|
||||
HideWindow();
|
||||
}
|
||||
|
||||
private void OnClosed(object sender, WindowEventArgs e)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
private void PrimeWindow()
|
||||
{
|
||||
if (_isPrimed || _hwnd == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_isPrimed = true;
|
||||
|
||||
if (_appWindow != null)
|
||||
{
|
||||
var currentPosition = _appWindow.Position;
|
||||
_appWindow.MoveAndResize(new RectInt32(currentPosition.X, currentPosition.Y, DefaultWidth, DefaultHeight));
|
||||
}
|
||||
|
||||
// Warm up the window while cloaked so the first summon does not pay XAML initialization cost.
|
||||
var cloaked = CloakWindow();
|
||||
if (cloaked)
|
||||
{
|
||||
ShowWindowNative(_hwnd, SwShowNoActivate);
|
||||
}
|
||||
}
|
||||
|
||||
private void HideFromTaskbar()
|
||||
{
|
||||
if (_appWindow == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_appWindow.IsShownInSwitchers = false;
|
||||
}
|
||||
|
||||
private bool CloakWindow()
|
||||
{
|
||||
if (_hwnd == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_isWindowCloaked)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int cloak = 1;
|
||||
var result = DwmSetWindowAttribute(_hwnd, DwmWaCloak, ref cloak, sizeof(int));
|
||||
if (result == 0)
|
||||
{
|
||||
_isWindowCloaked = true;
|
||||
SetWindowPosNative(_hwnd, HwndBottom, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpNoActivate);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void UncloakWindow()
|
||||
{
|
||||
if (_hwnd == IntPtr.Zero || !_isWindowCloaked)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int cloak = 0;
|
||||
var result = DwmSetWindowAttribute(_hwnd, DwmWaCloak, ref cloak, sizeof(int));
|
||||
if (result == 0)
|
||||
{
|
||||
_isWindowCloaked = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
StopEventListeners();
|
||||
|
||||
_showEvent?.Dispose();
|
||||
_showEvent = null;
|
||||
|
||||
_exitEvent?.Dispose();
|
||||
_exitEvent = null;
|
||||
|
||||
if (_hwnd != IntPtr.Zero && IsWindow(_hwnd))
|
||||
{
|
||||
UncloakWindow();
|
||||
}
|
||||
|
||||
RemoveGlobalMouseHook();
|
||||
|
||||
_coordinator.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
private static extern bool IsWindow(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "ShowWindow", SetLastError = true)]
|
||||
private static extern bool ShowWindowNative(IntPtr hWnd, int nCmdShow);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowLongPtr", SetLastError = true)]
|
||||
private static extern nint GetWindowLongPtrNative(IntPtr hWnd, int nIndex);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
|
||||
private static extern nint SetWindowLongPtrNative(IntPtr hWnd, int nIndex, nint dwNewLong);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowPos", SetLastError = true)]
|
||||
private static extern bool SetWindowPosNative(IntPtr hWnd, IntPtr hWndInsertAfter, int x, int y, int cx, int cy, uint uFlags);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetForegroundWindow", SetLastError = true)]
|
||||
private static extern bool SetForegroundWindowNative(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetForegroundWindow", SetLastError = true)]
|
||||
private static extern IntPtr GetForegroundWindowNative();
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId", SetLastError = true)]
|
||||
private static extern uint GetWindowThreadProcessIdNative(IntPtr hWnd, IntPtr lpdwProcessId);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "AttachThreadInput", SetLastError = true)]
|
||||
private static extern bool AttachThreadInputNative(uint idAttach, uint idAttachTo, bool fAttach);
|
||||
|
||||
[DllImport("dwmapi.dll", EntryPoint = "DwmSetWindowAttribute", SetLastError = true)]
|
||||
private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "MonitorFromPoint", SetLastError = true)]
|
||||
private static extern IntPtr MonitorFromPointNative(NativePoint pt, uint dwFlags);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetMonitorInfoW", SetLastError = true)]
|
||||
private static extern bool GetMonitorInfoNative(IntPtr hMonitor, ref MonitorInfo lpmi);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "SetWindowsHookExW", SetLastError = true)]
|
||||
private static extern IntPtr SetWindowsHookExNative(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "UnhookWindowsHookEx", SetLastError = true)]
|
||||
private static extern bool UnhookWindowsHookExNative(IntPtr hhk);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "CallNextHookEx", SetLastError = true)]
|
||||
private static extern IntPtr CallNextHookExNative(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "GetModuleHandleW", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
private static extern IntPtr GetModuleHandleNative([MarshalAs(UnmanagedType.LPWStr)] string? lpModuleName);
|
||||
|
||||
[DllImport("user32.dll", EntryPoint = "GetWindowRect", SetLastError = true)]
|
||||
private static extern bool GetWindowRectNative(IntPtr hWnd, out Rect rect);
|
||||
|
||||
private void EnsureGlobalMouseHook()
|
||||
{
|
||||
if (_mouseHook != IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_mouseHookDelegate ??= LowLevelMouseHookCallback;
|
||||
var moduleHandle = GetModuleHandleNative(null);
|
||||
_mouseHook = SetWindowsHookExNative(WhMouseLl, _mouseHookDelegate, moduleHandle, 0);
|
||||
}
|
||||
|
||||
private void RemoveGlobalMouseHook()
|
||||
{
|
||||
if (_mouseHook == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
UnhookWindowsHookExNative(_mouseHook);
|
||||
_mouseHook = IntPtr.Zero;
|
||||
}
|
||||
|
||||
private IntPtr LowLevelMouseHookCallback(int nCode, IntPtr wParam, IntPtr lParam)
|
||||
{
|
||||
if (nCode >= 0 && _isVisible && lParam != IntPtr.Zero && IsMouseButtonDownMessage(wParam))
|
||||
{
|
||||
var data = Marshal.PtrToStructure<LowLevelMouseInput>(lParam);
|
||||
if (!IsPointInsideWindow(data.Point))
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (_isVisible)
|
||||
{
|
||||
HideWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return CallNextHookExNative(_mouseHook, nCode, wParam, lParam);
|
||||
}
|
||||
|
||||
private static bool IsMouseButtonDownMessage(IntPtr wParam)
|
||||
{
|
||||
var message = wParam.ToInt32();
|
||||
return message == WmLbuttondown || message == WmRbuttondown || message == WmMbuttondown || message == WmXbuttondown;
|
||||
}
|
||||
|
||||
private bool IsPointInsideWindow(NativePoint point)
|
||||
{
|
||||
if (_hwnd == IntPtr.Zero)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!GetWindowRectNative(_hwnd, out var rect))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return point.X >= rect.Left && point.X <= rect.Right && point.Y >= rect.Top && point.Y <= rect.Bottom;
|
||||
}
|
||||
|
||||
private void EnsureListenerInfrastructure()
|
||||
{
|
||||
_listenerShutdownEvent ??= new ManualResetEventSlim(false);
|
||||
}
|
||||
|
||||
private void StartShowListenerThread()
|
||||
{
|
||||
if (_showEvent == null || _listenerShutdownEvent == null || _showListenerThread != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_showListenerThread = new Thread(ListenForShowEvents)
|
||||
{
|
||||
IsBackground = true,
|
||||
Name = "QuickAccess-ShowEventListener",
|
||||
};
|
||||
_showListenerThread.Start();
|
||||
}
|
||||
|
||||
private void StartExitListenerThread()
|
||||
{
|
||||
if (_exitEvent == null || _listenerShutdownEvent == null || _exitListenerThread != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_exitListenerThread = new Thread(ListenForExitEvents)
|
||||
{
|
||||
IsBackground = true,
|
||||
Name = "QuickAccess-ExitEventListener",
|
||||
};
|
||||
_exitListenerThread.Start();
|
||||
}
|
||||
|
||||
private void ListenForShowEvents()
|
||||
{
|
||||
if (_showEvent == null || _listenerShutdownEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var handles = new WaitHandle[] { _showEvent, _listenerShutdownEvent.WaitHandle };
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var index = WaitHandle.WaitAny(handles);
|
||||
if (index == 0)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(ShowWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
catch (ThreadInterruptedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void ListenForExitEvents()
|
||||
{
|
||||
if (_exitEvent == null || _listenerShutdownEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var handles = new WaitHandle[] { _exitEvent, _listenerShutdownEvent.WaitHandle };
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var index = WaitHandle.WaitAny(handles);
|
||||
if (index == 0)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(Close);
|
||||
break;
|
||||
}
|
||||
|
||||
if (index == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
catch (ThreadInterruptedException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void StopEventListeners()
|
||||
{
|
||||
if (_listenerShutdownEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_listenerShutdownEvent.Set();
|
||||
|
||||
JoinListenerThread(ref _showListenerThread);
|
||||
JoinListenerThread(ref _exitListenerThread);
|
||||
|
||||
_listenerShutdownEvent.Dispose();
|
||||
_listenerShutdownEvent = null;
|
||||
}
|
||||
|
||||
private static void JoinListenerThread(ref Thread? thread)
|
||||
{
|
||||
if (thread == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (!thread.Join(TimeSpan.FromMilliseconds(250)))
|
||||
{
|
||||
thread.Interrupt();
|
||||
thread.Join(TimeSpan.FromMilliseconds(250));
|
||||
}
|
||||
}
|
||||
catch (ThreadInterruptedException)
|
||||
{
|
||||
}
|
||||
catch (ThreadStateException)
|
||||
{
|
||||
}
|
||||
|
||||
thread = null;
|
||||
}
|
||||
|
||||
private void CustomizeWindowChrome()
|
||||
{
|
||||
if (_hwnd == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var windowAttributesChanged = false;
|
||||
|
||||
var stylePtr = GetWindowLongPtrNative(_hwnd, GwlStyle);
|
||||
var styleError = Marshal.GetLastWin32Error();
|
||||
if (!(stylePtr == nint.Zero && styleError != 0))
|
||||
{
|
||||
var styleValue = (long)stylePtr;
|
||||
var newStyleValue = styleValue & ~(WsSysmenu | WsMinimizeBox | WsMaximizeBox);
|
||||
|
||||
if (newStyleValue != styleValue)
|
||||
{
|
||||
SetWindowLongPtrNative(_hwnd, GwlStyle, (nint)newStyleValue);
|
||||
windowAttributesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
var exStylePtr = GetWindowLongPtrNative(_hwnd, GwlExStyle);
|
||||
var exStyleError = Marshal.GetLastWin32Error();
|
||||
if (!(exStylePtr == nint.Zero && exStyleError != 0))
|
||||
{
|
||||
var exStyleValue = (long)exStylePtr;
|
||||
var newExStyleValue = exStyleValue | WsExToolWindow;
|
||||
if (newExStyleValue != exStyleValue)
|
||||
{
|
||||
SetWindowLongPtrNative(_hwnd, GwlExStyle, (nint)newExStyleValue);
|
||||
windowAttributesChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (windowAttributesChanged)
|
||||
{
|
||||
// Apply the new chrome immediately so caption buttons disappear right away and the tool-window flag takes effect.
|
||||
SetWindowPosNative(_hwnd, IntPtr.Zero, 0, 0, 0, 0, SwpNoMove | SwpNoSize | SwpNoZorder | SwpNoActivate | SwpFrameChanged);
|
||||
}
|
||||
}
|
||||
|
||||
private const int WhMouseLl = 14;
|
||||
private const int WmLbuttondown = 0x0201;
|
||||
private const int WmRbuttondown = 0x0204;
|
||||
private const int WmMbuttondown = 0x0207;
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetCursorPos(out NativePoint lpPoint);
|
||||
|
||||
[DllImport("kernel32.dll")]
|
||||
private static extern bool SetProcessWorkingSetSize(IntPtr hProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
|
||||
|
||||
private const int WmXbuttondown = 0x020B;
|
||||
|
||||
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
|
||||
|
||||
private struct Rect
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct LowLevelMouseInput
|
||||
{
|
||||
public NativePoint Point;
|
||||
public int MouseData;
|
||||
public int Flags;
|
||||
public int Time;
|
||||
public IntPtr DwExtraInfo;
|
||||
}
|
||||
|
||||
private struct NativePoint
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct MonitorInfo
|
||||
{
|
||||
public int CbSize;
|
||||
public Rect RcMonitor;
|
||||
public Rect RcWork;
|
||||
public uint DwFlags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// 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.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Services;
|
||||
|
||||
public interface IQuickAccessCoordinator
|
||||
{
|
||||
bool IsRunnerElevated { get; }
|
||||
|
||||
void HideFlyout();
|
||||
|
||||
void OpenSettings();
|
||||
|
||||
void OpenGeneralSettingsForUpdates();
|
||||
|
||||
Task<bool> ShowDocumentationAsync();
|
||||
|
||||
void NotifyUserSettingsInteraction();
|
||||
|
||||
bool UpdateModuleEnabled(ModuleType moduleType, bool isEnabled);
|
||||
|
||||
void ReportBug();
|
||||
|
||||
void OnModuleLaunched(ModuleType moduleType);
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
// 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.Threading.Tasks;
|
||||
using Common.UI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.QuickAccess.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Services;
|
||||
|
||||
internal sealed class QuickAccessCoordinator : IQuickAccessCoordinator, IDisposable
|
||||
{
|
||||
private readonly MainWindow _window;
|
||||
private readonly QuickAccessLaunchContext _launchContext;
|
||||
private readonly SettingsUtils _settingsUtils = SettingsUtils.Default;
|
||||
private readonly object _generalSettingsLock = new();
|
||||
private readonly object _ipcLock = new();
|
||||
private TwoWayPipeMessageIPCManaged? _ipcManager;
|
||||
private bool _ipcUnavailableLogged;
|
||||
|
||||
public QuickAccessCoordinator(MainWindow window, QuickAccessLaunchContext launchContext)
|
||||
{
|
||||
_window = window;
|
||||
_launchContext = launchContext;
|
||||
InitializeIpc();
|
||||
}
|
||||
|
||||
public bool IsRunnerElevated => false; // TODO: wire up real elevation state.
|
||||
|
||||
public void HideFlyout()
|
||||
{
|
||||
_window.RequestHide();
|
||||
}
|
||||
|
||||
public void OpenSettings()
|
||||
{
|
||||
Common.UI.SettingsDeepLink.OpenSettings(Common.UI.SettingsDeepLink.SettingsWindow.Dashboard);
|
||||
_window.RequestHide();
|
||||
}
|
||||
|
||||
public void OpenGeneralSettingsForUpdates()
|
||||
{
|
||||
Common.UI.SettingsDeepLink.OpenSettings(Common.UI.SettingsDeepLink.SettingsWindow.Overview);
|
||||
_window.RequestHide();
|
||||
}
|
||||
|
||||
public Task<bool> ShowDocumentationAsync()
|
||||
{
|
||||
Logger.LogInfo("QuickAccessCoordinator.ShowDocumentationAsync is not yet connected.");
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
public void NotifyUserSettingsInteraction()
|
||||
{
|
||||
Logger.LogDebug("QuickAccessCoordinator.NotifyUserSettingsInteraction invoked.");
|
||||
}
|
||||
|
||||
public bool UpdateModuleEnabled(ModuleType moduleType, bool isEnabled)
|
||||
{
|
||||
GeneralSettings? updatedSettings = null;
|
||||
lock (_generalSettingsLock)
|
||||
{
|
||||
var repository = SettingsRepository<GeneralSettings>.GetInstance(_settingsUtils);
|
||||
var generalSettings = repository.SettingsConfig;
|
||||
var current = ModuleHelper.GetIsModuleEnabled(generalSettings, moduleType);
|
||||
if (current == isEnabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ModuleHelper.SetIsModuleEnabled(generalSettings, moduleType, isEnabled);
|
||||
_settingsUtils.SaveSettings(generalSettings.ToJsonString());
|
||||
Logger.LogInfo($"QuickAccess updated module '{moduleType}' enabled state to {isEnabled}.");
|
||||
updatedSettings = generalSettings;
|
||||
}
|
||||
|
||||
if (updatedSettings != null)
|
||||
{
|
||||
SendGeneralSettingsUpdate(updatedSettings);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ReportBug()
|
||||
{
|
||||
if (!TrySendIpcMessage("{\"bugreport\": 0 }", "bug report request"))
|
||||
{
|
||||
Logger.LogWarning("QuickAccessCoordinator: failed to dispatch bug report request; IPC unavailable.");
|
||||
}
|
||||
}
|
||||
|
||||
public void OnModuleLaunched(ModuleType moduleType)
|
||||
{
|
||||
Logger.LogInfo($"QuickAccessLauncher invoked module {moduleType}.");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeIpc();
|
||||
}
|
||||
|
||||
private void InitializeIpc()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_launchContext.RunnerPipeName) || string.IsNullOrEmpty(_launchContext.AppPipeName))
|
||||
{
|
||||
Logger.LogWarning("QuickAccessCoordinator: IPC pipe names not provided. Runner will not receive updates.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_ipcManager = new TwoWayPipeMessageIPCManaged(_launchContext.AppPipeName, _launchContext.RunnerPipeName, OnIpcMessageReceived);
|
||||
_ipcManager.Start();
|
||||
_ipcUnavailableLogged = false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("QuickAccessCoordinator: failed to start IPC channel to runner.", ex);
|
||||
DisposeIpc();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnIpcMessageReceived(string message)
|
||||
{
|
||||
Logger.LogDebug($"QuickAccessCoordinator received IPC payload: {message}");
|
||||
}
|
||||
|
||||
private void SendGeneralSettingsUpdate(GeneralSettings updatedSettings)
|
||||
{
|
||||
string payload;
|
||||
try
|
||||
{
|
||||
payload = new OutGoingGeneralSettings(updatedSettings).ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError("QuickAccessCoordinator: failed to serialize general settings payload.", ex);
|
||||
return;
|
||||
}
|
||||
|
||||
TrySendIpcMessage(payload, "general settings update");
|
||||
}
|
||||
|
||||
private bool TrySendIpcMessage(string payload, string operationDescription)
|
||||
{
|
||||
lock (_ipcLock)
|
||||
{
|
||||
if (_ipcManager == null)
|
||||
{
|
||||
if (!_ipcUnavailableLogged)
|
||||
{
|
||||
_ipcUnavailableLogged = true;
|
||||
Logger.LogWarning($"QuickAccessCoordinator: unable to send {operationDescription} because IPC is not available.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_ipcManager.Send(payload);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"QuickAccessCoordinator: failed to send {operationDescription}.", ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeIpc()
|
||||
{
|
||||
lock (_ipcLock)
|
||||
{
|
||||
if (_ipcManager == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_ipcManager.End();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogWarning($"QuickAccessCoordinator: exception while shutting down IPC. {ex.Message}");
|
||||
}
|
||||
|
||||
_ipcManager.Dispose();
|
||||
_ipcManager = null;
|
||||
_ipcUnavailableLogged = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// 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.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Controls;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.Services
|
||||
{
|
||||
public class QuickAccessLauncher : Microsoft.PowerToys.Settings.UI.Controls.QuickAccessLauncher
|
||||
{
|
||||
private readonly IQuickAccessCoordinator? _coordinator;
|
||||
|
||||
public QuickAccessLauncher(IQuickAccessCoordinator? coordinator)
|
||||
: base(coordinator?.IsRunnerElevated ?? false)
|
||||
{
|
||||
_coordinator = coordinator;
|
||||
}
|
||||
|
||||
public override bool Launch(ModuleType moduleType)
|
||||
{
|
||||
bool moduleRun = base.Launch(moduleType);
|
||||
|
||||
if (moduleRun)
|
||||
{
|
||||
_coordinator?.OnModuleLaunched(moduleType);
|
||||
}
|
||||
|
||||
_coordinator?.HideFlyout();
|
||||
|
||||
return moduleRun;
|
||||
}
|
||||
}
|
||||
}
|
||||
172
src/settings-ui/QuickAccess.UI/ViewModels/AllAppsViewModel.cs
Normal file
172
src/settings-ui/QuickAccess.UI/ViewModels/AllAppsViewModel.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.QuickAccess.Helpers;
|
||||
using Microsoft.PowerToys.QuickAccess.Services;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.ViewModels.Commands;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
|
||||
public sealed class AllAppsViewModel : Observable
|
||||
{
|
||||
private readonly IQuickAccessCoordinator _coordinator;
|
||||
private readonly ISettingsRepository<GeneralSettings> _settingsRepository;
|
||||
private readonly SettingsUtils _settingsUtils;
|
||||
private readonly ResourceLoader _resourceLoader;
|
||||
private readonly DispatcherQueue _dispatcherQueue;
|
||||
private GeneralSettings _generalSettings;
|
||||
|
||||
public ObservableCollection<FlyoutMenuItem> FlyoutMenuItems { get; }
|
||||
|
||||
public DashboardSortOrder DashboardSortOrder
|
||||
{
|
||||
get => _generalSettings.DashboardSortOrder;
|
||||
set
|
||||
{
|
||||
if (_generalSettings.DashboardSortOrder != value)
|
||||
{
|
||||
_generalSettings.DashboardSortOrder = value;
|
||||
_settingsUtils.SaveSettings(_generalSettings.ToJsonString(), _generalSettings.GetModuleName());
|
||||
OnPropertyChanged();
|
||||
RefreshFlyoutMenuItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AllAppsViewModel(IQuickAccessCoordinator coordinator)
|
||||
{
|
||||
_coordinator = coordinator;
|
||||
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
_settingsUtils = SettingsUtils.Default;
|
||||
_settingsRepository = SettingsRepository<GeneralSettings>.GetInstance(_settingsUtils);
|
||||
_generalSettings = _settingsRepository.SettingsConfig;
|
||||
_generalSettings.AddEnabledModuleChangeNotification(ModuleEnabledChangedOnSettingsPage);
|
||||
_settingsRepository.SettingsChanged += OnSettingsChanged;
|
||||
|
||||
_resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
|
||||
FlyoutMenuItems = new ObservableCollection<FlyoutMenuItem>();
|
||||
|
||||
RefreshFlyoutMenuItems();
|
||||
}
|
||||
|
||||
private void OnSettingsChanged(GeneralSettings newSettings)
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
_generalSettings = newSettings;
|
||||
_generalSettings.AddEnabledModuleChangeNotification(ModuleEnabledChangedOnSettingsPage);
|
||||
OnPropertyChanged(nameof(DashboardSortOrder));
|
||||
RefreshFlyoutMenuItems();
|
||||
});
|
||||
}
|
||||
|
||||
public void RefreshSettings()
|
||||
{
|
||||
if (_settingsRepository.ReloadSettings())
|
||||
{
|
||||
OnSettingsChanged(_settingsRepository.SettingsConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshFlyoutMenuItems()
|
||||
{
|
||||
var desiredItems = new List<FlyoutMenuItem>();
|
||||
|
||||
foreach (ModuleType moduleType in Enum.GetValues<ModuleType>())
|
||||
{
|
||||
if (moduleType == ModuleType.GeneralSettings)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var gpo = Helpers.ModuleGpoHelper.GetModuleGpoConfiguration(moduleType);
|
||||
var isLocked = gpo is GpoRuleConfigured.Enabled or GpoRuleConfigured.Disabled;
|
||||
var isEnabled = gpo == GpoRuleConfigured.Enabled || (!isLocked && Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetIsModuleEnabled(_generalSettings, moduleType));
|
||||
|
||||
var existingItem = FlyoutMenuItems.FirstOrDefault(x => x.Tag == moduleType);
|
||||
|
||||
if (existingItem != null)
|
||||
{
|
||||
existingItem.Label = _resourceLoader.GetString(Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleLabelResourceName(moduleType));
|
||||
existingItem.IsLocked = isLocked;
|
||||
existingItem.Icon = Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleTypeFluentIconName(moduleType);
|
||||
|
||||
if (existingItem.IsEnabled != isEnabled)
|
||||
{
|
||||
var callback = existingItem.EnabledChangedCallback;
|
||||
existingItem.EnabledChangedCallback = null;
|
||||
existingItem.IsEnabled = isEnabled;
|
||||
existingItem.EnabledChangedCallback = callback;
|
||||
}
|
||||
|
||||
desiredItems.Add(existingItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
desiredItems.Add(new FlyoutMenuItem
|
||||
{
|
||||
Label = _resourceLoader.GetString(Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleLabelResourceName(moduleType)),
|
||||
IsEnabled = isEnabled,
|
||||
IsLocked = isLocked,
|
||||
Tag = moduleType,
|
||||
Icon = Microsoft.PowerToys.Settings.UI.Library.Helpers.ModuleHelper.GetModuleTypeFluentIconName(moduleType),
|
||||
EnabledChangedCallback = EnabledChangedOnUI,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var sortedItems = DashboardSortOrder switch
|
||||
{
|
||||
DashboardSortOrder.ByStatus => desiredItems.OrderByDescending(x => x.IsEnabled).ThenBy(x => x.Label).ToList(),
|
||||
_ => desiredItems.OrderBy(x => x.Label).ToList(),
|
||||
};
|
||||
|
||||
for (int i = FlyoutMenuItems.Count - 1; i >= 0; i--)
|
||||
{
|
||||
if (!sortedItems.Contains(FlyoutMenuItems[i]))
|
||||
{
|
||||
FlyoutMenuItems.RemoveAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < sortedItems.Count; i++)
|
||||
{
|
||||
var item = sortedItems[i];
|
||||
var oldIndex = FlyoutMenuItems.IndexOf(item);
|
||||
|
||||
if (oldIndex < 0)
|
||||
{
|
||||
FlyoutMenuItems.Insert(i, item);
|
||||
}
|
||||
else if (oldIndex != i)
|
||||
{
|
||||
FlyoutMenuItems.Move(oldIndex, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnabledChangedOnUI(FlyoutMenuItem item)
|
||||
{
|
||||
if (_coordinator.UpdateModuleEnabled(item.Tag, item.IsEnabled))
|
||||
{
|
||||
_coordinator.NotifyUserSettingsInteraction();
|
||||
}
|
||||
}
|
||||
|
||||
private void ModuleEnabledChangedOnSettingsPage()
|
||||
{
|
||||
RefreshFlyoutMenuItems();
|
||||
}
|
||||
}
|
||||
52
src/settings-ui/QuickAccess.UI/ViewModels/FlyoutMenuItem.cs
Normal file
52
src/settings-ui/QuickAccess.UI/ViewModels/FlyoutMenuItem.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
// 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.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
|
||||
public sealed class FlyoutMenuItem : ModuleListItem
|
||||
{
|
||||
private bool _visible;
|
||||
|
||||
public string ToolTip { get; set; } = string.Empty;
|
||||
|
||||
public new ModuleType Tag
|
||||
{
|
||||
get => (ModuleType)(base.Tag ?? ModuleType.PowerLauncher);
|
||||
set => base.Tag = value;
|
||||
}
|
||||
|
||||
public override bool IsEnabled
|
||||
{
|
||||
get => base.IsEnabled;
|
||||
set
|
||||
{
|
||||
if (base.IsEnabled != value)
|
||||
{
|
||||
base.IsEnabled = value;
|
||||
EnabledChangedCallback?.Invoke(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Action<FlyoutMenuItem>? EnabledChangedCallback { get; set; }
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get => _visible;
|
||||
set
|
||||
{
|
||||
if (_visible != value)
|
||||
{
|
||||
_visible = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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.Collections.ObjectModel;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.QuickAccess.Services;
|
||||
using Microsoft.PowerToys.Settings.UI.Controls;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.Windows.ApplicationModel.Resources;
|
||||
|
||||
namespace Microsoft.PowerToys.QuickAccess.ViewModels;
|
||||
|
||||
public sealed class LauncherViewModel : Observable
|
||||
{
|
||||
private readonly IQuickAccessCoordinator _coordinator;
|
||||
private readonly ISettingsRepository<GeneralSettings> _settingsRepository;
|
||||
private readonly ResourceLoader _resourceLoader;
|
||||
private readonly DispatcherQueue _dispatcherQueue;
|
||||
private readonly QuickAccessViewModel _quickAccessViewModel;
|
||||
|
||||
public ObservableCollection<QuickAccessItem> FlyoutMenuItems => _quickAccessViewModel.Items;
|
||||
|
||||
public bool IsUpdateAvailable { get; private set; }
|
||||
|
||||
public LauncherViewModel(IQuickAccessCoordinator coordinator)
|
||||
{
|
||||
_coordinator = coordinator;
|
||||
_dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
var settingsUtils = SettingsUtils.Default;
|
||||
_settingsRepository = SettingsRepository<GeneralSettings>.GetInstance(settingsUtils);
|
||||
|
||||
_resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
|
||||
|
||||
_quickAccessViewModel = new QuickAccessViewModel(
|
||||
_settingsRepository,
|
||||
new Microsoft.PowerToys.QuickAccess.Services.QuickAccessLauncher(_coordinator),
|
||||
moduleType => Helpers.ModuleGpoHelper.GetModuleGpoConfiguration(moduleType) == GpoRuleConfigured.Disabled,
|
||||
_resourceLoader);
|
||||
var updatingSettings = UpdatingSettings.LoadSettings() ?? new UpdatingSettings();
|
||||
IsUpdateAvailable = updatingSettings.State is UpdatingSettings.UpdatingState.ReadyToInstall or UpdatingSettings.UpdatingState.ReadyToDownload;
|
||||
}
|
||||
}
|
||||
16
src/settings-ui/QuickAccess.UI/app.manifest
Normal file
16
src/settings-ui/QuickAccess.UI/app.manifest
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="PowerToys.QuickAccess.app" />
|
||||
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||
<application>
|
||||
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
|
||||
</application>
|
||||
</compatibility>
|
||||
</assembly>
|
||||
@@ -1,11 +1,11 @@
|
||||
// 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.
|
||||
|
||||
using System;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Converters
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls.Converters
|
||||
{
|
||||
public partial class EnumToBooleanConverter : IValueConverter
|
||||
{
|
||||
@@ -20,7 +20,7 @@ namespace Microsoft.PowerToys.Settings.UI.Converters
|
||||
var enumString = value.ToString();
|
||||
var parameterString = parameter.ToString();
|
||||
|
||||
return enumString.Equals(parameterString, StringComparison.OrdinalIgnoreCase);
|
||||
return enumString!.Equals(parameterString, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
@@ -0,0 +1,38 @@
|
||||
// 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 Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls.Converters
|
||||
{
|
||||
public partial class ModuleListSortOptionToBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is ModuleListSortOption sortOption && parameter is string paramString)
|
||||
{
|
||||
if (Enum.TryParse(typeof(ModuleListSortOption), paramString, out object? result) && result != null)
|
||||
{
|
||||
return sortOption == (ModuleListSortOption)result;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is bool isChecked && isChecked && parameter is string paramString)
|
||||
{
|
||||
if (Enum.TryParse(typeof(ModuleListSortOption), paramString, out object? result) && result != null)
|
||||
{
|
||||
return (ModuleListSortOption)result;
|
||||
}
|
||||
}
|
||||
|
||||
return ModuleListSortOption.Alphabetical;
|
||||
}
|
||||
}
|
||||
}
|
||||
107
src/settings-ui/Settings.UI.Controls/ModuleList/ModuleList.xaml
Normal file
107
src/settings-ui/Settings.UI.Controls/ModuleList/ModuleList.xaml
Normal file
@@ -0,0 +1,107 @@
|
||||
<UserControl
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Controls.ModuleList"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Controls.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:tk="using:CommunityToolkit.WinUI"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<UserControl.Resources>
|
||||
<converters:ModuleListSortOptionToBooleanConverter x:Key="ModuleListSortOptionToBooleanConverter" />
|
||||
<x:Double x:Key="SettingsCardWrapThreshold">0</x:Double>
|
||||
<tkconverters:BoolToVisibilityConverter
|
||||
x:Key="BoolToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
TrueValue="Visible" />
|
||||
<tkconverters:BoolToVisibilityConverter
|
||||
x:Key="ReverseBoolToVisibilityConverter"
|
||||
FalseValue="Visible"
|
||||
TrueValue="Collapsed" />
|
||||
<tkconverters:BoolNegationConverter x:Key="BoolNegationConverter" />
|
||||
|
||||
<Style x:Key="NewInfoBadgeStyle" TargetType="InfoBadge">
|
||||
<Setter Property="Padding" Value="5,1,5,2" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="InfoBadge">
|
||||
<Border
|
||||
x:Name="RootGrid"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.InfoBadgeCornerRadius}">
|
||||
<TextBlock
|
||||
x:Uid="NewInfoBadge"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
FontSize="10" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
<ItemsRepeater x:Name="DashboardView" ItemsSource="{x:Bind ItemsSource, Mode=OneWay}">
|
||||
<ItemsRepeater.Layout>
|
||||
<StackLayout Orientation="Vertical" Spacing="0" />
|
||||
</ItemsRepeater.Layout>
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate x:DataType="controls:ModuleListItem">
|
||||
<tkcontrols:SettingsCard
|
||||
MinWidth="0"
|
||||
MinHeight="0"
|
||||
Padding="12,4,12,4"
|
||||
tk:FrameworkElementExtensions.AncestorType="controls:ModuleList"
|
||||
Background="Transparent"
|
||||
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||
BorderThickness="{Binding (tk:FrameworkElementExtensions.Ancestor).DividerThickness, RelativeSource={RelativeSource Self}}"
|
||||
Click="OnSettingsCardClick"
|
||||
CornerRadius="0"
|
||||
IsClickEnabled="{Binding (tk:FrameworkElementExtensions.Ancestor).IsItemClickable, RelativeSource={RelativeSource Self}}"
|
||||
Tag="{x:Bind}">
|
||||
<tkcontrols:SettingsCard.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{x:Bind Label, Mode=OneWay}" />
|
||||
<!-- InfoBadge -->
|
||||
<InfoBadge
|
||||
x:Name="NewInfoBadge"
|
||||
Margin="4,0,0,0"
|
||||
Style="{StaticResource NewInfoBadgeStyle}"
|
||||
Visibility="{x:Bind IsNew, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<FontIcon
|
||||
Width="20"
|
||||
Margin="4,0,0,0"
|
||||
FontSize="16"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind IsLocked, Converter={StaticResource ReverseBoolToVisibilityConverter}, ConverterParameter=True}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="GPOWarning" TextWrapping="WrapWholeWords" />
|
||||
</ToolTipService.ToolTip>
|
||||
</FontIcon>
|
||||
</StackPanel>
|
||||
</tkcontrols:SettingsCard.Header>
|
||||
|
||||
<tkcontrols:SettingsCard.HeaderIcon>
|
||||
<ImageIcon>
|
||||
<ImageIcon.Source>
|
||||
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
|
||||
</ImageIcon.Source>
|
||||
</ImageIcon>
|
||||
</tkcontrols:SettingsCard.HeaderIcon>
|
||||
|
||||
<ToggleSwitch
|
||||
HorizontalAlignment="Right"
|
||||
AutomationProperties.Name="{x:Bind Label, Mode=OneWay}"
|
||||
IsEnabled="{x:Bind IsLocked, Converter={StaticResource BoolNegationConverter}, ConverterParameter=True, Mode=OneWay}"
|
||||
IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
|
||||
OffContent=""
|
||||
OnContent="" />
|
||||
</tkcontrols:SettingsCard>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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 Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public sealed partial class ModuleList : UserControl
|
||||
{
|
||||
public ModuleList()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
public Thickness DividerThickness
|
||||
{
|
||||
get => (Thickness)GetValue(DividerThicknessProperty);
|
||||
set => SetValue(DividerThicknessProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DividerThicknessProperty = DependencyProperty.Register(nameof(DividerThickness), typeof(Thickness), typeof(ModuleList), new PropertyMetadata(new Thickness(0, 1, 0, 0)));
|
||||
|
||||
public bool IsItemClickable
|
||||
{
|
||||
get => (bool)GetValue(IsItemClickableProperty);
|
||||
set => SetValue(IsItemClickableProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsItemClickableProperty = DependencyProperty.Register(nameof(IsItemClickable), typeof(bool), typeof(ModuleList), new PropertyMetadata(true));
|
||||
|
||||
public object ItemsSource
|
||||
{
|
||||
get => (object)GetValue(ItemsSourceProperty);
|
||||
set => SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(ModuleList), new PropertyMetadata(null));
|
||||
|
||||
public ModuleListSortOption SortOption
|
||||
{
|
||||
get => (ModuleListSortOption)GetValue(SortOptionProperty);
|
||||
set => SetValue(SortOptionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SortOptionProperty = DependencyProperty.Register(nameof(SortOption), typeof(ModuleListSortOption), typeof(ModuleList), new PropertyMetadata(ModuleListSortOption.Alphabetical));
|
||||
|
||||
private void OnSettingsCardClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is FrameworkElement element && element.Tag is ModuleListItem item)
|
||||
{
|
||||
item.ClickCommand?.Execute(item.Tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
// 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.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public class ModuleListItem : INotifyPropertyChanged
|
||||
{
|
||||
private bool _isEnabled;
|
||||
private string _label = string.Empty;
|
||||
private string _icon = string.Empty;
|
||||
private bool _isNew;
|
||||
private bool _isLocked;
|
||||
private object? _tag;
|
||||
private ICommand? _clickCommand;
|
||||
|
||||
public virtual string Label
|
||||
{
|
||||
get => _label;
|
||||
set
|
||||
{
|
||||
if (_label != value)
|
||||
{
|
||||
_label = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual string Icon
|
||||
{
|
||||
get => _icon;
|
||||
set
|
||||
{
|
||||
if (_icon != value)
|
||||
{
|
||||
_icon = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsNew
|
||||
{
|
||||
get => _isNew;
|
||||
set
|
||||
{
|
||||
if (_isNew != value)
|
||||
{
|
||||
_isNew = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsLocked
|
||||
{
|
||||
get => _isLocked;
|
||||
set
|
||||
{
|
||||
if (_isLocked != value)
|
||||
{
|
||||
_isLocked = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
set
|
||||
{
|
||||
if (_isEnabled != value)
|
||||
{
|
||||
_isEnabled = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual object? Tag
|
||||
{
|
||||
get => _tag;
|
||||
set
|
||||
{
|
||||
if (_tag != value)
|
||||
{
|
||||
_tag = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual ICommand? ClickCommand
|
||||
{
|
||||
get => _clickCommand;
|
||||
set
|
||||
{
|
||||
if (_clickCommand != value)
|
||||
{
|
||||
_clickCommand = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// 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.
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public enum ModuleListSortOption
|
||||
{
|
||||
Alphabetical,
|
||||
ByStatus,
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,11 @@
|
||||
BorderThickness="{x:Bind BorderThickness, Mode=OneWay}"
|
||||
CornerRadius="{x:Bind CornerRadius, Mode=OneWay}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" MinHeight="44" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid x:Name="TitleGrid">
|
||||
<Grid x:Name="TitleGrid" MinHeight="44">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
@@ -11,9 +11,9 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public static readonly DependencyProperty TitleContentProperty = DependencyProperty.Register(nameof(TitleContent), typeof(object), typeof(Card), new PropertyMetadata(defaultValue: null, OnVisualPropertyChanged));
|
||||
|
||||
public object TitleContent
|
||||
public object? TitleContent
|
||||
{
|
||||
get => (object)GetValue(TitleContentProperty);
|
||||
get => (object?)GetValue(TitleContentProperty);
|
||||
set => SetValue(TitleContentProperty, value);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DividerVisibilityProperty = DependencyProperty.Register(nameof(DividerVisibility), typeof(Visibility), typeof(Card), new PropertyMetadata(defaultValue: null));
|
||||
public static readonly DependencyProperty DividerVisibilityProperty = DependencyProperty.Register(nameof(DividerVisibility), typeof(Visibility), typeof(Card), new PropertyMetadata(defaultValue: Visibility.Visible));
|
||||
|
||||
public Visibility DividerVisibility
|
||||
{
|
||||
@@ -66,7 +66,6 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
else
|
||||
{
|
||||
VisualStateManager.GoToState(this, "TitleGridVisible", true);
|
||||
DividerVisibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// 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 ManagedCommon;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public interface IQuickAccessLauncher
|
||||
{
|
||||
bool Launch(ModuleType moduleType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// 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.Windows.Input;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.UI.Xaml;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public sealed class QuickAccessItem : Observable
|
||||
{
|
||||
private string _title = string.Empty;
|
||||
|
||||
public string Title
|
||||
{
|
||||
get => _title;
|
||||
set => Set(ref _title, value);
|
||||
}
|
||||
|
||||
private string _description = string.Empty;
|
||||
|
||||
public string Description
|
||||
{
|
||||
get => _description;
|
||||
set => Set(ref _description, value);
|
||||
}
|
||||
|
||||
private string _icon = string.Empty;
|
||||
|
||||
public string Icon
|
||||
{
|
||||
get => _icon;
|
||||
set => Set(ref _icon, value);
|
||||
}
|
||||
|
||||
private ICommand? _command;
|
||||
|
||||
public ICommand? Command
|
||||
{
|
||||
get => _command;
|
||||
set => Set(ref _command, value);
|
||||
}
|
||||
|
||||
private object? _commandParameter;
|
||||
|
||||
public object? CommandParameter
|
||||
{
|
||||
get => _commandParameter;
|
||||
set => Set(ref _commandParameter, value);
|
||||
}
|
||||
|
||||
private bool _visible = true;
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get => _visible;
|
||||
set => Set(ref _visible, value);
|
||||
}
|
||||
|
||||
private object? _tag;
|
||||
|
||||
public object? Tag
|
||||
{
|
||||
get => _tag;
|
||||
set => Set(ref _tag, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
// 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.Threading;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using PowerToys.Interop;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public class QuickAccessLauncher : IQuickAccessLauncher
|
||||
{
|
||||
private readonly bool _isElevated;
|
||||
|
||||
public QuickAccessLauncher(bool isElevated)
|
||||
{
|
||||
_isElevated = isElevated;
|
||||
}
|
||||
|
||||
public virtual bool Launch(ModuleType moduleType)
|
||||
{
|
||||
switch (moduleType)
|
||||
{
|
||||
case ModuleType.ColorPicker:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.EnvironmentVariables:
|
||||
{
|
||||
bool launchAdmin = SettingsRepository<EnvironmentVariablesSettings>.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.LaunchAdministrator;
|
||||
string eventName = !_isElevated && launchAdmin
|
||||
? Constants.ShowEnvironmentVariablesAdminSharedEvent()
|
||||
: Constants.ShowEnvironmentVariablesSharedEvent();
|
||||
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.FancyZones:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.FZEToggleEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.Hosts:
|
||||
{
|
||||
bool launchAdmin = SettingsRepository<HostsSettings>.GetInstance(SettingsUtils.Default).SettingsConfig.Properties.LaunchAdministrator;
|
||||
string eventName = !_isElevated && launchAdmin
|
||||
? Constants.ShowHostsAdminSharedEvent()
|
||||
: Constants.ShowHostsSharedEvent();
|
||||
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.PowerLauncher:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerLauncherSharedEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.PowerOCR:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.RegistryPreview:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.RegistryPreviewTriggerEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.MeasureTool:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.MeasureToolTriggerEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.ShortcutGuide:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShortcutGuideTriggerEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.CmdPal:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowCmdPalEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
case ModuleType.Workspaces:
|
||||
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.WorkspacesLaunchEditorEvent()))
|
||||
{
|
||||
eventHandle.Set();
|
||||
}
|
||||
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<UserControl
|
||||
x:Class="Microsoft.PowerToys.Settings.UI.Controls.QuickAccessList"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters">
|
||||
|
||||
<UserControl.Resources>
|
||||
<tkconverters:BoolToVisibilityConverter
|
||||
x:Key="BoolToVisibilityConverter"
|
||||
FalseValue="Collapsed"
|
||||
TrueValue="Visible" />
|
||||
<tkconverters:StringVisibilityConverter x:Key="StringVisibilityConverter" />
|
||||
</UserControl.Resources>
|
||||
|
||||
<ItemsControl ItemsSource="{x:Bind ItemsSource, Mode=OneWay}">
|
||||
<ItemsControl.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<tkcontrols:WrapPanel HorizontalAlignment="Stretch" VerticalSpacing="12" />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="local:QuickAccessItem">
|
||||
<local:FlyoutMenuButton
|
||||
AutomationProperties.Name="{x:Bind Title}"
|
||||
Command="{x:Bind Command}"
|
||||
CommandParameter="{x:Bind CommandParameter}"
|
||||
Visibility="{x:Bind Visible, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<local:FlyoutMenuButton.Content>
|
||||
<TextBlock
|
||||
Style="{StaticResource CaptionTextBlockStyle}"
|
||||
Text="{x:Bind Title}"
|
||||
TextAlignment="Center"
|
||||
TextWrapping="Wrap" />
|
||||
</local:FlyoutMenuButton.Content>
|
||||
<local:FlyoutMenuButton.Icon>
|
||||
<Image>
|
||||
<Image.Source>
|
||||
<BitmapImage UriSource="{x:Bind Icon}" />
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</local:FlyoutMenuButton.Icon>
|
||||
<ToolTipService.ToolTip>
|
||||
<ToolTip Content="{x:Bind Description}" Visibility="{x:Bind Description, Converter={StaticResource StringVisibilityConverter}}" />
|
||||
</ToolTipService.ToolTip>
|
||||
</local:FlyoutMenuButton>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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.Collections.Generic;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Controls
|
||||
{
|
||||
public sealed partial class QuickAccessList : UserControl
|
||||
{
|
||||
public QuickAccessList()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
public object ItemsSource
|
||||
{
|
||||
get => (object)GetValue(ItemsSourceProperty);
|
||||
set => SetValue(ItemsSourceProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(QuickAccessList), new PropertyMetadata(null));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user