mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-20 18:20:27 +01:00
Compare commits
8 Commits
async-cpp-
...
v0.94.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51aeaafb30 | ||
|
|
baaa4d8f88 | ||
|
|
931204abad | ||
|
|
aaded11741 | ||
|
|
e1117ca181 | ||
|
|
04963aceae | ||
|
|
d6fc550f3e | ||
|
|
4d294f5d83 |
1
.github/actions/spell-check/expect.txt
vendored
1
.github/actions/spell-check/expect.txt
vendored
@@ -49,6 +49,7 @@ ALPHATYPE
|
|||||||
AModifier
|
AModifier
|
||||||
amr
|
amr
|
||||||
ANDSCANS
|
ANDSCANS
|
||||||
|
animatedvisuals
|
||||||
Animnate
|
Animnate
|
||||||
ANull
|
ANull
|
||||||
AOC
|
AOC
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
||||||
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
|
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.Markdown" Version="7.1.2" />
|
||||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250703-build.2173" />
|
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.250703-build.2173" />
|
||||||
<PackageVersion Include="CommunityToolkit.Labs.WinUI.TitleBar" Version="0.0.1-build.2206" />
|
|
||||||
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
||||||
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
||||||
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
|
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
|
||||||
|
|||||||
@@ -1499,7 +1499,6 @@ SOFTWARE.
|
|||||||
- CoenM.ImageSharp.ImageHash
|
- CoenM.ImageSharp.ImageHash
|
||||||
- CommunityToolkit.Common
|
- CommunityToolkit.Common
|
||||||
- CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock
|
- CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock
|
||||||
- CommunityToolkit.Labs.WinUI.TitleBar
|
|
||||||
- CommunityToolkit.Mvvm
|
- CommunityToolkit.Mvvm
|
||||||
- CommunityToolkit.WinUI.Animations
|
- CommunityToolkit.WinUI.Animations
|
||||||
- CommunityToolkit.WinUI.Collections
|
- CommunityToolkit.WinUI.Collections
|
||||||
|
|||||||
@@ -19,6 +19,26 @@
|
|||||||
|
|
||||||
class FileLocksmithModule : public PowertoyModuleIface
|
class FileLocksmithModule : public PowertoyModuleIface
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
// Update registration based on enabled state
|
||||||
|
void UpdateRegistration(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
FileLocksmithRuntimeRegistration::EnsureRegistered();
|
||||||
|
Logger::info(L"File Locksmith context menu registered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
FileLocksmithRuntimeRegistration::Unregister();
|
||||||
|
Logger::info(L"File Locksmith context menu unregistered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileLocksmithModule()
|
FileLocksmithModule()
|
||||||
{
|
{
|
||||||
@@ -88,21 +108,16 @@ public:
|
|||||||
package::RegisterSparsePackage(path, packageUri);
|
package::RegisterSparsePackage(path, packageUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
|
||||||
FileLocksmithRuntimeRegistration::EnsureRegistered();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
m_enabled = true;
|
m_enabled = true;
|
||||||
|
UpdateRegistration(m_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void disable() override
|
virtual void disable() override
|
||||||
{
|
{
|
||||||
Logger::info(L"File Locksmith disabled");
|
Logger::info(L"File Locksmith disabled");
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
|
||||||
FileLocksmithRuntimeRegistration::Unregister();
|
|
||||||
Logger::info(L"File Locksmith context menu unregistered (Win10)");
|
|
||||||
#endif
|
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
|
UpdateRegistration(m_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool is_enabled() override
|
virtual bool is_enabled() override
|
||||||
@@ -135,6 +150,7 @@ private:
|
|||||||
{
|
{
|
||||||
m_enabled = FileLocksmithSettingsInstance().GetEnabled();
|
m_enabled = FileLocksmithSettingsInstance().GetEnabled();
|
||||||
m_extended_only = FileLocksmithSettingsInstance().GetShowInExtendedContextMenu();
|
m_extended_only = FileLocksmithSettingsInstance().GetShowInExtendedContextMenu();
|
||||||
|
UpdateRegistration(m_enabled);
|
||||||
Trace::EnableFileLocksmith(m_enabled);
|
Trace::EnableFileLocksmith(m_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,26 @@
|
|||||||
// Note: Settings are managed via Settings and UI Settings
|
// Note: Settings are managed via Settings and UI Settings
|
||||||
class NewModule : public PowertoyModuleIface
|
class NewModule : public PowertoyModuleIface
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
// Update registration based on enabled state
|
||||||
|
void UpdateRegistration(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
NewPlusRuntimeRegistration::EnsureRegisteredWin10();
|
||||||
|
Logger::info(L"New+ context menu registered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
NewPlusRuntimeRegistration::Unregister();
|
||||||
|
Logger::info(L"New+ context menu unregistered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NewModule()
|
NewModule()
|
||||||
{
|
{
|
||||||
@@ -98,14 +118,9 @@ public:
|
|||||||
{
|
{
|
||||||
newplus::utilities::register_msix_package();
|
newplus::utilities::register_msix_package();
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
|
||||||
NewPlusRuntimeRegistration::EnsureRegisteredWin10();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
powertoy_new_enabled = true;
|
powertoy_new_enabled = true;
|
||||||
|
UpdateRegistration(powertoy_new_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void disable() override
|
virtual void disable() override
|
||||||
@@ -150,19 +165,14 @@ private:
|
|||||||
{
|
{
|
||||||
Trace::EventToggleOnOff(false);
|
Trace::EventToggleOnOff(false);
|
||||||
}
|
}
|
||||||
if (!package::IsWin11OrGreater())
|
|
||||||
{
|
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
|
||||||
NewPlusRuntimeRegistration::Unregister();
|
|
||||||
Logger::info(L"New+ context menu unregistered (Win10)");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
powertoy_new_enabled = false;
|
powertoy_new_enabled = false;
|
||||||
|
UpdateRegistration(powertoy_new_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_settings()
|
void init_settings()
|
||||||
{
|
{
|
||||||
powertoy_new_enabled = NewSettingsInstance().GetEnabled();
|
powertoy_new_enabled = NewSettingsInstance().GetEnabled();
|
||||||
|
UpdateRegistration(powertoy_new_enabled);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
<XesUseOneStoreVersioning>true</XesUseOneStoreVersioning>
|
||||||
<XesBaseYearForStoreVersion>2025</XesBaseYearForStoreVersion>
|
<XesBaseYearForStoreVersion>2025</XesBaseYearForStoreVersion>
|
||||||
<VersionMajor>0</VersionMajor>
|
<VersionMajor>0</VersionMajor>
|
||||||
<VersionMinor>4</VersionMinor>
|
<VersionMinor>5</VersionMinor>
|
||||||
<VersionInfoProductName>Microsoft Command Palette</VersionInfoProductName>
|
<VersionInfoProductName>Microsoft Command Palette</VersionInfoProductName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -79,16 +79,22 @@ public sealed partial class TimeDateCalculator
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
List<(int Score, AvailableResult Item)> itemScores = [];
|
||||||
|
|
||||||
// Generate filtered list of results
|
// Generate filtered list of results
|
||||||
foreach (var f in availableFormats)
|
foreach (var f in availableFormats)
|
||||||
{
|
{
|
||||||
var score = f.Score(query, f.Label, f.AlternativeSearchTag);
|
var score = f.Score(query, f.Label, f.AlternativeSearchTag);
|
||||||
|
|
||||||
if (score > 0)
|
if (score > 0)
|
||||||
{
|
{
|
||||||
results.Add(f.ToListItem());
|
itemScores.Add((score, f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
results = itemScores
|
||||||
|
.OrderByDescending(s => s.Score)
|
||||||
|
.Select(s => s.Item.ToListItem())
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (results.Count == 0)
|
if (results.Count == 0)
|
||||||
|
|||||||
@@ -43,11 +43,32 @@ private:
|
|||||||
//contains the non localized key of the powertoy
|
//contains the non localized key of the powertoy
|
||||||
std::wstring app_key;
|
std::wstring app_key;
|
||||||
|
|
||||||
|
// Update registration based on enabled state
|
||||||
|
void UpdateRegistration(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
ImageResizerRuntimeRegistration::EnsureRegistered();
|
||||||
|
Logger::info(L"ImageResizer context menu registered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
ImageResizerRuntimeRegistration::Unregister();
|
||||||
|
Logger::info(L"ImageResizer context menu unregistered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
ImageResizerModule()
|
ImageResizerModule()
|
||||||
{
|
{
|
||||||
m_enabled = CSettingsInstance().GetEnabled();
|
m_enabled = CSettingsInstance().GetEnabled();
|
||||||
|
UpdateRegistration(m_enabled);
|
||||||
app_name = GET_RESOURCE_STRING(IDS_IMAGERESIZER);
|
app_name = GET_RESOURCE_STRING(IDS_IMAGERESIZER);
|
||||||
app_key = ImageResizerConstants::ModuleKey;
|
app_key = ImageResizerConstants::ModuleKey;
|
||||||
LoggerHelpers::init_logger(app_key, L"ModuleInterface", LogSettings::imageResizerLoggerName);
|
LoggerHelpers::init_logger(app_key, L"ModuleInterface", LogSettings::imageResizerLoggerName);
|
||||||
@@ -112,10 +133,7 @@ public:
|
|||||||
package::RegisterSparsePackage(path, packageUri);
|
package::RegisterSparsePackage(path, packageUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
UpdateRegistration(m_enabled);
|
||||||
ImageResizerRuntimeRegistration::EnsureRegistered();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Trace::EnableImageResizer(m_enabled);
|
Trace::EnableImageResizer(m_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,11 +141,8 @@ public:
|
|||||||
virtual void disable()
|
virtual void disable()
|
||||||
{
|
{
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
|
UpdateRegistration(m_enabled);
|
||||||
Trace::EnableImageResizer(m_enabled);
|
Trace::EnableImageResizer(m_enabled);
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
|
||||||
ImageResizerRuntimeRegistration::Unregister();
|
|
||||||
Logger::info(L"ImageResizer context menu unregistered (Win10)");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns if the powertoys is enabled
|
// Returns if the powertoys is enabled
|
||||||
|
|||||||
@@ -168,6 +168,25 @@ private:
|
|||||||
//contains the non localized key of the powertoy
|
//contains the non localized key of the powertoy
|
||||||
std::wstring app_key;
|
std::wstring app_key;
|
||||||
|
|
||||||
|
// Update registration based on enabled state
|
||||||
|
void UpdateRegistration(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
PowerRenameRuntimeRegistration::EnsureRegistered();
|
||||||
|
Logger::info(L"PowerRename context menu registered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
||||||
|
PowerRenameRuntimeRegistration::Unregister();
|
||||||
|
Logger::info(L"PowerRename context menu unregistered");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Return the localized display name of the powertoy
|
// Return the localized display name of the powertoy
|
||||||
virtual PCWSTR get_name() override
|
virtual PCWSTR get_name() override
|
||||||
@@ -202,9 +221,7 @@ public:
|
|||||||
package::RegisterSparsePackage(path, packageUri);
|
package::RegisterSparsePackage(path, packageUri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
UpdateRegistration(m_enabled);
|
||||||
PowerRenameRuntimeRegistration::EnsureRegistered();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable the powertoy
|
// Disable the powertoy
|
||||||
@@ -212,10 +229,7 @@ public:
|
|||||||
{
|
{
|
||||||
m_enabled = false;
|
m_enabled = false;
|
||||||
Logger::info(L"PowerRename disabled");
|
Logger::info(L"PowerRename disabled");
|
||||||
#if defined(ENABLE_REGISTRATION) || defined(NDEBUG)
|
UpdateRegistration(m_enabled);
|
||||||
PowerRenameRuntimeRegistration::Unregister();
|
|
||||||
Logger::info(L"PowerRename context menu unregistered (Win10)");
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns if the powertoy is enabled
|
// Returns if the powertoy is enabled
|
||||||
@@ -315,6 +329,7 @@ public:
|
|||||||
void init_settings()
|
void init_settings()
|
||||||
{
|
{
|
||||||
m_enabled = CSettingsInstance().GetEnabled();
|
m_enabled = CSettingsInstance().GetEnabled();
|
||||||
|
UpdateRegistration(m_enabled);
|
||||||
Trace::EnablePowerRename(m_enabled);
|
Trace::EnablePowerRename(m_enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,13 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
|
|||||||
"ShellPage.xaml",
|
"ShellPage.xaml",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Hardcoded panel-to-page mapping (temporary until generic panel host mapping is needed)
|
||||||
|
// Key: panel file base name (without .xaml), Value: owning page base name
|
||||||
|
private static readonly Dictionary<string, string> PanelPageMapping = new(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
{ "MouseJumpPanel", "MouseUtilsPage" },
|
||||||
|
};
|
||||||
|
|
||||||
private static JsonSerializerOptions serializeOption = new()
|
private static JsonSerializerOptions serializeOption = new()
|
||||||
{
|
{
|
||||||
WriteIndented = true,
|
WriteIndented = true,
|
||||||
@@ -33,32 +40,117 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
|
|||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
string xamlDirectory = args[0];
|
string xamlRootDirectory = args[0];
|
||||||
string outputFile = args[1];
|
string outputFile = args[1];
|
||||||
|
|
||||||
if (!Directory.Exists(xamlDirectory))
|
if (!Directory.Exists(xamlRootDirectory))
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"Error: Directory '{xamlDirectory}' does not exist.");
|
Debug.WriteLine($"Error: Directory '{xamlRootDirectory}' does not exist.");
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var searchableElements = new List<SettingEntry>();
|
var searchableElements = new List<SettingEntry>();
|
||||||
var xamlFiles = Directory.GetFiles(xamlDirectory, "*.xaml", SearchOption.AllDirectories);
|
var processedFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
foreach (var xamlFile in xamlFiles)
|
void ScanDirectory(string root)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileName(xamlFile);
|
if (!Directory.Exists(root))
|
||||||
if (ExcludedXamlFiles.Contains(fileName))
|
|
||||||
{
|
{
|
||||||
// Skip ShellPage.xaml as it contains many elements not relevant for search
|
return;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Debug.WriteLine($"Processing: {fileName}");
|
Debug.WriteLine($"[XamlIndexBuilder] Scanning root: {root}");
|
||||||
var elements = ExtractSearchableElements(xamlFile);
|
var xamlFilesLocal = Directory.GetFiles(root, "*.xaml", SearchOption.AllDirectories);
|
||||||
searchableElements.AddRange(elements);
|
foreach (var xamlFile in xamlFilesLocal)
|
||||||
|
{
|
||||||
|
var fullPath = Path.GetFullPath(xamlFile);
|
||||||
|
if (processedFiles.Contains(fullPath))
|
||||||
|
{
|
||||||
|
continue; // already handled (can happen if overlapping directories)
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileName = Path.GetFileName(xamlFile);
|
||||||
|
if (ExcludedXamlFiles.Contains(fileName))
|
||||||
|
{
|
||||||
|
continue; // explicitly excluded
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine($"Processing: {fileName}");
|
||||||
|
var elements = ExtractSearchableElements(xamlFile);
|
||||||
|
|
||||||
|
// Apply hardcoded panel mapping override
|
||||||
|
var baseName = Path.GetFileNameWithoutExtension(xamlFile);
|
||||||
|
if (PanelPageMapping.TryGetValue(baseName, out var hostPage))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < elements.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = elements[i];
|
||||||
|
entry.PageTypeName = hostPage;
|
||||||
|
elements[i] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchableElements.AddRange(elements);
|
||||||
|
processedFiles.Add(fullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scan well-known subdirectories under the provided root
|
||||||
|
var subDirs = new[] { "Views", "Panels" };
|
||||||
|
foreach (var sub in subDirs)
|
||||||
|
{
|
||||||
|
ScanDirectory(Path.Combine(xamlRootDirectory, sub));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: also scan root directly (in case some XAML lives at root level)
|
||||||
|
ScanDirectory(xamlRootDirectory);
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Explicit include section: add specific XAML files that we always want indexed
|
||||||
|
// even if future logic excludes them or they live outside typical scan patterns.
|
||||||
|
// Add future files to the ExplicitExtraXamlFiles array below.
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
string[] explicitExtraXamlFiles = new[]
|
||||||
|
{
|
||||||
|
"MouseJumpPanel.xaml", // Mouse Jump settings panel
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var extraFileName in explicitExtraXamlFiles)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var matches = Directory.GetFiles(xamlRootDirectory, extraFileName, SearchOption.AllDirectories);
|
||||||
|
foreach (var match in matches)
|
||||||
|
{
|
||||||
|
var full = Path.GetFullPath(match);
|
||||||
|
if (processedFiles.Contains(full))
|
||||||
|
{
|
||||||
|
continue; // already processed in general scan
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug.WriteLine($"Processing (explicit include): {extraFileName}");
|
||||||
|
var elements = ExtractSearchableElements(full);
|
||||||
|
var baseName = Path.GetFileNameWithoutExtension(full);
|
||||||
|
if (PanelPageMapping.TryGetValue(baseName, out var hostPage))
|
||||||
|
{
|
||||||
|
for (int i = 0; i < elements.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = elements[i];
|
||||||
|
entry.PageTypeName = hostPage;
|
||||||
|
elements[i] = entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
searchableElements.AddRange(elements);
|
||||||
|
processedFiles.Add(full);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine($"Explicit include failed for {extraFileName}: {ex.Message}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
searchableElements = searchableElements.OrderBy(e => e.PageTypeName).ThenBy(e => e.ElementName).ToList();
|
searchableElements = searchableElements.OrderBy(e => e.PageTypeName).ThenBy(e => e.ElementName).ToList();
|
||||||
@@ -97,15 +189,15 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
|
|||||||
.Where(e => e.Name.LocalName == "SettingsPageControl")
|
.Where(e => e.Name.LocalName == "SettingsPageControl")
|
||||||
.Where(e => e.Attribute(x + "Uid") != null);
|
.Where(e => e.Attribute(x + "Uid") != null);
|
||||||
|
|
||||||
// Extract SettingsCard elements
|
// Extract SettingsCard elements (support both Name and x:Name)
|
||||||
var settingsElements = doc.Descendants()
|
var settingsElements = doc.Descendants()
|
||||||
.Where(e => e.Name.LocalName == "SettingsCard")
|
.Where(e => e.Name.LocalName == "SettingsCard")
|
||||||
.Where(e => e.Attribute("Name") != null || e.Attribute(x + "Uid") != null);
|
.Where(e => e.Attribute("Name") != null || e.Attribute(x + "Name") != null || e.Attribute(x + "Uid") != null);
|
||||||
|
|
||||||
// Extract SettingsExpander elements
|
// Extract SettingsExpander elements (support both Name and x:Name)
|
||||||
var settingsExpanderElements = doc.Descendants()
|
var settingsExpanderElements = doc.Descendants()
|
||||||
.Where(e => e.Name.LocalName == "SettingsExpander")
|
.Where(e => e.Name.LocalName == "SettingsExpander")
|
||||||
.Where(e => e.Attribute("Name") != null || e.Attribute(x + "Uid") != null);
|
.Where(e => e.Attribute("Name") != null || e.Attribute(x + "Name") != null || e.Attribute(x + "Uid") != null);
|
||||||
|
|
||||||
// Process SettingsPageControl elements
|
// Process SettingsPageControl elements
|
||||||
foreach (var element in settingsPageElements)
|
foreach (var element in settingsPageElements)
|
||||||
@@ -185,16 +277,36 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
|
|||||||
|
|
||||||
public static string GetElementName(XElement element, XNamespace x)
|
public static string GetElementName(XElement element, XNamespace x)
|
||||||
{
|
{
|
||||||
// Get Name attribute (we call it ElementName in our indexing system)
|
|
||||||
var name = element.Attribute("Name")?.Value;
|
var name = element.Attribute("Name")?.Value;
|
||||||
|
if (string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
name = element.Attribute(x + "Name")?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetElementUid(XElement element, XNamespace x)
|
public static string GetElementUid(XElement element, XNamespace x)
|
||||||
{
|
{
|
||||||
// Try x:Uid
|
// Try x:Uid on the element itself
|
||||||
var uid = element.Attribute(x + "Uid")?.Value;
|
var uid = element.Attribute(x + "Uid")?.Value;
|
||||||
return uid;
|
if (!string.IsNullOrWhiteSpace(uid))
|
||||||
|
{
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: check the first direct child element's x:Uid
|
||||||
|
var firstChild = element.Elements().FirstOrDefault();
|
||||||
|
if (firstChild != null)
|
||||||
|
{
|
||||||
|
var childUid = firstChild.Attribute(x + "Uid")?.Value;
|
||||||
|
if (!string.IsNullOrWhiteSpace(childUid))
|
||||||
|
{
|
||||||
|
return childUid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string GetParentElementName(XElement element, XNamespace x)
|
public static string GetParentElementName(XElement element, XNamespace x)
|
||||||
@@ -211,6 +323,11 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
|
|||||||
if (expanderParent?.Name.LocalName == "SettingsExpander")
|
if (expanderParent?.Name.LocalName == "SettingsExpander")
|
||||||
{
|
{
|
||||||
var expanderName = expanderParent.Attribute("Name")?.Value;
|
var expanderName = expanderParent.Attribute("Name")?.Value;
|
||||||
|
if (string.IsNullOrEmpty(expanderName))
|
||||||
|
{
|
||||||
|
expanderName = expanderParent.Attribute(x + "Name")?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(expanderName))
|
if (!string.IsNullOrEmpty(expanderName))
|
||||||
{
|
{
|
||||||
return expanderName;
|
return expanderName;
|
||||||
@@ -221,6 +338,11 @@ namespace Microsoft.PowerToys.Tools.XamlIndexBuilder
|
|||||||
{
|
{
|
||||||
// Direct child of SettingsExpander
|
// Direct child of SettingsExpander
|
||||||
var expanderName = current.Attribute("Name")?.Value;
|
var expanderName = current.Attribute("Name")?.Value;
|
||||||
|
if (string.IsNullOrEmpty(expanderName))
|
||||||
|
{
|
||||||
|
expanderName = current.Attribute(x + "Name")?.Value;
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(expanderName))
|
if (!string.IsNullOrEmpty(expanderName))
|
||||||
{
|
{
|
||||||
return expanderName;
|
return expanderName;
|
||||||
|
|||||||
@@ -29,16 +29,15 @@
|
|||||||
<!-- Remove UI library reference to avoid pulling WindowsDesktop runtime (WindowsBase) -->
|
<!-- Remove UI library reference to avoid pulling WindowsDesktop runtime (WindowsBase) -->
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Fallback to dotnet if not provided by the environment -->
|
|
||||||
<DotNetExe Condition="'$(DotNetExe)' == ''">dotnet</DotNetExe>
|
<DotNetExe Condition="'$(DotNetExe)' == ''">dotnet</DotNetExe>
|
||||||
<XamlViewsDir Condition="'$(XamlViewsDir)' == ''">$(MSBuildProjectDirectory)\..\Settings.UI\SettingsXAML\Views</XamlViewsDir>
|
<XamlRootDir Condition="'$(XamlRootDir)' == ''">$(MSBuildProjectDirectory)\..\Settings.UI\SettingsXAML</XamlRootDir>
|
||||||
|
<XamlRootDir Condition="'$(XamlViewsDir)' != ''">$([System.IO.Path]::GetDirectoryName('$(XamlViewsDir)'))</XamlRootDir>
|
||||||
<GeneratedJsonFile Condition="'$(GeneratedJsonFile)' == ''">$(MSBuildProjectDirectory)\..\Settings.UI\Assets\Settings\search.index.json</GeneratedJsonFile>
|
<GeneratedJsonFile Condition="'$(GeneratedJsonFile)' == ''">$(MSBuildProjectDirectory)\..\Settings.UI\Assets\Settings\search.index.json</GeneratedJsonFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<Target Name="GenerateSearchIndexSelf" AfterTargets="Build">
|
<Target Name="GenerateSearchIndexSelf" AfterTargets="Build">
|
||||||
<RemoveDir Directories="$(MSBuildProjectDirectory)\obj\ARM64;$(MSBuildProjectDirectory)\obj\x64;$(MSBuildProjectDirectory)\bin" />
|
<RemoveDir Directories="$(MSBuildProjectDirectory)\obj\ARM64;$(MSBuildProjectDirectory)\obj\x64;$(MSBuildProjectDirectory)\bin" />
|
||||||
<MakeDir Directories="$([System.IO.Path]::GetDirectoryName('$(GeneratedJsonFile)'))" />
|
<MakeDir Directories="$([System.IO.Path]::GetDirectoryName('$(GeneratedJsonFile)'))" />
|
||||||
<Message Importance="high" Text="[XamlIndexBuilder] Generating search index. Views='$(XamlViewsDir)'; Out='$(GeneratedJsonFile)'; Tool='$(TargetPath)'; DotNet='$(DotNetExe)'." />
|
<Message Importance="high" Text="[XamlIndexBuilder] Generating search index. Root='$(XamlRootDir)'; Out='$(GeneratedJsonFile)'; Tool='$(TargetPath)'; DotNet='$(DotNetExe)'." />
|
||||||
<!-- Execute via dotnet so host architecture doesn't need to match -->
|
<Exec Command=""$(DotNetExe)" "$(TargetPath)" "$(XamlRootDir)" "$(GeneratedJsonFile)"" />
|
||||||
<Exec Command=""$(DotNetExe)" "$(TargetPath)" "$(XamlViewsDir)" "$(GeneratedJsonFile)"" />
|
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ using Microsoft.UI.Xaml;
|
|||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Microsoft.UI.Xaml.Hosting;
|
using Microsoft.UI.Xaml.Hosting;
|
||||||
using Microsoft.UI.Xaml.Media;
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
using Windows.UI;
|
||||||
|
|
||||||
namespace Microsoft.PowerToys.Settings.UI.Helpers;
|
namespace Microsoft.PowerToys.Settings.UI.Helpers;
|
||||||
|
|
||||||
public abstract partial class NavigatablePage : Page
|
public abstract partial class NavigatablePage : Page
|
||||||
{
|
{
|
||||||
private const int ExpandWaitDuration = 500;
|
private const int ExpandWaitDuration = 500;
|
||||||
private const int AnimationDuration = 1000;
|
private const int AnimationDuration = 1850;
|
||||||
|
|
||||||
private NavigationParams _pendingNavigationParams;
|
private NavigationParams _pendingNavigationParams;
|
||||||
|
|
||||||
@@ -79,21 +80,24 @@ public abstract partial class NavigatablePage : Page
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to set keyboard focus so that screen readers announce the element and keyboard users land directly on it.
|
||||||
|
TrySetFocus(target);
|
||||||
|
|
||||||
// Get the visual and compositor
|
// Get the visual and compositor
|
||||||
var visual = ElementCompositionPreview.GetElementVisual(target);
|
var visual = ElementCompositionPreview.GetElementVisual(target);
|
||||||
var compositor = visual.Compositor;
|
var compositor = visual.Compositor;
|
||||||
|
|
||||||
// Create a subtle glow effect using drop shadow
|
// Create a subtle glow effect using drop shadow
|
||||||
var dropShadow = compositor.CreateDropShadow();
|
var dropShadow = compositor.CreateDropShadow();
|
||||||
dropShadow.Color = Microsoft.UI.Colors.Gray;
|
dropShadow.Color = (Color)Application.Current.Resources["SystemAccentColorLight2"];
|
||||||
dropShadow.BlurRadius = 8f;
|
dropShadow.BlurRadius = 16f;
|
||||||
dropShadow.Opacity = 0f;
|
dropShadow.Opacity = 0f;
|
||||||
dropShadow.Offset = new Vector3(0, 0, 0);
|
dropShadow.Offset = new Vector3(0, 0, 0);
|
||||||
|
|
||||||
var spriteVisual = compositor.CreateSpriteVisual();
|
var spriteVisual = compositor.CreateSpriteVisual();
|
||||||
spriteVisual.Size = new Vector2((float)target.ActualWidth + 16, (float)target.ActualHeight + 16);
|
spriteVisual.Size = new Vector2((float)target.ActualWidth + 8, (float)target.ActualHeight + 8);
|
||||||
spriteVisual.Shadow = dropShadow;
|
spriteVisual.Shadow = dropShadow;
|
||||||
spriteVisual.Offset = new Vector3(-8, -8, 0);
|
spriteVisual.Offset = new Vector3(-4, -4, 0);
|
||||||
|
|
||||||
// Insert the shadow visual behind the target element
|
// Insert the shadow visual behind the target element
|
||||||
ElementCompositionPreview.SetElementChildVisual(target, spriteVisual);
|
ElementCompositionPreview.SetElementChildVisual(target, spriteVisual);
|
||||||
@@ -106,39 +110,135 @@ public abstract partial class NavigatablePage : Page
|
|||||||
fadeAnimation.Duration = TimeSpan.FromMilliseconds(AnimationDuration);
|
fadeAnimation.Duration = TimeSpan.FromMilliseconds(AnimationDuration);
|
||||||
|
|
||||||
dropShadow.StartAnimation("Opacity", fadeAnimation);
|
dropShadow.StartAnimation("Opacity", fadeAnimation);
|
||||||
|
await Task.Delay(AnimationDuration);
|
||||||
if (target is Control ctrl)
|
|
||||||
{
|
|
||||||
// TODO: ability to adjust brush color and animation from settings.
|
|
||||||
var originalBackground = ctrl.Background;
|
|
||||||
|
|
||||||
var highlightBrush = new SolidColorBrush();
|
|
||||||
var grayColor = Microsoft.UI.Colors.Gray;
|
|
||||||
grayColor.A = 50; // Very subtle transparency
|
|
||||||
highlightBrush.Color = grayColor;
|
|
||||||
|
|
||||||
// Apply the highlight
|
|
||||||
ctrl.Background = highlightBrush;
|
|
||||||
|
|
||||||
// Wait for animation to complete
|
|
||||||
await Task.Delay(AnimationDuration);
|
|
||||||
|
|
||||||
// Restore original background
|
|
||||||
ctrl.Background = originalBackground;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// For non-control elements, just wait for the glow animation
|
|
||||||
await Task.Delay(AnimationDuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up the shadow visual
|
// Clean up the shadow visual
|
||||||
ElementCompositionPreview.SetElementChildVisual(target, null);
|
ElementCompositionPreview.SetElementChildVisual(target, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void TrySetFocus(FrameworkElement target)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Prefer Control.Focus when available.
|
||||||
|
if (target is Control ctrl)
|
||||||
|
{
|
||||||
|
// Ensure it can receive focus.
|
||||||
|
if (!ctrl.IsTabStop)
|
||||||
|
{
|
||||||
|
ctrl.IsTabStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctrl.Focus(FocusState.Programmatic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Target is not a Control. Find first focusable descendant Control.
|
||||||
|
var focusCandidate = FindFirstFocusableDescendant(target);
|
||||||
|
if (focusCandidate != null)
|
||||||
|
{
|
||||||
|
if (!focusCandidate.IsTabStop)
|
||||||
|
{
|
||||||
|
focusCandidate.IsTabStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
focusCandidate.Focus(FocusState.Programmatic);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback: attempt to focus parent control if no descendant found.
|
||||||
|
if (target.Parent is Control parent)
|
||||||
|
{
|
||||||
|
if (!parent.IsTabStop)
|
||||||
|
{
|
||||||
|
parent.IsTabStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.Focus(FocusState.Programmatic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Swallow focus exceptions; not critical. Could log if logging enabled.
|
||||||
|
// Leave the default focus as it is.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Control FindFirstFocusableDescendant(FrameworkElement root)
|
||||||
|
{
|
||||||
|
if (root == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var queue = new System.Collections.Generic.Queue<DependencyObject>();
|
||||||
|
queue.Enqueue(root);
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
var current = queue.Dequeue();
|
||||||
|
if (current is Control c && c.IsEnabled && c.Visibility == Visibility.Visible)
|
||||||
|
{
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = VisualTreeHelper.GetChildrenCount(current);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
queue.Enqueue(VisualTreeHelper.GetChild(current, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
protected FrameworkElement FindElementByName(string name)
|
protected FrameworkElement FindElementByName(string name)
|
||||||
{
|
{
|
||||||
var element = this.FindName(name) as FrameworkElement;
|
var element = this.FindName(name) as FrameworkElement;
|
||||||
return element;
|
if (element != null)
|
||||||
|
{
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.Content is DependencyObject root)
|
||||||
|
{
|
||||||
|
var found = FindInDescendants(root, name);
|
||||||
|
if (found != null)
|
||||||
|
{
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FrameworkElement FindInDescendants(DependencyObject root, string name)
|
||||||
|
{
|
||||||
|
if (root == null || string.IsNullOrEmpty(name))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var queue = new System.Collections.Generic.Queue<DependencyObject>();
|
||||||
|
queue.Enqueue(root);
|
||||||
|
while (queue.Count > 0)
|
||||||
|
{
|
||||||
|
var current = queue.Dequeue();
|
||||||
|
if (current is FrameworkElement fe)
|
||||||
|
{
|
||||||
|
var local = fe.FindName(name) as FrameworkElement;
|
||||||
|
if (local != null)
|
||||||
|
{
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = VisualTreeHelper.GetChildrenCount(current);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var child = VisualTreeHelper.GetChild(current, i);
|
||||||
|
queue.Enqueue(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
<None Remove="SettingsXAML\Controls\Dashboard\CheckUpdateControl.xaml" />
|
<None Remove="SettingsXAML\Controls\Dashboard\CheckUpdateControl.xaml" />
|
||||||
<None Remove="SettingsXAML\Controls\Dashboard\ShortcutConflictControl.xaml" />
|
<None Remove="SettingsXAML\Controls\Dashboard\ShortcutConflictControl.xaml" />
|
||||||
<None Remove="SettingsXAML\Controls\KeyVisual\KeyCharPresenter.xaml" />
|
<None Remove="SettingsXAML\Controls\KeyVisual\KeyCharPresenter.xaml" />
|
||||||
|
<None Remove="SettingsXAML\Controls\TitleBar\TitleBar.xaml" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Page Remove="SettingsXAML\App.xaml" />
|
<Page Remove="SettingsXAML\App.xaml" />
|
||||||
@@ -63,7 +64,6 @@
|
|||||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
<PackageReference Include="CommunityToolkit.WinUI.Converters" />
|
||||||
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Markdown" />
|
<PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Markdown" />
|
||||||
<PackageReference Include="CommunityToolkit.Labs.WinUI.TitleBar" />
|
|
||||||
<PackageReference Include="System.Net.Http" />
|
<PackageReference Include="System.Net.Http" />
|
||||||
<PackageReference Include="System.Private.Uri" />
|
<PackageReference Include="System.Private.Uri" />
|
||||||
<PackageReference Include="System.Text.RegularExpressions" />
|
<PackageReference Include="System.Text.RegularExpressions" />
|
||||||
@@ -156,7 +156,8 @@
|
|||||||
</None>
|
</None>
|
||||||
<None Update="Assets\Settings\Scripts\DisableModule.ps1">
|
<None Update="Assets\Settings\Scripts\DisableModule.ps1">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</None>
|
</None> <Page Update="SettingsXAML\Controls\TitleBar\TitleBar.xaml">
|
||||||
|
</Page>
|
||||||
<Page Update="SettingsXAML\Controls\KeyVisual\KeyCharPresenter.xaml">
|
<Page Update="SettingsXAML\Controls\KeyVisual\KeyCharPresenter.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
@@ -180,14 +181,8 @@
|
|||||||
</Page>
|
</Page>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!-- Removed nested publish/exec and copy targets. -->
|
|
||||||
|
|
||||||
<!-- Build XamlIndexBuilder before compiling Settings to ensure the search index exists without taking a project reference. -->
|
|
||||||
<Target Name="BuildXamlIndexBeforeSettings" BeforeTargets="CoreCompile">
|
<Target Name="BuildXamlIndexBeforeSettings" BeforeTargets="CoreCompile">
|
||||||
<Message Importance="high" Text="[Settings] Building XamlIndexBuilder prior to compile. Views='$(MSBuildProjectDirectory)\SettingsXAML\Views' Out='$(GeneratedJsonFile)'" />
|
<Message Importance="high" Text="[Settings] Building XamlIndexBuilder prior to compile. Views='$(MSBuildProjectDirectory)\SettingsXAML\Views' Out='$(GeneratedJsonFile)'" />
|
||||||
<MSBuild
|
<MSBuild Projects="..\Settings.UI.XamlIndexBuilder\Settings.UI.XamlIndexBuilder.csproj" Targets="Build" Properties="Configuration=$(Configuration);Platform=Any CPU;TargetFramework=net9.0;XamlViewsDir=$(MSBuildProjectDirectory)\SettingsXAML\Views;GeneratedJsonFile=$(GeneratedJsonFile)" />
|
||||||
Projects="..\Settings.UI.XamlIndexBuilder\Settings.UI.XamlIndexBuilder.csproj"
|
|
||||||
Targets="Build"
|
|
||||||
Properties="Configuration=$(Configuration);Platform=Any CPU;TargetFramework=net9.0;XamlViewsDir=$(MSBuildProjectDirectory)\SettingsXAML\Views;GeneratedJsonFile=$(GeneratedJsonFile)" />
|
|
||||||
</Target>
|
</Target>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -170,7 +170,7 @@ namespace Microsoft.PowerToys.Settings.UI.Services
|
|||||||
|
|
||||||
if (string.IsNullOrEmpty(header))
|
if (string.IsNullOrEmpty(header))
|
||||||
{
|
{
|
||||||
Debug.WriteLine($"[SearchIndexService] WARNING: No header localization found for ElementUid: '{elementUid}'");
|
header = GetString(resourceLoader, $"{elementUid}/Content");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (header, description);
|
return (header, description);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
|
||||||
<ResourceDictionary Source="/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml" />
|
<ResourceDictionary Source="/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml" />
|
||||||
<ResourceDictionary Source="/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml" />
|
<ResourceDictionary Source="/SettingsXAML/Controls/KeyVisual/KeyCharPresenter.xaml" />
|
||||||
|
<ResourceDictionary Source="/SettingsXAML/Controls/TitleBar/TitleBar.xaml" />
|
||||||
<ResourceDictionary Source="/SettingsXAML/Styles/TextBlock.xaml" />
|
<ResourceDictionary Source="/SettingsXAML/Styles/TextBlock.xaml" />
|
||||||
<ResourceDictionary Source="/SettingsXAML/Styles/Button.xaml" />
|
<ResourceDictionary Source="/SettingsXAML/Styles/Button.xaml" />
|
||||||
<ResourceDictionary Source="/SettingsXAML/Styles/InfoBadge.xaml" />
|
<ResourceDictionary Source="/SettingsXAML/Styles/InfoBadge.xaml" />
|
||||||
|
|||||||
@@ -548,18 +548,14 @@ namespace Microsoft.PowerToys.Settings.UI.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (conflictingModules.Count > 0)
|
var moduleNames = conflictingModules.ToArray();
|
||||||
|
if (string.Equals(moduleNames[0], "System", StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var moduleNames = conflictingModules.ToArray();
|
c.ConflictMessage = ResourceLoaderInstance.ResourceLoader.GetString("SysHotkeyConflictTooltipText");
|
||||||
var conflictMessage = moduleNames.Length == 1
|
|
||||||
? $"Conflict detected with {moduleNames[0]}"
|
|
||||||
: $"Conflicts detected with: {string.Join(", ", moduleNames)}";
|
|
||||||
|
|
||||||
c.ConflictMessage = conflictMessage;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
c.ConflictMessage = "Conflict detected with unknown module";
|
c.ConflictMessage = ResourceLoaderInstance.ResourceLoader.GetString("InAppHotkeyConflictTooltipText");
|
||||||
}
|
}
|
||||||
|
|
||||||
c.HasConflict = true;
|
c.HasConflict = true;
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=IsWarningAltGr, Mode=OneWay}"
|
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=IsWarningAltGr, Mode=OneWay}"
|
||||||
Severity="Warning" />
|
Severity="Warning" />
|
||||||
<InfoBar
|
<InfoBar
|
||||||
Title="Hotkey Conflict"
|
x:Uid="WarningShortcutConflict"
|
||||||
IsClosable="False"
|
IsClosable="False"
|
||||||
IsOpen="{Binding ElementName=ShortcutContentControl, Path=HasConflict, Mode=OneWay}"
|
IsOpen="{Binding ElementName=ShortcutContentControl, Path=HasConflict, Mode=OneWay}"
|
||||||
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=HasConflict, Mode=OneWay}"
|
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=HasConflict, Mode=OneWay}"
|
||||||
|
|||||||
@@ -0,0 +1,229 @@
|
|||||||
|
// 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;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Controls;
|
||||||
|
|
||||||
|
public partial class TitleBar : Control
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="Icon"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(nameof(Icon), typeof(IconElement), typeof(TitleBar), new PropertyMetadata(null, IconChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="Title"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(TitleBar), new PropertyMetadata(default(string)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="Subtitle"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty SubtitleProperty = DependencyProperty.Register(nameof(Subtitle), typeof(string), typeof(TitleBar), new PropertyMetadata(default(string)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="Content"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(nameof(Content), typeof(object), typeof(TitleBar), new PropertyMetadata(null, ContentChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="Footer"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(nameof(Footer), typeof(object), typeof(TitleBar), new PropertyMetadata(null, FooterChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="IsBackButtonVisible"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IsBackButtonVisibleProperty = DependencyProperty.Register(nameof(IsBackButtonVisible), typeof(bool), typeof(TitleBar), new PropertyMetadata(false, IsBackButtonVisibleChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="IsPaneButtonVisible"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty IsPaneButtonVisibleProperty = DependencyProperty.Register(nameof(IsPaneButtonVisible), typeof(bool), typeof(TitleBar), new PropertyMetadata(false, IsPaneButtonVisibleChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="DisplayMode"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty DisplayModeProperty = DependencyProperty.Register(nameof(DisplayMode), typeof(DisplayMode), typeof(TitleBar), new PropertyMetadata(DisplayMode.Standard, DisplayModeChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="CompactStateBreakpoint
|
||||||
|
/// "/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty CompactStateBreakpointProperty = DependencyProperty.Register(nameof(CompactStateBreakpoint), typeof(int), typeof(TitleBar), new PropertyMetadata(850));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="AutoConfigureCustomTitleBar"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty AutoConfigureCustomTitleBarProperty = DependencyProperty.Register(nameof(AutoConfigureCustomTitleBar), typeof(bool), typeof(TitleBar), new PropertyMetadata(true, AutoConfigureCustomTitleBarChanged));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The backing <see cref="DependencyProperty"/> for the <see cref="Window"/> property.
|
||||||
|
/// </summary>
|
||||||
|
public static readonly DependencyProperty WindowProperty = DependencyProperty.Register(nameof(Window), typeof(Window), typeof(TitleBar), new PropertyMetadata(null));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The event that gets fired when the back button is clicked
|
||||||
|
/// </summary>
|
||||||
|
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
public event EventHandler<RoutedEventArgs>? BackButtonClick;
|
||||||
|
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The event that gets fired when the pane toggle button is clicked
|
||||||
|
/// </summary>
|
||||||
|
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
public event EventHandler<RoutedEventArgs>? PaneButtonClick;
|
||||||
|
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Icon
|
||||||
|
/// </summary>
|
||||||
|
public IconElement Icon
|
||||||
|
{
|
||||||
|
get => (IconElement)GetValue(IconProperty);
|
||||||
|
set => SetValue(IconProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Title
|
||||||
|
/// </summary>
|
||||||
|
public string Title
|
||||||
|
{
|
||||||
|
get => (string)GetValue(TitleProperty);
|
||||||
|
set => SetValue(TitleProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the Subtitle
|
||||||
|
/// </summary>
|
||||||
|
public string Subtitle
|
||||||
|
{
|
||||||
|
get => (string)GetValue(SubtitleProperty);
|
||||||
|
set => SetValue(SubtitleProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the content shown at the center of the TitleBar. When setting this, using DisplayMode=Tall is recommended.
|
||||||
|
/// </summary>
|
||||||
|
public object Content
|
||||||
|
{
|
||||||
|
get => (object)GetValue(ContentProperty);
|
||||||
|
set => SetValue(ContentProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the content shown at the right of the TitleBar, next to the caption buttons. When setting this, using DisplayMode=Tall is recommended.
|
||||||
|
/// </summary>
|
||||||
|
public object Footer
|
||||||
|
{
|
||||||
|
get => (object)GetValue(FooterProperty);
|
||||||
|
set => SetValue(FooterProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets DisplayMode. Compact is default (32px), Tall is recommended when setting the Content or Footer.
|
||||||
|
/// </summary>
|
||||||
|
public DisplayMode DisplayMode
|
||||||
|
{
|
||||||
|
get => (DisplayMode)GetValue(DisplayModeProperty);
|
||||||
|
set => SetValue(DisplayModeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether gets or sets the visibility of the back button.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsBackButtonVisible
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(IsBackButtonVisibleProperty);
|
||||||
|
set => SetValue(IsBackButtonVisibleProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether gets or sets the visibility of the pane toggle button.
|
||||||
|
/// </summary>
|
||||||
|
public bool IsPaneButtonVisible
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(IsPaneButtonVisibleProperty);
|
||||||
|
set => SetValue(IsPaneButtonVisibleProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the breakpoint of when the compact state is triggered.
|
||||||
|
/// </summary>
|
||||||
|
public int CompactStateBreakpoint
|
||||||
|
{
|
||||||
|
get => (int)GetValue(CompactStateBreakpointProperty);
|
||||||
|
set => SetValue(CompactStateBreakpointProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether gets or sets if the TitleBar should auto configure ExtendContentIntoTitleBar and CaptionButton background colors.
|
||||||
|
/// </summary>
|
||||||
|
public bool AutoConfigureCustomTitleBar
|
||||||
|
{
|
||||||
|
get => (bool)GetValue(AutoConfigureCustomTitleBarProperty);
|
||||||
|
set => SetValue(AutoConfigureCustomTitleBarProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the window the TitleBar should configure.
|
||||||
|
/// </summary>
|
||||||
|
public Window Window
|
||||||
|
{
|
||||||
|
get => (Window)GetValue(WindowProperty);
|
||||||
|
set => SetValue(WindowProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IsBackButtonVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IsPaneButtonVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DisplayModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void FooterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void IconChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AutoConfigureCustomTitleBarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (((TitleBar)d).AutoConfigureCustomTitleBar)
|
||||||
|
{
|
||||||
|
((TitleBar)d).Configure();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((TitleBar)d).Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DisplayMode
|
||||||
|
{
|
||||||
|
Standard,
|
||||||
|
Tall,
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using Microsoft.UI;
|
||||||
|
using Microsoft.UI.Input;
|
||||||
|
using Microsoft.UI.Windowing;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
|
using Microsoft.UI.Xaml.Controls;
|
||||||
|
using Microsoft.UI.Xaml.Media;
|
||||||
|
using Windows.Foundation;
|
||||||
|
using Windows.Graphics;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Controls;
|
||||||
|
|
||||||
|
[TemplatePart(Name = nameof(PART_FooterPresenter), Type = typeof(ContentPresenter))]
|
||||||
|
[TemplatePart(Name = nameof(PART_ContentPresenter), Type = typeof(ContentPresenter))]
|
||||||
|
|
||||||
|
public partial class TitleBar : Control
|
||||||
|
{
|
||||||
|
#pragma warning disable SA1306 // Field names should begin with lower-case letter
|
||||||
|
#pragma warning disable SA1310 // Field names should not contain underscore
|
||||||
|
#pragma warning disable SA1400 // Access modifier should be declared
|
||||||
|
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
ContentPresenter? PART_ContentPresenter;
|
||||||
|
ContentPresenter? PART_FooterPresenter;
|
||||||
|
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
#pragma warning restore SA1400 // Access modifier should be declared
|
||||||
|
#pragma warning restore SA1306 // Field names should begin with lower-case letter
|
||||||
|
#pragma warning restore SA1310 // Field names should not contain underscore
|
||||||
|
|
||||||
|
private void SetWASDKTitleBar()
|
||||||
|
{
|
||||||
|
if (this.Window == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AutoConfigureCustomTitleBar)
|
||||||
|
{
|
||||||
|
Window.AppWindow.TitleBar.ExtendsContentIntoTitleBar = true;
|
||||||
|
|
||||||
|
this.Window.SizeChanged -= Window_SizeChanged;
|
||||||
|
this.Window.SizeChanged += Window_SizeChanged;
|
||||||
|
this.Window.Activated -= Window_Activated;
|
||||||
|
this.Window.Activated += Window_Activated;
|
||||||
|
|
||||||
|
if (Window.Content is FrameworkElement rootElement)
|
||||||
|
{
|
||||||
|
UpdateCaptionButtons(rootElement);
|
||||||
|
rootElement.ActualThemeChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
UpdateCaptionButtons(rootElement);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
PART_ContentPresenter = GetTemplateChild(nameof(PART_ContentPresenter)) as ContentPresenter;
|
||||||
|
PART_FooterPresenter = GetTemplateChild(nameof(PART_FooterPresenter)) as ContentPresenter;
|
||||||
|
|
||||||
|
// Get caption button occlusion information.
|
||||||
|
int captionButtonOcclusionWidthRight = Window.AppWindow.TitleBar.RightInset;
|
||||||
|
int captionButtonOcclusionWidthLeft = Window.AppWindow.TitleBar.LeftInset;
|
||||||
|
PART_LeftPaddingColumn!.Width = new GridLength(captionButtonOcclusionWidthLeft);
|
||||||
|
PART_RightPaddingColumn!.Width = new GridLength(captionButtonOcclusionWidthRight);
|
||||||
|
|
||||||
|
if (DisplayMode == DisplayMode.Tall)
|
||||||
|
{
|
||||||
|
// Choose a tall title bar to provide more room for interactive elements
|
||||||
|
// like search box or person picture controls.
|
||||||
|
Window.AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Tall;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Window.AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Standard;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recalculate the drag region for the custom title bar
|
||||||
|
// if you explicitly defined new draggable areas.
|
||||||
|
SetDragRegionForCustomTitleBar();
|
||||||
|
|
||||||
|
_isAutoConfigCompleted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs args)
|
||||||
|
{
|
||||||
|
UpdateVisualStateAndDragRegion(args.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCaptionButtons(FrameworkElement rootElement)
|
||||||
|
{
|
||||||
|
Window.AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
|
||||||
|
Window.AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
|
||||||
|
if (rootElement.ActualTheme == ElementTheme.Dark)
|
||||||
|
{
|
||||||
|
Window.AppWindow.TitleBar.ButtonForegroundColor = Colors.White;
|
||||||
|
Window.AppWindow.TitleBar.ButtonInactiveForegroundColor = Colors.DarkGray;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Window.AppWindow.TitleBar.ButtonForegroundColor = Colors.Black;
|
||||||
|
Window.AppWindow.TitleBar.ButtonInactiveForegroundColor = Colors.DarkGray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetWASDKTitleBar()
|
||||||
|
{
|
||||||
|
if (this.Window == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only reset if we were the ones who configured
|
||||||
|
if (_isAutoConfigCompleted)
|
||||||
|
{
|
||||||
|
Window.AppWindow.TitleBar.ExtendsContentIntoTitleBar = false;
|
||||||
|
this.Window.SizeChanged -= Window_SizeChanged;
|
||||||
|
this.Window.Activated -= Window_Activated;
|
||||||
|
SizeChanged -= this.TitleBar_SizeChanged;
|
||||||
|
Window.AppWindow.TitleBar.ResetToDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Window_Activated(object sender, WindowActivatedEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.WindowActivationState == WindowActivationState.Deactivated)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, WindowDeactivatedState, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, WindowActivatedState, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDragRegionForCustomTitleBar()
|
||||||
|
{
|
||||||
|
if (AutoConfigureCustomTitleBar && Window is not null)
|
||||||
|
{
|
||||||
|
ClearDragRegions(NonClientRegionKind.Passthrough);
|
||||||
|
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
var items = new FrameworkElement?[] { PART_ContentPresenter, PART_FooterPresenter, PART_ButtonHolder };
|
||||||
|
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
var validItems = items.Where(x => x is not null).Select(x => x!).ToArray(); // Prune null items
|
||||||
|
|
||||||
|
SetDragRegion(NonClientRegionKind.Passthrough, validItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double GetRasterizationScaleForElement(UIElement element)
|
||||||
|
{
|
||||||
|
if (element.XamlRoot != null)
|
||||||
|
{
|
||||||
|
return element.XamlRoot.RasterizationScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetDragRegion(NonClientRegionKind nonClientRegionKind, params FrameworkElement[] frameworkElements)
|
||||||
|
{
|
||||||
|
List<RectInt32> rects = new List<RectInt32>();
|
||||||
|
var scale = GetRasterizationScaleForElement(this);
|
||||||
|
|
||||||
|
foreach (var frameworkElement in frameworkElements)
|
||||||
|
{
|
||||||
|
if (frameworkElement == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeneralTransform transformElement = frameworkElement.TransformToVisual(null);
|
||||||
|
Rect bounds = transformElement.TransformBounds(new Rect(0, 0, frameworkElement.ActualWidth, frameworkElement.ActualHeight));
|
||||||
|
var transparentRect = new RectInt32(
|
||||||
|
_X: (int)Math.Round(bounds.X * scale),
|
||||||
|
_Y: (int)Math.Round(bounds.Y * scale),
|
||||||
|
_Width: (int)Math.Round(bounds.Width * scale),
|
||||||
|
_Height: (int)Math.Round(bounds.Height * scale));
|
||||||
|
rects.Add(transparentRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rects.Count > 0)
|
||||||
|
{
|
||||||
|
InputNonClientPointerSource.GetForWindowId(Window.AppWindow.Id).SetRegionRects(nonClientRegionKind, rects.ToArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearDragRegions(NonClientRegionKind nonClientRegionKind)
|
||||||
|
{
|
||||||
|
InputNonClientPointerSource.GetForWindowId(Window.AppWindow.Id).ClearRegionRects(nonClientRegionKind);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,220 @@
|
|||||||
|
// 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;
|
||||||
|
using Windows.Foundation;
|
||||||
|
|
||||||
|
namespace Microsoft.PowerToys.Settings.UI.Controls;
|
||||||
|
|
||||||
|
[TemplateVisualState(Name = BackButtonVisibleState, GroupName = BackButtonStates)]
|
||||||
|
[TemplateVisualState(Name = BackButtonCollapsedState, GroupName = BackButtonStates)]
|
||||||
|
[TemplateVisualState(Name = PaneButtonVisibleState, GroupName = PaneButtonStates)]
|
||||||
|
[TemplateVisualState(Name = PaneButtonCollapsedState, GroupName = PaneButtonStates)]
|
||||||
|
[TemplateVisualState(Name = WindowActivatedState, GroupName = ActivationStates)]
|
||||||
|
[TemplateVisualState(Name = WindowDeactivatedState, GroupName = ActivationStates)]
|
||||||
|
[TemplateVisualState(Name = StandardState, GroupName = DisplayModeStates)]
|
||||||
|
[TemplateVisualState(Name = TallState, GroupName = DisplayModeStates)]
|
||||||
|
[TemplateVisualState(Name = IconVisibleState, GroupName = IconStates)]
|
||||||
|
[TemplateVisualState(Name = IconCollapsedState, GroupName = IconStates)]
|
||||||
|
[TemplateVisualState(Name = ContentVisibleState, GroupName = ContentStates)]
|
||||||
|
[TemplateVisualState(Name = ContentCollapsedState, GroupName = ContentStates)]
|
||||||
|
[TemplateVisualState(Name = FooterVisibleState, GroupName = FooterStates)]
|
||||||
|
[TemplateVisualState(Name = FooterCollapsedState, GroupName = FooterStates)]
|
||||||
|
[TemplateVisualState(Name = WideState, GroupName = ReflowStates)]
|
||||||
|
[TemplateVisualState(Name = NarrowState, GroupName = ReflowStates)]
|
||||||
|
[TemplatePart(Name = PartBackButton, Type = typeof(Button))]
|
||||||
|
[TemplatePart(Name = PartPaneButton, Type = typeof(Button))]
|
||||||
|
[TemplatePart(Name = nameof(PART_LeftPaddingColumn), Type = typeof(ColumnDefinition))]
|
||||||
|
[TemplatePart(Name = nameof(PART_RightPaddingColumn), Type = typeof(ColumnDefinition))]
|
||||||
|
[TemplatePart(Name = nameof(PART_ButtonHolder), Type = typeof(StackPanel))]
|
||||||
|
|
||||||
|
public partial class TitleBar : Control
|
||||||
|
{
|
||||||
|
private const string PartBackButton = "PART_BackButton";
|
||||||
|
private const string PartPaneButton = "PART_PaneButton";
|
||||||
|
|
||||||
|
private const string BackButtonVisibleState = "BackButtonVisible";
|
||||||
|
private const string BackButtonCollapsedState = "BackButtonCollapsed";
|
||||||
|
private const string BackButtonStates = "BackButtonStates";
|
||||||
|
|
||||||
|
private const string PaneButtonVisibleState = "PaneButtonVisible";
|
||||||
|
private const string PaneButtonCollapsedState = "PaneButtonCollapsed";
|
||||||
|
private const string PaneButtonStates = "PaneButtonStates";
|
||||||
|
|
||||||
|
private const string WindowActivatedState = "Activated";
|
||||||
|
private const string WindowDeactivatedState = "Deactivated";
|
||||||
|
private const string ActivationStates = "WindowActivationStates";
|
||||||
|
|
||||||
|
private const string IconVisibleState = "IconVisible";
|
||||||
|
private const string IconCollapsedState = "IconCollapsed";
|
||||||
|
private const string IconStates = "IconStates";
|
||||||
|
|
||||||
|
private const string StandardState = "Standard";
|
||||||
|
private const string TallState = "Tall";
|
||||||
|
private const string DisplayModeStates = "DisplayModeStates";
|
||||||
|
|
||||||
|
private const string ContentVisibleState = "ContentVisible";
|
||||||
|
private const string ContentCollapsedState = "ContentCollapsed";
|
||||||
|
private const string ContentStates = "ContentStates";
|
||||||
|
|
||||||
|
private const string FooterVisibleState = "FooterVisible";
|
||||||
|
private const string FooterCollapsedState = "FooterCollapsed";
|
||||||
|
private const string FooterStates = "FooterStates";
|
||||||
|
|
||||||
|
private const string WideState = "Wide";
|
||||||
|
private const string NarrowState = "Narrow";
|
||||||
|
private const string ReflowStates = "ReflowStates";
|
||||||
|
|
||||||
|
#pragma warning disable SA1306 // Field names should begin with lower-case letter
|
||||||
|
#pragma warning disable SA1310 // Field names should not contain underscore
|
||||||
|
#pragma warning disable SA1400 // Access modifier should be declared
|
||||||
|
#pragma warning disable CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
ColumnDefinition? PART_RightPaddingColumn;
|
||||||
|
ColumnDefinition? PART_LeftPaddingColumn;
|
||||||
|
StackPanel? PART_ButtonHolder;
|
||||||
|
#pragma warning restore CS8632 // The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
|
||||||
|
#pragma warning restore SA1400 // Access modifier should be declared
|
||||||
|
#pragma warning restore SA1306 // Field names should begin with lower-case letter
|
||||||
|
#pragma warning restore SA1310 // Field names should not contain underscore
|
||||||
|
|
||||||
|
// We only want to reset TitleBar configuration in app, if we're the TitleBar instance that's managing that state.
|
||||||
|
private bool _isAutoConfigCompleted;
|
||||||
|
|
||||||
|
public TitleBar()
|
||||||
|
{
|
||||||
|
this.DefaultStyleKey = typeof(TitleBar);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate()
|
||||||
|
{
|
||||||
|
PART_LeftPaddingColumn = GetTemplateChild(nameof(PART_LeftPaddingColumn)) as ColumnDefinition;
|
||||||
|
PART_RightPaddingColumn = GetTemplateChild(nameof(PART_RightPaddingColumn)) as ColumnDefinition;
|
||||||
|
ConfigureButtonHolder();
|
||||||
|
Configure();
|
||||||
|
if (GetTemplateChild(PartBackButton) is Button backButton)
|
||||||
|
{
|
||||||
|
backButton.Click -= BackButton_Click;
|
||||||
|
backButton.Click += BackButton_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetTemplateChild(PartPaneButton) is Button paneButton)
|
||||||
|
{
|
||||||
|
paneButton.Click -= PaneButton_Click;
|
||||||
|
paneButton.Click += PaneButton_Click;
|
||||||
|
}
|
||||||
|
|
||||||
|
SizeChanged -= this.TitleBar_SizeChanged;
|
||||||
|
SizeChanged += this.TitleBar_SizeChanged;
|
||||||
|
|
||||||
|
Update();
|
||||||
|
base.OnApplyTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TitleBar_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
UpdateVisualStateAndDragRegion(e.NewSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateVisualStateAndDragRegion(Size size)
|
||||||
|
{
|
||||||
|
if (size.Width <= CompactStateBreakpoint)
|
||||||
|
{
|
||||||
|
if (Content != null || Footer != null)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, NarrowState, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, WideState, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetDragRegionForCustomTitleBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BackButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
BackButtonClick?.Invoke(this, new RoutedEventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PaneButton_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
PaneButtonClick?.Invoke(this, new RoutedEventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConfigureButtonHolder()
|
||||||
|
{
|
||||||
|
if (PART_ButtonHolder != null)
|
||||||
|
{
|
||||||
|
PART_ButtonHolder.SizeChanged -= PART_ButtonHolder_SizeChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
PART_ButtonHolder = GetTemplateChild(nameof(PART_ButtonHolder)) as StackPanel;
|
||||||
|
|
||||||
|
if (PART_ButtonHolder != null)
|
||||||
|
{
|
||||||
|
PART_ButtonHolder.SizeChanged += PART_ButtonHolder_SizeChanged;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void PART_ButtonHolder_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||||
|
{
|
||||||
|
SetDragRegionForCustomTitleBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Configure()
|
||||||
|
{
|
||||||
|
SetWASDKTitleBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
ResetWASDKTitleBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update()
|
||||||
|
{
|
||||||
|
if (Icon != null)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, IconVisibleState, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, IconCollapsedState, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
VisualStateManager.GoToState(this, IsBackButtonVisible ? BackButtonVisibleState : BackButtonCollapsedState, true);
|
||||||
|
VisualStateManager.GoToState(this, IsPaneButtonVisible ? PaneButtonVisibleState : PaneButtonCollapsedState, true);
|
||||||
|
|
||||||
|
if (DisplayMode == DisplayMode.Tall)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, TallState, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, StandardState, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Content != null)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, ContentVisibleState, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, ContentCollapsedState, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Footer != null)
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, FooterVisibleState, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisualStateManager.GoToState(this, FooterCollapsedState, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetDragRegionForCustomTitleBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,371 @@
|
|||||||
|
<ResourceDictionary
|
||||||
|
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"
|
||||||
|
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls">
|
||||||
|
|
||||||
|
<x:Double x:Key="TitleBarCompactHeight">32</x:Double>
|
||||||
|
<x:Double x:Key="TitleBarTallHeight">48</x:Double>
|
||||||
|
<x:Double x:Key="TitleBarContentMinWidth">360</x:Double>
|
||||||
|
<Style BasedOn="{StaticResource DefaultTitleBarStyle}" TargetType="local:TitleBar" />
|
||||||
|
|
||||||
|
<Style x:Key="DefaultTitleBarStyle" TargetType="local:TitleBar">
|
||||||
|
<Setter Property="MinHeight" Value="{ThemeResource TitleBarCompactHeight}" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="local:TitleBar">
|
||||||
|
<Grid
|
||||||
|
x:Name="PART_RootGrid"
|
||||||
|
Height="{TemplateBinding MinHeight}"
|
||||||
|
Padding="4,0,0,0"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="{TemplateBinding Background}">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition x:Name="PART_LeftPaddingColumn" Width="0" />
|
||||||
|
<ColumnDefinition x:Name="PART_ButtonsHolderColumn" Width="Auto" />
|
||||||
|
<ColumnDefinition x:Name="PART_IconColumn" Width="Auto" />
|
||||||
|
<ColumnDefinition x:Name="PART_TitleColumn" Width="Auto" />
|
||||||
|
<ColumnDefinition
|
||||||
|
x:Name="PART_LeftDragColumn"
|
||||||
|
Width="*"
|
||||||
|
MinWidth="4" />
|
||||||
|
<ColumnDefinition x:Name="PART_ContentColumn" Width="Auto" />
|
||||||
|
<ColumnDefinition
|
||||||
|
x:Name="PART_RightDragColumn"
|
||||||
|
Width="*"
|
||||||
|
MinWidth="4" />
|
||||||
|
<ColumnDefinition x:Name="PART_FooterColumn" Width="Auto" />
|
||||||
|
<ColumnDefinition x:Name="PART_RightPaddingColumn" Width="0" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
<Border
|
||||||
|
x:Name="PART_IconHolder"
|
||||||
|
Grid.Column="2"
|
||||||
|
Margin="12,0,0,0"
|
||||||
|
VerticalAlignment="Center">
|
||||||
|
<Viewbox
|
||||||
|
x:Name="PART_Icon"
|
||||||
|
MaxWidth="16"
|
||||||
|
MaxHeight="16">
|
||||||
|
<ContentPresenter
|
||||||
|
x:Name="PART_IconPresenter"
|
||||||
|
AutomationProperties.AccessibilityView="Raw"
|
||||||
|
Content="{TemplateBinding Icon}"
|
||||||
|
HighContrastAdjustment="None" />
|
||||||
|
</Viewbox>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<StackPanel
|
||||||
|
x:Name="PART_TitleHolder"
|
||||||
|
Grid.Column="3"
|
||||||
|
Margin="16,0,0,0"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Orientation="Horizontal"
|
||||||
|
Spacing="4">
|
||||||
|
<TextBlock
|
||||||
|
x:Name="PART_TitleText"
|
||||||
|
MinWidth="48"
|
||||||
|
Margin="0,0,0,1"
|
||||||
|
Foreground="{ThemeResource TextFillColorPrimaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{TemplateBinding Title}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
TextWrapping="NoWrap" />
|
||||||
|
<TextBlock
|
||||||
|
x:Name="PART_SubtitleText"
|
||||||
|
MinWidth="48"
|
||||||
|
Margin="0,0,0,1"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{TemplateBinding Subtitle}"
|
||||||
|
TextTrimming="CharacterEllipsis"
|
||||||
|
TextWrapping="NoWrap" />
|
||||||
|
</StackPanel>
|
||||||
|
<Grid
|
||||||
|
x:Name="PART_DragRegion"
|
||||||
|
Grid.Column="2"
|
||||||
|
Grid.ColumnSpan="6"
|
||||||
|
Background="Transparent" />
|
||||||
|
<StackPanel
|
||||||
|
x:Name="PART_ButtonHolder"
|
||||||
|
Grid.Column="1"
|
||||||
|
Orientation="Horizontal">
|
||||||
|
<Button
|
||||||
|
x:Name="PART_BackButton"
|
||||||
|
Style="{ThemeResource TitleBarBackButtonStyle}"
|
||||||
|
ToolTipService.ToolTip="Back" />
|
||||||
|
<Button
|
||||||
|
x:Name="PART_PaneButton"
|
||||||
|
Style="{StaticResource TitleBarPaneToggleButtonStyle}"
|
||||||
|
ToolTipService.ToolTip="Toggle menu" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<ContentPresenter
|
||||||
|
x:Name="PART_ContentPresenter"
|
||||||
|
Grid.Column="5"
|
||||||
|
MinWidth="{ThemeResource TitleBarContentMinWidth}"
|
||||||
|
HorizontalAlignment="Stretch"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
Content="{TemplateBinding Content}" />
|
||||||
|
<ContentPresenter
|
||||||
|
x:Name="PART_FooterPresenter"
|
||||||
|
Grid.Column="7"
|
||||||
|
Margin="4,0,8,0"
|
||||||
|
HorizontalContentAlignment="Right"
|
||||||
|
Content="{TemplateBinding Footer}" />
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="BackButtonStates">
|
||||||
|
<VisualState x:Name="BackButtonVisible" />
|
||||||
|
<VisualState x:Name="BackButtonCollapsed">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_BackButton.Visibility" Value="Collapsed" />
|
||||||
|
<Setter Target="PART_BackButton.Visibility" Value="Collapsed" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="PaneButtonStates">
|
||||||
|
<VisualState x:Name="PaneButtonVisible" />
|
||||||
|
<VisualState x:Name="PaneButtonCollapsed">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_PaneButton.Visibility" Value="Collapsed" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="IconStates">
|
||||||
|
<VisualState x:Name="IconVisible" />
|
||||||
|
<VisualState x:Name="IconCollapsed">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_IconHolder.Visibility" Value="Collapsed" />
|
||||||
|
<Setter Target="PART_TitleHolder.Margin" Value="4,0,0,0" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ContentStates">
|
||||||
|
<VisualState x:Name="ContentVisible" />
|
||||||
|
<VisualState x:Name="ContentCollapsed">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_ContentPresenter.Visibility" Value="Collapsed" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="FooterStates">
|
||||||
|
<VisualState x:Name="FooterVisible" />
|
||||||
|
<VisualState x:Name="FooterCollapsed">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_FooterPresenter.Visibility" Value="Collapsed" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="ReflowStates">
|
||||||
|
<VisualState x:Name="Wide" />
|
||||||
|
<VisualState x:Name="Narrow">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_TitleHolder.Visibility" Value="Collapsed" />
|
||||||
|
<Setter Target="PART_LeftDragColumn.Width" Value="Auto" />
|
||||||
|
<Setter Target="PART_RightDragColumn.Width" Value="Auto" />
|
||||||
|
<Setter Target="PART_RightDragColumn.MinWidth" Value="16" />
|
||||||
|
<Setter Target="PART_LeftDragColumn.MinWidth" Value="16" />
|
||||||
|
<Setter Target="PART_ContentColumn.Width" Value="*" />
|
||||||
|
<!-- Content can stretch now -->
|
||||||
|
<Setter Target="PART_ContentPresenter.MinWidth" Value="0" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="WindowActivationStates">
|
||||||
|
<VisualState x:Name="Activated" />
|
||||||
|
<VisualState x:Name="Deactivated">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_TitleText.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||||
|
<Setter Target="PART_SubtitleText.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
|
||||||
|
<Setter Target="PART_BackButton.IsEnabled" Value="False" />
|
||||||
|
<Setter Target="PART_PaneButton.IsEnabled" Value="False" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
<VisualStateGroup x:Name="DisplayModeStates">
|
||||||
|
<VisualState x:Name="Standard" />
|
||||||
|
<VisualState x:Name="Tall">
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="PART_RootGrid.MinHeight" Value="{ThemeResource TitleBarTallHeight}" />
|
||||||
|
<Setter Target="PART_RootGrid.Padding" Value="4" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- Copy of WinUI NavigationBackButtonNormalStyle - cannot use it as it picks up the generic.xaml version, not the WinUI version -->
|
||||||
|
<Style x:Key="TitleBarBackButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{ThemeResource NavigationViewBackButtonBackground}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource NavigationViewItemForegroundChecked}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="16" />
|
||||||
|
<Setter Property="MaxHeight" Value="40" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||||
|
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
|
||||||
|
<Setter Property="Content" Value="" />
|
||||||
|
<Setter Property="Padding" Value="12,4,12,4" />
|
||||||
|
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid
|
||||||
|
x:Name="RootGrid"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="{TemplateBinding CornerRadius}">
|
||||||
|
<AnimatedIcon
|
||||||
|
x:Name="Content"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
|
AnimatedIcon.State="Normal"
|
||||||
|
AutomationProperties.AccessibilityView="Raw">
|
||||||
|
<animatedvisuals:AnimatedBackVisualSource />
|
||||||
|
<AnimatedIcon.FallbackIconSource>
|
||||||
|
<FontIconSource
|
||||||
|
FontFamily="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FontFamily}"
|
||||||
|
FontSize="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FontSize}"
|
||||||
|
Glyph="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
|
||||||
|
MirroredWhenRightToLeft="True" />
|
||||||
|
</AnimatedIcon.FallbackIconSource>
|
||||||
|
</AnimatedIcon>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonBackgroundPointerOver}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundPointerOver}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="Content.(AnimatedIcon.State)" Value="PointerOver" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonBackgroundPressed}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundPressed}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="Content.(AnimatedIcon.State)" Value="Pressed" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundDisabled}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<!-- Copy of WinUI PaneToggleButtonStyle - cannot use it as it picks up the generic.xaml version, not the WinUI version -->
|
||||||
|
<Style x:Key="TitleBarPaneToggleButtonStyle" TargetType="Button">
|
||||||
|
<Setter Property="Background" Value="{ThemeResource NavigationViewBackButtonBackground}" />
|
||||||
|
<Setter Property="Foreground" Value="{ThemeResource NavigationViewItemForegroundChecked}" />
|
||||||
|
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
|
||||||
|
<Setter Property="FontSize" Value="16" />
|
||||||
|
<Setter Property="MaxHeight" Value="40" />
|
||||||
|
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||||
|
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||||
|
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
|
||||||
|
<Setter Property="Content" Value="" />
|
||||||
|
<Setter Property="Padding" Value="12,4,12,4" />
|
||||||
|
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="Button">
|
||||||
|
<Grid
|
||||||
|
x:Name="RootGrid"
|
||||||
|
Padding="{TemplateBinding Padding}"
|
||||||
|
Background="{TemplateBinding Background}"
|
||||||
|
CornerRadius="{TemplateBinding CornerRadius}">
|
||||||
|
<AnimatedIcon
|
||||||
|
x:Name="Content"
|
||||||
|
Width="16"
|
||||||
|
Height="16"
|
||||||
|
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
|
AnimatedIcon.State="Normal"
|
||||||
|
AutomationProperties.AccessibilityView="Raw">
|
||||||
|
<animatedvisuals:AnimatedGlobalNavigationButtonVisualSource />
|
||||||
|
<AnimatedIcon.FallbackIconSource>
|
||||||
|
<FontIconSource
|
||||||
|
FontFamily="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FontFamily}"
|
||||||
|
FontSize="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FontSize}"
|
||||||
|
Glyph="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
|
||||||
|
MirroredWhenRightToLeft="True" />
|
||||||
|
</AnimatedIcon.FallbackIconSource>
|
||||||
|
</AnimatedIcon>
|
||||||
|
<VisualStateManager.VisualStateGroups>
|
||||||
|
<VisualStateGroup x:Name="CommonStates">
|
||||||
|
<VisualState x:Name="Normal" />
|
||||||
|
<VisualState x:Name="PointerOver">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonBackgroundPointerOver}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundPointerOver}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="Content.(AnimatedIcon.State)" Value="PointerOver" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
|
||||||
|
<VisualState x:Name="Pressed">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonBackgroundPressed}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundPressed}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
<VisualState.Setters>
|
||||||
|
<Setter Target="Content.(AnimatedIcon.State)" Value="Pressed" />
|
||||||
|
</VisualState.Setters>
|
||||||
|
</VisualState>
|
||||||
|
|
||||||
|
<VisualState x:Name="Disabled">
|
||||||
|
<Storyboard>
|
||||||
|
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Content" Storyboard.TargetProperty="Foreground">
|
||||||
|
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource NavigationViewButtonForegroundDisabled}" />
|
||||||
|
</ObjectAnimationUsingKeyFrames>
|
||||||
|
</Storyboard>
|
||||||
|
</VisualState>
|
||||||
|
</VisualStateGroup>
|
||||||
|
</VisualStateManager.VisualStateGroups>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</ResourceDictionary>
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
<controls:SettingsGroup x:Uid="MouseUtils_MouseJump">
|
<controls:SettingsGroup x:Uid="MouseUtils_MouseJump">
|
||||||
|
|
||||||
<tkcontrols:SettingsCard
|
<tkcontrols:SettingsCard
|
||||||
|
x:Name="MouseUtilsEnableMouseJump"
|
||||||
x:Uid="MouseUtils_Enable_MouseJump"
|
x:Uid="MouseUtils_Enable_MouseJump"
|
||||||
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseJump.png}"
|
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/Icons/MouseJump.png}"
|
||||||
IsEnabled="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
IsEnabled="{x:Bind ViewModel.IsJumpEnabledGpoConfigured, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
</InfoBar>
|
</InfoBar>
|
||||||
|
|
||||||
<tkcontrols:SettingsCard
|
<tkcontrols:SettingsCard
|
||||||
|
x:Name="MouseUtilsMouseJumpActivationShortcut"
|
||||||
x:Uid="MouseUtils_MouseJump_ActivationShortcut"
|
x:Uid="MouseUtils_MouseJump_ActivationShortcut"
|
||||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||||
IsEnabled="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=OneWay}">
|
IsEnabled="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=OneWay}">
|
||||||
@@ -126,6 +128,7 @@
|
|||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
|
|
||||||
<tkcontrols:SettingsExpander
|
<tkcontrols:SettingsExpander
|
||||||
|
x:Name="MouseUtilsMouseJumpAppearance"
|
||||||
x:Uid="MouseUtils_MouseJump_Appearance"
|
x:Uid="MouseUtils_MouseJump_Appearance"
|
||||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||||
IsEnabled="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=OneWay}"
|
IsEnabled="{x:Bind ViewModel.IsMouseJumpEnabled, Mode=OneWay}"
|
||||||
|
|||||||
@@ -70,19 +70,19 @@
|
|||||||
x:Uid="FancyZones_ZoneBehavior_GroupSettings"
|
x:Uid="FancyZones_ZoneBehavior_GroupSettings"
|
||||||
IsExpanded="True">
|
IsExpanded="True">
|
||||||
<tkcontrols:SettingsExpander.Items>
|
<tkcontrols:SettingsExpander.Items>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesShiftDragCheckBoxControlHeader" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_ShiftDragCheckBoxControl_Header" IsChecked="{x:Bind ViewModel.ShiftDrag, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_ShiftDragCheckBoxControl_Header" IsChecked="{x:Bind ViewModel.ShiftDrag, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesMouseDragCheckBoxControlHeader" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_MouseDragCheckBoxControl_Header" IsChecked="{x:Bind ViewModel.MouseSwitch, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_MouseDragCheckBoxControl_Header" IsChecked="{x:Bind ViewModel.MouseSwitch, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesMouseMiddleClickSpanningMultipleZonesCheckBoxControlHeader" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_MouseMiddleClickSpanningMultipleZonesCheckBoxControl_Header" IsChecked="{x:Bind ViewModel.MouseMiddleClickSpanningMultipleZones, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_MouseMiddleClickSpanningMultipleZonesCheckBoxControl_Header" IsChecked="{x:Bind ViewModel.MouseMiddleClickSpanningMultipleZones, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesShowZonesOnAllMonitorsCheckBoxControl" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_ShowZonesOnAllMonitorsCheckBoxControl" IsChecked="{x:Bind ViewModel.ShowOnAllMonitors, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_ShowZonesOnAllMonitorsCheckBoxControl" IsChecked="{x:Bind ViewModel.ShowOnAllMonitors, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesSpanZonesAcrossMonitors" ContentAlignment="Left">
|
||||||
<controls:CheckBoxWithDescriptionControl x:Uid="FancyZones_SpanZonesAcrossMonitors" IsChecked="{x:Bind ViewModel.SpanZonesAcrossMonitors, Mode=TwoWay}" />
|
<controls:CheckBoxWithDescriptionControl x:Uid="FancyZones_SpanZonesAcrossMonitors" IsChecked="{x:Bind ViewModel.SpanZonesAcrossMonitors, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard Name="FancyZonesOverlappingZones" x:Uid="FancyZones_OverlappingZones">
|
<tkcontrols:SettingsCard Name="FancyZonesOverlappingZones" x:Uid="FancyZones_OverlappingZones">
|
||||||
@@ -106,7 +106,7 @@
|
|||||||
<ComboBoxItem x:Uid="FancyZones_Radio_Default_Theme" />
|
<ComboBoxItem x:Uid="FancyZones_Radio_Default_Theme" />
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
<tkcontrols:SettingsExpander.Items>
|
<tkcontrols:SettingsExpander.Items>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesPreviewCard" ContentAlignment="Left">
|
||||||
<controls:FancyZonesPreviewControl
|
<controls:FancyZonesPreviewControl
|
||||||
Width="192"
|
Width="192"
|
||||||
Height="108"
|
Height="108"
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
IsSystemTheme="{x:Bind ViewModel.SystemTheme, Mode=OneWay}"
|
IsSystemTheme="{x:Bind ViewModel.SystemTheme, Mode=OneWay}"
|
||||||
ShowZoneNumber="{x:Bind Path=ViewModel.ShowZoneNumber, Mode=OneWay}" />
|
ShowZoneNumber="{x:Bind Path=ViewModel.ShowZoneNumber, Mode=OneWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesShowZoneNumberCheckBoxControl" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_ShowZoneNumberCheckBoxControl" IsChecked="{x:Bind ViewModel.ShowZoneNumber, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_ShowZoneNumberCheckBoxControl" IsChecked="{x:Bind ViewModel.ShowZoneNumber, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard Name="FancyZonesHighlightOpacity" x:Uid="FancyZones_HighlightOpacity">
|
<tkcontrols:SettingsCard Name="FancyZonesHighlightOpacity" x:Uid="FancyZones_HighlightOpacity">
|
||||||
@@ -164,28 +164,31 @@
|
|||||||
x:Uid="FancyZones_WindowBehavior_GroupSettings"
|
x:Uid="FancyZones_WindowBehavior_GroupSettings"
|
||||||
IsExpanded="True">
|
IsExpanded="True">
|
||||||
<tkcontrols:SettingsExpander.Items>
|
<tkcontrols:SettingsExpander.Items>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesDisplayOrWorkAreaChangeMoveWindowsCheckBoxControl" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_DisplayOrWorkAreaChangeMoveWindowsCheckBoxControl" IsChecked="{x:Bind ViewModel.DisplayOrWorkAreaChangeMoveWindows, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_DisplayOrWorkAreaChangeMoveWindowsCheckBoxControl" IsChecked="{x:Bind ViewModel.DisplayOrWorkAreaChangeMoveWindows, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesZoneSetChangeMoveWindows" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_ZoneSetChangeMoveWindows" IsChecked="{x:Bind ViewModel.ZoneSetChangeMoveWindows, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_ZoneSetChangeMoveWindows" IsChecked="{x:Bind ViewModel.ZoneSetChangeMoveWindows, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesAppLastZoneMoveWindows" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_AppLastZoneMoveWindows" IsChecked="{x:Bind ViewModel.AppLastZoneMoveWindows, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_AppLastZoneMoveWindows" IsChecked="{x:Bind ViewModel.AppLastZoneMoveWindows, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesOpenWindowOnActiveMonitor" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_OpenWindowOnActiveMonitor" IsChecked="{x:Bind ViewModel.OpenWindowOnActiveMonitor, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_OpenWindowOnActiveMonitor" IsChecked="{x:Bind ViewModel.OpenWindowOnActiveMonitor, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesRestoreSize" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_RestoreSize" IsChecked="{x:Bind ViewModel.RestoreSize, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_RestoreSize" IsChecked="{x:Bind ViewModel.RestoreSize, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesMakeDraggedWindowTransparentCheckBoxControl" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_MakeDraggedWindowTransparentCheckBoxControl" IsChecked="{x:Bind ViewModel.MakeDraggedWindowsTransparent, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_MakeDraggedWindowTransparentCheckBoxControl" IsChecked="{x:Bind ViewModel.MakeDraggedWindowsTransparent, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left">
|
<tkcontrols:SettingsCard Name="FancyZonesAllowChildWindowSnap" ContentAlignment="Left">
|
||||||
<CheckBox x:Uid="FancyZones_AllowChildWindowSnap" IsChecked="{x:Bind ViewModel.AllowChildWindowSnap, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_AllowChildWindowSnap" IsChecked="{x:Bind ViewModel.AllowChildWindowSnap, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left" Visibility="{x:Bind ViewModel.Windows11, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
<tkcontrols:SettingsCard
|
||||||
|
Name="FancyZonesDisableRoundCornersOnWindowSnap"
|
||||||
|
ContentAlignment="Left"
|
||||||
|
Visibility="{x:Bind ViewModel.Windows11, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||||
<CheckBox x:Uid="FancyZones_DisableRoundCornersOnWindowSnap" IsChecked="{x:Bind ViewModel.DisableRoundCornersOnWindowSnap, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_DisableRoundCornersOnWindowSnap" IsChecked="{x:Bind ViewModel.DisableRoundCornersOnWindowSnap, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
</tkcontrols:SettingsExpander.Items>
|
</tkcontrols:SettingsExpander.Items>
|
||||||
@@ -199,7 +202,7 @@
|
|||||||
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.WindowSwitching, Mode=TwoWay}" />
|
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.WindowSwitching, Mode=TwoWay}" />
|
||||||
<tkcontrols:SettingsExpander.Items>
|
<tkcontrols:SettingsExpander.Items>
|
||||||
<!-- HACK: For some weird reason, a Shortcut Control is not working correctly if it's the first item in the expander, so we add an invisible card as the first one. -->
|
<!-- HACK: For some weird reason, a Shortcut Control is not working correctly if it's the first item in the expander, so we add an invisible card as the first one. -->
|
||||||
<tkcontrols:SettingsCard Visibility="Collapsed" />
|
<tkcontrols:SettingsCard Name="FancyZonesWindowSwitchingPlaceholder" Visibility="Collapsed" />
|
||||||
<tkcontrols:SettingsCard
|
<tkcontrols:SettingsCard
|
||||||
Name="FancyZonesHotkeyNextTabControl"
|
Name="FancyZonesHotkeyNextTabControl"
|
||||||
x:Uid="FancyZones_HotkeyNextTabControl"
|
x:Uid="FancyZones_HotkeyNextTabControl"
|
||||||
@@ -248,7 +251,10 @@
|
|||||||
</ComboBoxItem>
|
</ComboBoxItem>
|
||||||
</ComboBox>
|
</ComboBox>
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind ViewModel.SnapHotkeysCategoryEnabled, Mode=OneWay}">
|
<tkcontrols:SettingsCard
|
||||||
|
Name="FancyZonesMoveWindowsAcrossAllMonitorsCheckBoxControl"
|
||||||
|
ContentAlignment="Left"
|
||||||
|
IsEnabled="{x:Bind ViewModel.SnapHotkeysCategoryEnabled, Mode=OneWay}">
|
||||||
<CheckBox x:Uid="FancyZones_MoveWindowsAcrossAllMonitorsCheckBoxControl" IsChecked="{x:Bind ViewModel.MoveWindowsAcrossMonitors, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_MoveWindowsAcrossAllMonitorsCheckBoxControl" IsChecked="{x:Bind ViewModel.MoveWindowsAcrossMonitors, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
</tkcontrols:SettingsExpander.Items>
|
</tkcontrols:SettingsExpander.Items>
|
||||||
@@ -262,7 +268,10 @@
|
|||||||
HeaderIcon="{ui:FontIcon Glyph=}">
|
HeaderIcon="{ui:FontIcon Glyph=}">
|
||||||
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.QuickLayoutSwitch, Mode=TwoWay}" />
|
<ToggleSwitch x:Uid="ToggleSwitch" IsOn="{x:Bind ViewModel.QuickLayoutSwitch, Mode=TwoWay}" />
|
||||||
<tkcontrols:SettingsExpander.Items>
|
<tkcontrols:SettingsExpander.Items>
|
||||||
<tkcontrols:SettingsCard ContentAlignment="Left" IsEnabled="{x:Bind ViewModel.QuickSwitchEnabled, Mode=OneWay}">
|
<tkcontrols:SettingsCard
|
||||||
|
Name="FancyZonesFlashZonesOnQuickSwitch"
|
||||||
|
ContentAlignment="Left"
|
||||||
|
IsEnabled="{x:Bind ViewModel.QuickSwitchEnabled, Mode=OneWay}">
|
||||||
<CheckBox x:Uid="FancyZones_FlashZonesOnQuickSwitch" IsChecked="{x:Bind ViewModel.FlashZonesOnQuickSwitch, Mode=TwoWay}" />
|
<CheckBox x:Uid="FancyZones_FlashZonesOnQuickSwitch" IsChecked="{x:Bind ViewModel.FlashZonesOnQuickSwitch, Mode=TwoWay}" />
|
||||||
</tkcontrols:SettingsCard>
|
</tkcontrols:SettingsCard>
|
||||||
</tkcontrols:SettingsExpander.Items>
|
</tkcontrols:SettingsExpander.Items>
|
||||||
@@ -277,7 +286,10 @@
|
|||||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||||
IsExpanded="True">
|
IsExpanded="True">
|
||||||
<tkcontrols:SettingsExpander.Items>
|
<tkcontrols:SettingsExpander.Items>
|
||||||
<tkcontrols:SettingsCard HorizontalContentAlignment="Stretch" ContentAlignment="Vertical">
|
<tkcontrols:SettingsCard
|
||||||
|
Name="FancyZonesExcludeAppsTextBoxControl"
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
ContentAlignment="Vertical">
|
||||||
<TextBox
|
<TextBox
|
||||||
x:Uid="FancyZones_ExcludeApps_TextBoxControl"
|
x:Uid="FancyZones_ExcludeApps_TextBoxControl"
|
||||||
MinWidth="240"
|
MinWidth="240"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using CommunityToolkit.WinUI.Controls;
|
||||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||||
using Microsoft.PowerToys.Settings.UI.Services;
|
using Microsoft.PowerToys.Settings.UI.Services;
|
||||||
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
using Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||||
@@ -32,7 +33,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
if (e.Parameter is SearchResultsNavigationParams searchParams)
|
if (e.Parameter is SearchResultsNavigationParams searchParams)
|
||||||
{
|
{
|
||||||
ViewModel.SetSearchResults(searchParams.Query, searchParams.Results);
|
ViewModel.SetSearchResults(searchParams.Query, searchParams.Results);
|
||||||
PageControl.ModuleDescription = string.Empty;
|
PageControl.ModuleDescription = $"{ResourceLoaderInstance.ResourceLoader.GetString("Search_ResultsFor")} '{searchParams.Query}'";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
|
|
||||||
private void ModuleButton_Click(object sender, RoutedEventArgs e)
|
private void ModuleButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is CommunityToolkit.WinUI.Controls.SettingsCard card && card.DataContext is SettingEntry tagEntry)
|
if (sender is SettingsCard card && card.DataContext is SettingEntry tagEntry)
|
||||||
{
|
{
|
||||||
NavigateToModule(tagEntry);
|
NavigateToModule(tagEntry);
|
||||||
}
|
}
|
||||||
@@ -51,7 +52,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
|
|
||||||
private void SettingButton_Click(object sender, RoutedEventArgs e)
|
private void SettingButton_Click(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
if (sender is CommunityToolkit.WinUI.Controls.SettingsCard card && card.DataContext is SettingEntry tagEntry)
|
if (sender is SettingsCard card && card.DataContext is SettingEntry tagEntry)
|
||||||
{
|
{
|
||||||
NavigateToSetting(tagEntry);
|
NavigateToSetting(tagEntry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||||
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
xmlns:animations="using:CommunityToolkit.WinUI.Animations"
|
||||||
|
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
|
||||||
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
|
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:helpers="using:Microsoft.PowerToys.Settings.UI.Helpers"
|
xmlns:helpers="using:Microsoft.PowerToys.Settings.UI.Helpers"
|
||||||
@@ -11,7 +12,6 @@
|
|||||||
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
|
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:models="using:Microsoft.PowerToys.Settings.UI.ViewModels"
|
xmlns:models="using:Microsoft.PowerToys.Settings.UI.ViewModels"
|
||||||
xmlns:tkcontrols="using:CommunityToolkit.WinUI.Controls"
|
|
||||||
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
xmlns:tkconverters="using:CommunityToolkit.WinUI.Converters"
|
||||||
xmlns:ui="using:CommunityToolkit.WinUI"
|
xmlns:ui="using:CommunityToolkit.WinUI"
|
||||||
xmlns:views="using:Microsoft.PowerToys.Settings.UI.Views"
|
xmlns:views="using:Microsoft.PowerToys.Settings.UI.Views"
|
||||||
@@ -57,12 +57,6 @@
|
|||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate x:Key="NoResultSearchResultTemplate" x:DataType="models:SuggestionItem">
|
<DataTemplate x:Key="NoResultSearchResultTemplate" x:DataType="models:SuggestionItem">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Rectangle
|
|
||||||
Height="1"
|
|
||||||
Margin="0,-4,0,0"
|
|
||||||
HorizontalAlignment="Stretch"
|
|
||||||
VerticalAlignment="Top"
|
|
||||||
Fill="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Margin="8"
|
Margin="8"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
@@ -71,10 +65,10 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
<DataTemplate x:Key="ShowAllSearchResultTemplate" x:DataType="models:SuggestionItem">
|
<DataTemplate x:Key="ShowAllSearchResultTemplate" x:DataType="models:SuggestionItem">
|
||||||
<Grid Padding="16,8">
|
<Grid>
|
||||||
<Rectangle
|
<Rectangle
|
||||||
Height="1"
|
Height="1"
|
||||||
Margin="0,-4,0,0"
|
Margin="0,-12,0,0"
|
||||||
HorizontalAlignment="Stretch"
|
HorizontalAlignment="Stretch"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
Fill="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
Fill="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||||
@@ -92,23 +86,22 @@
|
|||||||
<ic:InvokeCommandAction Command="{x:Bind ViewModel.LoadedCommand}" />
|
<ic:InvokeCommandAction Command="{x:Bind ViewModel.LoadedCommand}" />
|
||||||
</ic:EventTriggerBehavior>
|
</ic:EventTriggerBehavior>
|
||||||
</i:Interaction.Behaviors>
|
</i:Interaction.Behaviors>
|
||||||
|
|
||||||
<Grid x:Name="RootGrid">
|
<Grid x:Name="RootGrid">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="48" />
|
<RowDefinition Height="48" />
|
||||||
<RowDefinition Height="*" />
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<tkcontrols:TitleBar
|
<controls:TitleBar
|
||||||
x:Name="AppTitleBar"
|
x:Name="AppTitleBar"
|
||||||
AutoConfigureCustomTitleBar="True"
|
AutoConfigureCustomTitleBar="True"
|
||||||
PaneButtonClick="PaneToggleBtn_Click">
|
PaneButtonClick="PaneToggleBtn_Click">
|
||||||
<tkcontrols:TitleBar.Resources>
|
<controls:TitleBar.Resources>
|
||||||
<x:Double x:Key="TitleBarContentMinWidth">516</x:Double>
|
<x:Double x:Key="TitleBarContentMinWidth">516</x:Double>
|
||||||
</tkcontrols:TitleBar.Resources>
|
</controls:TitleBar.Resources>
|
||||||
<tkcontrols:TitleBar.Icon>
|
<controls:TitleBar.Icon>
|
||||||
<BitmapIcon ShowAsMonochrome="False" UriSource="/Assets/Settings/icon.ico" />
|
<BitmapIcon ShowAsMonochrome="False" UriSource="/Assets/Settings/icon.ico" />
|
||||||
</tkcontrols:TitleBar.Icon>
|
</controls:TitleBar.Icon>
|
||||||
<tkcontrols:TitleBar.Content>
|
<controls:TitleBar.Content>
|
||||||
<AutoSuggestBox
|
<AutoSuggestBox
|
||||||
x:Name="SearchBox"
|
x:Name="SearchBox"
|
||||||
x:Uid="Shell_SearchBox"
|
x:Uid="Shell_SearchBox"
|
||||||
@@ -129,8 +122,8 @@
|
|||||||
Modifiers="Control" />
|
Modifiers="Control" />
|
||||||
</AutoSuggestBox.KeyboardAccelerators>
|
</AutoSuggestBox.KeyboardAccelerators>
|
||||||
</AutoSuggestBox>
|
</AutoSuggestBox>
|
||||||
</tkcontrols:TitleBar.Content>
|
</controls:TitleBar.Content>
|
||||||
</tkcontrols:TitleBar>
|
</controls:TitleBar>
|
||||||
<NavigationView
|
<NavigationView
|
||||||
x:Name="navigationView"
|
x:Name="navigationView"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Common.Search;
|
using Common.Search;
|
||||||
using Common.Search.FuzzSearch;
|
using Common.Search.FuzzSearch;
|
||||||
using ManagedCommon;
|
using ManagedCommon;
|
||||||
|
using Microsoft.PowerToys.Settings.UI.Controls;
|
||||||
using Microsoft.PowerToys.Settings.UI.Helpers;
|
using Microsoft.PowerToys.Settings.UI.Helpers;
|
||||||
using Microsoft.PowerToys.Settings.UI.Library;
|
using Microsoft.PowerToys.Settings.UI.Library;
|
||||||
using Microsoft.PowerToys.Settings.UI.Services;
|
using Microsoft.PowerToys.Settings.UI.Services;
|
||||||
@@ -132,7 +132,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
|
|
||||||
public static bool IsUserAnAdmin { get; set; }
|
public static bool IsUserAnAdmin { get; set; }
|
||||||
|
|
||||||
public CommunityToolkit.WinUI.Controls.TitleBar TitleBar => AppTitleBar;
|
public Controls.TitleBar TitleBar => AppTitleBar;
|
||||||
|
|
||||||
private Dictionary<Type, NavigationViewItem> _navViewParentLookup = new Dictionary<Type, NavigationViewItem>();
|
private Dictionary<Type, NavigationViewItem> _navViewParentLookup = new Dictionary<Type, NavigationViewItem>();
|
||||||
private List<string> _searchSuggestions = [];
|
private List<string> _searchSuggestions = [];
|
||||||
@@ -141,8 +141,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
private const int SearchDebounceMs = 500;
|
private const int SearchDebounceMs = 500;
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
|
|
||||||
// Tracing id for correlating logs of a single search interaction
|
// Removed trace id counter per cleanup
|
||||||
private static long _searchTraceIdCounter;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="ShellPage"/> class.
|
/// Initializes a new instance of the <see cref="ShellPage"/> class.
|
||||||
@@ -442,25 +441,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
|
|
||||||
private void ShellPage_Loaded(object sender, RoutedEventArgs e)
|
private void ShellPage_Loaded(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("[Search][Index] Scheduling BuildIndex...");
|
|
||||||
var swIndex = Stopwatch.StartNew();
|
|
||||||
Task.Run(() =>
|
Task.Run(() =>
|
||||||
{
|
{
|
||||||
Logger.LogDebug("[Search][Index] BuildIndex started");
|
|
||||||
SearchIndexService.BuildIndex();
|
SearchIndexService.BuildIndex();
|
||||||
})
|
})
|
||||||
.ContinueWith(t =>
|
.ContinueWith(_ => { });
|
||||||
{
|
|
||||||
swIndex.Stop();
|
|
||||||
if (t.IsFaulted)
|
|
||||||
{
|
|
||||||
Logger.LogDebug($"[Search][Index] BuildIndex FAILED after {swIndex.ElapsedMilliseconds} ms: {t.Exception?.Flatten().InnerException?.Message}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger.LogDebug($"[Search][Index] BuildIndex completed in {swIndex.ElapsedMilliseconds} ms.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void NavigationView_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
|
private void NavigationView_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
|
||||||
@@ -511,10 +496,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
|
|
||||||
var query = sender.Text?.Trim() ?? string.Empty;
|
var query = sender.Text?.Trim() ?? string.Empty;
|
||||||
|
|
||||||
var traceId = Interlocked.Increment(ref _searchTraceIdCounter);
|
|
||||||
var swOverall = Stopwatch.StartNew();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] start. query='{query}'");
|
|
||||||
|
|
||||||
// Debounce: cancel previous pending search
|
// Debounce: cancel previous pending search
|
||||||
_searchDebounceCts?.Cancel();
|
_searchDebounceCts?.Cancel();
|
||||||
_searchDebounceCts?.Dispose();
|
_searchDebounceCts?.Dispose();
|
||||||
@@ -527,7 +508,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
sender.IsSuggestionListOpen = false;
|
sender.IsSuggestionListOpen = false;
|
||||||
_lastSearchResults.Clear();
|
_lastSearchResults.Clear();
|
||||||
_lastQueryText = string.Empty;
|
_lastQueryText = string.Empty;
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] empty query. end");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,14 +517,11 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
{
|
{
|
||||||
// A newer keystroke arrived; abandon this run
|
return; // debounce canceled
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] debounce canceled at +{swOverall.ElapsedMilliseconds} ms");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.IsCancellationRequested)
|
if (token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] token canceled post-debounce at +{swOverall.ElapsedMilliseconds} ms");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -553,106 +530,25 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// If the token is already canceled before scheduling, the task won't start.
|
// If the token is already canceled before scheduling, the task won't start.
|
||||||
var swSearch = Stopwatch.StartNew();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] dispatch search...");
|
|
||||||
results = await Task.Run(() => SearchIndexService.Search(query, token), token);
|
results = await Task.Run(() => SearchIndexService.Search(query, token), token);
|
||||||
swSearch.Stop();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] search done in {swSearch.ElapsedMilliseconds} ms. results={results?.Count ?? 0}");
|
|
||||||
}
|
}
|
||||||
catch (OperationCanceledException)
|
catch (OperationCanceledException)
|
||||||
{
|
{
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] search canceled at +{swOverall.ElapsedMilliseconds} ms");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token.IsCancellationRequested)
|
if (token.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] token canceled after search at +{swOverall.ElapsedMilliseconds} ms");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastSearchResults = results;
|
_lastSearchResults = results;
|
||||||
_lastQueryText = query;
|
_lastQueryText = query;
|
||||||
|
|
||||||
List<SuggestionItem> top;
|
var top = BuildSuggestionItems(query, results);
|
||||||
if (results.Count == 0)
|
|
||||||
{
|
|
||||||
// Explicit no-results row
|
|
||||||
var rl = ResourceLoaderInstance.ResourceLoader;
|
|
||||||
var noResultsPrefix = rl.GetString("Shell_Search_NoResults");
|
|
||||||
if (string.IsNullOrEmpty(noResultsPrefix))
|
|
||||||
{
|
|
||||||
noResultsPrefix = "No results for";
|
|
||||||
}
|
|
||||||
|
|
||||||
var headerText = $"{noResultsPrefix} '{query}'";
|
|
||||||
top =
|
|
||||||
[
|
|
||||||
new()
|
|
||||||
{
|
|
||||||
Header = headerText,
|
|
||||||
IsNoResults = true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] no results -> added placeholder item (count={top.Count})");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Project top 5 suggestions
|
|
||||||
var swProject = Stopwatch.StartNew();
|
|
||||||
top = [.. results.Take(5)
|
|
||||||
.Select(e =>
|
|
||||||
{
|
|
||||||
string subtitle = string.Empty;
|
|
||||||
if (e.Type != EntryType.SettingsPage)
|
|
||||||
{
|
|
||||||
var swSubtitle = Stopwatch.StartNew();
|
|
||||||
subtitle = SearchIndexService.GetLocalizedPageName(e.PageTypeName);
|
|
||||||
if (string.IsNullOrEmpty(subtitle))
|
|
||||||
{
|
|
||||||
// Fallback: look up the module title from the in-memory index
|
|
||||||
var swFallback = Stopwatch.StartNew();
|
|
||||||
subtitle = SearchIndexService.Index
|
|
||||||
.Where(x => x.Type == EntryType.SettingsPage && x.PageTypeName == e.PageTypeName)
|
|
||||||
.Select(x => x.Header)
|
|
||||||
.FirstOrDefault() ?? string.Empty;
|
|
||||||
swFallback.Stop();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] fallback subtitle for '{e.PageTypeName}' took {swFallback.ElapsedMilliseconds} ms");
|
|
||||||
}
|
|
||||||
|
|
||||||
swSubtitle.Stop();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] subtitle for '{e.PageTypeName}' took {swSubtitle.ElapsedMilliseconds} ms");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SuggestionItem
|
|
||||||
{
|
|
||||||
Header = e.Header,
|
|
||||||
Icon = e.Icon,
|
|
||||||
PageTypeName = e.PageTypeName,
|
|
||||||
ElementName = e.ElementName,
|
|
||||||
ParentElementName = e.ParentElementName,
|
|
||||||
Subtitle = subtitle,
|
|
||||||
IsShowAll = false,
|
|
||||||
};
|
|
||||||
})];
|
|
||||||
swProject.Stop();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] project suggestions took {swProject.ElapsedMilliseconds} ms. topCount={top.Count}");
|
|
||||||
|
|
||||||
if (results.Count > 5)
|
|
||||||
{
|
|
||||||
// Add a tail item to show all results if there are more than 5
|
|
||||||
top.Add(new SuggestionItem { IsShowAll = true });
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] added 'Show all results' item");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var swUi = Stopwatch.StartNew();
|
|
||||||
sender.ItemsSource = top;
|
sender.ItemsSource = top;
|
||||||
sender.IsSuggestionListOpen = top.Count > 0;
|
sender.IsSuggestionListOpen = top.Count > 0;
|
||||||
swUi.Stop();
|
|
||||||
swOverall.Stop();
|
|
||||||
Logger.LogDebug($"[Search][TextChanged][{traceId}] UI update took {swUi.ElapsedMilliseconds} ms. total={swOverall.ElapsedMilliseconds} ms");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
|
private void SearchBox_SuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
|
||||||
@@ -709,23 +605,98 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
private void CtrlF_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
private void CtrlF_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||||
{
|
{
|
||||||
SearchBox.Focus(FocusState.Programmatic);
|
SearchBox.Focus(FocusState.Programmatic);
|
||||||
|
args.Handled = true; // prevent further processing (e.g., unintended navigation)
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SearchBox_GotFocus(object sender, RoutedEventArgs e)
|
private void SearchBox_GotFocus(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
// do not prompt unless search for text.
|
var box = sender as AutoSuggestBox;
|
||||||
return;
|
var current = box?.Text?.Trim() ?? string.Empty;
|
||||||
|
if (string.IsNullOrEmpty(current))
|
||||||
|
{
|
||||||
|
return; // nothing to restore
|
||||||
|
}
|
||||||
|
|
||||||
|
// If current text matches last query and we have results, reconstruct the suggestion list.
|
||||||
|
if (string.Equals(current, _lastQueryText, StringComparison.Ordinal) && _lastSearchResults?.Count > 0)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var top = BuildSuggestionItems(current, _lastSearchResults);
|
||||||
|
box.ItemsSource = top;
|
||||||
|
box.IsSuggestionListOpen = top.Count > 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogError($"Error restoring suggestion list {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Centralized suggestion projection logic used by TextChanged & GotFocus restore.
|
||||||
|
private List<SuggestionItem> BuildSuggestionItems(string query, List<SettingEntry> results)
|
||||||
|
{
|
||||||
|
results ??= new();
|
||||||
|
if (results.Count == 0)
|
||||||
|
{
|
||||||
|
var rl = ResourceLoaderInstance.ResourceLoader;
|
||||||
|
var noResultsPrefix = rl.GetString("Shell_Search_NoResults");
|
||||||
|
if (string.IsNullOrEmpty(noResultsPrefix))
|
||||||
|
{
|
||||||
|
noResultsPrefix = "No results for";
|
||||||
|
}
|
||||||
|
|
||||||
|
var headerText = $"{noResultsPrefix} '{query}'";
|
||||||
|
return new List<SuggestionItem>
|
||||||
|
{
|
||||||
|
new()
|
||||||
|
{
|
||||||
|
Header = headerText,
|
||||||
|
IsNoResults = true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var list = results.Take(5).Select(e =>
|
||||||
|
{
|
||||||
|
string subtitle = string.Empty;
|
||||||
|
if (e.Type != EntryType.SettingsPage)
|
||||||
|
{
|
||||||
|
subtitle = SearchIndexService.GetLocalizedPageName(e.PageTypeName);
|
||||||
|
if (string.IsNullOrEmpty(subtitle))
|
||||||
|
{
|
||||||
|
subtitle = SearchIndexService.Index
|
||||||
|
.Where(x => x.Type == EntryType.SettingsPage && x.PageTypeName == e.PageTypeName)
|
||||||
|
.Select(x => x.Header)
|
||||||
|
.FirstOrDefault() ?? string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SuggestionItem
|
||||||
|
{
|
||||||
|
Header = e.Header,
|
||||||
|
Icon = e.Icon,
|
||||||
|
PageTypeName = e.PageTypeName,
|
||||||
|
ElementName = e.ElementName,
|
||||||
|
ParentElementName = e.ParentElementName,
|
||||||
|
Subtitle = subtitle,
|
||||||
|
IsShowAll = false,
|
||||||
|
};
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
if (results.Count > 5)
|
||||||
|
{
|
||||||
|
list.Add(new SuggestionItem { IsShowAll = true });
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void SearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
private async void SearchBox_QuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
||||||
{
|
{
|
||||||
var swSubmit = Stopwatch.StartNew();
|
|
||||||
Logger.LogDebug("[Search][Submit] start");
|
|
||||||
|
|
||||||
// If a suggestion is selected, navigate directly
|
// If a suggestion is selected, navigate directly
|
||||||
if (args.ChosenSuggestion is SuggestionItem chosen)
|
if (args.ChosenSuggestion is SuggestionItem chosen)
|
||||||
{
|
{
|
||||||
Logger.LogDebug($"[Search][Submit] chosen suggestion -> navigate to {chosen.PageTypeName} element={chosen.ElementName ?? "<page>"}");
|
|
||||||
NavigateFromSuggestion(chosen);
|
NavigateFromSuggestion(chosen);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -733,7 +704,6 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
var queryText = (args.QueryText ?? _lastQueryText)?.Trim();
|
var queryText = (args.QueryText ?? _lastQueryText)?.Trim();
|
||||||
if (string.IsNullOrWhiteSpace(queryText))
|
if (string.IsNullOrWhiteSpace(queryText))
|
||||||
{
|
{
|
||||||
Logger.LogDebug("[Search][Submit] empty query -> navigate Dashboard");
|
|
||||||
NavigationService.Navigate<DashboardPage>();
|
NavigationService.Navigate<DashboardPage>();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -741,21 +711,10 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||||||
// Prefer cached results (from live search); if empty, perform a fresh search
|
// Prefer cached results (from live search); if empty, perform a fresh search
|
||||||
var matched = _lastSearchResults?.Count > 0 && string.Equals(_lastQueryText, queryText, StringComparison.Ordinal)
|
var matched = _lastSearchResults?.Count > 0 && string.Equals(_lastQueryText, queryText, StringComparison.Ordinal)
|
||||||
? _lastSearchResults
|
? _lastSearchResults
|
||||||
: await Task.Run(() =>
|
: await Task.Run(() => SearchIndexService.Search(queryText));
|
||||||
{
|
|
||||||
var sw = Stopwatch.StartNew();
|
|
||||||
Logger.LogDebug($"[Search][Submit] background search for '{queryText}'...");
|
|
||||||
var r = SearchIndexService.Search(queryText);
|
|
||||||
sw.Stop();
|
|
||||||
Logger.LogDebug($"[Search][Submit] background search done in {sw.ElapsedMilliseconds} ms. results={r?.Count ?? 0}");
|
|
||||||
return r;
|
|
||||||
});
|
|
||||||
|
|
||||||
var searchParams = new SearchResultsNavigationParams(queryText, matched);
|
var searchParams = new SearchResultsNavigationParams(queryText, matched);
|
||||||
Logger.LogDebug($"[Search][Submit] navigate to SearchResultsPage (results={matched?.Count ?? 0})");
|
|
||||||
NavigationService.Navigate<SearchResultsPage>(searchParams);
|
NavigationService.Navigate<SearchResultsPage>(searchParams);
|
||||||
swSubmit.Stop();
|
|
||||||
Logger.LogDebug($"[Search][Submit] total {swSubmit.ElapsedMilliseconds} ms");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -2691,6 +2691,12 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<value>Shortcuts with **Ctrl** and **Alt** may remove functionality from some international keyboards, because **Ctrl** + **Alt** = **Alt Gr** in those keyboards.</value>
|
<value>Shortcuts with **Ctrl** and **Alt** may remove functionality from some international keyboards, because **Ctrl** + **Alt** = **Alt Gr** in those keyboards.</value>
|
||||||
<comment>The ** sequences are used for text formatting of the key names. Don't remove them on translation.</comment>
|
<comment>The ** sequences are used for text formatting of the key names. Don't remove them on translation.</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="WarningShortcutConflict.Title" xml:space="preserve">
|
||||||
|
<value>Shortcut conflict</value>
|
||||||
|
</data>
|
||||||
|
<data name="WarningShortcutConflict.ToolTipService.ToolTip" xml:space="preserve">
|
||||||
|
<value>A conflict has been detected for this shortcut.</value>
|
||||||
|
</data>
|
||||||
<data name="FancyZones_SpanZonesAcrossMonitors.Description" xml:space="preserve">
|
<data name="FancyZones_SpanZonesAcrossMonitors.Description" xml:space="preserve">
|
||||||
<value>All monitors must have the same DPI scaling and will be treated as one large combined rectangle which contains all monitors</value>
|
<value>All monitors must have the same DPI scaling and will be treated as one large combined rectangle which contains all monitors</value>
|
||||||
</data>
|
</data>
|
||||||
@@ -2896,20 +2902,19 @@ Right-click to remove the key combination, thereby deactivating the shortcut.</v
|
|||||||
<data name="MouseUtils_GlidingCursor.Description" xml:space="preserve">
|
<data name="MouseUtils_GlidingCursor.Description" xml:space="preserve">
|
||||||
<value>An accessibility feature that lets you control the mouse with a single button using guided horizontal and vertical lines</value>
|
<value>An accessibility feature that lets you control the mouse with a single button using guided horizontal and vertical lines</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MouseUtils_GlidingCursor_InitialSpeed.Header" xml:space="preserve">
|
<data name="MouseUtils_GlidingCursor_InitialSpeed.Header" xml:space="preserve">
|
||||||
<value>Initial line speed</value>
|
<value>Initial line speed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MouseUtils_GlidingCursor_InitialSpeed.Description" xml:space="preserve">
|
<data name="MouseUtils_GlidingCursor_InitialSpeed.Description" xml:space="preserve">
|
||||||
<value>Speed of the horizontal or vertical line when it begins moving</value>
|
<value>Speed of the horizontal or vertical line when it begins moving</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MouseUtils_GlidingCursor_DelaySpeed.Header" xml:space="preserve">
|
<data name="MouseUtils_GlidingCursor_DelaySpeed.Header" xml:space="preserve">
|
||||||
<value>Reduced line speed</value>
|
<value>Reduced line speed</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="MouseUtils_GlidingCursor_DelaySpeed.Description" xml:space="preserve">
|
<data name="MouseUtils_GlidingCursor_DelaySpeed.Description" xml:space="preserve">
|
||||||
<value>Speed after slowing down the line with a second shortcut press</value>
|
<value>Speed after slowing down the line with a second shortcut press</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="FancyZones_Radio_Custom_Colors.Content" xml:space="preserve">
|
||||||
<data name="FancyZones_Radio_Custom_Colors.Content" xml:space="preserve">
|
|
||||||
<value>Custom colors</value>
|
<value>Custom colors</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="FancyZones_Radio_Default_Theme.Content" xml:space="preserve">
|
<data name="FancyZones_Radio_Default_Theme.Content" xml:space="preserve">
|
||||||
@@ -5266,7 +5271,7 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
|||||||
<value>All shortcuts function correctly</value>
|
<value>All shortcuts function correctly</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ResolveConflicts_Button.Content" xml:space="preserve">
|
<data name="ResolveConflicts_Button.Content" xml:space="preserve">
|
||||||
<value>Resolve conflicts</value>
|
<value>Resolve conflicts</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="ShortcutConflictControl_Title.Text" xml:space="preserve">
|
<data name="ShortcutConflictControl_Title.Text" xml:space="preserve">
|
||||||
<value>Shortcut conflicts</value>
|
<value>Shortcut conflicts</value>
|
||||||
@@ -5287,4 +5292,8 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
|||||||
<data name="Hosts_NoLeadingSpaces.Description" xml:space="preserve">
|
<data name="Hosts_NoLeadingSpaces.Description" xml:space="preserve">
|
||||||
<value>Do not prepend spaces to active lines when saving the hosts file</value>
|
<value>Do not prepend spaces to active lines when saving the hosts file</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="Search_ResultsFor" xml:space="preserve">
|
||||||
|
<value>Results for</value>
|
||||||
|
<comment>Prefix for search string. E.g. "Results for 'shortcut'"</comment>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
@@ -126,14 +126,21 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
{
|
{
|
||||||
var assembly = Assembly.GetExecutingAssembly();
|
var assembly = Assembly.GetExecutingAssembly();
|
||||||
var assemblyName = new AssemblyName(assembly.FullName ?? throw new InvalidOperationException());
|
var assemblyName = new AssemblyName(assembly.FullName ?? throw new InvalidOperationException());
|
||||||
|
|
||||||
|
// Build the fully-qualified manifest resource name. Historically, subtle casing differences
|
||||||
|
// (e.g. folder names or the assembly name) caused exact (case-sensitive) lookup failures on
|
||||||
|
// some developer machines when the embedded resource's actual name differed only by case.
|
||||||
|
// Manifest resource name comparison here does not need to be case-sensitive, so we resolve
|
||||||
|
// the actual name using an OrdinalIgnoreCase match, then use the real casing for the stream.
|
||||||
var resourceName = $"Microsoft.{assemblyName.Name}.{filename.Replace("/", ".")}";
|
var resourceName = $"Microsoft.{assemblyName.Name}.{filename.Replace("/", ".")}";
|
||||||
var resourceNames = assembly.GetManifestResourceNames();
|
var resourceNames = assembly.GetManifestResourceNames();
|
||||||
if (!resourceNames.Contains(resourceName))
|
var actualResourceName = resourceNames.FirstOrDefault(n => string.Equals(n, resourceName, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (actualResourceName is null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"Embedded resource '{resourceName}' does not exist.");
|
throw new InvalidOperationException($"Embedded resource '{resourceName}' (case-insensitive) does not exist.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var stream = assembly.GetManifestResourceStream(resourceName)
|
var stream = assembly.GetManifestResourceStream(actualResourceName)
|
||||||
?? throw new InvalidOperationException();
|
?? throw new InvalidOperationException();
|
||||||
var image = (Bitmap)Image.FromStream(stream);
|
var image = (Bitmap)Image.FromStream(stream);
|
||||||
return image;
|
return image;
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
|||||||
{
|
{
|
||||||
// Get current hotkey settings (fresh from file) using the accessor's getter
|
// Get current hotkey settings (fresh from file) using the accessor's getter
|
||||||
module.HotkeySettings = hotkeyAccessor.Value;
|
module.HotkeySettings = hotkeyAccessor.Value;
|
||||||
|
module.HotkeySettings.ConflictDescription = isSystemConflict
|
||||||
|
? ResourceLoaderInstance.ResourceLoader.GetString("SysHotkeyConflictTooltipText")
|
||||||
|
: ResourceLoaderInstance.ResourceLoader.GetString("InAppHotkeyConflictTooltipText");
|
||||||
|
|
||||||
// Set header using localization key
|
// Set header using localization key
|
||||||
module.Header = GetHotkeyLocalizationHeader(module.ModuleName, module.HotkeyID, hotkeyAccessor.LocalizationHeaderKey);
|
module.Header = GetHotkeyLocalizationHeader(module.ModuleName, module.HotkeyID, hotkeyAccessor.LocalizationHeaderKey);
|
||||||
|
|||||||
Reference in New Issue
Block a user