mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-30 17:07:23 +01:00
Compare commits
16 Commits
leilzh/ver
...
msbuildcac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d154bfa2db | ||
|
|
7ad95e29b5 | ||
|
|
a6a874dd81 | ||
|
|
16742354c4 | ||
|
|
0134823de1 | ||
|
|
6d0af32e39 | ||
|
|
8412309fed | ||
|
|
471f6d1539 | ||
|
|
d65ba7f348 | ||
|
|
1952a17a17 | ||
|
|
20dda12dbc | ||
|
|
0c870d68c6 | ||
|
|
f31497e08e | ||
|
|
718600a379 | ||
|
|
63b13d219c | ||
|
|
1e79a98b2e |
@@ -22,6 +22,7 @@
|
||||
"CalculatorEngineCommon.dll",
|
||||
"PowerToys.ManagedTelemetry.dll",
|
||||
"PowerToys.ManagedCommon.dll",
|
||||
"PowerToys.ManagedCsWin32.dll",
|
||||
"PowerToys.Common.UI.dll",
|
||||
"PowerToys.Settings.UI.Lib.dll",
|
||||
"PowerToys.GPOWrapper.dll",
|
||||
|
||||
@@ -19,7 +19,7 @@ parameters:
|
||||
- name: enableMsBuildCaching
|
||||
type: boolean
|
||||
displayName: "Enable MSBuild Caching"
|
||||
default: false
|
||||
default: true
|
||||
- name: runTests
|
||||
type: boolean
|
||||
displayName: "Run Tests"
|
||||
@@ -36,7 +36,8 @@ extends:
|
||||
template: templates/pipeline-ci-build.yml
|
||||
parameters:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}:
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
useLatestWebView2: ${{ parameters.useLatestWebView2 }}
|
||||
|
||||
@@ -19,7 +19,7 @@ parameters:
|
||||
- name: enableMsBuildCaching
|
||||
type: boolean
|
||||
displayName: "Enable MSBuild Caching"
|
||||
default: false
|
||||
default: true
|
||||
- name: runTests
|
||||
type: boolean
|
||||
displayName: "Run Tests"
|
||||
@@ -42,7 +42,8 @@ extends:
|
||||
template: templates/pipeline-ci-build.yml
|
||||
parameters:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}:
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
useLatestWinAppSDK: ${{ parameters.useLatestWinAppSDK }}
|
||||
|
||||
@@ -32,7 +32,7 @@ parameters:
|
||||
- name: enableMsBuildCaching
|
||||
type: boolean
|
||||
displayName: "Enable MSBuild Caching"
|
||||
default: false
|
||||
default: true
|
||||
- name: runTests
|
||||
type: boolean
|
||||
displayName: "Run Tests"
|
||||
@@ -46,6 +46,7 @@ extends:
|
||||
template: templates/pipeline-ci-build.yml
|
||||
parameters:
|
||||
buildPlatforms: ${{ parameters.buildPlatforms }}
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
${{ if eq(variables['System.PullRequest.IsFork'], 'False') }}:
|
||||
enableMsBuildCaching: ${{ parameters.enableMsBuildCaching }}
|
||||
runTests: ${{ parameters.runTests }}
|
||||
useVSPreview: ${{ parameters.useVSPreview }}
|
||||
|
||||
@@ -3,9 +3,6 @@ variables:
|
||||
value: false
|
||||
- name: EnablePipelineCache
|
||||
value: true
|
||||
- ${{ if eq(parameters.enableMsBuildCaching, true) }}:
|
||||
- name: EnablePipelineCache
|
||||
value: true
|
||||
|
||||
parameters:
|
||||
- name: buildPlatforms
|
||||
|
||||
@@ -3,9 +3,6 @@ variables:
|
||||
value: false
|
||||
- name: EnablePipelineCache
|
||||
value: true
|
||||
- ${{ if eq(parameters.enableMsBuildCaching, true) }}:
|
||||
- name: EnablePipelineCache
|
||||
value: true
|
||||
|
||||
parameters:
|
||||
- name: buildPlatforms
|
||||
|
||||
@@ -9,6 +9,7 @@ Param(
|
||||
$DirPath = $targetDir; #this file is in pipeline, we need root.
|
||||
$items = Get-ChildItem -Path $DirPath -File -Include *.exe, *.dll, *.ttf, PTCustomActions -Recurse -Force -ErrorAction SilentlyContinue
|
||||
$versionExceptions = @(
|
||||
"AdaptiveCards.Templating.dll",
|
||||
"Microsoft.Windows.ApplicationModel.DynamicDependency.Projection.dll",
|
||||
"Microsoft.Windows.ApplicationModel.Resources.Projection.dll",
|
||||
"Microsoft.Windows.ApplicationModel.WindowsAppRuntime.Projection.dll",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.MSBuildCache.AzurePipelines" version="0.1.283-preview" />
|
||||
<package id="Microsoft.MSBuildCache.Local" version="0.1.283-preview" />
|
||||
<package id="Microsoft.MSBuildCache.SharedCompilation" version="0.1.283-preview" />
|
||||
<package id="Microsoft.MSBuildCache.AzurePipelines" version="0.1.318-preview" />
|
||||
<package id="Microsoft.MSBuildCache.Local" version="0.1.318-preview" />
|
||||
<package id="Microsoft.MSBuildCache.SharedCompilation" version="0.1.318-preview" />
|
||||
</packages>
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "pch.h"
|
||||
#include "MouseHighlighter.h"
|
||||
#include "trace.h"
|
||||
#include <cmath>
|
||||
|
||||
#ifdef COMPOSITION
|
||||
namespace winrt
|
||||
@@ -43,7 +44,7 @@ private:
|
||||
void AddDrawingPoint(MouseButton button);
|
||||
void UpdateDrawingPointPosition(MouseButton button);
|
||||
void StartDrawingPointFading(MouseButton button);
|
||||
void ClearDrawingPoint(MouseButton button);
|
||||
void ClearDrawingPoint();
|
||||
void ClearDrawing();
|
||||
void BringToFront();
|
||||
HHOOK m_mouseHook = NULL;
|
||||
@@ -66,10 +67,12 @@ private:
|
||||
winrt::CompositionSpriteShape m_leftPointer{ nullptr };
|
||||
winrt::CompositionSpriteShape m_rightPointer{ nullptr };
|
||||
winrt::CompositionSpriteShape m_alwaysPointer{ nullptr };
|
||||
winrt::CompositionSpriteShape m_spotlightPointer{ nullptr };
|
||||
|
||||
bool m_leftPointerEnabled = true;
|
||||
bool m_rightPointerEnabled = true;
|
||||
bool m_alwaysPointerEnabled = true;
|
||||
bool m_spotlightMode = false;
|
||||
|
||||
bool m_leftButtonPressed = false;
|
||||
bool m_rightButtonPressed = false;
|
||||
@@ -95,8 +98,7 @@ bool Highlighter::CreateHighlighter()
|
||||
try
|
||||
{
|
||||
// We need a dispatcher queue.
|
||||
DispatcherQueueOptions options =
|
||||
{
|
||||
DispatcherQueueOptions options = {
|
||||
sizeof(options),
|
||||
DQTYPE_THREAD_CURRENT,
|
||||
DQTAT_COM_ASTA,
|
||||
@@ -122,7 +124,8 @@ bool Highlighter::CreateHighlighter()
|
||||
m_root.Children().InsertAtTop(m_shape);
|
||||
|
||||
return true;
|
||||
} catch (...)
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -130,6 +133,9 @@ bool Highlighter::CreateHighlighter()
|
||||
|
||||
void Highlighter::AddDrawingPoint(MouseButton button)
|
||||
{
|
||||
if (!m_compositor)
|
||||
return;
|
||||
|
||||
POINT pt;
|
||||
|
||||
// Applies DPIs.
|
||||
@@ -141,6 +147,7 @@ void Highlighter::AddDrawingPoint(MouseButton button)
|
||||
// Create circle and add it.
|
||||
auto circleGeometry = m_compositor.CreateEllipseGeometry();
|
||||
circleGeometry.Radius({ m_radius, m_radius });
|
||||
|
||||
auto circleShape = m_compositor.CreateSpriteShape(circleGeometry);
|
||||
circleShape.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
if (button == MouseButton::Left)
|
||||
@@ -156,9 +163,22 @@ void Highlighter::AddDrawingPoint(MouseButton button)
|
||||
else
|
||||
{
|
||||
// always
|
||||
circleShape.FillBrush(m_compositor.CreateColorBrush(m_alwaysColor));
|
||||
m_alwaysPointer = circleShape;
|
||||
if (m_spotlightMode)
|
||||
{
|
||||
float borderThickness = static_cast<float>(std::hypot(GetSystemMetrics(SM_CXVIRTUALSCREEN), GetSystemMetrics(SM_CYVIRTUALSCREEN)));
|
||||
circleGeometry.Radius({ static_cast<float>(borderThickness / 2.0 + m_radius), static_cast<float>(borderThickness / 2.0 + m_radius) });
|
||||
circleShape.FillBrush(nullptr);
|
||||
circleShape.StrokeBrush(m_compositor.CreateColorBrush(m_alwaysColor));
|
||||
circleShape.StrokeThickness(borderThickness);
|
||||
m_spotlightPointer = circleShape;
|
||||
}
|
||||
else
|
||||
{
|
||||
circleShape.FillBrush(m_compositor.CreateColorBrush(m_alwaysColor));
|
||||
m_alwaysPointer = circleShape;
|
||||
}
|
||||
}
|
||||
|
||||
m_shape.Shapes().Append(circleShape);
|
||||
|
||||
// TODO: We're leaking shapes for long drawing sessions.
|
||||
@@ -190,7 +210,20 @@ void Highlighter::UpdateDrawingPointPosition(MouseButton button)
|
||||
else
|
||||
{
|
||||
// always
|
||||
m_alwaysPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
if (m_spotlightMode)
|
||||
{
|
||||
if (m_spotlightPointer)
|
||||
{
|
||||
m_spotlightPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_alwaysPointer)
|
||||
{
|
||||
m_alwaysPointer.Offset({ static_cast<float>(pt.x), static_cast<float>(pt.y) });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void Highlighter::StartDrawingPointFading(MouseButton button)
|
||||
@@ -229,20 +262,22 @@ void Highlighter::StartDrawingPointFading(MouseButton button)
|
||||
circleShape.FillBrush().StartAnimation(L"Color", animation);
|
||||
}
|
||||
|
||||
void Highlighter::ClearDrawingPoint(MouseButton _button)
|
||||
void Highlighter::ClearDrawingPoint()
|
||||
{
|
||||
winrt::Windows::UI::Composition::CompositionSpriteShape circleShape{ nullptr };
|
||||
|
||||
if (nullptr == m_alwaysPointer)
|
||||
if (m_spotlightMode)
|
||||
{
|
||||
// Guard against alwaysPointer not being initialized.
|
||||
return;
|
||||
if (m_spotlightPointer)
|
||||
{
|
||||
m_spotlightPointer.StrokeBrush().as<winrt::Windows::UI::Composition::CompositionColorBrush>().Color(winrt::Windows::UI::ColorHelper::FromArgb(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_alwaysPointer)
|
||||
{
|
||||
m_alwaysPointer.FillBrush().as<winrt::Windows::UI::Composition::CompositionColorBrush>().Color(winrt::Windows::UI::ColorHelper::FromArgb(0, 0, 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
// always
|
||||
circleShape = m_alwaysPointer;
|
||||
|
||||
circleShape.FillBrush().as<winrt::Windows::UI::Composition::CompositionColorBrush>().Color(winrt::Windows::UI::ColorHelper::FromArgb(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
void Highlighter::ClearDrawing()
|
||||
@@ -269,13 +304,14 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_rightButtonPressed)
|
||||
{
|
||||
// Clear AlwaysPointer only when it's enabled and RightPointer is not active
|
||||
instance->ClearDrawingPoint(MouseButton::None);
|
||||
instance->ClearDrawingPoint();
|
||||
}
|
||||
if (instance->m_leftButtonPressed)
|
||||
{
|
||||
// There might be a stray point from the user releasing the mouse button on an elevated window, which wasn't caught by us.
|
||||
instance->StartDrawingPointFading(MouseButton::Left);
|
||||
}
|
||||
|
||||
instance->AddDrawingPoint(MouseButton::Left);
|
||||
instance->m_leftButtonPressed = true;
|
||||
// start a timer for the scenario, when the user clicks a pinned window which has no focus.
|
||||
@@ -293,7 +329,7 @@ LRESULT CALLBACK Highlighter::MouseHookProc(int nCode, WPARAM wParam, LPARAM lPa
|
||||
if (instance->m_alwaysPointerEnabled && !instance->m_leftButtonPressed)
|
||||
{
|
||||
// Clear AlwaysPointer only when it's enabled and LeftPointer is not active
|
||||
instance->ClearDrawingPoint(MouseButton::None);
|
||||
instance->ClearDrawingPoint();
|
||||
}
|
||||
if (instance->m_rightButtonPressed)
|
||||
{
|
||||
@@ -358,13 +394,21 @@ void Highlighter::StartDrawing()
|
||||
{
|
||||
Logger::info("Starting draw mode.");
|
||||
Trace::StartHighlightingSession();
|
||||
|
||||
if (m_spotlightMode && m_alwaysColor.A != 0)
|
||||
{
|
||||
Trace::StartSpotlightSession();
|
||||
}
|
||||
|
||||
m_visible = true;
|
||||
|
||||
// HACK: Draw with 1 pixel off. Otherwise Windows glitches the task bar transparency when a transparent window fill the whole screen.
|
||||
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN) + 1, GetSystemMetrics(SM_YVIRTUALSCREEN) + 1, GetSystemMetrics(SM_CXVIRTUALSCREEN) - 2, GetSystemMetrics(SM_CYVIRTUALSCREEN) - 2, 0);
|
||||
ClearDrawing();
|
||||
ShowWindow(m_hwnd, SW_SHOWNOACTIVATE);
|
||||
instance->AddDrawingPoint(MouseButton::None);
|
||||
|
||||
instance->AddDrawingPoint(Highlighter::MouseButton::None);
|
||||
|
||||
m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookProc, m_hinstance, 0);
|
||||
}
|
||||
|
||||
@@ -377,6 +421,7 @@ void Highlighter::StopDrawing()
|
||||
m_leftPointer = nullptr;
|
||||
m_rightPointer = nullptr;
|
||||
m_alwaysPointer = nullptr;
|
||||
m_spotlightPointer = nullptr;
|
||||
ShowWindow(m_hwnd, SW_HIDE);
|
||||
UnhookWindowsHookEx(m_mouseHook);
|
||||
ClearDrawing();
|
||||
@@ -388,7 +433,8 @@ void Highlighter::SwitchActivationMode()
|
||||
PostMessage(m_hwnd, WM_SWITCH_ACTIVATION_MODE, 0, 0);
|
||||
}
|
||||
|
||||
void Highlighter::ApplySettings(MouseHighlighterSettings settings) {
|
||||
void Highlighter::ApplySettings(MouseHighlighterSettings settings)
|
||||
{
|
||||
m_radius = static_cast<float>(settings.radius);
|
||||
m_fadeDelay_ms = settings.fadeDelayMs;
|
||||
m_fadeDuration_ms = settings.fadeDurationMs;
|
||||
@@ -398,9 +444,23 @@ void Highlighter::ApplySettings(MouseHighlighterSettings settings) {
|
||||
m_leftPointerEnabled = settings.leftButtonColor.A != 0;
|
||||
m_rightPointerEnabled = settings.rightButtonColor.A != 0;
|
||||
m_alwaysPointerEnabled = settings.alwaysColor.A != 0;
|
||||
m_spotlightMode = settings.spotlightMode && settings.alwaysColor.A != 0;
|
||||
|
||||
if (m_spotlightMode)
|
||||
{
|
||||
m_leftPointerEnabled = false;
|
||||
m_rightPointerEnabled = false;
|
||||
}
|
||||
|
||||
if (instance->m_visible)
|
||||
{
|
||||
instance->StopDrawing();
|
||||
instance->StartDrawing();
|
||||
}
|
||||
}
|
||||
|
||||
void Highlighter::BringToFront() {
|
||||
void Highlighter::BringToFront()
|
||||
{
|
||||
// HACK: Draw with 1 pixel off. Otherwise Windows glitches the task bar transparency when a transparent window fill the whole screen.
|
||||
SetWindowPos(m_hwnd, HWND_TOPMOST, GetSystemMetrics(SM_XVIRTUALSCREEN) + 1, GetSystemMetrics(SM_YVIRTUALSCREEN) + 1, GetSystemMetrics(SM_CXVIRTUALSCREEN) - 2, GetSystemMetrics(SM_CYVIRTUALSCREEN) - 2, 0);
|
||||
}
|
||||
@@ -488,8 +548,7 @@ bool Highlighter::MyRegisterClass(HINSTANCE hInstance)
|
||||
m_hwndOwner = CreateWindow(L"static", nullptr, WS_POPUP, 0, 0, 0, 0, nullptr, nullptr, hInstance, nullptr);
|
||||
|
||||
DWORD exStyle = WS_EX_TRANSPARENT | WS_EX_LAYERED | WS_EX_NOREDIRECTIONBITMAP | WS_EX_TOOLWINDOW;
|
||||
return CreateWindowExW(exStyle, m_className, m_windowTitle, WS_POPUP,
|
||||
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hInstance, nullptr) != nullptr;
|
||||
return CreateWindowExW(exStyle, m_className, m_windowTitle, WS_POPUP, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, m_hwndOwner, nullptr, hInstance, nullptr) != nullptr;
|
||||
}
|
||||
|
||||
void Highlighter::Terminate()
|
||||
|
||||
@@ -18,6 +18,7 @@ struct MouseHighlighterSettings
|
||||
int fadeDelayMs = MOUSE_HIGHLIGHTER_DEFAULT_DELAY_MS;
|
||||
int fadeDurationMs = MOUSE_HIGHLIGHTER_DEFAULT_DURATION_MS;
|
||||
bool autoActivate = MOUSE_HIGHLIGHTER_DEFAULT_AUTO_ACTIVATE;
|
||||
bool spotlightMode = false;
|
||||
};
|
||||
|
||||
int MouseHighlighterMain(HINSTANCE hinst, MouseHighlighterSettings settings);
|
||||
|
||||
@@ -18,6 +18,7 @@ namespace
|
||||
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DELAY_MS[] = L"highlight_fade_delay_ms";
|
||||
const wchar_t JSON_KEY_HIGHLIGHT_FADE_DURATION_MS[] = L"highlight_fade_duration_ms";
|
||||
const wchar_t JSON_KEY_AUTO_ACTIVATE[] = L"auto_activate";
|
||||
const wchar_t JSON_KEY_SPOTLIGHT_MODE[] = L"spotlight_mode";
|
||||
}
|
||||
|
||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||
@@ -367,6 +368,16 @@ public:
|
||||
{
|
||||
Logger::warn("Failed to initialize auto activate from settings. Will use default value");
|
||||
}
|
||||
try
|
||||
{
|
||||
// Parse spotlight mode
|
||||
auto jsonPropertiesObject = settingsObject.GetNamedObject(JSON_KEY_PROPERTIES).GetNamedObject(JSON_KEY_SPOTLIGHT_MODE);
|
||||
highlightSettings.spotlightMode = jsonPropertiesObject.GetNamedBoolean(JSON_KEY_VALUE);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
Logger::warn("Failed to initialize spotlight mode settings. Will use default value");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -30,3 +30,13 @@ void Trace::StartHighlightingSession() noexcept
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
// Log that spotlight mode is enabled
|
||||
void Trace::StartSpotlightSession() noexcept
|
||||
{
|
||||
TraceLoggingWriteWrapper(
|
||||
g_hProvider,
|
||||
"MouseHighlighter_StartSpotlightSession",
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
@@ -10,4 +10,7 @@ public:
|
||||
|
||||
// Log that the user activated the module by starting a highlighting session
|
||||
static void StartHighlightingSession() noexcept;
|
||||
|
||||
// Log that spotlight mode is enabled
|
||||
static void StartSpotlightSession() noexcept;
|
||||
};
|
||||
|
||||
@@ -155,6 +155,7 @@ public partial class CommandBarViewModel : ObservableObject,
|
||||
ContextMenuStack.Add(new ContextMenuStackViewModel(command));
|
||||
OnPropertyChanging(nameof(ContextMenu));
|
||||
OnPropertyChanged(nameof(ContextMenu));
|
||||
WeakReferenceMessenger.Default.Send<PerformCommandMessage>(new(command.Command.Model, command.Model));
|
||||
return ContextKeybindingResult.KeepOpen;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.UI.ViewModels.BuiltinCommands;
|
||||
@@ -20,7 +21,7 @@ internal sealed partial class FallbackReloadItem : FallbackCommandItem
|
||||
|
||||
public override void UpdateQuery(string query)
|
||||
{
|
||||
_reloadCommand.Name = query.StartsWith('r') ? "Reload" : string.Empty;
|
||||
_reloadCommand.Name = query.StartsWith("r", StringComparison.OrdinalIgnoreCase) ? "Reload" : string.Empty;
|
||||
Title = _reloadCommand.Name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +173,25 @@ public class UWPApplication : IProgram
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string TryLoadIndirectString(string source, Span<char> buffer, string errorContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
PInvoke.SHLoadIndirectString(source, buffer).ThrowOnFailure();
|
||||
|
||||
var len = buffer.IndexOf('\0');
|
||||
var loaded = len >= 0
|
||||
? buffer[..len].ToString()
|
||||
: buffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Unable to load resource {source} : {errorContext} : {ex.Message}");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe string ResourceFromPri(string packageFullName, string resourceReference)
|
||||
{
|
||||
const string prefix = "ms-resource:";
|
||||
@@ -218,39 +237,18 @@ public class UWPApplication : IProgram
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var capacity = 1024U;
|
||||
PWSTR outBuffer = new PWSTR((char*)(void*)Marshal.AllocHGlobal((int)capacity * sizeof(char)));
|
||||
Span<char> outBuffer = stackalloc char[1024];
|
||||
var source = $"@{{{packageFullName}? {parsed}}}";
|
||||
|
||||
try
|
||||
{
|
||||
PInvoke.SHLoadIndirectString(source, outBuffer.AsSpan()).ThrowOnFailure();
|
||||
var loaded = TryLoadIndirectString(source, outBuffer, resourceReference);
|
||||
|
||||
var loaded = outBuffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
catch (Exception)
|
||||
if (!string.IsNullOrEmpty(loaded))
|
||||
{
|
||||
try
|
||||
{
|
||||
var sourceFallback = $"@{{{packageFullName}?{parsedFallback}}}";
|
||||
PInvoke.SHLoadIndirectString(sourceFallback, outBuffer.AsSpan()).ThrowOnFailure();
|
||||
var loaded = outBuffer.ToString();
|
||||
return string.IsNullOrEmpty(loaded) ? string.Empty : loaded;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// ProgramLogger.Exception($"Unable to load resource {resourceReference} from {packageFullName}", new InvalidOperationException(), GetType(), packageFullName);
|
||||
return string.Empty;
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal((IntPtr)outBuffer.Value);
|
||||
return loaded;
|
||||
}
|
||||
|
||||
var sourceFallback = $"@{{{packageFullName}?{parsedFallback}}}";
|
||||
return TryLoadIndirectString(sourceFallback, outBuffer, $"{resourceReference} (fallback)");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -84,11 +84,7 @@ public static class CalculateEngine
|
||||
|
||||
var decimalResult = Convert.ToDecimal(result, cultureInfo);
|
||||
|
||||
// Remove trailing zeros from the decimal string representation (e.g., "1.2300" -> "1.23")
|
||||
// This is necessary because the value extracted from exprtk may contain unnecessary trailing zeros.
|
||||
var formatted = decimalResult.ToString("G29", cultureInfo);
|
||||
decimalResult = Convert.ToDecimal(formatted, cultureInfo);
|
||||
var roundedResult = Round(decimalResult);
|
||||
var roundedResult = FormatMax15Digits(decimalResult, cultureInfo);
|
||||
|
||||
return new CalculateResult()
|
||||
{
|
||||
@@ -101,4 +97,28 @@ public static class CalculateEngine
|
||||
{
|
||||
return Math.Round(value, RoundingDigits, MidpointRounding.AwayFromZero);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Format a decimal so that the output contains **at most 15 total digits**
|
||||
/// (integer + fraction, not counting the decimal point or minus sign).
|
||||
/// Any extra fractional digits are rounded using “away-from-zero” rounding.
|
||||
/// Trailing zeros in the fractional part—and a dangling decimal point—are removed.
|
||||
/// Examples
|
||||
/// 1.9999999999 → "1.9999999999"
|
||||
/// 100000.9999999999 → "100001"
|
||||
/// 1234567890123.45 → "1234567890123.45"
|
||||
/// </summary>
|
||||
private static decimal FormatMax15Digits(decimal value, CultureInfo cultureInfo)
|
||||
{
|
||||
var absValue = Math.Abs(value);
|
||||
var integerDigits = absValue >= 1 ? (int)Math.Floor(Math.Log10((double)absValue)) + 1 : 1;
|
||||
|
||||
var maxDecimalDigits = Math.Max(0, 15 - integerDigits);
|
||||
|
||||
var rounded = Math.Round(value, maxDecimalDigits, MidpointRounding.AwayFromZero);
|
||||
|
||||
var formatted = rounded.ToString("G29", cultureInfo);
|
||||
|
||||
return Convert.ToDecimal(formatted, cultureInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Windows.AI.Actions;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
|
||||
public static class ActionRuntimeManager
|
||||
{
|
||||
private static readonly Lazy<Task<ActionRuntime>> _lazyRuntime = new(InitializeAsync);
|
||||
|
||||
public static Task<ActionRuntime> InstanceAsync => _lazyRuntime.Value;
|
||||
|
||||
private static async Task<ActionRuntime> InitializeAsync()
|
||||
{
|
||||
// If we tried 3 times and failed, should we think the action runtime is not working?
|
||||
// then we should not use it anymore.
|
||||
const int maxAttempts = 3;
|
||||
|
||||
for (var attempt = 1; attempt <= maxAttempts; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var runtime = ActionRuntimeFactory.CreateActionRuntime();
|
||||
await Task.Delay(500);
|
||||
|
||||
return runtime;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Attempt {attempt} to initialize ActionRuntime failed: {ex.Message}");
|
||||
|
||||
if (attempt == maxAttempts)
|
||||
{
|
||||
Logger.LogError($"Failed to initialize ActionRuntime: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,15 @@ namespace Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
|
||||
internal sealed partial class IndexerListItem : ListItem
|
||||
{
|
||||
internal static readonly bool IsActionsFeatureEnabled = GetFeatureFlag();
|
||||
|
||||
private static bool GetFeatureFlag()
|
||||
{
|
||||
var env = System.Environment.GetEnvironmentVariable("CMDPAL_ENABLE_ACTIONS_LIST");
|
||||
return !string.IsNullOrEmpty(env) &&
|
||||
(env == "1" || env.Equals("true", System.StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
internal string FilePath { get; private set; }
|
||||
|
||||
public IndexerListItem(
|
||||
@@ -45,7 +54,7 @@ internal sealed partial class IndexerListItem : ListItem
|
||||
..context,
|
||||
new CommandContextItem(new OpenWithCommand(indexerItem))];
|
||||
|
||||
if (ApiInformation.IsApiContractPresent("Windows.AI.Actions.ActionsContract", 4))
|
||||
if (IsActionsFeatureEnabled && ApiInformation.IsApiContractPresent("Windows.AI.Actions.ActionsContract", 4))
|
||||
{
|
||||
var actionsListContextItem = new ActionsListContextItem(indexerItem.FullPath);
|
||||
if (actionsListContextItem.AnyActions())
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
using Windows.Foundation.Metadata;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer;
|
||||
|
||||
@@ -17,6 +19,11 @@ public partial class IndexerCommandsProvider : CommandProvider
|
||||
Id = "Files";
|
||||
DisplayName = Resources.IndexerCommandsProvider_DisplayName;
|
||||
Icon = Icons.FileExplorer;
|
||||
|
||||
if (IndexerListItem.IsActionsFeatureEnabled && ApiInformation.IsApiContractPresent("Windows.AI.Actions.ActionsContract", 4))
|
||||
{
|
||||
_ = ActionRuntimeManager.InstanceAsync;
|
||||
}
|
||||
}
|
||||
|
||||
public override ICommandItem[] TopLevelCommands()
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
// The Microsoft Corporation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using ManagedCommon;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Commands;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Data;
|
||||
using Microsoft.CmdPal.Ext.Indexer.Properties;
|
||||
@@ -15,7 +17,7 @@ using Windows.System;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Indexer.Pages;
|
||||
|
||||
internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
internal sealed partial class ActionsListContextItem : CommandContextItem, IDisposable
|
||||
{
|
||||
private readonly string fullPath;
|
||||
private readonly List<CommandContextItem> actions = [];
|
||||
@@ -41,20 +43,24 @@ internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
|
||||
private void UpdateMoreCommands()
|
||||
{
|
||||
try
|
||||
lock (UpdateMoreCommandsLock)
|
||||
{
|
||||
lock (UpdateMoreCommandsLock)
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
actionRuntime = ActionRuntimeFactory.CreateActionRuntime();
|
||||
Task.Delay(500).Wait();
|
||||
}
|
||||
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed;
|
||||
actionRuntime = ActionRuntimeManager.InstanceAsync.GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
if (actionRuntime == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
actionRuntime.ActionCatalog.Changed += ActionCatalog_Changed;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var extension = System.IO.Path.GetExtension(fullPath).ToLower(CultureInfo.InvariantCulture);
|
||||
ActionEntity entity = null;
|
||||
if (extension != null)
|
||||
@@ -85,9 +91,20 @@ internal sealed partial class ActionsListContextItem : CommandContextItem
|
||||
MoreCommands = [.. actions];
|
||||
}
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
actionRuntime = null;
|
||||
Logger.LogError($"Error updating commands: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (UpdateMoreCommandsLock)
|
||||
{
|
||||
if (actionRuntime != null)
|
||||
{
|
||||
actionRuntime.ActionCatalog.Changed -= ActionCatalog_Changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
private readonly Lock _resultsLock = new();
|
||||
|
||||
private IList<ListItem> _results = new List<ListItem>();
|
||||
private bool _dataLoaded;
|
||||
|
||||
private SettingsManager _settingsManager;
|
||||
|
||||
@@ -33,11 +34,23 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
|
||||
public override IListItem[] GetItems()
|
||||
{
|
||||
ListItem[] results;
|
||||
lock (_resultsLock)
|
||||
{
|
||||
if (_dataLoaded)
|
||||
{
|
||||
results = _results.ToArray();
|
||||
_dataLoaded = false;
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
||||
DoExecuteSearch(string.Empty);
|
||||
|
||||
lock (_resultsLock)
|
||||
{
|
||||
ListItem[] results = _results.ToArray();
|
||||
results = _results.ToArray();
|
||||
_dataLoaded = false;
|
||||
return results;
|
||||
}
|
||||
}
|
||||
@@ -75,6 +88,7 @@ internal sealed partial class TimeDateExtensionPage : DynamicListPage
|
||||
lock (_resultsLock)
|
||||
{
|
||||
this._results = result;
|
||||
_dataLoaded = true;
|
||||
}
|
||||
|
||||
RaiseItemsChanged(this._results.Count);
|
||||
|
||||
@@ -20,7 +20,7 @@ internal sealed partial class CloseWindowCommand : InvokableCommand
|
||||
|
||||
public CloseWindowCommand(Window window)
|
||||
{
|
||||
Icon = new IconInfo("\xE8BB");
|
||||
Icon = new IconInfo("\uE894");
|
||||
Name = $"{Resources.windowwalker_Close}";
|
||||
_window = window;
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ using Microsoft.CommandPalette.Extensions.Toolkit;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.WindowWalker.Commands;
|
||||
|
||||
internal sealed partial class KillProcessCommand : InvokableCommand
|
||||
internal sealed partial class EndTaskCommand : InvokableCommand
|
||||
{
|
||||
private readonly Window _window;
|
||||
|
||||
public KillProcessCommand(Window window)
|
||||
public EndTaskCommand(Window window)
|
||||
{
|
||||
Icon = new IconInfo("\xE74D"); // Delete symbol
|
||||
Icon = new IconInfo("\uF140");
|
||||
Name = $"{Resources.windowwalker_Kill}";
|
||||
_window = window;
|
||||
}
|
||||
@@ -33,7 +33,7 @@ internal sealed class ContextMenuHelper
|
||||
if (!windowData.Process.IsShellProcess && !(windowData.Process.IsUwpApp && string.Equals(windowData.Process.Name, "ApplicationFrameHost.exe", StringComparison.OrdinalIgnoreCase))
|
||||
&& !(windowData.Process.IsFullAccessDenied && SettingsManager.Instance.HideKillProcessOnElevatedProcesses))
|
||||
{
|
||||
contextMenu.Add(new CommandContextItem(new KillProcessCommand(windowData))
|
||||
contextMenu.Add(new CommandContextItem(new EndTaskCommand(windowData))
|
||||
{
|
||||
RequestedShortcut = KeyChordHelpers.FromModifiers(true, false, false, false, (int)VirtualKey.Delete, 0),
|
||||
IsCritical = true,
|
||||
|
||||
@@ -124,7 +124,7 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Info: Killing the Explorer process isn't possible..
|
||||
/// Looks up a localized string similar to Info: Ending the Explorer process isn't possible..
|
||||
/// </summary>
|
||||
public static string windowwalker_ExplorerInfoTitle {
|
||||
get {
|
||||
@@ -133,7 +133,7 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Kill process.
|
||||
/// Looks up a localized string similar to End task.
|
||||
/// </summary>
|
||||
public static string windowwalker_Kill {
|
||||
get {
|
||||
@@ -142,7 +142,7 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Your are going to kill the following process:.
|
||||
/// Looks up a localized string similar to You are going to end the following process:.
|
||||
/// </summary>
|
||||
public static string windowwalker_KillMessage {
|
||||
get {
|
||||
@@ -160,7 +160,7 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Properties {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Kill process confirmation.
|
||||
/// Looks up a localized string similar to End task confirmation.
|
||||
/// </summary>
|
||||
public static string windowwalker_KillMessageTitle {
|
||||
get {
|
||||
|
||||
@@ -166,23 +166,23 @@
|
||||
<comment>Explorer is here the program File Explorer</comment>
|
||||
</data>
|
||||
<data name="windowwalker_ExplorerInfoTitle" xml:space="preserve">
|
||||
<value>Info: Killing the Explorer process isn't possible.</value>
|
||||
<value>Info: Ending the Explorer process isn't possible.</value>
|
||||
<comment>Explorer is here the program File Explorer</comment>
|
||||
</data>
|
||||
<data name="windowwalker_Close" xml:space="preserve">
|
||||
<value>Close window</value>
|
||||
</data>
|
||||
<data name="windowwalker_Kill" xml:space="preserve">
|
||||
<value>Kill process</value>
|
||||
<value>End task</value>
|
||||
</data>
|
||||
<data name="windowwalker_KillMessage" xml:space="preserve">
|
||||
<value>Your are going to kill the following process:</value>
|
||||
<value>The following process will be ended:</value>
|
||||
</data>
|
||||
<data name="windowwalker_KillMessageQuestion" xml:space="preserve">
|
||||
<value>Continue?</value>
|
||||
</data>
|
||||
<data name="windowwalker_KillMessageTitle" xml:space="preserve">
|
||||
<value>Kill process confirmation</value>
|
||||
<value>End task confirmation</value>
|
||||
</data>
|
||||
<data name="windowwalker_KillMessageUwp" xml:space="preserve">
|
||||
<value>Because this is an app process, all instances of the app will be killed. Continue?</value>
|
||||
|
||||
@@ -25,7 +25,7 @@ public class Program
|
||||
server.RegisterExtension(() => extensionInstance);
|
||||
|
||||
// This will make the main thread wait until the event is signalled by the extension class.
|
||||
// Since we have single instance of the extension object, we exit as soon as it is disposed.
|
||||
// Since we have a single instance of the extension object, we exit as soon as it is disposed.
|
||||
extensionDisposedEvent.WaitOne();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -12,4 +12,4 @@ To view the full docs, you can head over to [our docs site](https://go.microsoft
|
||||
There are samples of just about everything you can do in [the samples project].
|
||||
Head over there to see basic usage of the APIs.
|
||||
|
||||
[the samples project]: https://github.com/microsoft/PowerToys/tree/main/src/modules/cmdpal/Exts/SamplePagesExtension
|
||||
[the samples project]: https://github.com/microsoft/PowerToys/tree/main/src/modules/cmdpal/ext/SamplePagesExtension
|
||||
|
||||
@@ -180,9 +180,6 @@
|
||||
<value>Exit</value>
|
||||
<comment>Exit as a verb, as in Exit the application</comment>
|
||||
</data>
|
||||
<data name="SHOW_TRAY_ICON_MENU_TEXT" xml:space="preserve">
|
||||
<value>Show icon</value>
|
||||
</data>
|
||||
<data name="SUBMIT_BUG_TEXT" xml:space="preserve">
|
||||
<value>Report bug</value>
|
||||
</data>
|
||||
|
||||
@@ -164,7 +164,8 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save)
|
||||
else
|
||||
{
|
||||
delete_auto_start_task_for_this_user();
|
||||
if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_enabled || gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_not_configured) {
|
||||
if (gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_enabled || gpo_run_as_startup == powertoys_gpo::gpo_rule_configured_not_configured)
|
||||
{
|
||||
create_auto_start_task_for_this_user(run_as_elevated);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,4 +21,3 @@
|
||||
#define ID_REPORT_BUG_COMMAND 40004
|
||||
#define ID_DOCUMENTATION_MENU_COMMAND 40005
|
||||
#define ID_QUICK_ACCESS_MENU_COMMAND 40006
|
||||
#define ID_SHOW_TRAY_ICON_MENU_COMMAND 40007
|
||||
|
||||
Binary file not shown.
@@ -91,13 +91,6 @@ void handle_tray_command(HWND window, const WPARAM command_id, LPARAM lparam)
|
||||
}
|
||||
DestroyWindow(window);
|
||||
break;
|
||||
case ID_SHOW_TRAY_ICON_MENU_COMMAND:
|
||||
{
|
||||
GeneralSettings settings = get_general_settings();
|
||||
settings.showSystemTrayIcon = true;
|
||||
apply_general_settings(settings.to_json(), true);
|
||||
break;
|
||||
}
|
||||
case ID_ABOUT_MENU_COMMAND:
|
||||
if (!about_box_shown)
|
||||
{
|
||||
@@ -199,13 +192,11 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
{
|
||||
static std::wstring settings_menuitem_label = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT);
|
||||
static std::wstring exit_menuitem_label = GET_RESOURCE_STRING(IDS_EXIT_MENU_TEXT);
|
||||
static std::wstring show_tray_icon_menuitem_label = GET_RESOURCE_STRING(IDS_SHOW_TRAY_ICON_MENU_TEXT);
|
||||
static std::wstring submit_bug_menuitem_label = GET_RESOURCE_STRING(IDS_SUBMIT_BUG_TEXT);
|
||||
static std::wstring documentation_menuitem_label = GET_RESOURCE_STRING(IDS_DOCUMENTATION_MENU_TEXT);
|
||||
static std::wstring quick_access_menuitem_label = GET_RESOURCE_STRING(IDS_QUICK_ACCESS_MENU_TEXT);
|
||||
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
|
||||
change_menu_item_text(ID_EXIT_MENU_COMMAND, exit_menuitem_label.data());
|
||||
change_menu_item_text(ID_SHOW_TRAY_ICON_MENU_COMMAND, show_tray_icon_menuitem_label.data());
|
||||
change_menu_item_text(ID_REPORT_BUG_COMMAND, submit_bug_menuitem_label.data());
|
||||
bool bug_report_disabled = is_bug_report_running();
|
||||
EnableMenuItem(h_sub_menu, ID_REPORT_BUG_COMMAND, MF_BYCOMMAND | (bug_report_disabled ? MF_GRAYED : MF_ENABLED));
|
||||
|
||||
@@ -41,6 +41,9 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
[JsonPropertyName("auto_activate")]
|
||||
public BoolProperty AutoActivate { get; set; }
|
||||
|
||||
[JsonPropertyName("spotlight_mode")]
|
||||
public BoolProperty SpotlightMode { get; set; }
|
||||
|
||||
public MouseHighlighterProperties()
|
||||
{
|
||||
ActivationShortcut = DefaultActivationShortcut;
|
||||
@@ -52,6 +55,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
HighlightFadeDelayMs = new IntProperty(500);
|
||||
HighlightFadeDurationMs = new IntProperty(250);
|
||||
AutoActivate = new BoolProperty(false);
|
||||
SpotlightMode = new BoolProperty(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,15 +214,24 @@
|
||||
HeaderIcon="{ui:FontIcon Glyph=}"
|
||||
IsEnabled="{x:Bind ViewModel.IsMouseHighlighterEnabled, Mode=OneWay}">
|
||||
<tkcontrols:SettingsExpander.Items>
|
||||
<tkcontrols:SettingsCard x:Uid="MouseUtils_MouseHighlighter_PrimaryButtonClickColor">
|
||||
<tkcontrols:SettingsCard x:Uid="MouseUtils_MouseHighlighter_PrimaryButtonClickColor" IsEnabled="{x:Bind ViewModel.IsSpotlightModeEnabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<controls:AlphaColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterLeftButtonClickColor, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard x:Uid="MouseUtils_MouseHighlighter_SecondaryButtonClickColor">
|
||||
<tkcontrols:SettingsCard x:Uid="MouseUtils_MouseHighlighter_SecondaryButtonClickColor" IsEnabled="{x:Bind ViewModel.IsSpotlightModeEnabled, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}">
|
||||
<controls:AlphaColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterRightButtonClickColor, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard x:Uid="MouseUtils_MouseHighlighter_AlwaysColor">
|
||||
<controls:AlphaColorPickerButton SelectedColor="{x:Bind Path=ViewModel.MouseHighlighterAlwaysColor, Mode=TwoWay}" />
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard x:Uid="HighlightMode">
|
||||
<ComboBox
|
||||
x:Uid="MouseUtils_MouseHighlighter_SpotlightModeType"
|
||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||
SelectedIndex="{x:Bind ViewModel.IsSpotlightModeEnabled, Converter={StaticResource ReverseBoolToComboBoxIndexConverter}, Mode=TwoWay}">
|
||||
<ComboBoxItem x:Uid="HighlightMode_Spotlight_Mode" />
|
||||
<ComboBoxItem x:Uid="HighlightMode_Circle_Highlight_Mode" />
|
||||
</ComboBox>
|
||||
</tkcontrols:SettingsCard>
|
||||
<tkcontrols:SettingsCard x:Uid="MouseUtils_MouseHighlighter_HighlightRadius">
|
||||
<NumberBox
|
||||
MinWidth="{StaticResource SettingActionControlMinWidth}"
|
||||
|
||||
@@ -5068,4 +5068,16 @@ To record a specific window, enter the hotkey with the Alt key in the opposite m
|
||||
<data name="BugReportUnderConstruction" xml:space="preserve">
|
||||
<value>Bug report package is being created</value>
|
||||
</data>
|
||||
<data name="HighlightMode.Description" xml:space="preserve">
|
||||
<value>Highlight the cursor or dim the screen to spotlight it</value>
|
||||
</data>
|
||||
<data name="HighlightMode.Header" xml:space="preserve">
|
||||
<value>Highlight mode</value>
|
||||
</data>
|
||||
<data name="HighlightMode_Circle_Highlight_Mode.Content" xml:space="preserve">
|
||||
<value>Circle highlight</value>
|
||||
</data>
|
||||
<data name="HighlightMode_Spotlight_Mode.Content" xml:space="preserve">
|
||||
<value>Spotlight</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -72,6 +72,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
|
||||
string alwaysColor = MouseHighlighterSettingsConfig.Properties.AlwaysColor.Value;
|
||||
_highlighterAlwaysColor = !string.IsNullOrEmpty(alwaysColor) ? alwaysColor : "#00FF0000";
|
||||
_isSpotlightModeEnabled = MouseHighlighterSettingsConfig.Properties.SpotlightMode.Value;
|
||||
|
||||
_highlighterRadius = MouseHighlighterSettingsConfig.Properties.HighlightRadius.Value;
|
||||
_highlightFadeDelayMs = MouseHighlighterSettingsConfig.Properties.HighlightFadeDelayMs.Value;
|
||||
@@ -560,6 +561,20 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSpotlightModeEnabled
|
||||
{
|
||||
get => _isSpotlightModeEnabled;
|
||||
set
|
||||
{
|
||||
if (_isSpotlightModeEnabled != value)
|
||||
{
|
||||
_isSpotlightModeEnabled = value;
|
||||
MouseHighlighterSettingsConfig.Properties.SpotlightMode.Value = value;
|
||||
NotifyMouseHighlighterPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int MouseHighlighterRadius
|
||||
{
|
||||
get
|
||||
@@ -916,6 +931,7 @@ namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
private string _highlighterLeftButtonClickColor;
|
||||
private string _highlighterRightButtonClickColor;
|
||||
private string _highlighterAlwaysColor;
|
||||
private bool _isSpotlightModeEnabled;
|
||||
private int _highlighterRadius;
|
||||
private int _highlightFadeDelayMs;
|
||||
private int _highlightFadeDurationMs;
|
||||
|
||||
Reference in New Issue
Block a user