mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-01-26 22:17:15 +01:00
Compare commits
4 Commits
dev/vanzue
...
shawn/AddT
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2ff69e4c5 | ||
|
|
74511b3814 | ||
|
|
086c63b6af | ||
|
|
d192672c74 |
2
.github/actions/spell-check/expect.txt
vendored
2
.github/actions/spell-check/expect.txt
vendored
@@ -886,6 +886,7 @@ Ldr
|
||||
LEFTALIGN
|
||||
LEFTSCROLLBAR
|
||||
LEFTTEXT
|
||||
leftclick
|
||||
LError
|
||||
LEVELID
|
||||
LExit
|
||||
@@ -1011,6 +1012,7 @@ MENUITEMINFO
|
||||
MENUITEMINFOW
|
||||
MERGECOPY
|
||||
MERGEPAINT
|
||||
Metacharacter
|
||||
metadatamatters
|
||||
Metadatas
|
||||
metafile
|
||||
|
||||
@@ -33,23 +33,27 @@ static std::wstring SanitizeAndNormalize(const std::wstring& input)
|
||||
|
||||
// Normalize to NFC (Precomposed).
|
||||
// Get the size needed for the normalized string, including null terminator.
|
||||
int size = NormalizeString(NormalizationC, sanitized.c_str(), -1, nullptr, 0);
|
||||
if (size <= 0)
|
||||
int sizeEstimate = NormalizeString(NormalizationC, sanitized.c_str(), -1, nullptr, 0);
|
||||
if (sizeEstimate <= 0)
|
||||
{
|
||||
return sanitized; // Return unaltered if normalization fails.
|
||||
}
|
||||
|
||||
// Perform the normalization.
|
||||
std::wstring normalized;
|
||||
normalized.resize(size);
|
||||
NormalizeString(NormalizationC, sanitized.c_str(), -1, &normalized[0], size);
|
||||
normalized.resize(sizeEstimate);
|
||||
int actualSize = NormalizeString(NormalizationC, sanitized.c_str(), -1, &normalized[0], sizeEstimate);
|
||||
|
||||
// Remove the explicit null terminator added by NormalizeString.
|
||||
if (!normalized.empty() && normalized.back() == L'\0')
|
||||
if (actualSize <= 0)
|
||||
{
|
||||
normalized.pop_back();
|
||||
// Normalization failed, return sanitized string.
|
||||
return sanitized;
|
||||
}
|
||||
|
||||
// Resize to actual size minus the null terminator.
|
||||
// actualSize includes the null terminator when input length is -1.
|
||||
normalized.resize(static_cast<size_t>(actualSize) - 1);
|
||||
|
||||
return normalized;
|
||||
}
|
||||
|
||||
|
||||
@@ -695,6 +695,38 @@ TEST_METHOD(VerifyUnicodeAndWhitespaceNormalizationRegex)
|
||||
VerifyNormalizationHelper(UseRegularExpressions);
|
||||
}
|
||||
|
||||
TEST_METHOD(VerifyRegexMetacharacterDollarSign)
|
||||
{
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
DWORD flags = UseRegularExpressions;
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(L"$") == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"_end") == S_OK);
|
||||
unsigned long index = {};
|
||||
Assert::IsTrue(renameRegEx->Replace(L"test.txt", &result, index) == S_OK);
|
||||
Assert::AreEqual(L"test.txt_end", result);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
|
||||
TEST_METHOD(VerifyRegexMetacharacterCaret)
|
||||
{
|
||||
CComPtr<IPowerRenameRegEx> renameRegEx;
|
||||
Assert::IsTrue(CPowerRenameRegEx::s_CreateInstance(&renameRegEx) == S_OK);
|
||||
DWORD flags = UseRegularExpressions;
|
||||
Assert::IsTrue(renameRegEx->PutFlags(flags) == S_OK);
|
||||
|
||||
PWSTR result = nullptr;
|
||||
Assert::IsTrue(renameRegEx->PutSearchTerm(L"^") == S_OK);
|
||||
Assert::IsTrue(renameRegEx->PutReplaceTerm(L"start_") == S_OK);
|
||||
unsigned long index = {};
|
||||
Assert::IsTrue(renameRegEx->Replace(L"test.txt", &result, index) == S_OK);
|
||||
Assert::AreEqual(L"start_test.txt", result);
|
||||
CoTaskMemFree(result);
|
||||
}
|
||||
|
||||
#ifndef TESTS_PARTIAL
|
||||
};
|
||||
}
|
||||
|
||||
@@ -173,6 +173,10 @@
|
||||
<value>Settings\tDouble-click</value>
|
||||
<comment>Don't localize "\t" as that is what separates the click portion to be right aligned in the menu.</comment>
|
||||
</data>
|
||||
<data name="SETTINGS_MENU_TEXT_LEFTCLICK" xml:space="preserve">
|
||||
<value>Settings\tLeft-click</value>
|
||||
<comment>Don't localize "\t" as that is what separates the click portion to be right aligned in the menu. This is shown when Quick Access is disabled.</comment>
|
||||
</data>
|
||||
<data name="DOCUMENTATION_MENU_TEXT" xml:space="preserve">
|
||||
<value>Documentation</value>
|
||||
</data>
|
||||
|
||||
@@ -81,3 +81,36 @@ void Trace::UpdateDownloadCompleted(bool success, const std::wstring& version)
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
void Trace::TrayIconLeftClick(bool quickAccessEnabled)
|
||||
{
|
||||
TraceLoggingWriteWrapper(
|
||||
g_hProvider,
|
||||
"TrayIcon_LeftClick",
|
||||
TraceLoggingBoolean(quickAccessEnabled, "QuickAccessEnabled"),
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
void Trace::TrayIconDoubleClick(bool quickAccessEnabled)
|
||||
{
|
||||
TraceLoggingWriteWrapper(
|
||||
g_hProvider,
|
||||
"TrayIcon_DoubleClick",
|
||||
TraceLoggingBoolean(quickAccessEnabled, "QuickAccessEnabled"),
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
void Trace::TrayIconRightClick(bool quickAccessEnabled)
|
||||
{
|
||||
TraceLoggingWriteWrapper(
|
||||
g_hProvider,
|
||||
"TrayIcon_RightClick",
|
||||
TraceLoggingBoolean(quickAccessEnabled, "QuickAccessEnabled"),
|
||||
ProjectTelemetryPrivacyDataTag(ProjectTelemetryTag_ProductAndServicePerformance),
|
||||
TraceLoggingBoolean(TRUE, "UTCReplace_AppSessionGuid"),
|
||||
TraceLoggingKeyword(PROJECT_KEYWORD_MEASURE));
|
||||
}
|
||||
|
||||
@@ -13,4 +13,9 @@ public:
|
||||
// Auto-update telemetry
|
||||
static void UpdateCheckCompleted(bool success, bool updateAvailable, const std::wstring& fromVersion, const std::wstring& toVersion);
|
||||
static void UpdateDownloadCompleted(bool success, const std::wstring& version);
|
||||
|
||||
// Tray icon interaction telemetry
|
||||
static void TrayIconLeftClick(bool quickAccessEnabled);
|
||||
static void TrayIconDoubleClick(bool quickAccessEnabled);
|
||||
static void TrayIconRightClick(bool quickAccessEnabled);
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "centralized_kb_hook.h"
|
||||
#include "quick_access_host.h"
|
||||
#include "hotkey_conflict_detector.h"
|
||||
#include "trace.h"
|
||||
#include <Windows.h>
|
||||
|
||||
#include <common/utils/resources.h>
|
||||
@@ -40,6 +41,7 @@ namespace
|
||||
bool double_click_timer_running = false;
|
||||
bool double_clicked = false;
|
||||
POINT tray_icon_click_point;
|
||||
std::optional<bool> last_quick_access_state; // Track the last known Quick Access state
|
||||
|
||||
static ThemeListener theme_listener;
|
||||
static bool theme_adaptive_enabled = false;
|
||||
@@ -130,6 +132,9 @@ void click_timer_elapsed()
|
||||
double_click_timer_running = false;
|
||||
if (!double_clicked)
|
||||
{
|
||||
// Log telemetry for single click (confirmed it's not a double click)
|
||||
Trace::TrayIconLeftClick(get_general_settings().enableQuickAccess);
|
||||
|
||||
if (get_general_settings().enableQuickAccess)
|
||||
{
|
||||
open_quick_access_flyout_window();
|
||||
@@ -195,6 +200,21 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
case WM_RBUTTONUP:
|
||||
case WM_CONTEXTMENU:
|
||||
{
|
||||
bool quick_access_enabled = get_general_settings().enableQuickAccess;
|
||||
|
||||
// Log telemetry
|
||||
Trace::TrayIconRightClick(quick_access_enabled);
|
||||
|
||||
// Reload menu if Quick Access state has changed or is first time
|
||||
if (h_menu && (!last_quick_access_state.has_value() || quick_access_enabled != last_quick_access_state.value()))
|
||||
{
|
||||
DestroyMenu(h_menu);
|
||||
h_menu = nullptr;
|
||||
h_sub_menu = nullptr;
|
||||
}
|
||||
|
||||
last_quick_access_state = quick_access_enabled;
|
||||
|
||||
if (!h_menu)
|
||||
{
|
||||
h_menu = LoadMenu(reinterpret_cast<HINSTANCE>(&__ImageBase), MAKEINTRESOURCE(ID_TRAY_MENU));
|
||||
@@ -202,17 +222,39 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
if (h_menu)
|
||||
{
|
||||
static std::wstring settings_menuitem_label = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT);
|
||||
static std::wstring settings_menuitem_label_leftclick = GET_RESOURCE_STRING(IDS_SETTINGS_MENU_TEXT_LEFTCLICK);
|
||||
static std::wstring close_menuitem_label = GET_RESOURCE_STRING(IDS_CLOSE_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());
|
||||
|
||||
// Update Settings menu text based on Quick Access state
|
||||
if (quick_access_enabled)
|
||||
{
|
||||
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
change_menu_item_text(ID_SETTINGS_MENU_COMMAND, settings_menuitem_label_leftclick.data());
|
||||
}
|
||||
|
||||
change_menu_item_text(ID_CLOSE_MENU_COMMAND, close_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));
|
||||
change_menu_item_text(ID_DOCUMENTATION_MENU_COMMAND, documentation_menuitem_label.data());
|
||||
change_menu_item_text(ID_QUICK_ACCESS_MENU_COMMAND, quick_access_menuitem_label.data());
|
||||
|
||||
// Hide or show Quick Access menu item based on setting
|
||||
if (!h_sub_menu)
|
||||
{
|
||||
h_sub_menu = GetSubMenu(h_menu, 0);
|
||||
}
|
||||
if (!quick_access_enabled)
|
||||
{
|
||||
// Remove Quick Access menu item when disabled
|
||||
DeleteMenu(h_sub_menu, ID_QUICK_ACCESS_MENU_COMMAND, MF_BYCOMMAND);
|
||||
}
|
||||
}
|
||||
if (!h_sub_menu)
|
||||
{
|
||||
@@ -243,6 +285,9 @@ LRESULT __stdcall tray_icon_window_proc(HWND window, UINT message, WPARAM wparam
|
||||
}
|
||||
case WM_LBUTTONDBLCLK:
|
||||
{
|
||||
// Log telemetry
|
||||
Trace::TrayIconDoubleClick(get_general_settings().enableQuickAccess);
|
||||
|
||||
double_clicked = true;
|
||||
open_settings_window(std::nullopt);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user