Skip to content

Commit 184ccb7

Browse files
Merge origin/main into stable
2 parents 455dc52 + e6d346a commit 184ccb7

23 files changed

Lines changed: 385 additions & 220 deletions

File tree

.github/actions/spell-check/allow/code.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,9 @@ MRUINFO
330330
REGSTR
331331

332332
# Misc Win32 APIs and PInvokes
333+
DEFAULTTONEAREST
333334
INVOKEIDLIST
335+
LCMAP
334336
MEMORYSTATUSEX
335337
ABE
336338
Mdt
@@ -394,3 +396,10 @@ Nonpaged
394396

395397
# XAML
396398
Untargeted
399+
400+
# Program names
401+
SEARCHHOST
402+
SHELLEXPERIENCEHOST
403+
SHELLHOST
404+
STARTMENUEXPERIENCEHOST
405+
WIDGETBOARD

.github/actions/spell-check/expect.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,6 +1368,7 @@ POINTERUPDATE
13681368
Pokedex
13691369
Pomodoro
13701370
Popups
1371+
popups
13711372
POPUPWINDOW
13721373
POSITIONITEM
13731374
POWERBROADCAST

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,18 @@ But to get started quickly, choose one of the installation methods below:
5050
Go to the [PowerToys GitHub releases](https://aka.ms/installPowerToys), select **Assets** to reveal the installation files, and choose the one that matches your architecture and install scope. For most devices, that would be _x64 per-user_.
5151

5252
<!-- items that need to be updated release to release -->
53-
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.99%22
54-
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-x64.exe
55-
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysUserSetup-0.98.1-arm64.exe
56-
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-x64.exe
57-
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.98.1/PowerToysSetup-0.98.1-arm64.exe
53+
[github-next-release-work]: https://github.com/microsoft/PowerToys/issues?q=is%3Aissue+milestone%3A%22PowerToys+0.100%22
54+
[ptUserX64]: https://github.com/microsoft/PowerToys/releases/download/v0.99.0/PowerToysUserSetup-0.99.0-x64.exe
55+
[ptUserArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.99.0/PowerToysUserSetup-0.99.0-arm64.exe
56+
[ptMachineX64]: https://github.com/microsoft/PowerToys/releases/download/v0.99.0/PowerToysSetup-0.99.0-x64.exe
57+
[ptMachineArm64]: https://github.com/microsoft/PowerToys/releases/download/v0.99.0/PowerToysSetup-0.99.0-arm64.exe
5858

5959
| Description | Filename |
6060
| --- | --- |
61-
| Per user - x64 | [PowerToysUserSetup-0.98.1-x64.exe][ptUserX64] |
62-
| Per user - ARM64 | [PowerToysUserSetup-0.98.1-arm64.exe][ptUserArm64] |
63-
| Machine wide - x64 | [PowerToysSetup-0.98.1-x64.exe][ptMachineX64] |
64-
| Machine wide - ARM64 | [PowerToysSetup-0.98.1-arm64.exe][ptMachineArm64] |
61+
| Per user - x64 | [PowerToysUserSetup-0.99.0-x64.exe][ptUserX64] |
62+
| Per user - ARM64 | [PowerToysUserSetup-0.99.0-arm64.exe][ptUserArm64] |
63+
| Machine wide - x64 | [PowerToysSetup-0.99.0-x64.exe][ptMachineX64] |
64+
| Machine wide - ARM64 | [PowerToysSetup-0.99.0-arm64.exe][ptMachineArm64] |
6565

6666
</details>
6767

@@ -106,11 +106,11 @@ There are [community driven install methods](https://learn.microsoft.com/windows
106106

107107
[![What's new image](doc/images/readme/Release-Banner.png)](https://github.com/microsoft/PowerToys/releases)
108108

109-
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/tag/v0.98.1).
109+
To see what's new, check out the [release notes](https://github.com/microsoft/PowerToys/releases/tag/v0.99.0).
110110

111111
## 🛣️ Roadmap
112112

113-
We are planning some nice new features and improvements for the next releases – PowerDisplay, Command Palette improvements and a brand-new Shortcut Guide experience! Stay tuned for [v0.99][github-next-release-work]!
113+
We are planning some nice new features and improvements for the next releases – a brand-new Shortcut Guide experience, ensuring it's easier to find and install Command Palette extensions and so much more! Stay tuned for [v0.100][github-next-release-work]!
114114

115115
## ❤️ PowerToys Community
116116

2.82 KB
Loading

src/modules/GrabAndMove/GrabAndMove/main.cpp

Lines changed: 114 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -579,14 +579,16 @@ static void StopResizing()
579579
HideOverlay();
580580
}
581581

582-
static void ReplayAbsorbedAlt()
582+
static void ReplayAbsorbedModifier(bool alsoKeyUp)
583583
{
584-
INPUT keyboardInput = {};
585-
keyboardInput.type = INPUT_KEYBOARD;
586-
keyboardInput.ki.wVk = static_cast<WORD>(g_absorbedVk);
587-
keyboardInput.ki.wScan = static_cast<WORD>(g_absorbedScanCode);
588-
keyboardInput.ki.dwFlags = (g_absorbedFlags & LLKHF_EXTENDED) ? KEYEVENTF_EXTENDEDKEY : 0;
589-
SendInput(1, &keyboardInput, sizeof(INPUT));
584+
INPUT inputs[2] = {};
585+
inputs[0].type = INPUT_KEYBOARD;
586+
inputs[0].ki.wVk = static_cast<WORD>(g_absorbedVk);
587+
inputs[0].ki.wScan = static_cast<WORD>(g_absorbedScanCode);
588+
inputs[0].ki.dwFlags = (g_absorbedFlags & LLKHF_EXTENDED) ? KEYEVENTF_EXTENDEDKEY : 0;
589+
inputs[1] = inputs[0];
590+
inputs[1].ki.dwFlags |= KEYEVENTF_KEYUP;
591+
SendInput(alsoKeyUp ? 2 : 1, inputs, sizeof(INPUT));
590592
}
591593

592594
// ---------------------------------------------------------------------------
@@ -632,16 +634,111 @@ static void ShowTrayMenu(HWND hwnd)
632634

633635
static bool IsSystemClass(HWND hwnd)
634636
{
635-
wchar_t cls[64] = {};
636-
GetClassNameW(hwnd, cls, 64);
637-
return (wcscmp(cls, L"Progman") == 0 || wcscmp(cls, L"Shell_TrayWnd") == 0);
637+
wchar_t cls[256] = {};
638+
GetClassNameW(hwnd, cls, ARRAYSIZE(cls));
639+
640+
// Desktop and primary/secondary taskbars
641+
if (wcscmp(cls, L"Progman") == 0 ||
642+
wcscmp(cls, L"Shell_TrayWnd") == 0 ||
643+
wcscmp(cls, L"Shell_SecondaryTrayWnd") == 0)
644+
return true;
645+
646+
// System tray / notification area popups and overflow
647+
if (wcscmp(cls, L"NotifyIconOverflowWindow") == 0 ||
648+
wcscmp(cls, L"TopLevelWindowForOverflowXamlIsland") == 0)
649+
return true;
650+
651+
// Tooltips (e.g. "Show hidden icons" tooltip)
652+
if (wcscmp(cls, L"tooltips_class32") == 0)
653+
return true;
654+
655+
// Task View (Win+Tab)
656+
if (wcscmp(cls, L"MultitaskingViewFrame") == 0 ||
657+
wcscmp(cls, L"XamlExplorerHostIslandWindow") == 0)
658+
return true;
659+
660+
// System tray flyouts (Quick Settings, calendar, input switcher)
661+
if (wcscmp(cls, L"Windows.UI.Composition.DesktopWindowContentBridge") == 0 ||
662+
wcscmp(cls, L"Shell_InputSwitchTopLevelWindow") == 0)
663+
return true;
664+
665+
return false;
666+
}
667+
668+
669+
std::wstring ToUpperInvariant(std::wstring_view input)
670+
{
671+
int required = LCMapStringEx(
672+
LOCALE_NAME_INVARIANT,
673+
LCMAP_UPPERCASE,
674+
input.data(),
675+
static_cast<int>(input.size()),
676+
nullptr,
677+
0,
678+
nullptr,
679+
nullptr,
680+
0);
681+
682+
std::wstring result(required, L'\0');
683+
684+
LCMapStringEx(
685+
LOCALE_NAME_INVARIANT,
686+
LCMAP_UPPERCASE,
687+
input.data(),
688+
static_cast<int>(input.size()),
689+
result.data(),
690+
required,
691+
nullptr,
692+
nullptr,
693+
0);
694+
695+
return result;
638696
}
639697

640698
static bool IsExcluded(HWND hwnd)
641699
{
642700
if (IsSystemClass(hwnd))
643701
return true;
644702

703+
// To identify these for adding a new exception:
704+
// 1. Resolve the hwnd class name.
705+
// 2. Resolve the process path.
706+
// 3. Add OutputDebugStringW() for the class name and process path.
707+
// 4. Build the executable.
708+
// 5. Check with the debugger (or with Sysinternals DebugView) the outputs.
709+
// 6. Delete the added code.
710+
// 7. Add the exception below, according to the pattern there.
711+
//
712+
// Shell experience windows: Start menu, Notifications (Win+N), Search,
713+
// Quick Settings (volume / network / battery).
714+
// These use the generic Windows.UI.Core.CoreWindow class, so filter by process.
715+
{
716+
wchar_t cls[256] = {};
717+
GetClassNameW(hwnd, cls, ARRAYSIZE(cls));
718+
if (wcscmp(cls, L"Windows.UI.Core.CoreWindow") == 0)
719+
{
720+
std::wstring processPath = ToUpperInvariant(get_process_path(hwnd));
721+
if (processPath.find(L"STARTMENUEXPERIENCEHOST.EXE") != std::wstring::npos ||
722+
processPath.find(L"SHELLEXPERIENCEHOST.EXE") != std::wstring::npos ||
723+
processPath.find(L"SEARCHHOST.EXE") != std::wstring::npos)
724+
return true;
725+
}
726+
else if (wcscmp(cls, L"ControlCenterWindow") == 0)
727+
{
728+
// The Quick Settings flyout.
729+
std::wstring processPath = ToUpperInvariant(get_process_path(hwnd));
730+
if (processPath.find(L"SHELLHOST.EXE") != std::wstring::npos)
731+
return true;
732+
}
733+
else if (wcscmp(cls, L"WindowsDashboard") == 0)
734+
{
735+
// The Windows 11 Widgets flyout.
736+
std::wstring processPath = ToUpperInvariant(get_process_path(hwnd));
737+
if (processPath.find(L"WIDGETBOARD.EXE") != std::wstring::npos)
738+
return true;
739+
}
740+
}
741+
645742
auto apps = g_excludedApps.load();
646743
if (!apps || apps->empty())
647744
return false;
@@ -735,8 +832,9 @@ static LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
735832
g_dragConsumedAlt = false;
736833
return 1;
737834
}
738-
// No drag happened; replay the keydown, then let keyup through
739-
ReplayAbsorbedAlt();
835+
// No drag happened; replay the keydown, THEN the keyup
836+
ReplayAbsorbedModifier(true);
837+
return 1; // swallow this keyup since the replay already sent one
740838
}
741839
}
742840
goto forward; // let Win keyup pass through
@@ -793,7 +891,7 @@ static LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
793891
return 1;
794892
}
795893
// No drag happened; replay the keydown, then let keyup through
796-
ReplayAbsorbedAlt();
894+
ReplayAbsorbedModifier(false);
797895
}
798896
}
799897
}
@@ -803,7 +901,8 @@ static LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
803901
if (g_altAbsorbed && !g_dragConsumedAlt)
804902
{
805903
g_altAbsorbed = false;
806-
ReplayAbsorbedAlt();
904+
g_altPressed = false;
905+
ReplayAbsorbedModifier(false);
807906
}
808907
}
809908
}
@@ -813,7 +912,7 @@ static LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
813912
{
814913
g_winAbsorbed = false;
815914
g_winPressed = false;
816-
ReplayAbsorbedAlt();
915+
ReplayAbsorbedModifier(false);
817916
}
818917

819918
// Track held non-modifier keys (used to suppress GrabAndMove when the modifier

src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/AppStateModel.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System.Collections.Immutable;
6+
using System.Text.Json.Serialization;
67

78
namespace Microsoft.CmdPal.UI.ViewModels;
89

@@ -11,9 +12,21 @@ public record AppStateModel
1112
///////////////////////////////////////////////////////////////////////////
1213
// STATE HERE
1314
// Make sure that any new types you add are added to JsonSerializationContext!
14-
public RecentCommandsManager RecentCommands { get; init; } = new();
15+
private RecentCommandsManager? _recentCommands = new();
1516

16-
public ImmutableList<string> RunHistory { get; init; } = ImmutableList<string>.Empty;
17+
public RecentCommandsManager RecentCommands
18+
{
19+
get => _recentCommands ?? new();
20+
init => _recentCommands = value;
21+
}
22+
23+
private ImmutableList<string>? _runHistory = ImmutableList<string>.Empty;
24+
25+
public ImmutableList<string> RunHistory
26+
{
27+
get => _runHistory ?? ImmutableList<string>.Empty;
28+
init => _runHistory = value;
29+
}
1730

1831
// END SETTINGS
1932
///////////////////////////////////////////////////////////////////////////

src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Dock/DockBandSettingsViewModel.cs

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -46,45 +46,6 @@ public string Description
4646

4747
public IconInfoViewModel Icon => _adapter.IconViewModel;
4848

49-
private ShowLabelsOption _showLabels;
50-
51-
public ShowLabelsOption ShowLabels
52-
{
53-
get => _showLabels;
54-
set
55-
{
56-
if (value != _showLabels)
57-
{
58-
_showLabels = value;
59-
var newShowTitles = value switch
60-
{
61-
ShowLabelsOption.Default => (bool?)null,
62-
ShowLabelsOption.ShowLabels => true,
63-
ShowLabelsOption.HideLabels => false,
64-
_ => null,
65-
};
66-
UpdateModel(_dockSettingsModel with { ShowTitles = newShowTitles });
67-
}
68-
}
69-
}
70-
71-
private ShowLabelsOption FetchShowLabels()
72-
{
73-
if (_dockSettingsModel.ShowLabels == null)
74-
{
75-
return ShowLabelsOption.Default;
76-
}
77-
78-
return _dockSettingsModel.ShowLabels.Value ? ShowLabelsOption.ShowLabels : ShowLabelsOption.HideLabels;
79-
}
80-
81-
// used to map to ComboBox selection
82-
public int ShowLabelsIndex
83-
{
84-
get => (int)ShowLabels;
85-
set => ShowLabels = (ShowLabelsOption)value;
86-
}
87-
8849
private DockPinSide PinSide
8950
{
9051
get => _pinSide;
@@ -138,7 +99,6 @@ public DockBandSettingsViewModel(
13899
_bandViewModel = bandViewModel;
139100
_settingsService = settingsService;
140101
_pinSide = FetchPinSide();
141-
_showLabels = FetchShowLabels();
142102
}
143103

144104
private DockPinSide FetchPinSide()

src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/Dock/DockViewModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ public void AddBandToSection(TopLevelViewModel topLevel, DockPinSide targetSide)
559559
}
560560

561561
// Create settings for the new band
562-
var bandSettings = new DockBandSettings { ProviderId = topLevel.CommandProviderId, CommandId = bandId, ShowLabels = null };
562+
var bandSettings = new DockBandSettings { ProviderId = topLevel.CommandProviderId, CommandId = bandId };
563563
var dockSettings = _settings;
564564

565565
// Create the band view model

src/modules/cmdpal/Microsoft.CmdPal.UI.ViewModels/ProviderSettings.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) Microsoft Corporation
1+
// Copyright (c) Microsoft Corporation
22
// The Microsoft Corporation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

@@ -18,12 +18,24 @@ public record ProviderSettings
1818

1919
public bool IsEnabled { get; init; } = true;
2020

21-
public ImmutableDictionary<string, FallbackSettings> FallbackCommands { get; init; }
21+
private ImmutableDictionary<string, FallbackSettings>? _fallbackCommands
2222
= ImmutableDictionary<string, FallbackSettings>.Empty;
2323

24-
public ImmutableList<string> PinnedCommandIds { get; init; }
24+
public ImmutableDictionary<string, FallbackSettings> FallbackCommands
25+
{
26+
get => _fallbackCommands ?? ImmutableDictionary<string, FallbackSettings>.Empty;
27+
init => _fallbackCommands = value;
28+
}
29+
30+
private ImmutableList<string>? _pinnedCommandIds
2531
= ImmutableList<string>.Empty;
2632

33+
public ImmutableList<string> PinnedCommandIds
34+
{
35+
get => _pinnedCommandIds ?? ImmutableList<string>.Empty;
36+
init => _pinnedCommandIds = value;
37+
}
38+
2739
[JsonIgnore]
2840
public string ProviderId { get; init; } = string.Empty;
2941

@@ -37,7 +49,6 @@ public ProviderSettings()
3749
{
3850
}
3951

40-
[JsonConstructor]
4152
public ProviderSettings(bool isEnabled)
4253
{
4354
IsEnabled = isEnabled;

0 commit comments

Comments
 (0)