Skip to content

Commit c6ddf55

Browse files
committed
Change accelerators that use Ctrl+Alt
As per https://devblogs.microsoft.com/oldnewthing/20040329-00/?p=40003, Ctrl+Alt shouldn't be used as a shortcut modifier, since it acts as an alternate shift key on some keyboard layouts. Therefore, the shortcuts using Ctrl+Alt have been updated from: - Ctrl+Alt+S (wildcard select) - Ctrl+Alt+D (wildcard deselect) to: - Ctrl+Shift+S (wildcard select) - Ctrl+Shift+W (wildcard deselect) Some checks have been added to make sure that no other Ctrl+Alt shortcuts are added.
1 parent fd6de34 commit c6ddf55

File tree

5 files changed

+61
-2
lines changed

5 files changed

+61
-2
lines changed

Explorer++/Explorer++/AcceleratorHelper.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,41 @@ std::wstring BuildAcceleratorString(const ACCEL &accelerator);
1313

1414
std::vector<ACCEL> TableToAcceleratorItems(HACCEL acceleratorTable);
1515
wil::unique_haccel AcceleratorItemsToTable(std::span<const ACCEL> accelerators);
16+
17+
// As per https://devblogs.microsoft.com/oldnewthing/20040329-00/?p=40003, Ctrl+Alt shouldn't be
18+
// used as a shortcut modifier, since it acts as an alternate shift key on some keyboard layouts.
19+
constexpr bool DoAcceleratorsContainCtrlAlt(std::span<const ACCEL> accelerators)
20+
{
21+
auto itr = std::find_if(accelerators.begin(), accelerators.end(),
22+
[](const auto &accel) { return WI_AreAllFlagsSet(accel.fVirt, FCONTROL | FALT); });
23+
return itr != accelerators.end();
24+
}
25+
26+
// Checks whether there are any duplicate key entries within the specified set of accelerators.
27+
// (i.e. two or more entries that have the same key combination). Duplicate entries are invalid,
28+
// since only the first will actually be used.
29+
constexpr bool DoAcceleratorsContainDuplicates(std::span<const ACCEL> accelerators)
30+
{
31+
for (const auto &accelerator : accelerators)
32+
{
33+
auto numMatches = std::count_if(accelerators.begin(), accelerators.end(),
34+
[&accelerator](const auto &currentAccelerator)
35+
{
36+
return currentAccelerator.fVirt == accelerator.fVirt
37+
&& currentAccelerator.key == accelerator.key;
38+
});
39+
40+
if (numMatches > 1)
41+
{
42+
return true;
43+
}
44+
}
45+
46+
return false;
47+
}
48+
49+
constexpr bool AreAcceleratorsValid(std::span<const ACCEL> accelerators)
50+
{
51+
return !DoAcceleratorsContainCtrlAlt(accelerators)
52+
&& !DoAcceleratorsContainDuplicates(accelerators);
53+
}

Explorer++/Explorer++/AcceleratorManager.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ const std::vector<ACCEL> &AcceleratorManager::GetAccelerators() const
2323

2424
void AcceleratorManager::SetAccelerators(std::span<const ACCEL> updatedAccelerators)
2525
{
26+
DCHECK(AreAcceleratorsValid(updatedAccelerators));
27+
2628
m_acceleratorTable = AcceleratorItemsToTable(updatedAccelerators);
2729
m_accelerators = { updatedAccelerators.begin(), updatedAccelerators.end() };
2830
}

Explorer++/Explorer++/DefaultAccelerators.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "stdafx.h"
66
#include "DefaultAccelerators.h"
7+
#include "AcceleratorHelper.h"
78
#include "AcceleratorManager.h"
89
#include "MainResource.h"
910

@@ -50,8 +51,8 @@ constexpr ACCEL g_defaultAccelerators[] = {
5051
{ FVIRTKEY | FCONTROL | FSHIFT, 'M', IDM_EDIT_MOVETOFOLDER },
5152
{ FVIRTKEY | FCONTROL | FSHIFT, 'V', IDM_EDIT_PASTESHORTCUT },
5253
{ FVIRTKEY | FCONTROL | FSHIFT, 'N', IDM_EDIT_SELECTNONE },
53-
{ FVIRTKEY | FCONTROL | FALT, 'D', IDM_EDIT_WILDCARDDESELECT },
54-
{ FVIRTKEY | FCONTROL | FALT, 'S', IDM_EDIT_WILDCARDSELECTION },
54+
{ FVIRTKEY | FCONTROL | FSHIFT, 'W', IDM_EDIT_WILDCARDDESELECT },
55+
{ FVIRTKEY | FCONTROL | FSHIFT, 'S', IDM_EDIT_WILDCARDSELECTION },
5556
{ FVIRTKEY | FCONTROL, 'W', IDM_FILE_CLOSETAB },
5657
{ FVIRTKEY | FCONTROL, VK_F4, IDM_FILE_CLOSETAB },
5758
{ FVIRTKEY | FCONTROL | FSHIFT, 'P', IDM_FILE_COPYFOLDERPATH },
@@ -88,6 +89,8 @@ constexpr ACCEL g_defaultAccelerators[] = {
8889
};
8990
// clang-format on
9091

92+
static_assert(AreAcceleratorsValid(g_defaultAccelerators));
93+
9194
}
9295

9396
AcceleratorManager InitializeAcceleratorManager()

Explorer++/Explorer++/Explorer++.rc

8 Bytes
Binary file not shown.

Explorer++/TestExplorer++/AcceleratorHelperTest.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,19 @@ TEST(AcceleratorHelperTest, AcceleratorTableConversion)
4040
auto outputAccelerators = TableToAcceleratorItems(table.get());
4141
EXPECT_THAT(outputAccelerators, ElementsAreArray(accelerators));
4242
}
43+
44+
TEST(AcceleratorHelperTest, Validity)
45+
{
46+
WORD commandIdCounter = 1;
47+
EXPECT_FALSE(DoAcceleratorsContainCtrlAlt({ { { FVIRTKEY | FCONTROL, 'T', commandIdCounter++ },
48+
{ FVIRTKEY | FCONTROL | FSHIFT, 'N', commandIdCounter++ } } }));
49+
EXPECT_TRUE(DoAcceleratorsContainCtrlAlt({ { { FVIRTKEY, VK_F1, commandIdCounter++ },
50+
{ FVIRTKEY | FCONTROL | FALT, 'W', commandIdCounter++ } } }));
51+
52+
EXPECT_FALSE(DoAcceleratorsContainDuplicates(
53+
{ { { FVIRTKEY | FCONTROL | FSHIFT, 'P', commandIdCounter++ },
54+
{ FVIRTKEY, VK_F3, commandIdCounter++ } } }));
55+
EXPECT_TRUE(
56+
DoAcceleratorsContainDuplicates({ { { FVIRTKEY | FCONTROL, 'A', commandIdCounter++ },
57+
{ FVIRTKEY | FCONTROL, 'A', commandIdCounter++ } } }));
58+
}

0 commit comments

Comments
 (0)