Merge branch 'main' into dev/seraphima/tests/29246-fancyzones-tests-initial-step
@@ -24,7 +24,7 @@ namespace Microsoft.VariantAssignment.Contract
|
||||
public bool EnableCaching { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the the maximum time a cached variant assignment response may be used without re-validating.
|
||||
/// Gets or sets the maximum time a cached variant assignment response may be used without re-validating.
|
||||
/// </summary>
|
||||
public TimeSpan ResponseCacheTime { get; set; }
|
||||
}
|
||||
|
||||
16
src/common/Common.UI/OSVersionHelper.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// 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;
|
||||
|
||||
namespace Common.UI
|
||||
{
|
||||
public static class OSVersionHelper
|
||||
{
|
||||
public static bool IsWindows11()
|
||||
{
|
||||
return Environment.OSVersion.Version.Major >= 10 && Environment.OSVersion.Version.Build >= 22000;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Markdig.Signed" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" />
|
||||
<PackageReference Include="UTF.Unknown" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -107,6 +107,7 @@ namespace Microsoft.PowerToys.FilePreviewCommon
|
||||
public static string ReadIndexHtml()
|
||||
{
|
||||
string html;
|
||||
|
||||
using (StreamReader htmlFileReader = new StreamReader(new FileStream(MonacoDirectory + "\\index.html", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)))
|
||||
{
|
||||
html = htmlFileReader.ReadToEnd();
|
||||
|
||||
@@ -152,4 +152,12 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredEnvironmentVariablesEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredQoiPreviewEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredQoiPreviewEnabledValue());
|
||||
}
|
||||
GpoRuleConfigured GPOWrapper::GetConfiguredQoiThumbnailsEnabledValue()
|
||||
{
|
||||
return static_cast<GpoRuleConfigured>(powertoys_gpo::getConfiguredQoiThumbnailsEnabledValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,8 @@ namespace winrt::PowerToys::GPOWrapper::implementation
|
||||
static GpoRuleConfigured GetAllowExperimentationValue();
|
||||
static GpoRuleConfigured GetRunPluginEnabledValue(winrt::hstring const& pluginID);
|
||||
static GpoRuleConfigured GetConfiguredEnvironmentVariablesEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ namespace PowerToys
|
||||
static GpoRuleConfigured GetAllowExperimentationValue();
|
||||
static GpoRuleConfigured GetRunPluginEnabledValue(String pluginID);
|
||||
static GpoRuleConfigured GetConfiguredEnvironmentVariablesEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiPreviewEnabledValue();
|
||||
static GpoRuleConfigured GetConfiguredQoiThumbnailsEnabledValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
src/common/ManagedCommon/ModuleType.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace ManagedCommon
|
||||
{
|
||||
public enum ModuleType
|
||||
{
|
||||
AlwaysOnTop,
|
||||
Awake,
|
||||
ColorPicker,
|
||||
CropAndLock,
|
||||
EnvironmentVariables,
|
||||
FancyZones,
|
||||
FileLocksmith,
|
||||
FindMyMouse,
|
||||
Hosts,
|
||||
ImageResizer,
|
||||
KeyboardManager,
|
||||
MouseHighlighter,
|
||||
MouseJump,
|
||||
MousePointerCrosshairs,
|
||||
MouseWithoutBorders,
|
||||
PastePlain,
|
||||
Peek,
|
||||
PowerRename,
|
||||
PowerLauncher,
|
||||
PowerAccent,
|
||||
RegistryPreview,
|
||||
MeasureTool,
|
||||
ShortcutGuide,
|
||||
PowerOCR,
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,9 @@ namespace Microsoft.Interop.Tests
|
||||
serverPipe.Start();
|
||||
ClientPipe.Start();
|
||||
|
||||
// Test can be flaky as the pipes are still being set up and we end up receiving no message. Wait for a bit to avoid that.
|
||||
Thread.Sleep(100);
|
||||
|
||||
ClientPipe.Send(testString);
|
||||
reset.WaitOne();
|
||||
|
||||
|
||||
@@ -235,6 +235,10 @@ public
|
||||
return gcnew String(CommonSharedConstants::GCODE_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ QoiPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::QOI_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
static String ^ DevFilesPreviewResizeEvent() {
|
||||
return gcnew String(CommonSharedConstants::DEV_FILES_PREVIEW_RESIZE_EVENT);
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ void LayoutMap::LayoutMapImpl::UpdateLayout()
|
||||
keyboardLayoutMap[VK_RETURN | numpadOriginBit] = L"Enter (Numpad)";
|
||||
keyboardLayoutMap[VK_DIVIDE | numpadOriginBit] = L"/ (Numpad)";
|
||||
|
||||
keyboardLayoutMap[VK_SUBTRACT] = L"- (Substract)";
|
||||
keyboardLayoutMap[VK_SUBTRACT] = L"- (Subtract)";
|
||||
keyboardLayoutMap[VK_SELECT] = L"Select";
|
||||
keyboardLayoutMap[VK_PRINT] = L"Print";
|
||||
keyboardLayoutMap[VK_EXECUTE] = L"Execute";
|
||||
|
||||
@@ -62,6 +62,9 @@ namespace CommonSharedConstants
|
||||
// Path to the event used by GcodePreviewHandler
|
||||
const wchar_t GCODE_PREVIEW_RESIZE_EVENT[] = L"Local\\PowerToysGcodePreviewResizeEvent-6ff1f9bd-ccbd-4b24-a79f-40a34fb0317d";
|
||||
|
||||
// Path to the event used by QoiPreviewHandler
|
||||
const wchar_t QOI_PREVIEW_RESIZE_EVENT[] = L"Local\\PowerToysQoiPreviewResizeEvent-579518d1-8c8b-494f-8143-04f43d761ead";
|
||||
|
||||
// Path to the event used by DevFilesPreviewHandler
|
||||
const wchar_t DEV_FILES_PREVIEW_RESIZE_EVENT[] = L"Local\\PowerToysDevFilesPreviewResizeEvent-5707a22c-2cac-4ea2-82f0-27c03ef0b5f3";
|
||||
|
||||
|
||||
@@ -27,6 +27,10 @@ struct LogSettings
|
||||
inline const static std::wstring pdfPrevLogPath = L"logs\\FileExplorer_localLow\\PdfPrevHandler\\pdf-prev-handler-log.txt";
|
||||
inline const static std::string pdfThumbLoggerName = "PdfThumbnailProvider";
|
||||
inline const static std::wstring pdfThumbLogPath = L"logs\\FileExplorer_localLow\\PdfThumbnailProvider\\pdf-thumbnail-provider-log.txt";
|
||||
inline const static std::string qoiPrevLoggerName = "QoiPrevHandler";
|
||||
inline const static std::wstring qoiPrevLogPath = L"logs\\FileExplorer_localLow\\QoiPreviewHandler\\qoi-prev-handler-log.txt";
|
||||
inline const static std::string qoiThumbLoggerName = "QoiThumbnailProvider";
|
||||
inline const static std::wstring qoiThumbLogPath = L"logs\\FileExplorer_localLow\\QoiThumbnailProvider\\qoi-thumbnail-provider-log.txt";
|
||||
inline const static std::string stlThumbLoggerName = "StlThumbnailProvider";
|
||||
inline const static std::wstring stlThumbLogPath = L"logs\\FileExplorer_localLow\\StlThumbnailProvider\\stl-thumbnail-provider-log.txt";
|
||||
inline const static std::string svgPrevLoggerName = "SvgPrevHandler";
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 5205)
|
||||
#include <winrt/base.h>
|
||||
#pragma warning(default : 5205)
|
||||
#pragma warning(pop)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <Windows.h>
|
||||
|
||||
@@ -56,6 +56,8 @@ namespace powertoys_gpo {
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_MOUSE_WITHOUT_BORDERS = L"ConfigureEnabledUtilityMouseWithoutBorders";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_PEEK = L"ConfigureEnabledUtilityPeek";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_ENVIRONMENT_VARIABLES = L"ConfigureEnabledUtilityEnvironmentVariables";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_QOI_PREVIEW = L"ConfigureEnabledUtilityFileExplorerQOIPreview";
|
||||
const std::wstring POLICY_CONFIGURE_ENABLED_QOI_THUMBNAILS = L"ConfigureEnabledUtilityFileExplorerQOIThumbnails";
|
||||
|
||||
// The registry value names for PowerToys installer and update policies.
|
||||
const std::wstring POLICY_DISABLE_PER_USER_INSTALLATION = L"PerUserInstallationDisabled";
|
||||
@@ -366,7 +368,7 @@ namespace powertoys_gpo {
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_MOUSE_WITHOUT_BORDERS);
|
||||
}
|
||||
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredPeekEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_PEEK);
|
||||
@@ -446,4 +448,14 @@ namespace powertoys_gpo {
|
||||
return getConfiguredValue(POLICY_CONFIGURE_ENABLED_POWER_LAUNCHER_ALL_PLUGINS);
|
||||
}
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredQoiPreviewEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_QOI_PREVIEW);
|
||||
}
|
||||
|
||||
inline gpo_rule_configured_t getConfiguredQoiThumbnailsEnabledValue()
|
||||
{
|
||||
return getUtilityEnabledValue(POLICY_CONFIGURE_ENABLED_QOI_THUMBNAILS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,4 +70,40 @@ namespace json
|
||||
{
|
||||
return value; // identity function overload for convenience
|
||||
}
|
||||
|
||||
template<typename T, typename D = std::optional<T>>
|
||||
requires std::constructible_from<std::optional<T>, D>
|
||||
void get(const json::JsonObject& o, const wchar_t* name, T& destination, D default_value = std::nullopt)
|
||||
{
|
||||
try
|
||||
{
|
||||
if constexpr (std::is_same_v<T, bool>)
|
||||
{
|
||||
destination = o.GetNamedBoolean(name);
|
||||
}
|
||||
else if constexpr (std::is_arithmetic_v<T>)
|
||||
{
|
||||
destination = static_cast<T>(o.GetNamedNumber(name));
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, std::wstring>)
|
||||
{
|
||||
destination = o.GetNamedString(name);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, json::JsonObject>)
|
||||
{
|
||||
destination = o.GetNamedObject(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
static_assert(std::bool_constant<std::is_same_v<T, T&>>::value, "Unsupported type");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
std::optional<T> maybe_default{ std::move(default_value) };
|
||||
if (maybe_default.has_value())
|
||||
destination = std::move(*maybe_default);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@ namespace NonLocalizable
|
||||
const static std::vector<std::wstring> ExtPDF = { L".pdf" };
|
||||
const static std::vector<std::wstring> ExtGCode = { L".gcode" };
|
||||
const static std::vector<std::wstring> ExtSTL = { L".stl" };
|
||||
const static std::vector<std::wstring> ExtNoNoNo = {
|
||||
const static std::vector<std::wstring> ExtQOI = { L".qoi" };
|
||||
const static std::vector<std::wstring> ExtNoNoNo = {
|
||||
L".svgz" //Monaco cannot handle this file type at all; it's a binary file.
|
||||
};
|
||||
}
|
||||
@@ -145,6 +146,19 @@ inline registry::ChangeSet getGcodePreviewHandlerChangeSet(const std::wstring in
|
||||
NonLocalizable::ExtGCode);
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getQoiPreviewHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::preview,
|
||||
perUser,
|
||||
L"{729B72CD-B72E-4FE9-BCBF-E954B33FE699}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } / LR"d(PowerToys.QoiPreviewHandlerCpp.dll)d").wstring(),
|
||||
L"QoiPreviewHandler",
|
||||
L"Qoi Preview Handler",
|
||||
NonLocalizable::ExtQOI);
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getSvgThumbnailHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
@@ -156,6 +170,7 @@ inline registry::ChangeSet getSvgThumbnailHandlerChangeSet(const std::wstring in
|
||||
L"SvgThumbnailProvider",
|
||||
L"Svg Thumbnail Provider",
|
||||
NonLocalizable::ExtSVG,
|
||||
L"image",
|
||||
L"Picture");
|
||||
}
|
||||
|
||||
@@ -198,6 +213,21 @@ inline registry::ChangeSet getStlThumbnailHandlerChangeSet(const std::wstring in
|
||||
NonLocalizable::ExtSTL);
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getQoiThumbnailHandlerChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
using namespace registry::shellex;
|
||||
return generatePreviewHandler(PreviewHandlerType::thumbnail,
|
||||
perUser,
|
||||
L"{AD856B15-D25E-4008-AFB7-AFAA55586188}",
|
||||
get_std_product_version(),
|
||||
(fs::path{ installationDir } / LR"d(PowerToys.QoiThumbnailProviderCpp.dll)d").wstring(),
|
||||
L"QoiThumbnailProvider",
|
||||
L"Qoi Thumbnail Provider",
|
||||
NonLocalizable::ExtQOI,
|
||||
L"image",
|
||||
L"Picture");
|
||||
}
|
||||
|
||||
inline registry::ChangeSet getRegistryPreviewSetDefaultAppChangeSet(const std::wstring installationDir, const bool perUser)
|
||||
{
|
||||
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
|
||||
@@ -245,9 +275,11 @@ inline std::vector<registry::ChangeSet> getAllOnByDefaultModulesChangeSets(const
|
||||
getMdPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getMonacoPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodePreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getQoiPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getSvgThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getStlThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getQoiThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getRegistryPreviewChangeSet(installationDir, PER_USER) };
|
||||
}
|
||||
|
||||
@@ -259,10 +291,12 @@ inline std::vector<registry::ChangeSet> getAllModulesChangeSets(const std::wstri
|
||||
getMonacoPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getPdfPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodePreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getQoiPreviewHandlerChangeSet(installationDir, PER_USER),
|
||||
getSvgThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getPdfThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getGcodeThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getStlThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getQoiThumbnailHandlerChangeSet(installationDir, PER_USER),
|
||||
getRegistryPreviewChangeSet(installationDir, PER_USER),
|
||||
getRegistryPreviewSetDefaultAppChangeSet(installationDir, PER_USER) };
|
||||
}
|
||||
|
||||
@@ -395,6 +395,7 @@ namespace registry
|
||||
std::wstring className,
|
||||
std::wstring displayName,
|
||||
std::vector<std::wstring> fileTypes,
|
||||
std::wstring perceivedType = L"",
|
||||
std::wstring fileKindType = L"")
|
||||
{
|
||||
const HKEY scope = perUser ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
|
||||
@@ -436,9 +437,8 @@ namespace registry
|
||||
|
||||
for (const auto& fileType : fileTypes)
|
||||
{
|
||||
std::wstring fileAssociationPath = L"Software\\Classes\\";
|
||||
fileAssociationPath += fileType;
|
||||
fileAssociationPath += L"\\shellex\\";
|
||||
std::wstring fileTypePath = L"Software\\Classes\\" + fileType;
|
||||
std::wstring fileAssociationPath = fileTypePath + L"\\shellex\\";
|
||||
fileAssociationPath += handlerType == PreviewHandlerType::preview ? IPREVIEW_HANDLER_CLSID : ITHUMBNAIL_PROVIDER_CLSID;
|
||||
changes.push_back({ scope, fileAssociationPath, std::nullopt, handlerClsid });
|
||||
if (!fileKindType.empty())
|
||||
@@ -448,6 +448,10 @@ namespace registry
|
||||
std::wstring kindMapPath = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\KindMap";
|
||||
changes.push_back({ HKEY_LOCAL_MACHINE, kindMapPath, fileType, fileKindType, false});
|
||||
}
|
||||
if (!perceivedType.empty())
|
||||
{
|
||||
changes.push_back({ scope, fileTypePath, L"PerceivedType", perceivedType });
|
||||
}
|
||||
if (handlerType == PreviewHandlerType::preview && fileType == L".reg")
|
||||
{
|
||||
// this regfile registry key has precedence over Software\Classes\.reg for .reg files
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.4" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitions xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.5" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyNamespaces>
|
||||
<target prefix="powertoys" namespace="Microsoft.Policies.PowerToys" />
|
||||
</policyNamespaces>
|
||||
<resources minRequiredRevision="1.4"/><!-- Last changed with PowerToys v0.75.0 -->
|
||||
<resources minRequiredRevision="1.6"/><!-- Last changed with PowerToys v0.76.0 -->
|
||||
<supportedOn>
|
||||
<definitions>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_64_0" displayName="$(string.SUPPORTED_POWERTOYS_0_64_0)"/>
|
||||
@@ -14,6 +14,7 @@
|
||||
<definition name="SUPPORTED_POWERTOYS_0_70_0" displayName="$(string.SUPPORTED_POWERTOYS_0_70_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_73_0" displayName="$(string.SUPPORTED_POWERTOYS_0_73_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_75_0" displayName="$(string.SUPPORTED_POWERTOYS_0_75_0)"/>
|
||||
<definition name="SUPPORTED_POWERTOYS_0_76_0" displayName="$(string.SUPPORTED_POWERTOYS_0_76_0)"/>
|
||||
</definitions>
|
||||
</supportedOn>
|
||||
<categories>
|
||||
@@ -78,6 +79,16 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityEnvironmentVariables" class="Both" displayName="$(string.ConfigureEnabledUtilityEnvironmentVariables)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityEnvironmentVariables">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_75_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityFancyZones" class="Both" displayName="$(string.ConfigureEnabledUtilityFancyZones)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityFancyZones">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
@@ -178,6 +189,26 @@
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityFileExplorerQOIPreview" class="Both" displayName="$(string.ConfigureEnabledUtilityFileExplorerQOIPreview)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityFileExplorerQOIPreview">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_76_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityFileExplorerQOIThumbnails" class="Both" displayName="$(string.ConfigureEnabledUtilityFileExplorerQOIThumbnails)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityFileExplorerQOIThumbnails">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_76_0" />
|
||||
<enabledValue>
|
||||
<decimal value="1" />
|
||||
</enabledValue>
|
||||
<disabledValue>
|
||||
<decimal value="0" />
|
||||
</disabledValue>
|
||||
</policy>
|
||||
<policy name="ConfigureEnabledUtilityFileExplorerSTLThumbnails" class="Both" displayName="$(string.ConfigureEnabledUtilityFileExplorerSTLThumbnails)" explainText="$(string.ConfigureEnabledUtilityDescription)" key="Software\Policies\PowerToys" valueName="ConfigureEnabledUtilityFileExplorerSTLThumbnails">
|
||||
<parentCategory ref="PowerToys" />
|
||||
<supportedOn ref="SUPPORTED_POWERTOYS_0_64_0" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (c) Microsoft Corporation.
|
||||
Licensed under the MIT License. -->
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.4" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<policyDefinitionResources xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" revision="1.6" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions">
|
||||
<displayName>PowerToys</displayName>
|
||||
<description>PowerToys</description>
|
||||
<resources>
|
||||
@@ -16,6 +16,7 @@
|
||||
<string id="SUPPORTED_POWERTOYS_0_70_0">PowerToys version 0.70.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_73_0">PowerToys version 0.73.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_75_0">PowerToys version 0.75.0 or later</string>
|
||||
<string id="SUPPORTED_POWERTOYS_0_76_0">PowerToys version 0.76.0 or later</string>
|
||||
|
||||
<string id="ConfigureGlobalUtilityEnabledStateDescription">This policy configures the enabled state for all PowerToys utilities.
|
||||
|
||||
@@ -23,7 +24,7 @@ If you enable this setting, all utilities will be always enabled and the user wo
|
||||
|
||||
If you disable this setting, all utilities will be always disabled and the user won't be able to enable it.
|
||||
|
||||
If you don't configure this setting, users are able to disable or enable the utilities.
|
||||
If you don't configure this setting, users are able to enable or disable the utilities.
|
||||
|
||||
The individual enabled state policies for the utilities will override this policy.
|
||||
</string>
|
||||
@@ -34,7 +35,7 @@ If you enable this setting, the utility will be always enabled and the user won'
|
||||
|
||||
If you disable this setting, the utility will be always disabled and the user won't be able to enable it.
|
||||
|
||||
If you don't configure this setting, users are able to disable or enable the utility.
|
||||
If you don't configure this setting, users are able to enable or disable the utility.
|
||||
|
||||
This policy has a higher priority than the policy "Configure global utility enabled state" and overrides it.
|
||||
</string>
|
||||
@@ -46,7 +47,7 @@ If you enable this setting, the utility will be always enabled and the user won'
|
||||
|
||||
If you disable this setting, the utility will be always disabled and the user won't be able to enable it.
|
||||
|
||||
If you don't configure this setting, users are able to disable or enable the utility.
|
||||
If you don't configure this setting, users are able to enable or disable the utility.
|
||||
|
||||
This policy has a higher priority than the policy "Configure global utility enabled state" and overrides it.
|
||||
</string>
|
||||
@@ -78,7 +79,7 @@ If disabled or not configured, the automatic update checks are enabled.
|
||||
</string>
|
||||
<string id="AllowExperimentationDescription">This policy configures whether PowerToys experimentation is allowed. With experimentation allowed the user sees the new features being experimented if it gets selected as part of the test group. (Experimentation will only happen on Windows Insider builds.)
|
||||
|
||||
If this setting is not configured or enabled, the user can control experimentation in the PowerToys settings menu.
|
||||
If this setting is enabled or not configured, the user can control experimentation in the PowerToys settings menu.
|
||||
|
||||
If this setting is disabled, experimentation is not allowed.
|
||||
</string>
|
||||
@@ -88,22 +89,22 @@ If you enable this setting, the plugins will be always enabled and the user won'
|
||||
|
||||
If you disable this setting, the plugins will be always disabled and the user won't be able to enable it.
|
||||
|
||||
If you don't configure this setting, users are able to disable or enable the plugins.
|
||||
If you don't configure this setting, users are able to enable or disable the plugins.
|
||||
|
||||
You can override this policy for individual plugins using the policy "Configure enabled state for individual plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
<string id="PowerToysRunIndividualPluginEnabledStateDescription">With this policy you can configures an individual enabled state for each PowerToys Run plugin that you add to the list.
|
||||
<string id="PowerToysRunIndividualPluginEnabledStateDescription">With this policy you can configure an individual enabled state for each PowerToys Run plugin that you add to the list.
|
||||
|
||||
If you enable this setting, you can define the list of plugins and their enabled states:
|
||||
- The value name (first column) is the plugin ID. You will find it in the plugin.json which is located in the plugin folder.
|
||||
- The value name (first column) is the plugin ID. You will find it in the plugin.json file which is located in the plugin folder.
|
||||
- The value (second column) is a numeric value: 0 for disabled, 1 for enabled and 2 for user takes control.
|
||||
- Example to disable the Program plugin: 791FC278BA414111B8D1886DFE447410 | 0
|
||||
|
||||
If you disable or don't configure this policy, either the user or the policy "Configure enabled state for all plugins" takes control over the enabled state of the plugins.
|
||||
|
||||
You can set the enabled state for all plugins not listed here using the policy "Configure enabled state for all plugins".
|
||||
You can set the enabled state for all plugins not configured by this policy using the policy "Configure enabled state for all plugins".
|
||||
|
||||
Note: Changes require a restart of PowerToys Run.
|
||||
</string>
|
||||
@@ -112,6 +113,7 @@ Note: Changes require a restart of PowerToys Run.
|
||||
<string id="ConfigureEnabledUtilityAwake">Awake: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityColorPicker">Color Picker: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityCropAndLock">Crop And Lock: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityEnvironmentVariables">Environment Variables: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFancyZones">FancyZones: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileLocksmith">File Locksmith: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerSVGPreview">SVG file preview: Configure enabled state</string>
|
||||
@@ -148,6 +150,8 @@ Note: Changes require a restart of PowerToys Run.
|
||||
<string id="AllowExperimentation">Allow Experimentation</string>
|
||||
<string id="PowerToysRunAllPluginsEnabledState">Configure enabled state for all plugins</string>
|
||||
<string id="PowerToysRunIndividualPluginEnabledState">Configure enabled state for individual plugins</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIPreview">QOI file preview: Configure enabled state</string>
|
||||
<string id="ConfigureEnabledUtilityFileExplorerQOIThumbnails">QOI file thumbnail: Configure enabled state</string>
|
||||
</stringTable>
|
||||
|
||||
<presentationTable>
|
||||
|
||||
@@ -87,12 +87,29 @@ void ReparentCropAndLockWindow::CropAndLock(HWND windowToCrop, RECT cropRect)
|
||||
DisconnectTarget();
|
||||
m_currentTarget = windowToCrop;
|
||||
|
||||
// Adjust the crop rect to be in the window space as reported by win32k
|
||||
// Save original state
|
||||
SaveOriginalState();
|
||||
|
||||
RECT windowRect = {};
|
||||
winrt::check_bool(GetWindowRect(m_currentTarget, &windowRect));
|
||||
auto clientRect = ClientAreaInScreenSpace(m_currentTarget);
|
||||
|
||||
WINDOWPLACEMENT windowPlacement = { sizeof(windowPlacement) };
|
||||
winrt::check_bool(GetWindowPlacement(m_currentTarget, &windowPlacement));
|
||||
bool isMaximized = (windowPlacement.showCmd == SW_SHOWMAXIMIZED);
|
||||
|
||||
auto diffX = clientRect.left - windowRect.left;
|
||||
auto diffY = clientRect.top - windowRect.top;
|
||||
|
||||
if (isMaximized)
|
||||
{
|
||||
MONITORINFO mi = { sizeof(mi) };
|
||||
winrt::check_bool(GetMonitorInfo(MonitorFromWindow(m_currentTarget, MONITOR_DEFAULTTONEAREST), &mi));
|
||||
|
||||
diffX = mi.rcWork.left - windowRect.left;
|
||||
diffY = mi.rcWork.top - windowRect.top;
|
||||
}
|
||||
|
||||
auto adjustedCropRect = cropRect;
|
||||
adjustedCropRect.left += diffX;
|
||||
adjustedCropRect.top += diffY;
|
||||
@@ -100,8 +117,6 @@ void ReparentCropAndLockWindow::CropAndLock(HWND windowToCrop, RECT cropRect)
|
||||
adjustedCropRect.bottom += diffY;
|
||||
cropRect = adjustedCropRect;
|
||||
|
||||
// Save the previous position of the target so that we can restore it.
|
||||
m_previousPosition = { windowRect.left, windowRect.top };
|
||||
auto newX = adjustedCropRect.left + windowRect.left;
|
||||
auto newY = adjustedCropRect.top + windowRect.top;
|
||||
|
||||
@@ -152,12 +167,54 @@ void ReparentCropAndLockWindow::DisconnectTarget()
|
||||
// The child window was closed by other means?
|
||||
m_currentTarget = nullptr;
|
||||
return;
|
||||
}
|
||||
winrt::check_bool(SetWindowPos(m_currentTarget, nullptr, m_previousPosition.x, m_previousPosition.y, 0, 0, SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED));
|
||||
SetParent(m_currentTarget, nullptr);
|
||||
auto targetStyle = static_cast<DWORD>(GetWindowLongPtrW(m_currentTarget, GWL_STYLE));
|
||||
targetStyle &= ~WS_CHILD;
|
||||
SetWindowLongPtrW(m_currentTarget, GWL_STYLE, targetStyle);
|
||||
m_currentTarget = nullptr;
|
||||
}
|
||||
|
||||
RestoreOriginalState();
|
||||
}
|
||||
}
|
||||
|
||||
void ReparentCropAndLockWindow::SaveOriginalState()
|
||||
{
|
||||
if (m_currentTarget != nullptr)
|
||||
{
|
||||
originalPlacement.length = sizeof(WINDOWPLACEMENT);
|
||||
winrt::check_bool(GetWindowPlacement(m_currentTarget, &originalPlacement));
|
||||
|
||||
originalExStyle = GetWindowLongPtr(m_currentTarget, GWL_EXSTYLE);
|
||||
winrt::check_bool(originalExStyle != 0 || GetLastError() == ERROR_SUCCESS);
|
||||
|
||||
originalStyle = GetWindowLongPtr(m_currentTarget, GWL_STYLE);
|
||||
winrt::check_bool(originalStyle != 0 || GetLastError() == ERROR_SUCCESS);
|
||||
|
||||
winrt::check_bool(GetWindowRect(m_currentTarget, &originalRect));
|
||||
}
|
||||
}
|
||||
|
||||
void ReparentCropAndLockWindow::RestoreOriginalState()
|
||||
{
|
||||
if (m_currentTarget)
|
||||
{
|
||||
// Restore window position and dimensions
|
||||
int width = originalRect.right - originalRect.left;
|
||||
int height = originalRect.bottom - originalRect.top;
|
||||
winrt::check_bool(SetWindowPos(m_currentTarget, nullptr, originalRect.left, originalRect.top, width, height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED));
|
||||
|
||||
SetParent(m_currentTarget, nullptr);
|
||||
|
||||
// Restore the original placement
|
||||
if (originalPlacement.showCmd != SW_SHOWMAXIMIZED)
|
||||
{
|
||||
originalPlacement.showCmd = SW_RESTORE;
|
||||
}
|
||||
|
||||
winrt::check_bool(SetWindowPlacement(m_currentTarget, &originalPlacement));
|
||||
|
||||
// Set the original extended style and style
|
||||
originalStyle &= ~WS_CHILD;
|
||||
LONG_PTR prevExStyle = SetWindowLongPtr(m_currentTarget, GWL_EXSTYLE, originalExStyle);
|
||||
winrt::check_bool(prevExStyle != 0 || GetLastError() == ERROR_SUCCESS);
|
||||
|
||||
LONG_PTR prevStyle = SetWindowLongPtr(m_currentTarget, GWL_STYLE, originalStyle);
|
||||
winrt::check_bool(prevStyle != 0 || GetLastError() == ERROR_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,17 @@ private:
|
||||
|
||||
void Hide();
|
||||
void DisconnectTarget();
|
||||
void SaveOriginalState();
|
||||
void RestoreOriginalState();
|
||||
|
||||
private:
|
||||
HWND m_currentTarget = nullptr;
|
||||
POINT m_previousPosition = {};
|
||||
std::unique_ptr<ChildWindow> m_childWindow;
|
||||
bool m_destroyed = false;
|
||||
std::function<void(HWND)> m_closedCallback;
|
||||
|
||||
LONG_PTR originalExStyle = 0;
|
||||
LONG_PTR originalStyle = 0;
|
||||
WINDOWPLACEMENT originalPlacement = { sizeof(WINDOWPLACEMENT) };
|
||||
RECT originalRect = {};
|
||||
};
|
||||
@@ -188,7 +188,7 @@ int WINAPI wWinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ PWSTR lpCmdLine, _I
|
||||
m_reparent_event_handle = CreateEventW(nullptr, false, false, CommonSharedConstants::CROP_AND_LOCK_REPARENT_EVENT);
|
||||
m_thumbnail_event_handle = CreateEventW(nullptr, false, false, CommonSharedConstants::CROP_AND_LOCK_THUMBNAIL_EVENT);
|
||||
m_exit_event_handle = CreateEventW(nullptr, false, false, CommonSharedConstants::CROP_AND_LOCK_EXIT_EVENT);
|
||||
if (!m_reparent_event_handle || !m_reparent_event_handle || !m_exit_event_handle)
|
||||
if (!m_reparent_event_handle || !m_thumbnail_event_handle || !m_exit_event_handle)
|
||||
{
|
||||
Logger::warn(L"Failed to create events. {}", get_last_error_or_default(GetLastError()));
|
||||
return 1;
|
||||
|
||||
@@ -12,21 +12,66 @@
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonBackground" Color="{ThemeResource SubtleFillColorTransparent}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundDisabled" Color="{ThemeResource ControlFillColorDisabled}" />
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonForeground" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPointerOver" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPressed" Color="{ThemeResource TextFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundDisabled" Color="{ThemeResource TextFillColorDisabled}" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Style x:Key="SubtleButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
@@ -53,11 +98,11 @@
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Foreground="{TemplateBinding Foreground}">
|
||||
<ContentPresenter.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</ContentPresenter.BackgroundTransition>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
@@ -66,6 +111,9 @@
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -74,12 +122,14 @@
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -88,12 +138,14 @@
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
@@ -24,10 +24,24 @@
|
||||
<DataTemplate x:Key="VariableTemplate" x:DataType="models:Variable">
|
||||
<controls:SettingsCard
|
||||
CommandParameter="{x:Bind (models:Variable)}"
|
||||
Header="{x:Bind Name, Mode=TwoWay}"
|
||||
IsActionIconVisible="False"
|
||||
IsClickEnabled="False"
|
||||
Style="{StaticResource DefaultSettingsExpanderItemStyle}">
|
||||
<controls:SettingsCard.Header>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock Text="{x:Bind Name, Mode=TwoWay}" />
|
||||
<FontIcon
|
||||
Margin="6,0,6,0"
|
||||
FontSize="16"
|
||||
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||
Glyph=""
|
||||
Visibility="{x:Bind IsAppliedFromProfile, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="VariableIsAppliedByActiveProfileTooltip" TextWrapping="Wrap" />
|
||||
</ToolTipService.ToolTip>
|
||||
</FontIcon>
|
||||
</StackPanel>
|
||||
</controls:SettingsCard.Header>
|
||||
<controls:SettingsCard.Description>
|
||||
<StackPanel HorizontalAlignment="Left">
|
||||
<ItemsControl
|
||||
@@ -52,7 +66,6 @@
|
||||
Visibility="{x:Bind ShowAsList, Converter={StaticResource BoolToInvertedVisibilityConverter}}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard.Description>
|
||||
|
||||
<Button
|
||||
Content="{ui:FontIcon Glyph=}"
|
||||
IsEnabled="{x:Bind IsEditable}"
|
||||
@@ -622,7 +635,8 @@
|
||||
<Flyout
|
||||
x:Name="AddVariableFlyout"
|
||||
Closed="AddVariableFlyout_Closed"
|
||||
Placement="Right">
|
||||
Placement="Right"
|
||||
ShouldConstrainToRootBounds="False">
|
||||
<Grid Width="320" Height="480">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
|
||||
@@ -21,25 +21,25 @@ namespace EnvironmentVariables.Helpers
|
||||
|
||||
internal static Variable GetExisting(string variableName)
|
||||
{
|
||||
var userVariables = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.User);
|
||||
DefaultVariablesSet userSet = new DefaultVariablesSet(Guid.NewGuid(), "tmpUser", VariablesSetType.User);
|
||||
GetVariables(EnvironmentVariableTarget.User, userSet);
|
||||
|
||||
foreach (DictionaryEntry variable in userVariables)
|
||||
foreach (var variable in userSet.Variables)
|
||||
{
|
||||
var key = variable.Key as string;
|
||||
if (key.Equals(variableName, StringComparison.OrdinalIgnoreCase))
|
||||
if (variable.Name.Equals(variableName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Variable(key, userVariables[key] as string, VariablesSetType.User);
|
||||
return new Variable(variable.Name, variable.Values, VariablesSetType.User);
|
||||
}
|
||||
}
|
||||
|
||||
var systemVariables = Environment.GetEnvironmentVariables(EnvironmentVariableTarget.Machine);
|
||||
DefaultVariablesSet systemSet = new DefaultVariablesSet(Guid.NewGuid(), "tmpSystem", VariablesSetType.System);
|
||||
GetVariables(EnvironmentVariableTarget.Machine, systemSet);
|
||||
|
||||
foreach (DictionaryEntry variable in systemVariables)
|
||||
foreach (var variable in systemSet.Variables)
|
||||
{
|
||||
var key = variable.Key as string;
|
||||
if (key.Equals(variableName, StringComparison.OrdinalIgnoreCase))
|
||||
if (variable.Name.Equals(variableName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
return new Variable(key, systemVariables[key] as string, VariablesSetType.System);
|
||||
return new Variable(variable.Name, variable.Values, VariablesSetType.System);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,9 @@ namespace EnvironmentVariables.Helpers
|
||||
return baseKey.OpenSubKey(keyName, writable: writable);
|
||||
}
|
||||
|
||||
// Code taken from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs
|
||||
// Set variables directly to registry instead of using Environment API - Environment.SetEnvironmentVariable() has 1 second timeout for SendNotifyMessage(WM_SETTINGSCHANGED).
|
||||
// When applying profile, this would take num_of_variables * 1s to propagate the changes. We do manually SendNotifyMessage with no timeout where needed.
|
||||
private static void SetEnvironmentVariableFromRegistryWithoutNotify(string variable, string value, bool fromMachine)
|
||||
{
|
||||
const int MaxUserEnvVariableLength = 255; // User-wide env vars stored in the registry have names limited to 255 chars
|
||||
@@ -84,7 +87,15 @@ namespace EnvironmentVariables.Helpers
|
||||
}
|
||||
else
|
||||
{
|
||||
environmentKey.SetValue(variable, value);
|
||||
// If a variable contains %, we save it as a REG_EXPAND_SZ, which is the same behavior as the Windows default environment variables editor.
|
||||
if (value.Contains('%'))
|
||||
{
|
||||
environmentKey.SetValue(variable, value, RegistryValueKind.ExpandString);
|
||||
}
|
||||
else
|
||||
{
|
||||
environmentKey.SetValue(variable, value, RegistryValueKind.String);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,23 +113,32 @@ namespace EnvironmentVariables.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
// Code taken from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs
|
||||
// Reading variables from registry instead of using Environment API, because Environment API expands variables by default.
|
||||
internal static void GetVariables(EnvironmentVariableTarget target, VariablesSet set)
|
||||
{
|
||||
var variables = Environment.GetEnvironmentVariables(target);
|
||||
var sortedList = new SortedList<string, Variable>();
|
||||
|
||||
foreach (DictionaryEntry variable in variables)
|
||||
bool fromMachine = target == EnvironmentVariableTarget.Machine ? true : false;
|
||||
|
||||
using (RegistryKey environmentKey = OpenEnvironmentKeyIfExists(fromMachine, writable: false))
|
||||
{
|
||||
string key = variable.Key as string;
|
||||
string value = variable.Value as string;
|
||||
|
||||
if (string.IsNullOrEmpty(key))
|
||||
if (environmentKey != null)
|
||||
{
|
||||
continue;
|
||||
foreach (string name in environmentKey.GetValueNames())
|
||||
{
|
||||
string value = environmentKey.GetValue(name, string.Empty, RegistryValueOptions.DoNotExpandEnvironmentNames).ToString();
|
||||
try
|
||||
{
|
||||
Variable entry = new Variable(name, value, set.Type);
|
||||
sortedList.Add(name, entry);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
// Throw and catch intentionally to provide non-fatal notification about corrupted environment block
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Variable entry = new Variable(key, value, set.Type);
|
||||
sortedList.Add(key, entry);
|
||||
}
|
||||
|
||||
set.Variables = new System.Collections.ObjectModel.ObservableCollection<Variable>(sortedList.Values);
|
||||
|
||||
@@ -28,12 +28,17 @@ namespace EnvironmentVariables.Models
|
||||
[ObservableProperty]
|
||||
private bool _applyToSystem;
|
||||
|
||||
[JsonIgnore]
|
||||
[property: JsonIgnore]
|
||||
[ObservableProperty]
|
||||
private bool _isAppliedFromProfile; // Used to mark that a variable in a default set is applied by a profile. Used to disable editing / mark it in the UI.
|
||||
|
||||
[JsonIgnore]
|
||||
public bool IsEditable
|
||||
{
|
||||
get
|
||||
{
|
||||
return ParentType != VariablesSetType.System || App.GetService<IElevationHelper>().IsElevated;
|
||||
return (ParentType != VariablesSetType.System || App.GetService<IElevationHelper>().IsElevated) && !IsAppliedFromProfile;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -280,4 +280,7 @@
|
||||
<data name="StateProfileNotApplicableMsg" xml:space="preserve">
|
||||
<value>Variables or backup variables are invalid.</value>
|
||||
</data>
|
||||
<data name="VariableIsAppliedByActiveProfileTooltip.Text" xml:space="preserve">
|
||||
<value>This variable is written by the active profile</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -67,6 +67,16 @@ namespace EnvironmentVariables.ViewModels
|
||||
foreach (var variable in UserDefaultSet.Variables)
|
||||
{
|
||||
DefaultVariables.Variables.Add(variable);
|
||||
if (AppliedProfile != null)
|
||||
{
|
||||
if (AppliedProfile.Variables.Where(
|
||||
x => (x.Name.Equals(variable.Name, StringComparison.OrdinalIgnoreCase) && x.Values.Equals(variable.Values, StringComparison.OrdinalIgnoreCase))
|
||||
|| variable.Name.Equals(EnvironmentVariablesHelper.GetBackupVariableName(x, AppliedProfile.Name), StringComparison.OrdinalIgnoreCase)).Any())
|
||||
{
|
||||
// If it's a user variable that's also in the profile or is a backup variable, mark it as applied from profile.
|
||||
variable.IsAppliedFromProfile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var variable in SystemDefaultSet.Variables)
|
||||
@@ -132,10 +142,13 @@ namespace EnvironmentVariables.ViewModels
|
||||
var variables = new List<Variable>();
|
||||
if (AppliedProfile != null)
|
||||
{
|
||||
variables = variables.Concat(AppliedProfile.Variables.OrderBy(x => x.Name)).ToList();
|
||||
variables = variables.Concat(AppliedProfile.Variables.Select(x => new Variable(x.Name, Environment.ExpandEnvironmentVariables(x.Values), VariablesSetType.Profile)).OrderBy(x => x.Name)).ToList();
|
||||
}
|
||||
|
||||
variables = variables.Concat(UserDefaultSet.Variables.OrderBy(x => x.Name)).Concat(SystemDefaultSet.Variables.OrderBy(x => x.Name)).ToList();
|
||||
// Variables are expanded to be shown in the applied variables section, so the user sees their actual values.
|
||||
variables = variables.Concat(UserDefaultSet.Variables.Select(x => new Variable(x.Name, Environment.ExpandEnvironmentVariables(x.Values), VariablesSetType.User)).OrderBy(x => x.Name))
|
||||
.Concat(SystemDefaultSet.Variables.Select(x => new Variable(x.Name, Environment.ExpandEnvironmentVariables(x.Values), VariablesSetType.System)).OrderBy(x => x.Name))
|
||||
.ToList();
|
||||
|
||||
// Handle PATH variable - add USER value to the end of the SYSTEM value
|
||||
var profilePath = variables.Where(x => x.Name.Equals("PATH", StringComparison.OrdinalIgnoreCase) && x.ParentType == VariablesSetType.Profile).FirstOrDefault();
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
//contains the non localized key of the powertoy
|
||||
std::wstring app_key;
|
||||
|
||||
HANDLE m_hProcess;
|
||||
HANDLE m_hProcess = nullptr;
|
||||
|
||||
HANDLE m_hShowEvent;
|
||||
|
||||
|
||||
@@ -309,9 +309,8 @@ std::wstring NtdllExtensions::pid_to_user(DWORD pid)
|
||||
}
|
||||
|
||||
DWORD token_size = 0;
|
||||
GetTokenInformation(token, TokenUser, nullptr, 0, &token_size);
|
||||
|
||||
if (token_size < 0)
|
||||
const bool ok = GetTokenInformation(token, TokenUser, nullptr, 0, &token_size);
|
||||
if ((!ok && GetLastError() != ERROR_INSUFFICIENT_BUFFER) || !token_size)
|
||||
{
|
||||
return user;
|
||||
}
|
||||
|
||||
@@ -10,24 +10,67 @@
|
||||
<!-- Other merged dictionaries here -->
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonBackground" Color="{ThemeResource SubtleFillColorTransparent}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundDisabled" Color="{ThemeResource SubtleFillColorTransparent}" />
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonForeground" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPointerOver" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPressed" Color="{ThemeResource TextFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundDisabled" Color="{ThemeResource TextFillColorDisabled}" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Style x:Key="SubtleButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Width" Value="36" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Height" Value="36" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
|
||||
@@ -53,11 +96,11 @@
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Foreground="{TemplateBinding Foreground}">
|
||||
<ContentPresenter.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</ContentPresenter.BackgroundTransition>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
@@ -66,6 +109,9 @@
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -74,12 +120,14 @@
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -88,12 +136,14 @@
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -110,7 +160,6 @@
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System.IO.Abstractions.TestingHelpers;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Hosts.Exceptions;
|
||||
using Hosts.Helpers;
|
||||
using Hosts.Models;
|
||||
using Hosts.Settings;
|
||||
@@ -18,11 +19,13 @@ namespace Hosts.Tests
|
||||
[TestClass]
|
||||
public class HostsServiceTest
|
||||
{
|
||||
private static Mock<IUserSettings> _userSettings;
|
||||
private static Mock<IElevationHelper> _elevationHelper;
|
||||
|
||||
[ClassInitialize]
|
||||
public static void ClassInitialize(TestContext context)
|
||||
{
|
||||
_userSettings = new Mock<IUserSettings>();
|
||||
_elevationHelper = new Mock<IElevationHelper>();
|
||||
_elevationHelper.Setup(m => m.IsElevated).Returns(true);
|
||||
}
|
||||
@@ -31,8 +34,7 @@ namespace Hosts.Tests
|
||||
public void Hosts_Exists()
|
||||
{
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(string.Empty));
|
||||
var result = service.Exists();
|
||||
|
||||
@@ -43,8 +45,7 @@ namespace Hosts.Tests
|
||||
public void Hosts_Not_Exists()
|
||||
{
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
var result = service.Exists();
|
||||
|
||||
Assert.IsFalse(result);
|
||||
@@ -65,8 +66,7 @@ namespace Hosts.Tests
|
||||
";
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var data = await service.ReadAsync();
|
||||
@@ -91,8 +91,7 @@ namespace Hosts.Tests
|
||||
";
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var data = await service.ReadAsync();
|
||||
@@ -118,8 +117,7 @@ namespace Hosts.Tests
|
||||
";
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var data = await service.ReadAsync();
|
||||
@@ -138,9 +136,7 @@ namespace Hosts.Tests
|
||||
public async Task Empty_Hosts()
|
||||
{
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(string.Empty));
|
||||
|
||||
await service.WriteAsync(string.Empty, Enumerable.Empty<Entry>());
|
||||
@@ -203,7 +199,6 @@ namespace Hosts.Tests
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
userSettings.Setup(m => m.AdditionalLinesPosition).Returns(HostsAdditionalLinesPosition.Bottom);
|
||||
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
@@ -228,8 +223,7 @@ namespace Hosts.Tests
|
||||
";
|
||||
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var service = new HostsService(fileSystem, userSettings.Object, _elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
fileSystem.AddFile(service.HostsFilePath, new MockFileData(content));
|
||||
|
||||
var data = await service.ReadAsync();
|
||||
@@ -243,12 +237,37 @@ namespace Hosts.Tests
|
||||
public async Task Save_NotRunningElevatedException()
|
||||
{
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var userSettings = new Mock<IUserSettings>();
|
||||
var elevationHelper = new Mock<IElevationHelper>();
|
||||
elevationHelper.Setup(m => m.IsElevated).Returns(false);
|
||||
|
||||
var service = new HostsService(fileSystem, userSettings.Object, elevationHelper.Object);
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, elevationHelper.Object);
|
||||
await Assert.ThrowsExceptionAsync<NotRunningElevatedException>(async () => await service.WriteAsync("# Empty hosts file", Enumerable.Empty<Entry>()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public async Task Save_ReadOnlyHostsException()
|
||||
{
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
var hostsFile = new MockFileData(string.Empty);
|
||||
hostsFile.Attributes = System.IO.FileAttributes.ReadOnly;
|
||||
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
||||
|
||||
await Assert.ThrowsExceptionAsync<ReadOnlyHostsException>(async () => await service.WriteAsync("# Empty hosts file", Enumerable.Empty<Entry>()));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Remove_ReadOnly()
|
||||
{
|
||||
var fileSystem = new CustomMockFileSystem();
|
||||
var service = new HostsService(fileSystem, _userSettings.Object, _elevationHelper.Object);
|
||||
var hostsFile = new MockFileData(string.Empty);
|
||||
hostsFile.Attributes = System.IO.FileAttributes.ReadOnly;
|
||||
fileSystem.AddFile(service.HostsFilePath, hostsFile);
|
||||
|
||||
service.RemoveReadOnly();
|
||||
var readOnly = fileSystem.FileInfo.FromFileName(service.HostsFilePath).Attributes.HasFlag(System.IO.FileAttributes.ReadOnly);
|
||||
Assert.IsFalse(readOnly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace Hosts.Helpers
|
||||
namespace Hosts.Exceptions
|
||||
{
|
||||
public class NotRunningElevatedException : Exception
|
||||
{
|
||||
12
src/modules/Hosts/Hosts/Exceptions/ReadOnlyHostsException.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Hosts.Exceptions
|
||||
{
|
||||
public class ReadOnlyHostsException : Exception
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Hosts.Exceptions;
|
||||
using Hosts.Models;
|
||||
using Hosts.Settings;
|
||||
using ManagedCommon;
|
||||
@@ -129,6 +130,11 @@ namespace Hosts.Helpers
|
||||
throw new NotRunningElevatedException();
|
||||
}
|
||||
|
||||
if (_fileSystem.FileInfo.FromFileName(HostsFilePath).IsReadOnly)
|
||||
{
|
||||
throw new ReadOnlyHostsException();
|
||||
}
|
||||
|
||||
var lines = new List<string>();
|
||||
|
||||
if (entries.Any())
|
||||
@@ -288,6 +294,15 @@ namespace Hosts.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveReadOnly()
|
||||
{
|
||||
var fileInfo = _fileSystem.FileInfo.FromFileName(HostsFilePath);
|
||||
if (fileInfo.IsReadOnly)
|
||||
{
|
||||
fileInfo.IsReadOnly = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
|
||||
@@ -24,5 +24,7 @@ namespace Hosts.Helpers
|
||||
void CleanupBackup();
|
||||
|
||||
void OpenHostsFile();
|
||||
|
||||
void RemoveReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,24 +11,66 @@
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonBackground" Color="{ThemeResource SubtleFillColorTransparent}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonBackgroundDisabled" Color="{ThemeResource ControlFillColorDisabled}" />
|
||||
<ResourceDictionary.ThemeDictionaries>
|
||||
<ResourceDictionary x:Key="Default">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<SolidColorBrush x:Key="SubtleButtonForeground" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPointerOver" Color="{ThemeResource TextFillColorPrimary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundPressed" Color="{ThemeResource TextFillColorSecondary}" />
|
||||
<SolidColorBrush x:Key="SubtleButtonForegroundDisabled" Color="{ThemeResource TextFillColorDisabled}" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<SolidColorBrush x:Key="WindowCaptionBackground">Transparent</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="WindowCaptionBackgroundDisabled">Transparent</SolidColorBrush>
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Light">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SubtleFillColorTransparent" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SubtleFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SubtleFillColorTertiary" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SubtleFillColorTransparent" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="TextFillColorPrimary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="TextFillColorSecondary" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="TextFillColorDisabled" />
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="HighContrast">
|
||||
<StaticResource x:Key="SubtleButtonBackground" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPointerOver" ResourceKey="SystemColorHighlightTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundPressed" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBackgroundDisabled" ResourceKey="SystemControlBackgroundBaseLowBrush" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonBorderBrush" ResourceKey="SystemColorWindowColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPointerOver" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushPressed" ResourceKey="SystemColorHighlightColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonBorderBrushDisabled" ResourceKey="SystemColorGrayTextColor" />
|
||||
|
||||
<StaticResource x:Key="SubtleButtonForeground" ResourceKey="SystemColorButtonTextColorBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPointerOver" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundPressed" ResourceKey="SystemControlHighlightBaseHighBrush" />
|
||||
<StaticResource x:Key="SubtleButtonForegroundDisabled" ResourceKey="SystemControlDisabledBaseMediumLowBrush" />
|
||||
</ResourceDictionary>
|
||||
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
<Style x:Key="SubtleButtonStyle" TargetType="Button">
|
||||
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
|
||||
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
|
||||
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="{ThemeResource SubtleButtonBorderBrush}" />
|
||||
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
|
||||
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
@@ -55,11 +97,11 @@
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
ContentTransitions="{TemplateBinding ContentTransitions}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}">
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Foreground="{TemplateBinding Foreground}">
|
||||
<ContentPresenter.BackgroundTransition>
|
||||
<BrushTransition Duration="0:0:0.083" />
|
||||
</ContentPresenter.BackgroundTransition>
|
||||
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="CommonStates">
|
||||
<VisualState x:Name="Normal" />
|
||||
@@ -68,6 +110,9 @@
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -76,12 +121,14 @@
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Pressed">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
@@ -90,12 +137,14 @@
|
||||
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
|
||||
</VisualState.Setters>
|
||||
</VisualState>
|
||||
|
||||
<VisualState x:Name="Disabled">
|
||||
<Storyboard>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBorderBrushDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
|
||||
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
|
||||
</ObjectAnimationUsingKeyFrames>
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
FontSize=16}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
<Button.Flyout>
|
||||
<Flyout>
|
||||
<Flyout ShouldConstrainToRootBounds="False">
|
||||
<StackPanel
|
||||
Width="320"
|
||||
HorizontalAlignment="Stretch"
|
||||
@@ -377,7 +377,15 @@
|
||||
IsOpen="{x:Bind ViewModel.Error, Mode=TwoWay}"
|
||||
Message="{x:Bind ViewModel.ErrorMessage, Mode=TwoWay}"
|
||||
Severity="Error"
|
||||
Visibility="{x:Bind ViewModel.Error, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
Visibility="{x:Bind ViewModel.Error, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<InfoBar.ActionButton>
|
||||
<Button
|
||||
x:Uid="MakeWritable"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Bind ViewModel.OverwriteHostsCommand}"
|
||||
Visibility="{x:Bind ViewModel.IsReadOnly, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
</InfoBar.ActionButton>
|
||||
</InfoBar>
|
||||
<InfoBar
|
||||
x:Uid="FileChanged"
|
||||
Margin="0,8,0,0"
|
||||
@@ -385,7 +393,10 @@
|
||||
Severity="Informational"
|
||||
Visibility="{x:Bind ViewModel.FileChanged, Mode=TwoWay, Converter={StaticResource BoolToVisibilityConverter}}">
|
||||
<InfoBar.ActionButton>
|
||||
<Button x:Uid="Reload" Command="{x:Bind ViewModel.ReadHostsCommand}" />
|
||||
<Button
|
||||
x:Uid="Reload"
|
||||
HorizontalAlignment="Right"
|
||||
Command="{x:Bind ViewModel.ReadHostsCommand}" />
|
||||
</InfoBar.ActionButton>
|
||||
</InfoBar>
|
||||
</StackPanel>
|
||||
|
||||
@@ -228,6 +228,10 @@
|
||||
<value>The hosts file cannot be saved because the program isn't running as administrator.</value>
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="FileSaveError_ReadOnly" xml:space="preserve">
|
||||
<value>The hosts file cannot be saved because it is read-only.</value>
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="FilterBtn.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Filters</value>
|
||||
</data>
|
||||
@@ -246,6 +250,9 @@
|
||||
<value>Hosts</value>
|
||||
<comment>"Hosts" refers to the system hosts file, do not loc</comment>
|
||||
</data>
|
||||
<data name="MakeWritable.Content" xml:space="preserve">
|
||||
<value>Make writable</value>
|
||||
</data>
|
||||
<data name="MoveDown.Text" xml:space="preserve">
|
||||
<value>Move down</value>
|
||||
</data>
|
||||
|
||||
@@ -15,6 +15,7 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using CommunityToolkit.WinUI;
|
||||
using CommunityToolkit.WinUI.Collections;
|
||||
using Hosts.Exceptions;
|
||||
using Hosts.Helpers;
|
||||
using Hosts.Models;
|
||||
using Hosts.Settings;
|
||||
@@ -48,6 +49,9 @@ namespace Hosts.ViewModels
|
||||
[ObservableProperty]
|
||||
private string _errorMessage;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _isReadOnly;
|
||||
|
||||
[ObservableProperty]
|
||||
private bool _fileChanged;
|
||||
|
||||
@@ -262,6 +266,13 @@ namespace Hosts.ViewModels
|
||||
_hostsService.OpenHostsFile();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void OverwriteHosts()
|
||||
{
|
||||
_hostsService.RemoveReadOnly();
|
||||
_ = Task.Run(SaveAsync);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing: true);
|
||||
@@ -374,6 +385,7 @@ namespace Hosts.ViewModels
|
||||
{
|
||||
bool error = true;
|
||||
string errorMessage = string.Empty;
|
||||
bool isReadOnly = false;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -385,6 +397,12 @@ namespace Hosts.ViewModels
|
||||
var resourceLoader = ResourceLoaderInstance.ResourceLoader;
|
||||
errorMessage = resourceLoader.GetString("FileSaveError_NotElevated");
|
||||
}
|
||||
catch (ReadOnlyHostsException)
|
||||
{
|
||||
isReadOnly = true;
|
||||
var resourceLoader = ResourceLoaderInstance.ResourceLoader;
|
||||
errorMessage = resourceLoader.GetString("FileSaveError_ReadOnly");
|
||||
}
|
||||
catch (IOException ex) when ((ex.HResult & 0x0000FFFF) == 32)
|
||||
{
|
||||
// There are some edge cases where a big hosts file is being locked by svchost.exe https://github.com/microsoft/PowerToys/issues/28066
|
||||
@@ -402,6 +420,7 @@ namespace Hosts.ViewModels
|
||||
{
|
||||
Error = error;
|
||||
ErrorMessage = errorMessage;
|
||||
IsReadOnly = isReadOnly;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@ namespace
|
||||
winrt::com_ptr<ID2D1Bitmap> ConvertID3D11Texture2DToD2D1Bitmap(winrt::com_ptr<ID2D1RenderTarget> rt,
|
||||
const MappedTextureView* capturedScreenTexture)
|
||||
{
|
||||
capturedScreenTexture->view.pixels;
|
||||
|
||||
D2D1_BITMAP_PROPERTIES props = { .pixelFormat = rt->GetPixelFormat() };
|
||||
rt->GetDpi(&props.dpiX, &props.dpiY);
|
||||
const auto sizeF = rt->GetSize();
|
||||
|
||||
@@ -85,28 +85,6 @@ namespace MouseWithoutBorders
|
||||
return stack;
|
||||
}
|
||||
|
||||
internal static void SuspendAllThreadsBut(int threadId)
|
||||
{
|
||||
lock (ThreadsLock)
|
||||
{
|
||||
#pragma warning disable 618 // Temporary
|
||||
threads.Where(t => t.IsAlive && t.ManagedThreadId != threadId).ToList().ForEach(
|
||||
t =>
|
||||
{
|
||||
try
|
||||
{
|
||||
t.Suspend();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// This method is suspending every thread so that it can kill the process right after restarting.
|
||||
// Makes no sense to crash on a thread suspension fail, since we're killing the process afterwards, anyway.
|
||||
}
|
||||
});
|
||||
#pragma warning restore 618
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetApartmentState(ApartmentState apartmentState)
|
||||
{
|
||||
thread.SetApartmentState(apartmentState);
|
||||
|
||||
@@ -349,8 +349,6 @@ namespace MouseWithoutBorders
|
||||
_ = Process.Start(Application.ExecutablePath, desktop);
|
||||
LogDebug($"Started on desktop {desktop}");
|
||||
|
||||
Thread.SuspendAllThreadsBut(Thread.CurrentThread.ManagedThreadId);
|
||||
|
||||
Process.GetCurrentProcess().KillProcess(true);
|
||||
},
|
||||
$"{actionName} watchdog").Start();
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ui:ThemesDictionary Theme="Dark" />
|
||||
<ui:ControlsDictionary />
|
||||
<ResourceDictionary Source="/Styles/Colors.xaml" />
|
||||
<ResourceDictionary Source="/Styles/ButtonStyles.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
||||
@@ -3,12 +3,13 @@
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:PowerOCR"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:p="clr-namespace:PowerOCR.Properties"
|
||||
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
|
||||
Title="TextExtractor"
|
||||
Width="200"
|
||||
Height="200"
|
||||
ui:Design.Background="Transparent"
|
||||
AllowsTransparency="True"
|
||||
Background="Transparent"
|
||||
Loaded="Window_Loaded"
|
||||
@@ -23,19 +24,22 @@
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Window.Resources>
|
||||
<Style x:Key="SymbolTextStyle" TargetType="TextBlock">
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="FontFamily" Value="Segoe MDL2 Assets" />
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="Margin" Value="4" />
|
||||
<Style BasedOn="{StaticResource DefaultToggleButtonStyle}" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="Margin" Value="4,0" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Width" Value="32" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style TargetType="ToggleButton">
|
||||
<Setter Property="Margin" Value="2,0" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
<Setter Property="Width" Value="30" />
|
||||
<Setter Property="Height" Value="30" />
|
||||
|
||||
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="{x:Type Button}">
|
||||
<Setter Property="Margin" Value="4,0" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="Width" Value="32" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
</Window.Resources>
|
||||
|
||||
@@ -70,23 +74,23 @@
|
||||
<MenuItem
|
||||
Name="SingleLineMenuItem"
|
||||
Click="SingleLineMenuItem_Click"
|
||||
Header="Make Result Text Single Line"
|
||||
Header="{x:Static p:Resources.ResultTextSingleLine}"
|
||||
IsCheckable="True" />
|
||||
<MenuItem
|
||||
Name="TableMenuItem"
|
||||
Click="TableToggleButton_Click"
|
||||
Header="OCR text as a table"
|
||||
Header="{x:Static p:Resources.ResultTextTable}"
|
||||
IsCheckable="True" />
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Name="SettingsMenuItem"
|
||||
Click="SettingsMenuItem_Click"
|
||||
Header="Settings" />
|
||||
Header="{x:Static p:Resources.Settings}" />
|
||||
<Separator />
|
||||
<MenuItem
|
||||
Name="CancelMenuItem"
|
||||
Click="CancelMenuItem_Click"
|
||||
Header="Cancel" />
|
||||
Header="{x:Static p:Resources.Cancel}" />
|
||||
</ContextMenu>
|
||||
</Canvas.ContextMenu>
|
||||
</Canvas>
|
||||
@@ -96,7 +100,6 @@
|
||||
Padding="4,8,12,8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
d:Background="White"
|
||||
d:Visibility="Visible"
|
||||
Background="{DynamicResource ApplicationBackgroundBrush}"
|
||||
CornerRadius="8"
|
||||
@@ -104,75 +107,60 @@
|
||||
<Border.Effect>
|
||||
<DropShadowEffect
|
||||
BlurRadius="32"
|
||||
Direction="-90"
|
||||
Opacity="0.6"
|
||||
RenderingBias="Performance" />
|
||||
Opacity="0.28"
|
||||
RenderingBias="Performance"
|
||||
ShadowDepth="1" />
|
||||
</Border.Effect>
|
||||
|
||||
<StackPanel
|
||||
Margin="2,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Horizontal">
|
||||
<ComboBox
|
||||
x:Name="LanguagesComboBox"
|
||||
Margin="2,0"
|
||||
Padding="4,2,0,2"
|
||||
Foreground="{DynamicResource TextFillColorPrimaryBrush}"
|
||||
Height="32"
|
||||
Margin="4,0"
|
||||
AutomationProperties.Name="{x:Static p:Resources.SelectedLang}"
|
||||
SelectionChanged="LanguagesComboBox_SelectionChanged">
|
||||
<ComboBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
FontFamily="Segoe UI"
|
||||
Style="{StaticResource SymbolTextStyle}"
|
||||
Text="{Binding NativeName}" />
|
||||
</DataTemplate>
|
||||
</ComboBox.ItemTemplate>
|
||||
</ComboBox>
|
||||
<ToggleButton
|
||||
x:Name="SingleLineToggleButton"
|
||||
Width="34"
|
||||
Height="34"
|
||||
Margin="2,0"
|
||||
d:IsChecked="True"
|
||||
AutomationProperties.Name="{x:Static p:Resources.ResultTextSingleLine}"
|
||||
Click="SingleLineMenuItem_Click"
|
||||
IsChecked="{Binding IsChecked, ElementName=SingleLineMenuItem, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSymbolButton}"
|
||||
ToolTip="(S) Make result a single line">
|
||||
<TextBlock Style="{StaticResource SymbolTextStyle}" Text="" />
|
||||
ToolTip="{x:Static p:Resources.ResultTextSingleLineShortcut}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="SubtractSquare24" />
|
||||
</ToggleButton>
|
||||
<ToggleButton
|
||||
x:Name="TableToggleButton"
|
||||
Width="34"
|
||||
Height="34"
|
||||
Margin="2,0"
|
||||
d:IsChecked="True"
|
||||
AutomationProperties.Name="{x:Static p:Resources.ResultTextTable}"
|
||||
Click="TableToggleButton_Click"
|
||||
IsChecked="{Binding IsChecked, ElementName=TableMenuItem, Mode=TwoWay}"
|
||||
Style="{StaticResource ToggleSymbolButton}"
|
||||
ToolTip="(T) OCR text as a table">
|
||||
<TextBlock FontFamily="Segoe MDL2 Assets" Text="" />
|
||||
ToolTip="{x:Static p:Resources.ResultTextTableShortcut}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Table24" />
|
||||
</ToggleButton>
|
||||
<Button
|
||||
x:Name="SettingsButton"
|
||||
Width="34"
|
||||
Height="34"
|
||||
Margin="2,0"
|
||||
AutomationProperties.Name="{x:Static p:Resources.Settings}"
|
||||
Click="SettingsMenuItem_Click"
|
||||
Style="{StaticResource SymbolButton}"
|
||||
ToolTip="Settings">
|
||||
<TextBlock Style="{StaticResource SymbolTextStyle}" Text="" />
|
||||
ToolTip="{x:Static p:Resources.Settings}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Settings24" />
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="CancelButton"
|
||||
Width="34"
|
||||
Height="34"
|
||||
Margin="2,0,0,0"
|
||||
Click="CancelMenuItem_Click"
|
||||
Style="{StaticResource SymbolButton}"
|
||||
ToolTip="(Esc) Cancel">
|
||||
<TextBlock Style="{StaticResource SymbolTextStyle}" Text="" />
|
||||
ToolTip="{x:Static p:Resources.CancelShortcut}">
|
||||
<ui:SymbolIcon FontSize="18" Symbol="Dismiss24" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@@ -49,7 +49,7 @@ public partial class OCROverlay : Window
|
||||
Top = screenRectangle.Top >= 0 ? screenRectangle.Top : screenRectangle.Top + (screenRectangle.Height / 2);
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this, Wpf.Ui.Controls.WindowBackdropType.None);
|
||||
PopulateLanguageMenu();
|
||||
}
|
||||
|
||||
|
||||
@@ -61,4 +61,20 @@
|
||||
<ProjectReference Include="..\..\..\common\Common.UI\Common.UI.csproj" />
|
||||
<ProjectReference Include="..\..\..\settings-ui\Settings.UI.Library\Settings.UI.Library.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>PublicResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
135
src/modules/PowerOCR/PowerOCR/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,135 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace PowerOCR.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
public class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PowerOCR.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
public static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel.
|
||||
/// </summary>
|
||||
public static string Cancel {
|
||||
get {
|
||||
return ResourceManager.GetString("Cancel", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Cancel (Esc).
|
||||
/// </summary>
|
||||
public static string CancelShortcut {
|
||||
get {
|
||||
return ResourceManager.GetString("CancelShortcut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Format result as a single line.
|
||||
/// </summary>
|
||||
public static string ResultTextSingleLine {
|
||||
get {
|
||||
return ResourceManager.GetString("ResultTextSingleLine", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Format result as a single line (S).
|
||||
/// </summary>
|
||||
public static string ResultTextSingleLineShortcut {
|
||||
get {
|
||||
return ResourceManager.GetString("ResultTextSingleLineShortcut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Format result as a table.
|
||||
/// </summary>
|
||||
public static string ResultTextTable {
|
||||
get {
|
||||
return ResourceManager.GetString("ResultTextTable", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Format result as a table (T).
|
||||
/// </summary>
|
||||
public static string ResultTextTableShortcut {
|
||||
get {
|
||||
return ResourceManager.GetString("ResultTextTableShortcut", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Selected language.
|
||||
/// </summary>
|
||||
public static string SelectedLang {
|
||||
get {
|
||||
return ResourceManager.GetString("SelectedLang", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Settings.
|
||||
/// </summary>
|
||||
public static string Settings {
|
||||
get {
|
||||
return ResourceManager.GetString("Settings", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
147
src/modules/PowerOCR/PowerOCR/Properties/Resources.resx
Normal file
@@ -0,0 +1,147 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="Cancel" xml:space="preserve">
|
||||
<value>Cancel</value>
|
||||
</data>
|
||||
<data name="CancelShortcut" xml:space="preserve">
|
||||
<value>Cancel (Esc)</value>
|
||||
<comment>(Esc) indicates the keyboard shortcut</comment>
|
||||
</data>
|
||||
<data name="ResultTextSingleLine" xml:space="preserve">
|
||||
<value>Format result as a single line</value>
|
||||
</data>
|
||||
<data name="ResultTextSingleLineShortcut" xml:space="preserve">
|
||||
<value>Format result as a single line (S)</value>
|
||||
<comment>(S) indicates the keyboard shortcut</comment>
|
||||
</data>
|
||||
<data name="ResultTextTable" xml:space="preserve">
|
||||
<value>Format result as a table</value>
|
||||
</data>
|
||||
<data name="ResultTextTableShortcut" xml:space="preserve">
|
||||
<value>Format result as a table (T)</value>
|
||||
<comment>(T) indicates the keyboard shortcut</comment>
|
||||
</data>
|
||||
<data name="SelectedLang" xml:space="preserve">
|
||||
<value>Selected language</value>
|
||||
</data>
|
||||
<data name="Settings" xml:space="preserve">
|
||||
<value>Settings</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,695 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<SolidColorBrush x:Key="Menu.Static.Background" Color="{DynamicResource SolidBackgroundFillColorSecondaryBrush}" />
|
||||
<SolidColorBrush x:Key="Menu.Static.Border" Color="{DynamicResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="Menu.Static.Foreground" Color="White" />
|
||||
<SolidColorBrush x:Key="Menu.Static.Separator" Color="{DynamicResource SystemAccentColorSecondary}" />
|
||||
<SolidColorBrush x:Key="Menu.Disabled.Foreground" Color="#FF707070" />
|
||||
<SolidColorBrush x:Key="MenuItem.Selected.Background" Color="#3D26A0DA" />
|
||||
<SolidColorBrush x:Key="MenuItem.Selected.Border" Color="{DynamicResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="MenuItem.Highlight.Background" Color="#3D26A0DA" />
|
||||
<SolidColorBrush x:Key="MenuItem.Highlight.Border" Color="{DynamicResource SystemAccentColor}" />
|
||||
<SolidColorBrush x:Key="MenuItem.Highlight.Disabled.Background" Color="#0A000000" />
|
||||
<SolidColorBrush x:Key="MenuItem.Highlight.Disabled.Border" Color="#21000000" />
|
||||
<MenuScrollingVisibilityConverter x:Key="MenuScrollingVisibilityConverter" />
|
||||
<Geometry x:Key="DownArrow">M 0,0 L 3.5,4 L 7,0 Z</Geometry>
|
||||
<Geometry x:Key="UpArrow">M 0,4 L 3.5,0 L 7,4 Z</Geometry>
|
||||
<Geometry x:Key="RightArrow">M 0,0 L 4,3.5 L 0,7 Z</Geometry>
|
||||
<Geometry x:Key="Checkmark">F1 M 10.0,1.2 L 4.7,9.1 L 4.5,9.1 L 0,5.2 L 1.3,3.5 L 4.3,6.1L 8.3,0 L 10.0,1.2 Z</Geometry>
|
||||
<Style x:Key="FocusVisual">
|
||||
<Setter Property="Control.Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate>
|
||||
<Rectangle
|
||||
Margin="2"
|
||||
SnapsToDevicePixels="true"
|
||||
Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"
|
||||
StrokeDashArray="1 2"
|
||||
StrokeThickness="1" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<SolidColorBrush x:Key="Button.Static.Background" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="Button.Static.Border" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="Button.MouseOver.Background" Color="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
<SolidColorBrush x:Key="Button.MouseOver.Border" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="Button.Pressed.Background" Color="#071818" />
|
||||
<SolidColorBrush x:Key="Button.Pressed.Border" Color="#071818" />
|
||||
<SolidColorBrush x:Key="Button.Disabled.Background" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="Button.Disabled.Border" Color="Transparent" />
|
||||
<SolidColorBrush x:Key="Button.Disabled.Foreground" Color="#FF838383" />
|
||||
|
||||
|
||||
<Style x:Key="ToggleSymbolButton" TargetType="{x:Type ToggleButton}">
|
||||
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}" />
|
||||
<Setter Property="Background" Value="{StaticResource Button.Static.Background}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource Button.Static.Border}" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Border
|
||||
x:Name="border"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
CornerRadius="4"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
x:Name="contentPresenter"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="Button.IsDefaulted" Value="true">
|
||||
<Setter TargetName="border" Property="BorderBrush" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource SystemAccentColorBrush}" />
|
||||
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource Button.Pressed.Border}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="false">
|
||||
<Setter TargetName="border" Property="Background" Value="{StaticResource Button.Disabled.Background}" />
|
||||
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource Button.Disabled.Border}" />
|
||||
<Setter TargetName="contentPresenter" Property="TextElement.Foreground" Value="{StaticResource Button.Disabled.Foreground}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style
|
||||
x:Key="MenuScrollButton"
|
||||
BasedOn="{x:Null}"
|
||||
TargetType="{x:Type RepeatButton}">
|
||||
<Setter Property="ClickMode" Value="Hover" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type RepeatButton}">
|
||||
<Border
|
||||
x:Name="templateRoot"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent"
|
||||
BorderThickness="1"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
Margin="6"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=TopLevelItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
|
||||
<Border
|
||||
x:Name="templateRoot"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
SnapsToDevicePixels="true">
|
||||
<Grid VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
x:Name="Icon"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="3"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Icon"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<Path
|
||||
x:Name="GlyphPanel"
|
||||
Margin="3"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource Checkmark}"
|
||||
Fill="{StaticResource Menu.Static.Foreground}"
|
||||
FlowDirection="LeftToRight"
|
||||
Visibility="Collapsed" />
|
||||
<ContentPresenter
|
||||
Grid.Column="1"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ContentSource="Header"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="Icon" Value="{x:Null}">
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="true">
|
||||
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsHighlighted" Value="True">
|
||||
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource MenuItem.Highlight.Background}" />
|
||||
<Setter TargetName="templateRoot" Property="BorderBrush" Value="{StaticResource MenuItem.Highlight.Border}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
<Setter TargetName="GlyphPanel" Property="Fill" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsHighlighted" Value="True" />
|
||||
<Condition Property="IsEnabled" Value="False" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource MenuItem.Highlight.Disabled.Background}" />
|
||||
<Setter TargetName="templateRoot" Property="BorderBrush" Value="{StaticResource MenuItem.Highlight.Disabled.Border}" />
|
||||
</MultiTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=TopLevelHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
|
||||
<Border
|
||||
x:Name="templateRoot"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
SnapsToDevicePixels="true">
|
||||
<Grid VerticalAlignment="Center">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
x:Name="Icon"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="3"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Icon"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<Path
|
||||
x:Name="GlyphPanel"
|
||||
Margin="3"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource Checkmark}"
|
||||
Fill="{TemplateBinding Foreground}"
|
||||
FlowDirection="LeftToRight"
|
||||
Visibility="Collapsed" />
|
||||
<ContentPresenter
|
||||
Grid.Column="1"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
ContentSource="Header"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<Popup
|
||||
x:Name="PART_Popup"
|
||||
AllowsTransparency="true"
|
||||
Focusable="false"
|
||||
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Placement="Bottom"
|
||||
PlacementTarget="{Binding ElementName=templateRoot}"
|
||||
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}">
|
||||
<Border
|
||||
x:Name="SubMenuBorder"
|
||||
Padding="2"
|
||||
Background="{StaticResource Menu.Static.Background}"
|
||||
BorderBrush="{StaticResource Menu.Static.Border}"
|
||||
BorderThickness="1">
|
||||
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
|
||||
<Grid RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas
|
||||
Width="0"
|
||||
Height="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top">
|
||||
<Rectangle
|
||||
x:Name="OpaqueRect"
|
||||
Width="{Binding ActualWidth, ElementName=SubMenuBorder}"
|
||||
Height="{Binding ActualHeight, ElementName=SubMenuBorder}"
|
||||
Fill="{Binding Background, ElementName=SubMenuBorder}" />
|
||||
</Canvas>
|
||||
<Rectangle
|
||||
Width="1"
|
||||
Margin="29,2,0,2"
|
||||
HorizontalAlignment="Left"
|
||||
Fill="{StaticResource Menu.Static.Separator}" />
|
||||
<ItemsPresenter
|
||||
x:Name="ItemsPresenter"
|
||||
Grid.IsSharedSizeScope="true"
|
||||
KeyboardNavigation.DirectionalNavigation="Cycle"
|
||||
KeyboardNavigation.TabNavigation="Cycle"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsSuspendingPopupAnimation" Value="true">
|
||||
<Setter TargetName="PART_Popup" Property="PopupAnimation" Value="None" />
|
||||
</Trigger>
|
||||
<Trigger Property="Icon" Value="{x:Null}">
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="true">
|
||||
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsHighlighted" Value="True">
|
||||
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource MenuItem.Highlight.Background}" />
|
||||
<Setter TargetName="templateRoot" Property="BorderBrush" Value="{StaticResource MenuItem.Highlight.Border}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
<Setter TargetName="GlyphPanel" Property="Fill" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
</Trigger>
|
||||
<Trigger SourceName="SubMenuScrollViewer" Property="ScrollViewer.CanContentScroll" Value="false">
|
||||
<Setter TargetName="OpaqueRect" Property="Canvas.Top" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}" />
|
||||
<Setter TargetName="OpaqueRect" Property="Canvas.Left" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=SubmenuItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
|
||||
<Border
|
||||
x:Name="templateRoot"
|
||||
Height="22"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
SnapsToDevicePixels="true">
|
||||
<Grid Margin="-1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition
|
||||
Width="Auto"
|
||||
MinWidth="22"
|
||||
SharedSizeGroup="MenuItemIconColumnGroup" />
|
||||
<ColumnDefinition Width="13" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup" />
|
||||
<ColumnDefinition Width="20" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
x:Name="Icon"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="3"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Icon"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<Border
|
||||
x:Name="GlyphPanel"
|
||||
Width="22"
|
||||
Height="22"
|
||||
Margin="-1,0,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Background="{StaticResource MenuItem.Selected.Background}"
|
||||
BorderBrush="{StaticResource MenuItem.Selected.Border}"
|
||||
BorderThickness="1"
|
||||
ClipToBounds="False"
|
||||
Visibility="Hidden">
|
||||
<Path
|
||||
x:Name="Glyph"
|
||||
Width="10"
|
||||
Height="11"
|
||||
Data="{StaticResource Checkmark}"
|
||||
Fill="{StaticResource Menu.Static.Foreground}"
|
||||
FlowDirection="LeftToRight" />
|
||||
</Border>
|
||||
<ContentPresenter
|
||||
x:Name="menuHeaderContainer"
|
||||
Grid.Column="2"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Header"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<TextBlock
|
||||
x:Name="menuGestureText"
|
||||
Grid.Column="4"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Center"
|
||||
Opacity="0.7"
|
||||
Text="{TemplateBinding InputGestureText}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="Icon" Value="{x:Null}">
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsHighlighted" Value="True">
|
||||
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource MenuItem.Highlight.Background}" />
|
||||
<Setter TargetName="templateRoot" Property="BorderBrush" Value="{StaticResource MenuItem.Highlight.Border}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
<Setter TargetName="Glyph" Property="Fill" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
</Trigger>
|
||||
<MultiTrigger>
|
||||
<MultiTrigger.Conditions>
|
||||
<Condition Property="IsHighlighted" Value="True" />
|
||||
<Condition Property="IsEnabled" Value="False" />
|
||||
</MultiTrigger.Conditions>
|
||||
<Setter TargetName="templateRoot" Property="Background" Value="{StaticResource MenuItem.Highlight.Disabled.Background}" />
|
||||
<Setter TargetName="templateRoot" Property="BorderBrush" Value="{StaticResource MenuItem.Highlight.Disabled.Border}" />
|
||||
</MultiTrigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="{ComponentResourceKey ResourceId=SubmenuHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}" TargetType="{x:Type MenuItem}">
|
||||
<Border
|
||||
x:Name="templateRoot"
|
||||
Height="22"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="{TemplateBinding BorderThickness}"
|
||||
SnapsToDevicePixels="true">
|
||||
<Grid Margin="-1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition
|
||||
Width="Auto"
|
||||
MinWidth="22"
|
||||
SharedSizeGroup="MenuItemIconColumnGroup" />
|
||||
<ColumnDefinition Width="13" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="30" />
|
||||
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGTColumnGroup" />
|
||||
<ColumnDefinition Width="20" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter
|
||||
x:Name="Icon"
|
||||
Width="16"
|
||||
Height="16"
|
||||
Margin="3"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Icon"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<Border
|
||||
x:Name="GlyphPanel"
|
||||
Width="22"
|
||||
Height="22"
|
||||
Margin="-1,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Background="{StaticResource MenuItem.Highlight.Background}"
|
||||
BorderBrush="{StaticResource MenuItem.Highlight.Border}"
|
||||
BorderThickness="1"
|
||||
Visibility="Hidden">
|
||||
<Path
|
||||
x:Name="Glyph"
|
||||
Width="9"
|
||||
Height="11"
|
||||
Data="{DynamicResource Checkmark}"
|
||||
Fill="{StaticResource Menu.Static.Foreground}"
|
||||
FlowDirection="LeftToRight" />
|
||||
</Border>
|
||||
<ContentPresenter
|
||||
Grid.Column="2"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
ContentSource="Header"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<TextBlock
|
||||
Grid.Column="4"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
VerticalAlignment="Center"
|
||||
Opacity="0.7"
|
||||
Text="{TemplateBinding InputGestureText}" />
|
||||
<Path
|
||||
x:Name="RightArrow"
|
||||
Grid.Column="5"
|
||||
Margin="10,0,0,0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Data="{StaticResource RightArrow}"
|
||||
Fill="{StaticResource Menu.Static.Foreground}" />
|
||||
<Popup
|
||||
x:Name="PART_Popup"
|
||||
AllowsTransparency="true"
|
||||
Focusable="false"
|
||||
HorizontalOffset="-2"
|
||||
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
Placement="Right"
|
||||
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
|
||||
VerticalOffset="-3">
|
||||
<Border
|
||||
x:Name="SubMenuBorder"
|
||||
Padding="2"
|
||||
Background="{StaticResource Menu.Static.Background}"
|
||||
BorderBrush="{StaticResource Menu.Static.Border}"
|
||||
BorderThickness="1">
|
||||
<ScrollViewer x:Name="SubMenuScrollViewer" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
|
||||
<Grid RenderOptions.ClearTypeHint="Enabled">
|
||||
<Canvas
|
||||
Width="0"
|
||||
Height="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Top">
|
||||
<Rectangle
|
||||
x:Name="OpaqueRect"
|
||||
Width="{Binding ActualWidth, ElementName=SubMenuBorder}"
|
||||
Height="{Binding ActualHeight, ElementName=SubMenuBorder}"
|
||||
Fill="{Binding Background, ElementName=SubMenuBorder}" />
|
||||
</Canvas>
|
||||
<Rectangle
|
||||
Width="1"
|
||||
Margin="29,2,0,2"
|
||||
HorizontalAlignment="Left"
|
||||
Fill="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
|
||||
<ItemsPresenter
|
||||
x:Name="ItemsPresenter"
|
||||
Grid.IsSharedSizeScope="true"
|
||||
KeyboardNavigation.DirectionalNavigation="Cycle"
|
||||
KeyboardNavigation.TabNavigation="Cycle"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsSuspendingPopupAnimation" Value="true">
|
||||
<Setter TargetName="PART_Popup" Property="PopupAnimation" Value="None" />
|
||||
</Trigger>
|
||||
<Trigger Property="Icon" Value="{x:Null}">
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsChecked" Value="True">
|
||||
<Setter TargetName="GlyphPanel" Property="Visibility" Value="Visible" />
|
||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsHighlighted" Value="True">
|
||||
<Setter TargetName="templateRoot" Property="Background" Value="Transparent" />
|
||||
<Setter TargetName="templateRoot" Property="BorderBrush" Value="{StaticResource MenuItem.Highlight.Border}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="templateRoot" Property="TextElement.Foreground" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
<Setter TargetName="Glyph" Property="Fill" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
<Setter TargetName="RightArrow" Property="Fill" Value="{StaticResource Menu.Disabled.Foreground}" />
|
||||
</Trigger>
|
||||
<Trigger SourceName="SubMenuScrollViewer" Property="ScrollViewer.CanContentScroll" Value="false">
|
||||
<Setter TargetName="OpaqueRect" Property="Canvas.Top" Value="{Binding VerticalOffset, ElementName=SubMenuScrollViewer}" />
|
||||
<Setter TargetName="OpaqueRect" Property="Canvas.Left" Value="{Binding HorizontalOffset, ElementName=SubMenuScrollViewer}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<Style x:Key="DarkMenuItemStyle" TargetType="{x:Type MenuItem}">
|
||||
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
|
||||
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="ScrollViewer.PanningMode" Value="Both" />
|
||||
<Setter Property="Stylus.IsFlicksEnabled" Value="False" />
|
||||
<Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=SubmenuItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="Role" Value="TopLevelHeader">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Menu.Static.Foreground}" />
|
||||
<Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=TopLevelHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}" />
|
||||
<Setter Property="Padding" Value="6,0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Role" Value="TopLevelItem">
|
||||
<Setter Property="Background" Value="{StaticResource Menu.Static.Background}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource Menu.Static.Border}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Menu.Static.Foreground}" />
|
||||
<Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=TopLevelItemTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}" />
|
||||
<Setter Property="Padding" Value="6,0" />
|
||||
</Trigger>
|
||||
<Trigger Property="Role" Value="SubmenuHeader">
|
||||
<Setter Property="Template" Value="{DynamicResource {ComponentResourceKey ResourceId=SubmenuHeaderTemplateKey, TypeInTargetAssembly={x:Type MenuItem}}}" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TitleBarCloseButtonStyle" TargetType="Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
x:Name="border"
|
||||
BorderThickness="0"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
x:Name="contentPresenter"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="Red" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="DarkRed" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="TitleBarButtonStyle" TargetType="Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
x:Name="border"
|
||||
BorderThickness="0"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
x:Name="contentPresenter"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="{StaticResource Menu.Static.Border}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="{StaticResource Menu.Static.Separator}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="TealColor" TargetType="Button">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter Property="Background" Value="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
<Setter Property="Padding" Value="0" />
|
||||
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
x:Name="border"
|
||||
Background="{TemplateBinding Background}"
|
||||
CornerRadius="4"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
x:Name="contentPresenter"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="border" Property="Background" Value="#071818" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="border" Property="Opacity" Value="0.4" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
<Style x:Key="SymbolButton" TargetType="Button">
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Padding" Value="6" />
|
||||
<Setter Property="WindowChrome.IsHitTestVisibleInChrome" Value="True" />
|
||||
<Setter Property="IsTabStop" Value="False" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border
|
||||
x:Name="border"
|
||||
CornerRadius="4"
|
||||
SnapsToDevicePixels="true">
|
||||
<ContentPresenter
|
||||
x:Name="contentPresenter"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"
|
||||
Focusable="False"
|
||||
RecognizesAccessKey="True" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="true">
|
||||
<Setter TargetName="border" Property="Background" Value="#071818" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource SystemAccentColorSecondaryBrush}" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="Opacity" Value="0.3" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
@@ -1,6 +0,0 @@
|
||||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<SolidColorBrush x:Key="DarkBackground" Color="{DynamicResource ApplicationBackgroundColor}" />
|
||||
<SolidColorBrush x:Key="DarkControlBackground" Color="{DynamicResource SolidBackgroundFillColorQuarternaryBrushColor}" />
|
||||
<SolidColorBrush x:Key="DarkTeal" Color="{DynamicResource SystemAccentColorSecondary}" />
|
||||
<SolidColorBrush x:Key="Teal" Color="{DynamicResource SystemAccentColor}" />
|
||||
</ResourceDictionary>
|
||||
@@ -12,6 +12,7 @@
|
||||
#include <common/interop/shared_constants.h>
|
||||
#include <common/utils/logger_helper.h>
|
||||
#include <common/utils/winapi_error.h>
|
||||
#include <common/utils/package.h>
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE /*hModule*/,
|
||||
DWORD ul_reason_for_call,
|
||||
@@ -293,6 +294,13 @@ public:
|
||||
{
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
// Returns whether the PowerToys should be enabled by default
|
||||
virtual bool is_enabled_by_default() const override
|
||||
{
|
||||
// disabled by default for Windows 11 and enabled by default on Windows 10
|
||||
return !package::IsWin11OrGreater();
|
||||
}
|
||||
};
|
||||
|
||||
extern "C" __declspec(dllexport) PowertoyModuleIface* __cdecl powertoy_create()
|
||||
|
||||
@@ -79,6 +79,11 @@
|
||||
<Compile Update="Program.cs">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</Compile>
|
||||
<Compile Update="Properties\Resources.Designer.cs">
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -87,11 +92,17 @@
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Update="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Update="Microsoft.CodeAnalysis.NetAnalyzers">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -6,12 +6,14 @@ using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Reactive.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using Awake.Core.Models;
|
||||
using Awake.Core.Native;
|
||||
using Awake.Properties;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Telemetry;
|
||||
using Microsoft.Win32;
|
||||
@@ -274,9 +276,9 @@ namespace Awake.Core
|
||||
{
|
||||
Dictionary<string, int> optionsList = new Dictionary<string, int>
|
||||
{
|
||||
{ "30 minutes", 1800 },
|
||||
{ "1 hour", 3600 },
|
||||
{ "2 hours", 7200 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, Resources.AWAKE_MINUTES, 30), 1800 },
|
||||
{ Resources.AWAKE_1_HOUR, 3600 },
|
||||
{ string.Format(CultureInfo.InvariantCulture, Resources.AWAKE_HOURS, 2), 7200 },
|
||||
};
|
||||
return optionsList;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using Awake.Core.Models;
|
||||
using Awake.Core.Native;
|
||||
using Awake.Properties;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
@@ -115,11 +117,11 @@ namespace Awake.Core
|
||||
if (!startedFromPowerToys)
|
||||
{
|
||||
// If Awake is started from PowerToys, the correct way to exit it is disabling it from Settings.
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING, (uint)TrayCommands.TC_EXIT, "Exit");
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING, (uint)TrayCommands.TC_EXIT, Resources.AWAKE_EXIT);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_SEPARATOR, 0, string.Empty);
|
||||
}
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (keepDisplayOn ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED) | (mode == AwakeMode.PASSIVE ? Native.Constants.MF_DISABLED : Native.Constants.MF_ENABLED), (uint)TrayCommands.TC_DISPLAY_SETTING, "Keep screen on");
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (keepDisplayOn ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED) | (mode == AwakeMode.PASSIVE ? Native.Constants.MF_DISABLED : Native.Constants.MF_ENABLED), (uint)TrayCommands.TC_DISPLAY_SETTING, Resources.AWAKE_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
// In case there are no tray shortcuts defined for the application default to a
|
||||
@@ -137,10 +139,10 @@ namespace Awake.Core
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_SEPARATOR, 0, string.Empty);
|
||||
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (mode == AwakeMode.PASSIVE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_PASSIVE, "Off (keep using the selected power plan)");
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (mode == AwakeMode.INDEFINITE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_INDEFINITE, "Keep awake indefinitely");
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_POPUP | (mode == AwakeMode.TIMED ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)awakeTimeMenu, "Keep awake on interval");
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | Native.Constants.MF_DISABLED | (mode == AwakeMode.EXPIRABLE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_EXPIRABLE, "Keep awake until expiration date and time");
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (mode == AwakeMode.PASSIVE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_PASSIVE, Resources.AWAKE_OFF);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | (mode == AwakeMode.INDEFINITE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_INDEFINITE, Resources.AWAKE_KEEP_INDEFINITELY);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_POPUP | (mode == AwakeMode.TIMED ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)awakeTimeMenu, Resources.AWAKE_KEEP_ON_INTERVAL);
|
||||
Bridge.InsertMenu(TrayMenu, 0, Native.Constants.MF_BYPOSITION | Native.Constants.MF_STRING | Native.Constants.MF_DISABLED | (mode == AwakeMode.EXPIRABLE ? Native.Constants.MF_CHECKED : Native.Constants.MF_UNCHECKED), (uint)TrayCommands.TC_MODE_EXPIRABLE, Resources.AWAKE_KEEP_UNTIL_EXPIRATION);
|
||||
|
||||
TrayIcon.Text = text;
|
||||
}
|
||||
@@ -157,7 +159,7 @@ namespace Awake.Core
|
||||
|
||||
public override AccessibleRole Role => AccessibleRole.CheckButton;
|
||||
|
||||
public override string Name => _menuItem.Text + ", " + Role + ", " + (_menuItem.Checked ? "Checked" : "Unchecked");
|
||||
public override string Name => _menuItem.Text + ", " + Role + ", " + (_menuItem.Checked ? Resources.AWAKE_CHECKED : Resources.AWAKE_UNCHECKED);
|
||||
}
|
||||
|
||||
private sealed class CheckButtonToolStripMenuItem : ToolStripMenuItem
|
||||
|
||||
171
src/modules/awake/Awake/Properties/Resources.Designer.cs
generated
Normal file
@@ -0,0 +1,171 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Awake.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Awake.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1 hour.
|
||||
/// </summary>
|
||||
internal static string AWAKE_1_HOUR {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_1_HOUR", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to 1 minute.
|
||||
/// </summary>
|
||||
internal static string AWAKE_1_MINUTE {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_1_MINUTE", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Checked.
|
||||
/// </summary>
|
||||
internal static string AWAKE_CHECKED {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_CHECKED", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Exit.
|
||||
/// </summary>
|
||||
internal static string AWAKE_EXIT {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_EXIT", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} hours.
|
||||
/// </summary>
|
||||
internal static string AWAKE_HOURS {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_HOURS", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Keep awake indefinitely.
|
||||
/// </summary>
|
||||
internal static string AWAKE_KEEP_INDEFINITELY {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_KEEP_INDEFINITELY", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Keep awake on interval.
|
||||
/// </summary>
|
||||
internal static string AWAKE_KEEP_ON_INTERVAL {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_KEEP_ON_INTERVAL", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Keep screen on.
|
||||
/// </summary>
|
||||
internal static string AWAKE_KEEP_SCREEN_ON {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_KEEP_SCREEN_ON", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Keep awake until expiration date and time.
|
||||
/// </summary>
|
||||
internal static string AWAKE_KEEP_UNTIL_EXPIRATION {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_KEEP_UNTIL_EXPIRATION", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to {0} minutes.
|
||||
/// </summary>
|
||||
internal static string AWAKE_MINUTES {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_MINUTES", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Off (keep using the selected power plan).
|
||||
/// </summary>
|
||||
internal static string AWAKE_OFF {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_OFF", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Unchecked.
|
||||
/// </summary>
|
||||
internal static string AWAKE_UNCHECKED {
|
||||
get {
|
||||
return ResourceManager.GetString("AWAKE_UNCHECKED", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
162
src/modules/awake/Awake/Properties/Resources.resx
Normal file
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<data name="AWAKE_CHECKED" xml:space="preserve">
|
||||
<value>Checked</value>
|
||||
</data>
|
||||
<data name="AWAKE_EXIT" xml:space="preserve">
|
||||
<value>Exit</value>
|
||||
</data>
|
||||
<data name="AWAKE_1_HOUR" xml:space="preserve">
|
||||
<value>1 hour</value>
|
||||
</data>
|
||||
<data name="AWAKE_HOURS" xml:space="preserve">
|
||||
<value>{0} hours</value>
|
||||
<comment>{0} shouldn't be removed. It will be replaced by a number greater than 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
|
||||
</data>
|
||||
<data name="AWAKE_KEEP_INDEFINITELY" xml:space="preserve">
|
||||
<value>Keep awake indefinitely</value>
|
||||
<comment>Keep the system awake forever</comment>
|
||||
</data>
|
||||
<data name="AWAKE_KEEP_ON_INTERVAL" xml:space="preserve">
|
||||
<value>Keep awake on interval</value>
|
||||
<comment>Keep the system awake for a given time</comment>
|
||||
</data>
|
||||
<data name="AWAKE_KEEP_SCREEN_ON" xml:space="preserve">
|
||||
<value>Keep screen on</value>
|
||||
</data>
|
||||
<data name="AWAKE_KEEP_UNTIL_EXPIRATION" xml:space="preserve">
|
||||
<value>Keep awake until expiration date and time</value>
|
||||
<comment>Keep the system awake until expiration date and time</comment>
|
||||
</data>
|
||||
<data name="AWAKE_1_MINUTE" xml:space="preserve">
|
||||
<value>1 minute</value>
|
||||
</data>
|
||||
<data name="AWAKE_MINUTES" xml:space="preserve">
|
||||
<value>{0} minutes</value>
|
||||
<comment>{0} shouldn't be removed. It will be replaced by a number greater than 1 at runtime by the application. Used for defining a period to keep the PC awake.</comment>
|
||||
</data>
|
||||
<data name="AWAKE_OFF" xml:space="preserve">
|
||||
<value>Off (keep using the selected power plan)</value>
|
||||
<comment>Don't keep the system awake, use the selected system power plan</comment>
|
||||
</data>
|
||||
<data name="AWAKE_UNCHECKED" xml:space="preserve">
|
||||
<value>Unchecked</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -394,6 +394,15 @@ void FancyZones::WindowCreated(HWND window) noexcept
|
||||
return;
|
||||
}
|
||||
|
||||
// Hotfix
|
||||
// Avoid automatically moving popup windows, as they can be just popup menus.
|
||||
bool isPopup = FancyZonesWindowUtils::IsPopupWindow(window);
|
||||
bool hasThickFrame = FancyZonesWindowUtils::HasThickFrame(window);
|
||||
if (isPopup && !hasThickFrame)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Avoid already stamped (zoned) windows
|
||||
const bool isZoned = !FancyZonesWindowProperties::RetrieveZoneIndexProperty(window).empty();
|
||||
if (isZoned)
|
||||
|
||||
@@ -27,9 +27,8 @@ bool FancyZonesWindowProcessing::IsProcessable(HWND window) noexcept
|
||||
|
||||
// popup could be the window we don't want to snap: start menu, notification popup, tray window, etc.
|
||||
// also, popup could be the windows we want to snap disregarding the "allowSnapPopupWindows" setting, e.g. Telegram
|
||||
bool isPopup = FancyZonesWindowUtils::IsPopupWindow(window);
|
||||
bool hasThickFrame = FancyZonesWindowUtils::HasThickFrame(window);
|
||||
if (isPopup && (!hasThickFrame || !FancyZonesSettings::settings().allowSnapPopupWindows))
|
||||
bool isPopup = FancyZonesWindowUtils::IsPopupWindow(window) && !FancyZonesWindowUtils::HasThickFrameAndMinimizeMaximizeButtons(window);
|
||||
if (isPopup && !FancyZonesSettings::settings().allowSnapPopupWindows)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ void FancyZonesSettings::LoadSettings()
|
||||
if (auto val = values.get_int_value(NonLocalizable::OverlappingZonesAlgorithmID))
|
||||
{
|
||||
// Avoid undefined behavior
|
||||
if (*val >= 0 || *val < static_cast<int>(OverlappingZonesAlgorithm::EnumElements))
|
||||
if (*val >= 0 && *val < static_cast<int>(OverlappingZonesAlgorithm::EnumElements))
|
||||
{
|
||||
auto algorithm = (OverlappingZonesAlgorithm)*val;
|
||||
if (m_settings.overlappingZonesAlgorithm != algorithm)
|
||||
|
||||
@@ -306,26 +306,23 @@ void FancyZonesWindowUtils::SizeWindowToRect(HWND window, RECT rect) noexcept
|
||||
::GetWindowPlacement(window, &placement);
|
||||
}
|
||||
|
||||
if (!IsWindowVisible(window))
|
||||
{
|
||||
placement.showCmd = SW_HIDE;
|
||||
}
|
||||
else
|
||||
if (IsWindowVisible(window))
|
||||
{
|
||||
// Do not restore minimized windows. We change their placement though so they restore to the correct zone.
|
||||
if ((placement.showCmd != SW_SHOWMINIMIZED) &&
|
||||
(placement.showCmd != SW_MINIMIZE))
|
||||
{
|
||||
placement.showCmd = SW_RESTORE;
|
||||
}
|
||||
// Remove maximized show command to make sure window is moved to the correct zone.
|
||||
if (placement.showCmd == SW_SHOWMAXIMIZED)
|
||||
placement.flags &= ~WPF_RESTORETOMAXIMIZED;
|
||||
|
||||
// Remove maximized show command to make sure window is moved to the correct zone.
|
||||
if (placement.showCmd == SW_SHOWMAXIMIZED)
|
||||
{
|
||||
placement.showCmd = SW_RESTORE;
|
||||
placement.flags &= ~WPF_RESTORETOMAXIMIZED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
placement.showCmd = SW_HIDE;
|
||||
}
|
||||
|
||||
ScreenToWorkAreaCoords(window, rect);
|
||||
|
||||
|
||||
@@ -38,4 +38,4 @@
|
||||
<v:VisibilityBoolConverter x:Key="VisibilityBoolConverter" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
</Application>
|
||||
@@ -44,7 +44,7 @@ namespace ImageResizer.ViewModels
|
||||
{
|
||||
if (_batch.Files.Count == 0)
|
||||
{
|
||||
_batch.Files.AddRange(view?.OpenPictureFiles());
|
||||
_batch.Files.AddRange(view.OpenPictureFiles());
|
||||
}
|
||||
|
||||
CurrentPage = new InputViewModel(_settings, this, view, _batch);
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
ExtendsContentIntoTitleBar="True"
|
||||
Icon="/PowerToys.ImageResizer;component/Resources/ImageResizer.ico"
|
||||
ResizeMode="NoResize"
|
||||
WindowBackdropType="Mica"
|
||||
WindowCornerPreference="Default"
|
||||
WindowStartupLocation="CenterScreen">
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Common.UI;
|
||||
using ImageResizer.ViewModels;
|
||||
using Microsoft.Win32;
|
||||
using Wpf.Ui.Controls;
|
||||
@@ -17,7 +18,17 @@ namespace ImageResizer.Views
|
||||
public MainWindow(MainViewModel viewModel)
|
||||
{
|
||||
DataContext = viewModel;
|
||||
Wpf.Ui.Appearance.Watcher.Watch(this);
|
||||
Wpf.Ui.Appearance.SystemThemeWatcher.Watch(this);
|
||||
|
||||
if (OSVersionHelper.IsWindows11())
|
||||
{
|
||||
WindowBackdropType = WindowBackdropType.Mica;
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowBackdropType = WindowBackdropType.None;
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />
|
||||
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 ..\dll resource.base.h resource.h KeyboardManager.base.rc KeyboardManager.rc" />
|
||||
</Target>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<!-- Project configurations -->
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup>
|
||||
<NoWarn>81010002</NoWarn>
|
||||
@@ -98,7 +100,7 @@
|
||||
<AdditionalIncludeDirectories>./;$(SolutionDir)src\modules\;$(SolutionDir)src\modules\KeyboardManager\KeyboardManagerEditorLibrary\;$(SolutionDir)src\common\Display;$(SolutionDir)src\common\inc;$(SolutionDir)src\common\Telemetry;$(SolutionDir)src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -109,7 +111,7 @@
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>Display.lib;shcore.lib;Dbghelp.lib;dwmapi.lib;uxtheme.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)$(Platform)\$(ConfigurationName);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
@@ -160,6 +162,10 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
</ImportGroup>
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
@@ -171,5 +177,15 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.7\build\native\Microsoft.VCRTForwarders.140.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Target Name="FakeResourcesPriMerge" BeforeTargets="FinalizeBuildStatus" DependsOnTargets="CopyFilesToOutputDirectory">
|
||||
<Message Text="Renaming Microsoft.UI.Xaml.pri to resources.pri" />
|
||||
<Move SourceFiles="$(OutDir)\Microsoft.UI.Xaml.pri" DestinationFiles="$(OutDir)\resources.pri" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -1,4 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.2-prerelease.220830001" targetFramework="native" />
|
||||
<package id="Microsoft.VCRTForwarders.140" version="1.0.7" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2088.41" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.221104.6" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "EditKeyboardWindow.h"
|
||||
#include "SingleKeyRemapControl.h"
|
||||
#include "KeyDropDownControl.h"
|
||||
#include "XamlBridge.h"
|
||||
#include "XamlBridge2.h"
|
||||
#include "Styles.h"
|
||||
#include "Dialog.h"
|
||||
#include "LoadingAndSavingRemappingHelper.h"
|
||||
@@ -41,12 +41,12 @@ HWND hwndEditKeyboardNativeWindow = nullptr;
|
||||
std::mutex editKeyboardWindowMutex;
|
||||
|
||||
// Stores a pointer to the Xaml Bridge object so that it can be accessed from the window procedure
|
||||
static XamlBridge* xamlBridgePtr = nullptr;
|
||||
static XamlBridge2* xamlBridgePtr = nullptr;
|
||||
|
||||
// Theming
|
||||
ThemeListener theme_listener{};
|
||||
static ThemeListener theme_listener{};
|
||||
|
||||
void handleTheme()
|
||||
static void handleTheme()
|
||||
{
|
||||
auto theme = theme_listener.AppTheme;
|
||||
auto isDark = theme == AppTheme::Dark;
|
||||
@@ -137,7 +137,7 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
windowClass.lpfnWndProc = EditKeyboardWindowProc;
|
||||
windowClass.hInstance = hInst;
|
||||
windowClass.lpszClassName = szWindowClass;
|
||||
windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
|
||||
windowClass.hbrBackground = CreateSolidBrush((ThemeHelpers::GetAppTheme() == AppTheme::Dark) ? 0x00000000 : 0x00FFFFFF);
|
||||
windowClass.hIcon = static_cast<HICON>(LoadImageW(
|
||||
windowClass.hInstance,
|
||||
MAKEINTRESOURCE(IDS_KEYBOARDMANAGER_ICON),
|
||||
@@ -196,17 +196,19 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
hwndEditKeyboardNativeWindow = _hWndEditKeyboardWindow;
|
||||
hwndLock.unlock();
|
||||
|
||||
// Hide icon and caption from title bar
|
||||
const DWORD windowThemeOptionsMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
|
||||
WTA_OPTIONS windowThemeOptions{ windowThemeOptionsMask, windowThemeOptionsMask };
|
||||
SetWindowThemeAttribute(_hWndEditKeyboardWindow, WTA_NONCLIENT, &windowThemeOptions, sizeof(windowThemeOptions));
|
||||
|
||||
handleTheme();
|
||||
theme_listener.AddChangedHandler(handleTheme);
|
||||
|
||||
// Create the xaml bridge object
|
||||
XamlBridge xamlBridge(_hWndEditKeyboardWindow);
|
||||
|
||||
// DesktopSource needs to be declared before the RelativePanel xamlContainer object to avoid errors
|
||||
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource desktopSource;
|
||||
XamlBridge2 xamlBridge(_hWndEditKeyboardWindow);
|
||||
|
||||
// Create the desktop window xaml source object and set its content
|
||||
hWndXamlIslandEditKeyboardWindow = xamlBridge.InitDesktopWindowsXamlSource(desktopSource);
|
||||
hWndXamlIslandEditKeyboardWindow = xamlBridge.InitBridge();
|
||||
|
||||
// Set the pointer to the xaml bridge object
|
||||
xamlBridgePtr = &xamlBridge;
|
||||
@@ -322,11 +324,8 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
|
||||
// Add remap key button
|
||||
Windows::UI::Xaml::Controls::Button addRemapKey;
|
||||
FontIcon plusSymbol;
|
||||
plusSymbol.FontFamily(Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
plusSymbol.Glyph(L"\xE710");
|
||||
addRemapKey.Content(plusSymbol);
|
||||
addRemapKey.Margin({ 10, 10, 0, 25 });
|
||||
addRemapKey.Style(AccentButtonStyle());
|
||||
addRemapKey.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
SingleKeyRemapControl::AddNewControlKeyRemapRow(keyRemapTable, keyboardRemapControlObjects);
|
||||
|
||||
@@ -337,14 +336,19 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
UIHelpers::SetFocusOnTypeButtonInLastRow(keyRemapTable, EditorConstants::RemapTableColCount);
|
||||
});
|
||||
|
||||
// Remap key button content
|
||||
StackPanel addRemapKeyContent;
|
||||
addRemapKeyContent.Orientation(Orientation::Horizontal);
|
||||
addRemapKeyContent.Spacing(10);
|
||||
addRemapKeyContent.Children().Append(SymbolIcon(Symbol::Add));
|
||||
TextBlock addRemapKeyText;
|
||||
addRemapKeyText.Text(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON));
|
||||
addRemapKeyContent.Children().Append(addRemapKeyText);
|
||||
addRemapKey.Content(addRemapKeyContent);
|
||||
|
||||
// Set accessible name for the addRemapKey button
|
||||
addRemapKey.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON)));
|
||||
|
||||
// Add tooltip for add button which would appear on hover
|
||||
ToolTip addRemapKeytoolTip;
|
||||
addRemapKeytoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_ADD_KEY_REMAP_BUTTON)));
|
||||
ToolTipService::SetToolTip(addRemapKey, addRemapKeytoolTip);
|
||||
|
||||
// Header and example text at the top of the window
|
||||
StackPanel helperText;
|
||||
helperText.Children().Append(keyRemapInfoHeader);
|
||||
@@ -381,7 +385,20 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
{
|
||||
}
|
||||
|
||||
desktopSource.Content(xamlContainer);
|
||||
UserControl xamlContent;
|
||||
xamlContent.Content(xamlContainer);
|
||||
if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent(L"Windows.UI.Composition.ICompositionSupportsSystemBackdrop"))
|
||||
{
|
||||
// Apply Mica
|
||||
muxc::BackdropMaterial::SetApplyToRootOrPageBackground(xamlContent, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mica isn't available
|
||||
xamlContainer.Background(Application::Current().Resources().Lookup(box_value(L"ApplicationPageBackgroundThemeBrush")).as<Media::SolidColorBrush>());
|
||||
}
|
||||
Window::Current().Content(xamlContent);
|
||||
|
||||
////End XAML Island section
|
||||
if (_hWndEditKeyboardWindow)
|
||||
{
|
||||
@@ -400,9 +417,6 @@ inline void CreateEditKeyboardWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMan
|
||||
hwndEditKeyboardNativeWindow = nullptr;
|
||||
keyboardManagerState.ResetUIState();
|
||||
keyboardManagerState.ClearRegisteredKeyDelays();
|
||||
|
||||
// Cannot be done in WM_DESTROY because that causes crashes due to fatal app exit
|
||||
xamlBridge.ClearXamlIslands();
|
||||
}
|
||||
|
||||
void CreateEditKeyboardWindow(HINSTANCE hInst, KBMEditor::KeyboardManagerState& keyboardManagerState, MappingConfiguration& mappingConfiguration)
|
||||
|
||||
@@ -13,9 +13,10 @@
|
||||
#include "ShortcutControl.h"
|
||||
#include "Styles.h"
|
||||
#include "UIHelpers.h"
|
||||
#include "XamlBridge.h"
|
||||
#include "XamlBridge2.h"
|
||||
#include "ShortcutErrorType.h"
|
||||
#include "EditorConstants.h"
|
||||
#include <common/Themes/theme_listener.h>
|
||||
|
||||
using namespace winrt::Windows::Foundation;
|
||||
|
||||
@@ -34,7 +35,21 @@ HWND hwndEditShortcutsNativeWindow = nullptr;
|
||||
std::mutex editShortcutsWindowMutex;
|
||||
|
||||
// Stores a pointer to the Xaml Bridge object so that it can be accessed from the window procedure
|
||||
static XamlBridge* xamlBridgePtr = nullptr;
|
||||
static XamlBridge2* xamlBridgePtr = nullptr;
|
||||
|
||||
// Theming
|
||||
static ThemeListener theme_listener{};
|
||||
|
||||
static void handleTheme()
|
||||
{
|
||||
auto theme = theme_listener.AppTheme;
|
||||
auto isDark = theme == AppTheme::Dark;
|
||||
Logger::info(L"Theme is now {}", isDark ? L"Dark" : L"Light");
|
||||
if (hwndEditShortcutsNativeWindow != nullptr)
|
||||
{
|
||||
ThemeHelpers::SetImmersiveDarkMode(hwndEditShortcutsNativeWindow, isDark);
|
||||
}
|
||||
}
|
||||
|
||||
static IAsyncAction OnClickAccept(
|
||||
KBMEditor::KeyboardManagerState& keyboardManagerState,
|
||||
@@ -75,7 +90,7 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
windowClass.lpfnWndProc = EditShortcutsWindowProc;
|
||||
windowClass.hInstance = hInst;
|
||||
windowClass.lpszClassName = szWindowClass;
|
||||
windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
|
||||
windowClass.hbrBackground = CreateSolidBrush((ThemeHelpers::GetAppTheme() == AppTheme::Dark) ? 0x00000000 : 0x00FFFFFF);
|
||||
windowClass.hIcon = static_cast<HICON>(LoadImageW(
|
||||
windowClass.hInstance,
|
||||
MAKEINTRESOURCE(IDS_KEYBOARDMANAGER_ICON),
|
||||
@@ -132,14 +147,19 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
hwndEditShortcutsNativeWindow = _hWndEditShortcutsWindow;
|
||||
hwndLock.unlock();
|
||||
|
||||
// Hide icon and caption from title bar
|
||||
const DWORD windowThemeOptionsMask = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON;
|
||||
WTA_OPTIONS windowThemeOptions{ windowThemeOptionsMask, windowThemeOptionsMask };
|
||||
SetWindowThemeAttribute(_hWndEditShortcutsWindow, WTA_NONCLIENT, &windowThemeOptions, sizeof(windowThemeOptions));
|
||||
|
||||
handleTheme();
|
||||
theme_listener.AddChangedHandler(handleTheme);
|
||||
|
||||
// Create the xaml bridge object
|
||||
XamlBridge xamlBridge(_hWndEditShortcutsWindow);
|
||||
|
||||
// DesktopSource needs to be declared before the RelativePanel xamlContainer object to avoid errors
|
||||
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource desktopSource;
|
||||
XamlBridge2 xamlBridge(_hWndEditShortcutsWindow);
|
||||
|
||||
// Create the desktop window xaml source object and set its content
|
||||
hWndXamlIslandEditShortcutsWindow = xamlBridge.InitDesktopWindowsXamlSource(desktopSource);
|
||||
hWndXamlIslandEditShortcutsWindow = xamlBridge.InitBridge();
|
||||
|
||||
// Set the pointer to the xaml bridge object
|
||||
xamlBridgePtr = &xamlBridge;
|
||||
@@ -276,11 +296,8 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
|
||||
// Add shortcut button
|
||||
Windows::UI::Xaml::Controls::Button addShortcut;
|
||||
FontIcon plusSymbol;
|
||||
plusSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
plusSymbol.Glyph(L"\xE710");
|
||||
addShortcut.Content(plusSymbol);
|
||||
addShortcut.Margin({ 10, 10, 0, 25 });
|
||||
addShortcut.Style(AccentButtonStyle());
|
||||
addShortcut.Click([&](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
ShortcutControl::AddNewShortcutControlRow(shortcutTable, keyboardRemapControlObjects);
|
||||
|
||||
@@ -291,14 +308,19 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
UIHelpers::SetFocusOnTypeButtonInLastRow(shortcutTable, EditorConstants::ShortcutTableColCount);
|
||||
});
|
||||
|
||||
// Remap shortcut button content
|
||||
StackPanel addShortcutContent;
|
||||
addShortcutContent.Orientation(Orientation::Horizontal);
|
||||
addShortcutContent.Spacing(10);
|
||||
addShortcutContent.Children().Append(SymbolIcon(Symbol::Add));
|
||||
TextBlock addShortcutText;
|
||||
addShortcutText.Text(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON));
|
||||
addShortcutContent.Children().Append(addShortcutText);
|
||||
addShortcut.Content(addShortcutContent);
|
||||
|
||||
// Set accessible name for the add shortcut button
|
||||
addShortcut.SetValue(Automation::AutomationProperties::NameProperty(), box_value(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON)));
|
||||
|
||||
// Add tooltip for add button which would appear on hover
|
||||
ToolTip addShortcuttoolTip;
|
||||
addShortcuttoolTip.Content(box_value(GET_RESOURCE_STRING(IDS_ADD_SHORTCUT_BUTTON)));
|
||||
ToolTipService::SetToolTip(addShortcut, addShortcuttoolTip);
|
||||
|
||||
// Header and example text at the top of the window
|
||||
StackPanel helperText;
|
||||
helperText.Children().Append(shortcutRemapInfoHeader);
|
||||
@@ -334,7 +356,19 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
{
|
||||
}
|
||||
|
||||
desktopSource.Content(xamlContainer);
|
||||
UserControl xamlContent;
|
||||
xamlContent.Content(xamlContainer);
|
||||
if (Windows::Foundation::Metadata::ApiInformation::IsTypePresent(L"Windows.UI.Composition.ICompositionSupportsSystemBackdrop"))
|
||||
{
|
||||
// Apply Mica
|
||||
muxc::BackdropMaterial::SetApplyToRootOrPageBackground(xamlContent, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mica isn't available
|
||||
xamlContainer.Background(Application::Current().Resources().Lookup(box_value(L"ApplicationPageBackgroundThemeBrush")).as<Media::SolidColorBrush>());
|
||||
}
|
||||
Window::Current().Content(xamlContent);
|
||||
|
||||
////End XAML Island section
|
||||
if (_hWndEditShortcutsWindow)
|
||||
@@ -353,9 +387,6 @@ inline void CreateEditShortcutsWindowImpl(HINSTANCE hInst, KBMEditor::KeyboardMa
|
||||
hwndEditShortcutsNativeWindow = nullptr;
|
||||
keyboardManagerState.ResetUIState();
|
||||
keyboardManagerState.ClearRegisteredKeyDelays();
|
||||
|
||||
// Cannot be done in WM_DESTROY because that causes crashes due to fatal app exit
|
||||
xamlBridge.ClearXamlIslands();
|
||||
}
|
||||
|
||||
void CreateEditShortcutsWindow(HINSTANCE hInst, KBMEditor::KeyboardManagerState& keyboardManagerState, MappingConfiguration& mappingConfiguration)
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
namespace EditorConstants
|
||||
{
|
||||
// Default window sizes
|
||||
inline const int DefaultEditKeyboardWindowWidth = 800;
|
||||
inline const int DefaultEditKeyboardWindowWidth = 960;
|
||||
inline const int DefaultEditKeyboardWindowHeight = 600;
|
||||
inline const int MinimumEditKeyboardWindowWidth = 500;
|
||||
inline const int MinimumEditKeyboardWindowHeight = 450;
|
||||
inline const int EditKeyboardTableMinWidth = 700;
|
||||
inline const int DefaultEditShortcutsWindowWidth = 1050;
|
||||
inline const int DefaultEditShortcutsWindowWidth = 1410;
|
||||
inline const int DefaultEditShortcutsWindowHeight = 600;
|
||||
inline const int MinimumEditShortcutsWindowWidth = 500;
|
||||
inline const int MinimumEditShortcutsWindowHeight = 500;
|
||||
@@ -21,7 +21,9 @@ namespace EditorConstants
|
||||
inline const long RemapTableArrowColIndex = 1;
|
||||
inline const long RemapTableNewColIndex = 2;
|
||||
inline const long RemapTableRemoveColIndex = 3;
|
||||
inline const DWORD64 RemapTableDropDownWidth = 110;
|
||||
inline const DWORD64 RemapTableDropDownWidth = 160;
|
||||
inline const DWORD64 RemapTableDropDownSpacing = 10;
|
||||
inline const long RemapTargetColumnWidth = 3 * RemapTableDropDownWidth + 3 * RemapTableDropDownSpacing + 65;
|
||||
|
||||
// Shortcut table constants
|
||||
inline const long ShortcutTableColCount = 5;
|
||||
@@ -32,14 +34,14 @@ namespace EditorConstants
|
||||
inline const long ShortcutTableTargetAppColIndex = 3;
|
||||
inline const long ShortcutTableRemoveColIndex = 4;
|
||||
inline const long ShortcutArrowColumnWidth = 90;
|
||||
inline const DWORD64 ShortcutTableDropDownWidth = 110;
|
||||
inline const DWORD64 ShortcutTableDropDownWidth = 160;
|
||||
inline const DWORD64 ShortcutTableDropDownSpacing = 10;
|
||||
inline const long ShortcutOriginColumnWidth = 3 * ShortcutTableDropDownWidth + 3 * ShortcutTableDropDownSpacing;
|
||||
inline const long ShortcutTargetColumnWidth = 3 * ShortcutTableDropDownWidth + 3 * ShortcutTableDropDownSpacing + 15;
|
||||
|
||||
// Drop down height used for both Edit Keyboard and Edit Shortcuts
|
||||
inline const DWORD64 TableDropDownHeight = 200;
|
||||
inline const DWORD64 TableArrowColWidth = 230;
|
||||
inline const DWORD64 TableArrowColWidth = 130;
|
||||
inline const DWORD64 TableRemoveColWidth = 20;
|
||||
inline const DWORD64 TableWarningColWidth = 20;
|
||||
inline const DWORD64 TableTargetAppColWidth = ShortcutTableDropDownWidth + TableRemoveColWidth * 2;
|
||||
|
||||
@@ -51,8 +51,10 @@ std::vector<std::pair<DWORD, std::wstring>> KeyDropDownControl::GetKeyList(bool
|
||||
void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisable)
|
||||
{
|
||||
dropDown = ComboBox();
|
||||
#ifndef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
warningFlyout = Flyout();
|
||||
warningMessage = TextBlock();
|
||||
#endif
|
||||
|
||||
if (!isShortcut)
|
||||
{
|
||||
@@ -77,6 +79,19 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
CheckAndUpdateKeyboardLayout(currentDropDown, isShortcut, renderDisable);
|
||||
});
|
||||
|
||||
#ifdef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
// Attach the tip to the drop down
|
||||
warningTip.Target(dropDown.as<ComboBox>());
|
||||
dropDown.as<ComboBox>().Loaded([&](winrt::Windows::Foundation::IInspectable const& sender, auto args) {
|
||||
Media::VisualTreeHelper::GetChild(dropDown.as<ComboBox>(), 0).as<Grid>().Children().Append(warningTip);
|
||||
});
|
||||
|
||||
// Tip properties
|
||||
muxc::SymbolIconSource warningIcon;
|
||||
warningIcon.Symbol(Symbol::Important);
|
||||
warningTip.IconSource(warningIcon);
|
||||
warningTip.IsLightDismissEnabled(true);
|
||||
#else
|
||||
// Attach flyout to the drop down
|
||||
warningFlyout.as<Flyout>().Content(warningMessage.as<TextBlock>());
|
||||
|
||||
@@ -86,6 +101,7 @@ void KeyDropDownControl::SetDefaultProperties(bool isShortcut, bool renderDisabl
|
||||
style.Setters().Append(Setter(Windows::UI::Xaml::Controls::Control::TabNavigationProperty(), winrt::box_value(Windows::UI::Xaml::Input::KeyboardNavigationMode::Cycle)));
|
||||
warningFlyout.as<Flyout>().FlyoutPresenterStyle(style);
|
||||
dropDown.as<ComboBox>().ContextFlyout().SetAttachedFlyout((FrameworkElement)dropDown.as<ComboBox>(), warningFlyout.as<Flyout>());
|
||||
#endif
|
||||
|
||||
// To set the accessible name of the combo-box (by default index 1)
|
||||
SetAccessibleNameForComboBox(dropDown.as<ComboBox>(), 1);
|
||||
@@ -376,6 +392,11 @@ void KeyDropDownControl::ValidateShortcutFromDropDownList(StackPanel table, Stac
|
||||
void KeyDropDownControl::SetDropDownError(ComboBox currentDropDown, hstring message)
|
||||
{
|
||||
currentDropDown.SelectedIndex(-1);
|
||||
|
||||
#ifdef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
warningTip.Title(message);
|
||||
warningTip.IsOpen(true);
|
||||
#else
|
||||
warningMessage.as<TextBlock>().Text(message);
|
||||
try
|
||||
{
|
||||
@@ -386,6 +407,7 @@ void KeyDropDownControl::SetDropDownError(ComboBox currentDropDown, hstring mess
|
||||
// If it's loading and some remaps are invalid from previous configs, avoid crashing when flyouts can't be showed yet.
|
||||
Logger::error(L"Failed to show dropdown error flyout: {}", message);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Function to add a shortcut to the UI control as combo boxes
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
|
||||
#include <keyboardmanager/common/Shortcut.h>
|
||||
|
||||
// Enables the WinUI teaching tip to show as the new warning flyout
|
||||
#define USE_NEW_DROPDOWN_WARNING_TIP
|
||||
|
||||
namespace KBMEditor
|
||||
{
|
||||
class KeyboardManagerState;
|
||||
@@ -38,11 +41,16 @@ private:
|
||||
// Stores the previous layout
|
||||
HKL previousLayout = 0;
|
||||
|
||||
#ifdef USE_NEW_DROPDOWN_WARNING_TIP
|
||||
// Stores the teaching tip attached to the current drop down
|
||||
muxc::TeachingTip warningTip;
|
||||
#else
|
||||
// Stores the flyout warning message
|
||||
winrt::Windows::Foundation::IInspectable warningMessage;
|
||||
|
||||
// Stores the flyout attached to the current drop down
|
||||
winrt::Windows::Foundation::IInspectable warningFlyout;
|
||||
#endif
|
||||
|
||||
// Stores whether a key to shortcut warning has to be ignored
|
||||
bool ignoreKeyToShortcutWarning;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>16.0</VCProjectVersion>
|
||||
@@ -53,6 +55,7 @@
|
||||
<ClInclude Include="trace.h" />
|
||||
<ClInclude Include="UIHelpers.h" />
|
||||
<ClInclude Include="XamlBridge.h" />
|
||||
<ClInclude Include="XamlBridge2.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BufferValidationHelpers.cpp" />
|
||||
@@ -74,6 +77,7 @@
|
||||
<ClCompile Include="trace.cpp" />
|
||||
<ClCompile Include="UIHelpers.cpp" />
|
||||
<ClCompile Include="XamlBridge.cpp" />
|
||||
<ClCompile Include="XamlBridge2.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
@@ -95,6 +99,9 @@
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets" Condition="Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" />
|
||||
<Import Project="..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets" Condition="Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" />
|
||||
</ImportGroup>
|
||||
<Import Project="..\..\..\..\deps\spdlog.props" />
|
||||
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
|
||||
@@ -103,6 +110,11 @@
|
||||
</PropertyGroup>
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Windows.CppWinRT.2.0.221104.6\build\native\Microsoft.Windows.CppWinRT.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.1.3\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.Web.WebView2.1.0.2088.41\build\native\Microsoft.Web.WebView2.targets'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.props'))" />
|
||||
<Error Condition="!Exists('..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\..\packages\Microsoft.UI.Xaml.2.8.2-prerelease.220830001\build\native\Microsoft.UI.Xaml.targets'))" />
|
||||
</Target>
|
||||
<Target Name="GenerateResourceFiles" BeforeTargets="PrepareForBuild">
|
||||
<Exec Command="powershell -NonInteractive -executionpolicy Unrestricted $(SolutionDir)tools\build\convert-resx-to-rc.ps1 $(MSBuildThisFileDirectory)\..\KeyboardManagerEditor\ resource.base.h resource.h KeyboardManagerEditor.base.rc KeyboardManagerEditor.rc" />
|
||||
|
||||
@@ -75,6 +75,9 @@
|
||||
<ClInclude Include="EditorConstants.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="XamlBridge2.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pch.cpp">
|
||||
@@ -128,6 +131,9 @@
|
||||
<ClCompile Include="KeyDelay.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="XamlBridge2.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
@@ -118,8 +118,15 @@ void KeyboardManagerState::AddKeyToLayout(const StackPanel& panel, const hstring
|
||||
|
||||
border.Padding({ 20, 10, 20, 10 });
|
||||
border.Margin({ 0, 0, 10, 0 });
|
||||
// Use the base low brush to be consistent with the theme
|
||||
border.Background(Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundBaseLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>());
|
||||
|
||||
// Based on settings-ui\Settings.UI\SettingsXAML\Controls\KeyVisual\KeyVisual.xaml
|
||||
border.Background(Application::Current().Resources().Lookup(box_value(L"ButtonBackground")).as<Media::Brush>());
|
||||
border.BorderBrush(Application::Current().Resources().Lookup(box_value(L"ButtonBorderBrush")).as<Media::Brush>());
|
||||
border.BorderThickness(unbox_value<Thickness>(Application::Current().Resources().Lookup(box_value(L"ButtonBorderThemeThickness"))));
|
||||
border.CornerRadius(unbox_value<CornerRadius>(Application::Current().Resources().Lookup(box_value(L"ControlCornerRadius"))));
|
||||
remapKey.Foreground(Application::Current().Resources().Lookup(box_value(L"ButtonForeground")).as<Media::Brush>());
|
||||
remapKey.FontWeight(Text::FontWeights::SemiBold());
|
||||
|
||||
remapKey.FontSize(20);
|
||||
border.HorizontalAlignment(HorizontalAlignment::Left);
|
||||
border.Child(remapKey);
|
||||
|
||||
@@ -90,13 +90,12 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
newrow.emplace_back(std::make_unique<ShortcutControl>(parent, row, 1, targetAppTextBox));
|
||||
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||
|
||||
row.Padding({ 10, 10, 10, 10 });
|
||||
row.Padding({ 10, 15, 10, 5 });
|
||||
row.Margin({ 0, 0, 0, 2 });
|
||||
row.Orientation(Orientation::Horizontal);
|
||||
auto brush = Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundListLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
if (keyboardRemapControlObjects.size() % 2)
|
||||
{
|
||||
row.Background(brush);
|
||||
}
|
||||
row.Background(Application::Current().Resources().Lookup(box_value(L"CardBackgroundFillColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderBrush(Application::Current().Resources().Lookup(box_value(L"CardStrokeColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderThickness({ 0, 1, 0, 1 });
|
||||
|
||||
// ShortcutControl for the original shortcut
|
||||
auto origin = keyboardRemapControlObjects.back()[0]->GetShortcutControl();
|
||||
@@ -104,14 +103,13 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
row.Children().Append(origin);
|
||||
|
||||
// Arrow icon
|
||||
FontIcon arrowIcon;
|
||||
arrowIcon.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
arrowIcon.Glyph(L"\xE72A");
|
||||
SymbolIcon arrowIcon(Symbol::Forward);
|
||||
arrowIcon.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIcon.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
auto arrowIconContainer = UIHelpers::GetWrapped(arrowIcon, EditorConstants::ShortcutArrowColumnWidth).as<StackPanel>();
|
||||
arrowIconContainer.Orientation(Orientation::Vertical);
|
||||
arrowIconContainer.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIconContainer.Margin({ 0, 0, 0, 10 });
|
||||
row.Children().Append(arrowIconContainer);
|
||||
|
||||
// ShortcutControl for the new shortcut
|
||||
@@ -122,6 +120,7 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
targetAppTextBox.Width(EditorConstants::ShortcutTableDropDownWidth);
|
||||
targetAppTextBox.PlaceholderText(KeyboardManagerEditorStrings::DefaultAppName());
|
||||
targetAppTextBox.Text(targetAppName);
|
||||
targetAppTextBox.Margin({ 0, 0, 0, 10 });
|
||||
|
||||
// GotFocus handler will be called whenever the user tabs into or clicks on the textbox
|
||||
targetAppTextBox.GotFocus([targetAppTextBox](auto const& sender, auto const& e) {
|
||||
@@ -194,13 +193,11 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
|
||||
// Delete row button
|
||||
Windows::UI::Xaml::Controls::Button deleteShortcut;
|
||||
FontIcon deleteSymbol;
|
||||
deleteSymbol.FontFamily(Xaml::Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
deleteSymbol.Glyph(L"\xE74D");
|
||||
deleteShortcut.Content(deleteSymbol);
|
||||
deleteShortcut.Content(SymbolIcon(Symbol::Delete));
|
||||
deleteShortcut.Background(Media::SolidColorBrush(Colors::Transparent()));
|
||||
deleteShortcut.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
deleteShortcut.Click([&, parent, row, brush, deleteShortcut](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
deleteShortcut.Margin({ 0, 0, 0, 10 });
|
||||
deleteShortcut.Click([&, parent, row, deleteShortcut](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
Button currentButton = sender.as<Button>();
|
||||
uint32_t rowIndex;
|
||||
// Get index of delete button
|
||||
@@ -216,7 +213,6 @@ void ShortcutControl::AddNewShortcutControlRow(StackPanel& parent, std::vector<s
|
||||
for (uint32_t i = rowIndex + 1; i < children.Size(); i++)
|
||||
{
|
||||
StackPanel row = children.GetAt(i).as<StackPanel>();
|
||||
row.Background(i % 2 ? brush : Media::SolidColorBrush(Colors::Transparent()));
|
||||
StackPanel sourceCol = row.Children().GetAt(0).as<StackPanel>();
|
||||
StackPanel targetCol = row.Children().GetAt(2).as<StackPanel>();
|
||||
TextBox targetApp = row.Children().GetAt(3).as<StackPanel>().Children().GetAt(0).as<StackPanel>().Children().GetAt(0).as<TextBox>();
|
||||
@@ -294,8 +290,6 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
// ContentDialog requires manually setting the XamlRoot (https://learn.microsoft.com/uwp/api/windows.ui.xaml.controls.contentdialog#contentdialog-in-appwindow-or-xaml-islands)
|
||||
detectShortcutBox.XamlRoot(xamlRoot);
|
||||
detectShortcutBox.Title(box_value(GET_RESOURCE_STRING(IDS_TYPESHORTCUT_TITLE)));
|
||||
detectShortcutBox.IsPrimaryButtonEnabled(false);
|
||||
detectShortcutBox.IsSecondaryButtonEnabled(false);
|
||||
|
||||
// Get the linked stack panel for the "Type shortcut" button that was clicked
|
||||
VariableSizedWrapGrid linkedShortcutVariableSizedWrapGrid = UIHelpers::GetSiblingElement(sender).as<VariableSizedWrapGrid>();
|
||||
@@ -359,16 +353,13 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
onReleaseEnter();
|
||||
};
|
||||
|
||||
TextBlock primaryButtonText;
|
||||
primaryButtonText.Text(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
|
||||
Button primaryButton;
|
||||
primaryButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
primaryButton.Margin({ 2, 2, 2, 2 });
|
||||
primaryButton.Content(primaryButtonText);
|
||||
|
||||
// OK button
|
||||
primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
detectShortcutBox.DefaultButton(ContentDialogButton::Primary);
|
||||
detectShortcutBox.PrimaryButtonText(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
detectShortcutBox.PrimaryButtonClick([onAccept](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
onAccept();
|
||||
});
|
||||
|
||||
@@ -376,12 +367,10 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
keyboardManagerState.RegisterKeyDelay(
|
||||
VK_RETURN,
|
||||
selectDetectedShortcutAndResetKeys,
|
||||
[primaryButton, onPressEnter, detectShortcutBox](DWORD) {
|
||||
[onPressEnter, detectShortcutBox](DWORD) {
|
||||
detectShortcutBox.Dispatcher().RunAsync(
|
||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||
[primaryButton, onPressEnter] {
|
||||
// Use the base medium low brush to be consistent with the theme
|
||||
primaryButton.Background(Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundBaseMediumLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>());
|
||||
[onPressEnter] {
|
||||
onPressEnter();
|
||||
});
|
||||
},
|
||||
@@ -393,9 +382,6 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
});
|
||||
});
|
||||
|
||||
TextBlock cancelButtonText;
|
||||
cancelButtonText.Text(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
|
||||
auto onCancel = [&keyboardManagerState,
|
||||
detectShortcutBox,
|
||||
unregisterKeys,
|
||||
@@ -418,12 +404,12 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
unregisterKeys();
|
||||
};
|
||||
|
||||
Button cancelButton;
|
||||
cancelButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
cancelButton.Margin({ 2, 2, 2, 2 });
|
||||
cancelButton.Content(cancelButtonText);
|
||||
// Cancel button
|
||||
cancelButton.Click([onCancel](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
detectShortcutBox.CloseButtonText(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
detectShortcutBox.CloseButtonClick([onCancel](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
onCancel();
|
||||
});
|
||||
|
||||
@@ -474,21 +460,6 @@ void ShortcutControl::CreateDetectShortcutWindow(winrt::Windows::Foundation::IIn
|
||||
holdEnterInfo.Margin({ 0, 0, 0, 0 });
|
||||
stackPanel.Children().Append(holdEnterInfo);
|
||||
|
||||
ColumnDefinition primaryButtonColumn;
|
||||
ColumnDefinition cancelButtonColumn;
|
||||
|
||||
Grid buttonPanel;
|
||||
buttonPanel.Margin({ 0, 20, 0, 0 });
|
||||
buttonPanel.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
buttonPanel.ColumnDefinitions().Append(primaryButtonColumn);
|
||||
buttonPanel.ColumnDefinitions().Append(cancelButtonColumn);
|
||||
buttonPanel.SetColumn(primaryButton, 0);
|
||||
buttonPanel.SetColumn(cancelButton, 1);
|
||||
|
||||
buttonPanel.Children().Append(primaryButton);
|
||||
buttonPanel.Children().Append(cancelButton);
|
||||
|
||||
stackPanel.Children().Append(buttonPanel);
|
||||
try
|
||||
{
|
||||
// If a layout update has been triggered by other methods (e.g.: adapting to zoom level), this may throw an exception.
|
||||
|
||||
@@ -84,33 +84,31 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
newrow.emplace_back(std::make_unique<SingleKeyRemapControl>(parent, row, 1));
|
||||
keyboardRemapControlObjects.push_back(std::move(newrow));
|
||||
|
||||
row.Padding({ 10, 10, 10, 10 });
|
||||
row.Padding({ 10, 15, 10, 5 });
|
||||
row.Margin({ 0, 0, 0, 2 });
|
||||
row.Orientation(Orientation::Horizontal);
|
||||
auto brush = Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundListLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>();
|
||||
if (keyboardRemapControlObjects.size() % 2)
|
||||
{
|
||||
row.Background(brush);
|
||||
}
|
||||
row.Background(Application::Current().Resources().Lookup(box_value(L"CardBackgroundFillColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderBrush(Application::Current().Resources().Lookup(box_value(L"CardStrokeColorDefaultBrush")).as<Media::Brush>());
|
||||
row.BorderThickness({ 0, 1, 0, 1 });
|
||||
|
||||
// SingleKeyRemapControl for the original key.
|
||||
auto originalElement = keyboardRemapControlObjects.back()[0]->getSingleKeyRemapControl();
|
||||
originalElement.Width(EditorConstants::RemapTableDropDownWidth + EditorConstants::ShortcutTableDropDownSpacing);
|
||||
originalElement.Width(EditorConstants::RemapTableDropDownWidth + EditorConstants::RemapTableDropDownSpacing);
|
||||
row.Children().Append(originalElement);
|
||||
|
||||
// Arrow icon
|
||||
FontIcon arrowIcon;
|
||||
arrowIcon.FontFamily(Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
arrowIcon.Glyph(L"\xE72A");
|
||||
SymbolIcon arrowIcon(Symbol::Forward);
|
||||
arrowIcon.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIcon.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
auto arrowIconContainer = UIHelpers::GetWrapped(arrowIcon, EditorConstants::TableArrowColWidth).as<StackPanel>();
|
||||
arrowIconContainer.Orientation(Orientation::Vertical);
|
||||
arrowIconContainer.VerticalAlignment(VerticalAlignment::Center);
|
||||
arrowIconContainer.Margin({ 0, 0, 0, 10 });
|
||||
row.Children().Append(arrowIconContainer);
|
||||
|
||||
// SingleKeyRemapControl for the new remap key
|
||||
auto targetElement = keyboardRemapControlObjects.back()[1]->getSingleKeyRemapControl();
|
||||
targetElement.Width(EditorConstants::ShortcutTargetColumnWidth);
|
||||
targetElement.Width(EditorConstants::RemapTargetColumnWidth);
|
||||
row.Children().Append(targetElement);
|
||||
|
||||
// Set the key text if the two keys are not null (i.e. default args)
|
||||
@@ -135,13 +133,11 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
|
||||
// Delete row button
|
||||
Windows::UI::Xaml::Controls::Button deleteRemapKeys;
|
||||
FontIcon deleteSymbol;
|
||||
deleteSymbol.FontFamily(Media::FontFamily(L"Segoe MDL2 Assets"));
|
||||
deleteSymbol.Glyph(L"\xE74D");
|
||||
deleteRemapKeys.Content(deleteSymbol);
|
||||
deleteRemapKeys.Content(SymbolIcon(Symbol::Delete));
|
||||
deleteRemapKeys.Background(Media::SolidColorBrush(Colors::Transparent()));
|
||||
deleteRemapKeys.HorizontalAlignment(HorizontalAlignment::Center);
|
||||
deleteRemapKeys.Click([&, parent, row, brush, deleteRemapKeys](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
deleteRemapKeys.Margin({ 0, 0, 0, 10 });
|
||||
deleteRemapKeys.Click([&, parent, row, deleteRemapKeys](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
uint32_t rowIndex;
|
||||
// Get index of delete button
|
||||
UIElementCollection children = parent.Children();
|
||||
@@ -157,7 +153,6 @@ void SingleKeyRemapControl::AddNewControlKeyRemapRow(StackPanel& parent, std::ve
|
||||
for (uint32_t i = rowIndex + 1; i < children.Size(); i++)
|
||||
{
|
||||
StackPanel row = children.GetAt(i).as<StackPanel>();
|
||||
row.Background(i % 2 ? brush : Media::SolidColorBrush(Colors::Transparent()));
|
||||
StackPanel sourceCol = row.Children().GetAt(0).as<StackPanel>();
|
||||
StackPanel targetCol = row.Children().GetAt(2).as<StackPanel>();
|
||||
Button delButton = row.Children().GetAt(3).as<Button>();
|
||||
@@ -224,8 +219,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
// ContentDialog requires manually setting the XamlRoot (https://learn.microsoft.com/uwp/api/windows.ui.xaml.controls.contentdialog#contentdialog-in-appwindow-or-xaml-islands)
|
||||
detectRemapKeyBox.XamlRoot(xamlRoot);
|
||||
detectRemapKeyBox.Title(box_value(GET_RESOURCE_STRING(IDS_TYPEKEY_TITLE)));
|
||||
detectRemapKeyBox.IsPrimaryButtonEnabled(false);
|
||||
detectRemapKeyBox.IsSecondaryButtonEnabled(false);
|
||||
|
||||
// Get the linked text block for the "Type Key" button that was clicked
|
||||
ComboBox linkedRemapDropDown = UIHelpers::GetSiblingElement(sender).as<ComboBox>();
|
||||
@@ -269,14 +262,13 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
onReleaseEnter();
|
||||
};
|
||||
|
||||
TextBlock primaryButtonText;
|
||||
primaryButtonText.Text(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
// OK button
|
||||
detectRemapKeyBox.DefaultButton(ContentDialogButton::Primary);
|
||||
detectRemapKeyBox.PrimaryButtonText(GET_RESOURCE_STRING(IDS_OK_BUTTON));
|
||||
detectRemapKeyBox.PrimaryButtonClick([onAccept](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
Button primaryButton;
|
||||
primaryButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
primaryButton.Margin({ 2, 2, 2, 2 });
|
||||
primaryButton.Content(primaryButtonText);
|
||||
primaryButton.Click([onAccept](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
onAccept();
|
||||
});
|
||||
|
||||
@@ -284,12 +276,10 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
keyboardManagerState.RegisterKeyDelay(
|
||||
VK_RETURN,
|
||||
std::bind(&KBMEditor::KeyboardManagerState::SelectDetectedRemapKey, &keyboardManagerState, std::placeholders::_1),
|
||||
[primaryButton, onPressEnter, detectRemapKeyBox](DWORD) {
|
||||
[onPressEnter, detectRemapKeyBox](DWORD) {
|
||||
detectRemapKeyBox.Dispatcher().RunAsync(
|
||||
Windows::UI::Core::CoreDispatcherPriority::Normal,
|
||||
[primaryButton, onPressEnter] {
|
||||
// Use the base medium low brush to be consistent with the theme
|
||||
primaryButton.Background(Windows::UI::Xaml::Application::Current().Resources().Lookup(box_value(L"SystemControlBackgroundBaseMediumLowBrush")).as<Windows::UI::Xaml::Media::SolidColorBrush>());
|
||||
[onPressEnter] {
|
||||
onPressEnter();
|
||||
});
|
||||
},
|
||||
@@ -301,9 +291,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
});
|
||||
});
|
||||
|
||||
TextBlock cancelButtonText;
|
||||
cancelButtonText.Text(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
|
||||
auto onCancel = [&keyboardManagerState,
|
||||
detectRemapKeyBox,
|
||||
unregisterKeys] {
|
||||
@@ -317,13 +304,12 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
unregisterKeys();
|
||||
};
|
||||
|
||||
Button cancelButton;
|
||||
cancelButton.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
cancelButton.Margin({ 2, 2, 2, 2 });
|
||||
cancelButton.Content(cancelButtonText);
|
||||
|
||||
// Cancel button
|
||||
cancelButton.Click([onCancel](winrt::Windows::Foundation::IInspectable const& sender, RoutedEventArgs const&) {
|
||||
detectRemapKeyBox.CloseButtonText(GET_RESOURCE_STRING(IDS_CANCEL_BUTTON));
|
||||
detectRemapKeyBox.CloseButtonClick([onCancel](winrt::Windows::Foundation::IInspectable const& sender, ContentDialogButtonClickEventArgs const& args) {
|
||||
// Cancel default dialog events
|
||||
args.Cancel(true);
|
||||
|
||||
onCancel();
|
||||
});
|
||||
|
||||
@@ -367,21 +353,6 @@ void SingleKeyRemapControl::createDetectKeyWindow(winrt::Windows::Foundation::II
|
||||
holdEnterInfo.Margin({ 0, 0, 0, 0 });
|
||||
stackPanel.Children().Append(holdEnterInfo);
|
||||
|
||||
ColumnDefinition primaryButtonColumn;
|
||||
ColumnDefinition cancelButtonColumn;
|
||||
|
||||
Grid buttonPanel;
|
||||
buttonPanel.Margin({ 0, 20, 0, 0 });
|
||||
buttonPanel.HorizontalAlignment(HorizontalAlignment::Stretch);
|
||||
buttonPanel.ColumnDefinitions().Append(primaryButtonColumn);
|
||||
buttonPanel.ColumnDefinitions().Append(cancelButtonColumn);
|
||||
buttonPanel.SetColumn(primaryButton, 0);
|
||||
buttonPanel.SetColumn(cancelButton, 1);
|
||||
|
||||
buttonPanel.Children().Append(primaryButton);
|
||||
buttonPanel.Children().Append(cancelButton);
|
||||
|
||||
stackPanel.Children().Append(buttonPanel);
|
||||
try
|
||||
{
|
||||
// If a layout update has been triggered by other methods (e.g.: adapting to zoom level), this may throw an exception.
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
#include "pch.h"
|
||||
#include "Styles.h"
|
||||
#include <common/themes/windows_colors.h>
|
||||
|
||||
Style AccentButtonStyle()
|
||||
{
|
||||
Style style{ winrt::xaml_typename<Controls::Button>() };
|
||||
style.Setters().Append(Setter{
|
||||
Controls::Control::BackgroundProperty(),
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush{ WindowsColors::get_accent_color() } });
|
||||
style.Setters().Append(Setter{
|
||||
Controls::Control::ForegroundProperty(),
|
||||
winrt::Windows::UI::Xaml::Media::SolidColorBrush{ winrt::Windows::UI::Colors::White() } });
|
||||
return style;
|
||||
return Application::Current().Resources().Lookup(box_value(L"AccentButtonStyle")).as<Style>();
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "pch.h"
|
||||
#include "XamlBridge2.h"
|
||||
#include <CoreWindow.h> // ICoreWindowInterop
|
||||
|
||||
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.XamlTypeInfo.h>
|
||||
|
||||
namespace wac = Windows::ApplicationModel::Core;
|
||||
|
||||
// Stubbed implementation for frameworkView.Initialize()
|
||||
struct XamlBridgeCoreAppViewImpl : implements<XamlBridgeCoreAppViewImpl, wac::ICoreApplicationView>
|
||||
{
|
||||
auto CoreWindow() { return Core::CoreWindow::GetForCurrentThread(); }
|
||||
auto Activated(Windows::Foundation::TypedEventHandler<wac::CoreApplicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs> const&) { return event_token(); }
|
||||
auto Activated(event_token const&) {}
|
||||
auto IsMain() { return true; }
|
||||
auto IsHosted() { return false; }
|
||||
};
|
||||
|
||||
// Function to run the message loop for the xaml window
|
||||
void XamlBridge2::MessageLoop()
|
||||
{
|
||||
Logger::trace("XamlBridge2::MessageLoop()");
|
||||
frameworkView.Run();
|
||||
Logger::trace("XamlBridge2::MessageLoop() stopped");
|
||||
}
|
||||
|
||||
// Function to initialize the xaml bridge
|
||||
HWND XamlBridge2::InitBridge()
|
||||
{
|
||||
Logger::trace("XamlBridge2::InitBridge()");
|
||||
HRESULT hr = S_OK;
|
||||
winrt::init_apartment(apartment_type::single_threaded);
|
||||
|
||||
auto windowsUIHandle = LoadLibrary(TEXT("Windows.UI.dll"));
|
||||
auto pfnPrivateCreateCoreWindow = reinterpret_cast<fnPrivateCreateCoreWindow>(GetProcAddress(windowsUIHandle, MAKEINTRESOURCEA(1500)));
|
||||
|
||||
// Create the core window to host the XAML content
|
||||
void* pCoreWindow;
|
||||
hr = pfnPrivateCreateCoreWindow(IMMERSIVE_HOSTED, L"", 0, 0, 0, 0, 0, parentWindow, winrt::guid_of<Core::ICoreWindow>(), &pCoreWindow);
|
||||
winrt::check_hresult(hr);
|
||||
coreWindow = Core::CoreWindow(pCoreWindow, winrt::take_ownership_from_abi);
|
||||
|
||||
// Prep for the WinUI resources
|
||||
auto app = Microsoft::Toolkit::Win32::UI::XamlHost::XamlApplication({ Microsoft::UI::Xaml::XamlTypeInfo::XamlControlsXamlMetaDataProvider() });
|
||||
|
||||
// Initialize the XAML framework
|
||||
frameworkView.Initialize(*reinterpret_cast<wac::CoreApplicationView*>(&make<XamlBridgeCoreAppViewImpl>()));
|
||||
frameworkView.SetWindow(coreWindow);
|
||||
|
||||
// Add the WinUI resources
|
||||
app.Resources().MergedDictionaries().Append(muxc::XamlControlsResources());
|
||||
|
||||
auto coreWindowInterop = coreWindow.as<ICoreWindowInterop>();
|
||||
hr = coreWindowInterop->get_WindowHandle(&coreWindowHwnd);
|
||||
winrt::check_hresult(hr);
|
||||
|
||||
SetParent(coreWindowHwnd, parentWindow);
|
||||
SetWindowLong(coreWindowHwnd, GWL_STYLE, WS_CHILD | WS_VISIBLE);
|
||||
|
||||
return coreWindowHwnd;
|
||||
}
|
||||
|
||||
// Message Handler function for Xaml windows
|
||||
LRESULT XamlBridge2::MessageHandler(UINT const message, WPARAM const wParam, LPARAM const lParam) noexcept
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_ACTIVATE:
|
||||
case WM_MOVE:
|
||||
SendMessage(coreWindowHwnd, message, wParam, lParam);
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(parentWindow, message, wParam, lParam);
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
// This class is used for handling XAML operations
|
||||
class XamlBridge2
|
||||
{
|
||||
public:
|
||||
// Function to run the message loop for the xaml window
|
||||
void MessageLoop();
|
||||
|
||||
// Constructor
|
||||
XamlBridge2(HWND parent) : parentWindow(parent) {}
|
||||
|
||||
// Function to initialize the xaml bridge
|
||||
HWND InitBridge();
|
||||
|
||||
// Message Handler function for Xaml windows
|
||||
LRESULT MessageHandler(UINT const message, WPARAM const wParam, LPARAM const lParam) noexcept;
|
||||
|
||||
private:
|
||||
// Defines the window types for core windows
|
||||
enum WINDOW_TYPE
|
||||
{
|
||||
IMMERSIVE_BODY = 0x0,
|
||||
IMMERSIVE_DOCK = 0x1,
|
||||
IMMERSIVE_HOSTED = 0x2,
|
||||
IMMERSIVE_TEST = 0x3,
|
||||
IMMERSIVE_BODY_ACTIVE = 0x4,
|
||||
IMMERSIVE_DOCK_ACTIVE = 0x5,
|
||||
NOT_IMMERSIVE = 0x6,
|
||||
};
|
||||
|
||||
// Function signature for PrivateCreateCoreWindow
|
||||
typedef HRESULT(CDECL* fnPrivateCreateCoreWindow)(WINDOW_TYPE WindowType, LPCWSTR pWindowTitle, INT X, INT Y, UINT uWidth, UINT uHeight, DWORD dwAttributes, HWND hOwnerWindow, REFIID riid, void** ppv);
|
||||
|
||||
// Stores the handle of the parent native window
|
||||
HWND parentWindow = nullptr;
|
||||
|
||||
// Stores the core window for the UI thread
|
||||
Core::CoreWindow coreWindow = nullptr;
|
||||
|
||||
// Stores the handle of the core window
|
||||
HWND coreWindowHwnd = nullptr;
|
||||
|
||||
// Stores the xaml framework view for the UI thread
|
||||
FrameworkView frameworkView;
|
||||
};
|
||||
@@ -1,4 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.1.3" targetFramework="native" />
|
||||
<package id="Microsoft.UI.Xaml" version="2.8.2-prerelease.220830001" targetFramework="native" />
|
||||
<package id="Microsoft.Web.WebView2" version="1.0.2088.41" targetFramework="native" />
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.221104.6" targetFramework="native" />
|
||||
</packages>
|
||||
@@ -10,8 +10,10 @@
|
||||
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
|
||||
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Foundation.Metadata.h>
|
||||
#include <winrt/Windows.UI.Core.h>
|
||||
#include <winrt/Windows.UI.Text.h>
|
||||
#include <winrt/Windows.ApplicationModel.Core.h>
|
||||
|
||||
#pragma push_macro("GetCurrentTime")
|
||||
#undef GetCurrentTime
|
||||
@@ -21,6 +23,7 @@
|
||||
#include <winrt/Windows.UI.Xaml.Hosting.h>
|
||||
#include <winrt/Windows.UI.Xaml.Interop.h>
|
||||
#include <winrt/Windows.ui.xaml.media.h>
|
||||
#include <winrt/Microsoft.UI.Xaml.Controls.h>
|
||||
#pragma pop_macro("GetCurrentTime")
|
||||
|
||||
#include <common/logger/logger.h>
|
||||
@@ -37,4 +40,5 @@ using namespace Windows::UI::Composition;
|
||||
using namespace Windows::UI::Xaml::Hosting;
|
||||
using namespace Windows::Foundation::Numerics;
|
||||
using namespace Windows::UI::Xaml;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
using namespace Windows::UI::Xaml::Controls;
|
||||
namespace muxc = Microsoft::UI::Xaml::Controls;
|
||||
@@ -12,8 +12,7 @@ namespace KeyboardEventHandlers
|
||||
// Num Lock's key state is applied before it is intercepted by low level keyboard hooks, so we have to manually set back the state when we suppress the key. This is done by sending an additional key up, key down set of messages.
|
||||
// We need 2 key events because after Num Lock is suppressed, key up to release num lock key and key down to revert the num lock state
|
||||
int key_count = 2;
|
||||
LPINPUT keyEventList = new INPUT[size_t(key_count)]();
|
||||
memset(keyEventList, 0, sizeof(keyEventList));
|
||||
LPINPUT keyEventList = new INPUT[size_t(key_count)]{};
|
||||
|
||||
// Use the suppress flag to ensure these are not intercepted by any remapped keys or shortcuts
|
||||
Helpers::SetKeyEvent(keyEventList, 0, INPUT_KEYBOARD, VK_NUMLOCK, KEYEVENTF_KEYUP, KeyboardManagerConstants::KEYBOARDMANAGER_SUPPRESS_FLAG);
|
||||
|
||||
|
Before Width: | Height: | Size: 360 B After Width: | Height: | Size: 364 B |
|
Before Width: | Height: | Size: 357 B After Width: | Height: | Size: 328 B |
@@ -98,7 +98,7 @@ namespace Community.PowerToys.Run.Plugin.UnitConverter
|
||||
PluginName = Name,
|
||||
Title = Properties.Resources.context_menu_copy,
|
||||
Glyph = "\xE8C8",
|
||||
FontFamily = "Segoe MDL2 Assets",
|
||||
FontFamily = "Segoe Fluent Icons,Segoe MDL2 Assets",
|
||||
AcceleratorKey = Key.Enter,
|
||||
Action = _ =>
|
||||
{
|
||||
|
||||
@@ -65,10 +65,10 @@
|
||||
<None Update="Images\monitor.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Images\code-dark.png">
|
||||
<None Update="Images\code.dark.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="Images\code-light.png">
|
||||
<None Update="Images\code.light.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
|
Before Width: | Height: | Size: 353 B |
|
Before Width: | Height: | Size: 353 B |
|
After Width: | Height: | Size: 437 B |
|
After Width: | Height: | Size: 405 B |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper
|
||||
{
|
||||
int bitmap1Width = bitmap1.Width;
|
||||
int bitmap1Height = bitmap1.Height;
|
||||
|
||||
bitmap1.SetResolution(144, 144);
|
||||
using Bitmap overlayBitmapResized = new Bitmap(overlayBitmap, new System.Drawing.Size(bitmap1Width / 2, bitmap1Height / 2));
|
||||
|
||||
float marginLeft = (float)((bitmap1Width * 0.7) - (overlayBitmapResized.Width * 0.5));
|
||||
@@ -71,72 +71,90 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.VSCodeHelper
|
||||
|
||||
foreach (var path in paths)
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
var files = Directory.GetFiles(path)
|
||||
.Where(x => (x.Contains("code", StringComparison.OrdinalIgnoreCase) || x.Contains("VSCodium", StringComparison.OrdinalIgnoreCase))
|
||||
&& !x.EndsWith(".cmd", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
|
||||
var iconPath = Path.GetDirectoryName(path);
|
||||
|
||||
if (files.Length > 0)
|
||||
{
|
||||
var file = files[0];
|
||||
var version = string.Empty;
|
||||
|
||||
var instance = new VSCodeInstance
|
||||
{
|
||||
ExecutablePath = file,
|
||||
};
|
||||
|
||||
if (file.EndsWith("code", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "Code";
|
||||
instance.VSCodeVersion = VSCodeVersion.Stable;
|
||||
}
|
||||
else if (file.EndsWith("code-insiders", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "Code - Insiders";
|
||||
instance.VSCodeVersion = VSCodeVersion.Insiders;
|
||||
}
|
||||
else if (file.EndsWith("code-exploration", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "Code - Exploration";
|
||||
instance.VSCodeVersion = VSCodeVersion.Exploration;
|
||||
}
|
||||
else if (file.EndsWith("VSCodium", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "VSCodium";
|
||||
instance.VSCodeVersion = VSCodeVersion.Stable; // ?
|
||||
}
|
||||
|
||||
if (version != string.Empty)
|
||||
{
|
||||
var portableData = Path.Join(iconPath, "data");
|
||||
instance.AppData = Directory.Exists(portableData) ? Path.Join(portableData, "user-data") : Path.Combine(_userAppDataPath, version);
|
||||
|
||||
var vsCodeIconPath = Path.Join(iconPath, $"{version}.exe");
|
||||
var vsCodeIcon = Icon.ExtractAssociatedIcon(vsCodeIconPath);
|
||||
|
||||
if (vsCodeIcon != null)
|
||||
{
|
||||
using var vsCodeIconBitmap = vsCodeIcon.ToBitmap();
|
||||
|
||||
// workspace
|
||||
using var folderIcon = (Bitmap)Image.FromFile(Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Images//folder.png"));
|
||||
using var bitmapFolderIcon = BitmapOverlayToCenter(folderIcon, vsCodeIconBitmap);
|
||||
instance.WorkspaceIconBitMap = Bitmap2BitmapImage(bitmapFolderIcon);
|
||||
|
||||
// remote
|
||||
using var monitorIcon = (Bitmap)Image.FromFile(Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Images//monitor.png"));
|
||||
using var bitmapMonitorIcon = BitmapOverlayToCenter(monitorIcon, vsCodeIconBitmap);
|
||||
instance.RemoteIconBitMap = Bitmap2BitmapImage(bitmapMonitorIcon);
|
||||
}
|
||||
|
||||
Instances.Add(instance);
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
var files = Directory.GetFiles(path)
|
||||
.Where(x => (x.Contains("code", StringComparison.OrdinalIgnoreCase) || x.Contains("codium", StringComparison.OrdinalIgnoreCase))
|
||||
&& !x.EndsWith(".cmd", StringComparison.OrdinalIgnoreCase)).ToArray();
|
||||
|
||||
// Remove the trailing backslash to always get the correct path
|
||||
var iconPath = Path.GetDirectoryName(path.TrimEnd('\\'));
|
||||
|
||||
if (files.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var file = files[0];
|
||||
var version = string.Empty;
|
||||
|
||||
var instance = new VSCodeInstance
|
||||
{
|
||||
ExecutablePath = file,
|
||||
};
|
||||
|
||||
if (file.EndsWith("code", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "Code";
|
||||
instance.VSCodeVersion = VSCodeVersion.Stable;
|
||||
}
|
||||
else if (file.EndsWith("code-insiders", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "Code - Insiders";
|
||||
instance.VSCodeVersion = VSCodeVersion.Insiders;
|
||||
}
|
||||
else if (file.EndsWith("code-exploration", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "Code - Exploration";
|
||||
instance.VSCodeVersion = VSCodeVersion.Exploration;
|
||||
}
|
||||
else if (file.EndsWith("codium", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "VSCodium";
|
||||
instance.VSCodeVersion = VSCodeVersion.Stable;
|
||||
}
|
||||
else if (file.EndsWith("codium-insiders", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
version = "VSCodium - Insiders";
|
||||
instance.VSCodeVersion = VSCodeVersion.Insiders;
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(version))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var portableData = Path.Join(iconPath, "data");
|
||||
instance.AppData = Directory.Exists(portableData) ? Path.Join(portableData, "user-data") : Path.Combine(_userAppDataPath, version);
|
||||
var vsCodeIconPath = Path.Join(iconPath, $"{version}.exe");
|
||||
if (!File.Exists(vsCodeIconPath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var vsCodeIcon = Icon.ExtractAssociatedIcon(vsCodeIconPath);
|
||||
|
||||
if (vsCodeIcon == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var vsCodeIconBitmap = vsCodeIcon.ToBitmap();
|
||||
|
||||
// Workspace
|
||||
using var folderIcon = (Bitmap)Image.FromFile(Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Images//folder.png"));
|
||||
using var bitmapFolderIcon = BitmapOverlayToCenter(folderIcon, vsCodeIconBitmap);
|
||||
instance.WorkspaceIconBitMap = Bitmap2BitmapImage(bitmapFolderIcon);
|
||||
|
||||
// Remote
|
||||
using var monitorIcon = (Bitmap)Image.FromFile(Path.Join(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Images//monitor.png"));
|
||||
using var bitmapMonitorIcon = BitmapOverlayToCenter(monitorIcon, vsCodeIconBitmap);
|
||||
instance.RemoteIconBitMap = Bitmap2BitmapImage(bitmapMonitorIcon);
|
||||
|
||||
Instances.Add(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
|
||||
{
|
||||
public class ParseVSCodeAuthority
|
||||
{
|
||||
private static readonly Dictionary<string, WorkspaceEnvironment> EnvironmentTypes = new()
|
||||
{
|
||||
{ string.Empty, WorkspaceEnvironment.Local },
|
||||
{ "ssh-remote", WorkspaceEnvironment.RemoteSSH },
|
||||
{ "wsl", WorkspaceEnvironment.RemoteWSL },
|
||||
{ "vsonline", WorkspaceEnvironment.Codespaces },
|
||||
{ "dev-container", WorkspaceEnvironment.DevContainer },
|
||||
{ "tunnel", WorkspaceEnvironment.RemoteTunnel },
|
||||
};
|
||||
|
||||
private static string GetRemoteName(string authority)
|
||||
{
|
||||
if (authority is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var pos = authority.IndexOf('+');
|
||||
if (pos < 0)
|
||||
{
|
||||
return authority;
|
||||
}
|
||||
|
||||
return authority[..pos];
|
||||
}
|
||||
|
||||
public static (WorkspaceEnvironment? WorkspaceEnvironment, string MachineName) GetWorkspaceEnvironment(string authority)
|
||||
{
|
||||
var remoteName = GetRemoteName(authority);
|
||||
var machineName = remoteName.Length < authority.Length ? authority[(remoteName.Length + 1)..] : null;
|
||||
return EnvironmentTypes.TryGetValue(remoteName, out WorkspaceEnvironment workspace) ?
|
||||
(workspace, machineName) :
|
||||
(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
// 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.Text.RegularExpressions;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
|
||||
{
|
||||
public class ParseVSCodeUri
|
||||
{
|
||||
private static readonly Regex LocalWorkspace = new Regex("^file:///(.+)$", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex RemoteSSHWorkspace = new Regex(@"^vscode-remote://ssh-remote\+(.+?(?=\/))(.+)$", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex RemoteWSLWorkspace = new Regex(@"^vscode-remote://wsl\+(.+?(?=\/))(.+)$", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex CodespacesWorkspace = new Regex(@"^vscode-remote://vsonline\+(.+?(?=\/))(.+)$", RegexOptions.Compiled);
|
||||
|
||||
private static readonly Regex DevContainerWorkspace = new Regex(@"^vscode-remote://dev-container\+(.+?(?=\/))(.+)$", RegexOptions.Compiled);
|
||||
|
||||
public static (WorkspaceEnvironment? WorkspaceEnvironment, string MachineName, string Path) GetWorkspaceEnvironment(string uri)
|
||||
{
|
||||
if (LocalWorkspace.IsMatch(uri))
|
||||
{
|
||||
var match = LocalWorkspace.Match(uri);
|
||||
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
return (WorkspaceEnvironment.Local, null, match.Groups[1].Value);
|
||||
}
|
||||
}
|
||||
else if (RemoteSSHWorkspace.IsMatch(uri))
|
||||
{
|
||||
var match = RemoteSSHWorkspace.Match(uri);
|
||||
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
return (WorkspaceEnvironment.RemoteSSH, match.Groups[1].Value, match.Groups[2].Value);
|
||||
}
|
||||
}
|
||||
else if (RemoteWSLWorkspace.IsMatch(uri))
|
||||
{
|
||||
var match = RemoteWSLWorkspace.Match(uri);
|
||||
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
return (WorkspaceEnvironment.RemoteWSL, match.Groups[1].Value, match.Groups[2].Value);
|
||||
}
|
||||
}
|
||||
else if (CodespacesWorkspace.IsMatch(uri))
|
||||
{
|
||||
var match = CodespacesWorkspace.Match(uri);
|
||||
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
return (WorkspaceEnvironment.Codespaces, null, match.Groups[2].Value);
|
||||
}
|
||||
}
|
||||
else if (DevContainerWorkspace.IsMatch(uri))
|
||||
{
|
||||
var match = DevContainerWorkspace.Match(uri);
|
||||
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
return (WorkspaceEnvironment.DevContainer, null, match.Groups[2].Value);
|
||||
}
|
||||
}
|
||||
|
||||
return (null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Microsoft Corporation
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
|
||||
{
|
||||
// Use regex to parse URI since System.Uri is not compliant with RFC 3986, see https://github.com/dotnet/runtime/issues/64707
|
||||
public partial class Rfc3986Uri
|
||||
{
|
||||
// The following regex is referenced from https://www.rfc-editor.org/rfc/rfc3986.html#appendix-B
|
||||
[GeneratedRegex(@"^((?<scheme>[^:/?#]+):)?(//(?<authority>[^/?#]*))?(?<path>[^?#]*)(\?(?<query>[^#]*))?(#(?<fragment>.*))?$")]
|
||||
private static partial Regex Rfc3986();
|
||||
|
||||
public string Scheme { get; private set; }
|
||||
|
||||
public string Authority { get; private set; }
|
||||
|
||||
public string Path { get; private set; }
|
||||
|
||||
public string Query { get; private set; }
|
||||
|
||||
public string Fragment { get; private set; }
|
||||
|
||||
public static Rfc3986Uri Parse([StringSyntax("Uri")] string uriString)
|
||||
{
|
||||
return uriString is not null && Rfc3986().Match(uriString) is { Success: true } match
|
||||
? new Rfc3986Uri()
|
||||
{
|
||||
Scheme = match.Groups["scheme"].Value,
|
||||
Authority = match.Groups["authority"].Value,
|
||||
Path = match.Groups["path"].Value,
|
||||
Query = match.Groups["query"].Value,
|
||||
Fragment = match.Groups["fragment"].Value,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,10 +29,10 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
|
||||
{
|
||||
case WorkspaceEnvironment.Local: return Resources.TypeWorkspaceLocal;
|
||||
case WorkspaceEnvironment.Codespaces: return "Codespaces";
|
||||
case WorkspaceEnvironment.RemoteContainers: return Resources.TypeWorkspaceContainer;
|
||||
case WorkspaceEnvironment.RemoteSSH: return "SSH";
|
||||
case WorkspaceEnvironment.RemoteWSL: return "WSL";
|
||||
case WorkspaceEnvironment.DevContainer: return Resources.TypeWorkspaceDevContainer;
|
||||
case WorkspaceEnvironment.RemoteTunnel: return "Tunnel";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
@@ -45,8 +45,8 @@ namespace Community.PowerToys.Run.Plugin.VSCodeWorkspaces.WorkspacesHelper
|
||||
Codespaces = 2,
|
||||
RemoteWSL = 3,
|
||||
RemoteSSH = 4,
|
||||
RemoteContainers = 5,
|
||||
DevContainer = 6,
|
||||
DevContainer = 5,
|
||||
RemoteTunnel = 6,
|
||||
}
|
||||
|
||||
public enum WorkspaceType
|
||||
|
||||