···1212 private static readonly object[][] key_combination_display_test_cases =
1313 {
1414 // test single combination matches.
1515- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.LShift), false, true },
1616- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.RShift), false, true },
1717- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift), false, true },
1818- new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.RShift), false, false },
1919- new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.RShift), false, true },
1515+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.LShift), KeyCombinationMatchingMode.Any, true },
1616+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Any, true },
1717+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift), KeyCombinationMatchingMode.Any, true },
1818+ new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Any, false },
1919+ new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Any, true },
20202121- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.LShift), true, true },
2222- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.RShift), true, true },
2323- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift), true, true },
2424- new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.RShift), true, false },
2525- new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.RShift), true, true },
2121+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.LShift), KeyCombinationMatchingMode.Exact, true },
2222+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Exact, true },
2323+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift), KeyCombinationMatchingMode.Exact, true },
2424+ new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Exact, false },
2525+ new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Exact, true },
2626+2727+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.LShift), KeyCombinationMatchingMode.Modifiers, true },
2828+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Modifiers, true },
2929+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift), KeyCombinationMatchingMode.Modifiers, true },
3030+ new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Modifiers, false },
3131+ new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.RShift), KeyCombinationMatchingMode.Modifiers, true },
26322733 // test multiple combination matches.
2828- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.LShift), false, true },
2929- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.RShift), false, true },
3030- new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.Shift, InputKey.RShift), false, false },
3131- new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.Shift, InputKey.RShift), false, true },
3434+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.LShift), KeyCombinationMatchingMode.Any, true },
3535+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Any, true },
3636+ new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Any, false },
3737+ new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Any, true },
3838+3939+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.LShift), KeyCombinationMatchingMode.Exact, true },
4040+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Exact, true },
4141+ new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Exact, false },
4242+ new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Exact, true },
32433333- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.LShift), true, true },
3434- new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.RShift), true, true },
3535- new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.Shift, InputKey.RShift), true, false },
3636- new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.Shift, InputKey.RShift), true, true },
4444+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.LShift), KeyCombinationMatchingMode.Modifiers, true },
4545+ new object[] { new KeyCombination(InputKey.Shift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Modifiers, true },
4646+ new object[] { new KeyCombination(InputKey.LShift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Modifiers, false },
4747+ new object[] { new KeyCombination(InputKey.RShift), new KeyCombination(InputKey.Shift, InputKey.RShift), KeyCombinationMatchingMode.Modifiers, true },
3748 };
38493950 [TestCaseSource(nameof(key_combination_display_test_cases))]
4040- public void TestLeftRightModifierHandling(KeyCombination candidate, KeyCombination pressed, bool exactModifiers, bool shouldContain)
4141- => Assert.AreEqual(shouldContain, KeyCombination.ContainsAll(candidate.Keys, pressed.Keys, exactModifiers));
5151+ public void TestLeftRightModifierHandling(KeyCombination candidate, KeyCombination pressed, KeyCombinationMatchingMode matchingMode, bool shouldContain)
5252+ => Assert.AreEqual(shouldContain, KeyCombination.ContainsAll(candidate.Keys, pressed.Keys, matchingMode));
4253 }
4354}
+21-23
osu.Framework/Input/Bindings/KeyCombination.cs
···7878 if (Keys == pressedKeys.Keys) // Fast test for reference equality of underlying array
7979 return true;
80808181- switch (matchingMode)
8282- {
8383- case KeyCombinationMatchingMode.Any:
8484- return ContainsAll(pressedKeys.Keys, Keys, false);
8585-8686- case KeyCombinationMatchingMode.Exact:
8787- // Keys are always ordered
8888- return pressedKeys.Keys.SequenceEqual(Keys);
8989-9090- case KeyCombinationMatchingMode.Modifiers:
9191- return ContainsAll(pressedKeys.Keys, Keys, true);
9292-9393- default:
9494- return false;
9595- }
8181+ return ContainsAll(pressedKeys.Keys, Keys, matchingMode);
9682 }
97839884 /// <summary>
···10086 /// </summary>
10187 /// <param name="pressedKey">The keys which have been pressed by a user.</param>
10288 /// <param name="candidateKey">The candidate key binding to match against.</param>
103103- /// <param name="exactModifiers">Whether exact matching should be used (ie. no excess modifier keys can be pressed).</param>
8989+ /// <param name="matchingMode">The matching mode to be used when checking.</param>
10490 /// <returns>Whether this is a match.</returns>
10591 [MethodImpl(MethodImplOptions.AggressiveInlining)]
106106- internal static bool ContainsAll(ImmutableArray<InputKey> pressedKey, ImmutableArray<InputKey> candidateKey, bool exactModifiers)
9292+ internal static bool ContainsAll(ImmutableArray<InputKey> pressedKey, ImmutableArray<InputKey> candidateKey, KeyCombinationMatchingMode matchingMode)
10793 {
10894 // can be local function once attribute on local functions are implemented
10995 // optimized to avoid allocation
···114100 return false;
115101 }
116102117117- if (exactModifiers)
103103+ switch (matchingMode)
118104 {
119119- foreach (var key in pressedKey)
120120- {
121121- if (IsModifierKey(key) && !ContainsKey(candidateKey, key))
122122- return false;
123123- }
105105+ case KeyCombinationMatchingMode.Exact:
106106+ foreach (var key in pressedKey)
107107+ {
108108+ if (!ContainsKey(candidateKey, key))
109109+ return false;
110110+ }
111111+112112+ break;
113113+114114+ case KeyCombinationMatchingMode.Modifiers:
115115+ foreach (var key in pressedKey)
116116+ {
117117+ if (IsModifierKey(key) && !ContainsKey(candidateKey, key))
118118+ return false;
119119+ }
120120+121121+ break;
124122 }
125123126124 return true;