Bug 1764201 Part 3: Remove screen info stuff from gfxPlatform. r=jgilbert,geckoview...
[gecko.git] / gfx / layers / apz / src / KeyboardMap.cpp
blob00b1363b381855750fd74aa23e16e07ec1ae3990
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozilla/layers/KeyboardMap.h"
9 #include "mozilla/TextEvents.h" // for IgnoreModifierState, ShortcutKeyCandidate
11 namespace mozilla {
12 namespace layers {
14 KeyboardShortcut::KeyboardShortcut()
15 : mKeyCode(0),
16 mCharCode(0),
17 mModifiers(0),
18 mModifiersMask(0),
19 mEventType(KeyboardInput::KeyboardEventType::KEY_OTHER),
20 mDispatchToContent(false) {}
22 KeyboardShortcut::KeyboardShortcut(KeyboardInput::KeyboardEventType aEventType,
23 uint32_t aKeyCode, uint32_t aCharCode,
24 Modifiers aModifiers,
25 Modifiers aModifiersMask,
26 const KeyboardScrollAction& aAction)
27 : mAction(aAction),
28 mKeyCode(aKeyCode),
29 mCharCode(aCharCode),
30 mModifiers(aModifiers),
31 mModifiersMask(aModifiersMask),
32 mEventType(aEventType),
33 mDispatchToContent(false) {}
35 KeyboardShortcut::KeyboardShortcut(KeyboardInput::KeyboardEventType aEventType,
36 uint32_t aKeyCode, uint32_t aCharCode,
37 Modifiers aModifiers,
38 Modifiers aModifiersMask)
39 : mKeyCode(aKeyCode),
40 mCharCode(aCharCode),
41 mModifiers(aModifiers),
42 mModifiersMask(aModifiersMask),
43 mEventType(aEventType),
44 mDispatchToContent(true) {}
46 /* static */
47 void KeyboardShortcut::AppendHardcodedShortcuts(
48 nsTArray<KeyboardShortcut>& aShortcuts) {
49 // Tab
50 KeyboardShortcut tab1;
51 tab1.mDispatchToContent = true;
52 tab1.mKeyCode = NS_VK_TAB;
53 tab1.mCharCode = 0;
54 tab1.mModifiers = 0;
55 tab1.mModifiersMask = 0;
56 tab1.mEventType = KeyboardInput::KEY_PRESS;
57 aShortcuts.AppendElement(tab1);
59 // F6
60 KeyboardShortcut tab2;
61 tab2.mDispatchToContent = true;
62 tab2.mKeyCode = NS_VK_F6;
63 tab2.mCharCode = 0;
64 tab2.mModifiers = 0;
65 tab2.mModifiersMask = 0;
66 tab2.mEventType = KeyboardInput::KEY_PRESS;
67 aShortcuts.AppendElement(tab2);
70 bool KeyboardShortcut::Matches(const KeyboardInput& aInput,
71 const IgnoreModifierState& aIgnore,
72 uint32_t aOverrideCharCode) const {
73 return mEventType == aInput.mType && MatchesKey(aInput, aOverrideCharCode) &&
74 MatchesModifiers(aInput, aIgnore);
77 bool KeyboardShortcut::MatchesKey(const KeyboardInput& aInput,
78 uint32_t aOverrideCharCode) const {
79 // Compare by the key code if we have one
80 if (!mCharCode) {
81 return mKeyCode == aInput.mKeyCode;
84 // We are comparing by char code
85 uint32_t charCode;
87 // If we are comparing against a shortcut candidate then we might
88 // have an override char code
89 if (aOverrideCharCode) {
90 charCode = aOverrideCharCode;
91 } else {
92 charCode = aInput.mCharCode;
95 // Both char codes must be in lowercase to compare correctly
96 if (IS_IN_BMP(charCode)) {
97 charCode = ToLowerCase(static_cast<char16_t>(charCode));
100 return mCharCode == charCode;
103 bool KeyboardShortcut::MatchesModifiers(
104 const KeyboardInput& aInput, const IgnoreModifierState& aIgnore) const {
105 Modifiers modifiersMask = mModifiersMask;
107 // If we are ignoring Shift or Meta (Windows key), then unset that part of the
108 // mask
109 if (aIgnore.mMeta) {
110 modifiersMask &= ~MODIFIER_META;
112 if (aIgnore.mShift) {
113 modifiersMask &= ~MODIFIER_SHIFT;
116 // Mask off the modifiers we are ignoring from the keyboard input
117 return (aInput.modifiers & modifiersMask) == mModifiers;
120 KeyboardMap::KeyboardMap(nsTArray<KeyboardShortcut>&& aShortcuts)
121 : mShortcuts(aShortcuts) {}
123 KeyboardMap::KeyboardMap() = default;
125 Maybe<KeyboardShortcut> KeyboardMap::FindMatch(
126 const KeyboardInput& aEvent) const {
127 // If there are no shortcut candidates, then just search with with the
128 // keyboard input
129 if (aEvent.mShortcutCandidates.IsEmpty()) {
130 return FindMatchInternal(aEvent, IgnoreModifierState());
133 // Otherwise do a search with each shortcut candidate in order
134 for (const auto& key : aEvent.mShortcutCandidates) {
135 IgnoreModifierState ignoreModifierState;
136 ignoreModifierState.mShift =
137 key.mShiftState == ShortcutKeyCandidate::ShiftState::Ignorable;
139 auto match = FindMatchInternal(aEvent, ignoreModifierState, key.mCharCode);
140 if (match) {
141 return match;
144 return Nothing();
147 Maybe<KeyboardShortcut> KeyboardMap::FindMatchInternal(
148 const KeyboardInput& aEvent, const IgnoreModifierState& aIgnore,
149 uint32_t aOverrideCharCode) const {
150 for (auto& shortcut : mShortcuts) {
151 if (shortcut.Matches(aEvent, aIgnore, aOverrideCharCode)) {
152 return Some(shortcut);
156 #ifdef XP_WIN
157 // Windows native applications ignore Windows-Logo key state when checking
158 // shortcut keys even if the key is pressed. Therefore, if there is no
159 // shortcut key which exactly matches current modifier state, we should
160 // retry to look for a shortcut key without the Windows-Logo key press.
161 if (!aIgnore.mMeta && (aEvent.modifiers & MODIFIER_META)) {
162 IgnoreModifierState ignoreModifierState(aIgnore);
163 ignoreModifierState.mMeta = true;
164 return FindMatchInternal(aEvent, ignoreModifierState, aOverrideCharCode);
166 #endif
168 return Nothing();
171 } // namespace layers
172 } // namespace mozilla