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

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