Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: third_party/WebKit/Source/core/input/KeyboardEventManager.cpp

Issue 2036643003: Creat a KeyboardEventManager class (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removing comment Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "KeyboardEventManager.h"
6
7 #include "core/dom/Element.h"
8 #include "core/editing/Editor.h"
9 #include "core/events/KeyboardEvent.h"
10 #include "core/html/HTMLDialogElement.h"
11 #include "core/input/EventHandler.h"
12 #include "core/layout/LayoutObject.h"
13 #include "core/layout/LayoutTextControlSingleLine.h"
14 #include "core/loader/FrameLoaderClient.h"
15 #include "core/page/ChromeClient.h"
16 #include "core/page/FocusController.h"
17 #include "core/page/Page.h"
18 #include "core/page/SpatialNavigation.h"
19 #include "platform/PlatformKeyboardEvent.h"
20 #include "platform/UserGestureIndicator.h"
21 #include "platform/WindowsKeyboardCodes.h"
22
23 namespace blink {
24
25 namespace {
26
27 WebFocusType focusDirectionForKey(const AtomicString& keyIdentifier)
28 {
29 DEFINE_STATIC_LOCAL(AtomicString, Down, ("Down"));
30 DEFINE_STATIC_LOCAL(AtomicString, Up, ("Up"));
31 DEFINE_STATIC_LOCAL(AtomicString, Left, ("Left"));
32 DEFINE_STATIC_LOCAL(AtomicString, Right, ("Right"));
33
34 WebFocusType retVal = WebFocusTypeNone;
35
36 if (keyIdentifier == Down)
37 retVal = WebFocusTypeDown;
38 else if (keyIdentifier == Up)
39 retVal = WebFocusTypeUp;
40 else if (keyIdentifier == Left)
41 retVal = WebFocusTypeLeft;
42 else if (keyIdentifier == Right)
43 retVal = WebFocusTypeRight;
44
45 return retVal;
46 }
47
48 } // namespace
49
50 PlatformEvent::Modifiers KeyboardEventManager::accessKeyModifiers()
mustaq 2016/06/07 15:28:36 This is not specific to event handling, belongs to
Navid Zolghadr 2016/06/07 15:59:17 Done.
51 {
52 #if OS(MACOSX)
53 return static_cast<PlatformEvent::Modifiers>(PlatformEvent::CtrlKey | Platfo rmEvent::AltKey);
54 #else
55 return PlatformEvent::AltKey;
56 #endif
57 }
58
59 KeyboardEventManager::KeyboardEventManager(
60 LocalFrame* frame, ScrollManager* scrollManager)
61 : m_frame(frame)
62 , m_scrollManager(scrollManager)
63 {
64 }
65
66 KeyboardEventManager::~KeyboardEventManager()
67 {
68 }
69
70 bool KeyboardEventManager::handleAccessKey(const PlatformKeyboardEvent& evt)
71 {
72 // FIXME: Ignoring the state of Shift key is what neither IE nor Firefox do.
73 // IE matches lower and upper case access keys regardless of Shift key state - but if both upper and
74 // lower case variants are present in a document, the correct element is mat ched based on Shift key state.
75 // Firefox only matches an access key if Shift is not pressed, and does that case-insensitively.
76 DCHECK(!(accessKeyModifiers() & PlatformEvent::ShiftKey));
77 if ((evt.getModifiers() & (PlatformEvent::KeyModifiers & ~PlatformEvent::Shi ftKey)) != accessKeyModifiers())
78 return false;
79 String key = evt.unmodifiedText();
80 Element* elem = m_frame->document()->getElementByAccessKey(key.lower());
81 if (!elem)
82 return false;
83 elem->accessKeyAction(false);
84 return true;
85 }
86
87 WebInputEventResult KeyboardEventManager::keyEvent(
88 const PlatformKeyboardEvent& initialKeyEvent)
89 {
90 m_frame->chromeClient().clearToolTip();
91
92 if (initialKeyEvent.windowsVirtualKeyCode() == VK_CAPITAL)
93 capsLockStateMayHaveChanged();
94
95 #if OS(WIN)
96 if (m_scrollManager->panScrollInProgress()) {
97 // If a key is pressed while the panScroll is in progress then we want t o stop
98 if (initialKeyEvent.type() == PlatformEvent::KeyDown || initialKeyEvent. type() == PlatformEvent::RawKeyDown)
99 m_scrollManager->stopAutoscroll();
100
101 // If we were in panscroll mode, we swallow the key event
102 return WebInputEventResult::HandledSuppressed;
103 }
104 #endif
105
106 // Check for cases where we are too early for events -- possible unmatched k ey up
107 // from pressing return in the location bar.
108 Node* node = eventTargetNodeForDocument(m_frame->document());
109 if (!node)
110 return WebInputEventResult::NotHandled;
111
112 UserGestureIndicator gestureIndicator(DefinitelyProcessingUserGesture);
113
114 // In IE, access keys are special, they are handled after default keydown pr ocessing, but cannot be canceled - this is hard to match.
115 // On Mac OS X, we process them before dispatching keydown, as the default k eydown handler implements Emacs key bindings, which may conflict
116 // with access keys. Then we dispatch keydown, but suppress its default hand ling.
117 // On Windows, WebKit explicitly calls handleAccessKey() instead of dispatch ing a keypress event for WM_SYSCHAR messages.
118 // Other platforms currently match either Mac or Windows behavior, depending on whether they send combined KeyDown events.
119 bool matchedAnAccessKey = false;
120 if (initialKeyEvent.type() == PlatformEvent::KeyDown)
121 matchedAnAccessKey = handleAccessKey(initialKeyEvent);
122
123 // FIXME: it would be fair to let an input method handle KeyUp events before DOM dispatch.
124 if (initialKeyEvent.type() == PlatformEvent::KeyUp || initialKeyEvent.type() == PlatformEvent::Char) {
125 KeyboardEvent* domEvent = KeyboardEvent::create(initialKeyEvent, m_frame ->document()->domWindow());
126
127 return EventHandler::toWebInputEventResult(node->dispatchEvent(domEvent) );
128 }
129
130 PlatformKeyboardEvent keyDownEvent = initialKeyEvent;
131 if (keyDownEvent.type() != PlatformEvent::RawKeyDown)
132 keyDownEvent.disambiguateKeyDownEvent(PlatformEvent::RawKeyDown);
133 KeyboardEvent* keydown = KeyboardEvent::create(keyDownEvent, m_frame->docume nt()->domWindow());
134 if (matchedAnAccessKey)
135 keydown->setDefaultPrevented(true);
136 keydown->setTarget(node);
137
138 DispatchEventResult dispatchResult = node->dispatchEvent(keydown);
139 if (dispatchResult != DispatchEventResult::NotCanceled)
140 return EventHandler::toWebInputEventResult(dispatchResult);
141 // If frame changed as a result of keydown dispatch, then return early to av oid sending a subsequent keypress message to the new frame.
142 bool changedFocusedFrame = m_frame->page() && m_frame != m_frame->page()->fo cusController().focusedOrMainFrame();
143 if (changedFocusedFrame)
144 return WebInputEventResult::HandledSystem;
145
146 if (initialKeyEvent.type() == PlatformEvent::RawKeyDown)
147 return WebInputEventResult::NotHandled;
148
149 // Focus may have changed during keydown handling, so refetch node.
150 // But if we are dispatching a fake backward compatibility keypress, then we pretend that the keypress happened on the original node.
151 node = eventTargetNodeForDocument(m_frame->document());
152 if (!node)
153 return WebInputEventResult::NotHandled;
154
155 PlatformKeyboardEvent keyPressEvent = initialKeyEvent;
156 keyPressEvent.disambiguateKeyDownEvent(PlatformEvent::Char);
157 if (keyPressEvent.text().isEmpty())
158 return WebInputEventResult::NotHandled;
159 KeyboardEvent* keypress = KeyboardEvent::create(keyPressEvent, m_frame->docu ment()->domWindow());
160 keypress->setTarget(node);
161 return EventHandler::toWebInputEventResult(node->dispatchEvent(keypress));
162 }
163
164 void KeyboardEventManager::capsLockStateMayHaveChanged()
165 {
166 if (Element* element = m_frame->document()->focusedElement()) {
167 if (LayoutObject* r = element->layoutObject()) {
168 if (r->isTextField())
169 toLayoutTextControlSingleLine(r)->capsLockStateMayHaveChanged();
170 }
171 }
172 }
173
174 void KeyboardEventManager::defaultKeyboardEventHandler(
175 KeyboardEvent* event, Node* possibleFocusedNode)
176 {
177 if (event->type() == EventTypeNames::keydown) {
178 // Clear caret blinking suspended state to make sure that caret blinks
179 // when we type again after long pressing on an empty input field.
180 if (m_frame && m_frame->selection().isCaretBlinkingSuspended())
181 m_frame->selection().setCaretBlinkingSuspended(false);
182
183 m_frame->editor().handleKeyboardEvent(event);
184 if (event->defaultHandled())
185 return;
186 if (event->keyIdentifier() == "U+0009") {
187 defaultTabEventHandler(event);
188 } else if (event->keyIdentifier() == "U+0008") {
189 defaultBackspaceEventHandler(event);
190 } else if (event->keyIdentifier() == "U+001B") {
191 defaultEscapeEventHandler(event);
192 } else {
193 WebFocusType type = focusDirectionForKey(AtomicString(event->keyIden tifier()));
194 if (type != WebFocusTypeNone)
195 defaultArrowEventHandler(type, event);
196 }
197 }
198 if (event->type() == EventTypeNames::keypress) {
199 m_frame->editor().handleKeyboardEvent(event);
200 if (event->defaultHandled())
201 return;
202 if (event->charCode() == ' ')
203 defaultSpaceEventHandler(event, possibleFocusedNode);
204 }
205 }
206
207 void KeyboardEventManager::defaultSpaceEventHandler(
208 KeyboardEvent* event, Node* possibleFocusedNode)
209 {
210 DCHECK_EQ(event->type(), EventTypeNames::keypress);
211
212 if (event->ctrlKey() || event->metaKey() || event->altKey())
213 return;
214
215 ScrollDirection direction = event->shiftKey() ? ScrollBlockDirectionBackward : ScrollBlockDirectionForward;
216
217 // FIXME: enable scroll customization in this case. See crbug.com/410974.
218 if (m_scrollManager->logicalScroll(direction, ScrollByPage, nullptr, possibl eFocusedNode)) {
219 event->setDefaultHandled();
220 return;
221 }
222 }
223
224 void KeyboardEventManager::defaultBackspaceEventHandler(KeyboardEvent* event)
225 {
226 DCHECK_EQ(event->type(), EventTypeNames::keydown);
227
228 if (!RuntimeEnabledFeatures::backspaceDefaultHandlerEnabled())
229 return;
230
231 if (event->ctrlKey() || event->metaKey() || event->altKey())
232 return;
233
234 if (!m_frame->editor().behavior().shouldNavigateBackOnBackspace())
235 return;
236 UseCounter::count(m_frame->document(), UseCounter::BackspaceNavigatedBack);
237 if (m_frame->page()->chromeClient().hadFormInteraction())
238 UseCounter::count(m_frame->document(), UseCounter::BackspaceNavigatedBac kAfterFormInteraction);
239 bool handledEvent = m_frame->loader().client()->navigateBackForward(event->s hiftKey() ? 1 : -1);
240 if (handledEvent)
241 event->setDefaultHandled();
242 }
243
244 void KeyboardEventManager::defaultArrowEventHandler(WebFocusType focusType, Keyb oardEvent* event)
245 {
246 DCHECK_EQ(event->type(), EventTypeNames::keydown);
247
248 if (event->ctrlKey() || event->metaKey() || event->shiftKey())
249 return;
250
251 Page* page = m_frame->page();
252 if (!page)
253 return;
254
255 if (!isSpatialNavigationEnabled(m_frame))
256 return;
257
258 // Arrows and other possible directional navigation keys can be used in desi gn
259 // mode editing.
260 if (m_frame->document()->inDesignMode())
261 return;
262
263 if (page->focusController().advanceFocus(focusType))
264 event->setDefaultHandled();
265 }
266
267 void KeyboardEventManager::defaultTabEventHandler(KeyboardEvent* event)
268 {
269 DCHECK_EQ(event->type(), EventTypeNames::keydown);
270
271 // We should only advance focus on tabs if no special modifier keys are held down.
272 if (event->ctrlKey() || event->metaKey())
273 return;
274
275 #if !OS(MACOSX)
276 // Option-Tab is a shortcut based on a system-wide preference on Mac but
277 // should be ignored on all other platforms.
278 if (event->altKey())
279 return;
280 #endif
281
282 Page* page = m_frame->page();
283 if (!page)
284 return;
285 if (!page->tabKeyCyclesThroughElements())
286 return;
287
288 WebFocusType focusType = event->shiftKey() ? WebFocusTypeBackward : WebFocus TypeForward;
289
290 // Tabs can be used in design mode editing.
291 if (m_frame->document()->inDesignMode())
292 return;
293
294 if (page->focusController().advanceFocus(focusType, InputDeviceCapabilities: :doesntFireTouchEventsSourceCapabilities()))
295 event->setDefaultHandled();
296 }
297
298 void KeyboardEventManager::defaultEscapeEventHandler(KeyboardEvent* event)
299 {
300 if (HTMLDialogElement* dialog = m_frame->document()->activeModalDialog())
301 dialog->dispatchEvent(Event::createCancelable(EventTypeNames::cancel));
302 }
303
304 DEFINE_TRACE(KeyboardEventManager)
305 {
306 visitor->trace(m_frame);
307 }
308
309 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/input/KeyboardEventManager.h ('k') | third_party/WebKit/Source/web/WebAXObject.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698