1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "NativeKeyBindings.h"
9 #include "nsCocoaUtils.h"
10 #include "mozilla/Logging.h"
11 #include "mozilla/Maybe.h"
12 #include "mozilla/NativeKeyBindingsType.h"
13 #include "mozilla/TextEvents.h"
14 #include "mozilla/WritingModes.h"
16 #import <Cocoa/Cocoa.h>
17 #import <Carbon/Carbon.h>
22 static LazyLogModule gNativeKeyBindingsLog("NativeKeyBindings");
24 NativeKeyBindings* NativeKeyBindings::sInstanceForSingleLineEditor = nullptr;
25 NativeKeyBindings* NativeKeyBindings::sInstanceForMultiLineEditor = nullptr;
28 NativeKeyBindings* NativeKeyBindings::GetInstance(NativeKeyBindingsType aType) {
30 case NativeKeyBindingsType::SingleLineEditor:
31 if (!sInstanceForSingleLineEditor) {
32 sInstanceForSingleLineEditor = new NativeKeyBindings();
33 sInstanceForSingleLineEditor->Init(aType);
35 return sInstanceForSingleLineEditor;
36 case NativeKeyBindingsType::MultiLineEditor:
37 case NativeKeyBindingsType::RichTextEditor:
38 if (!sInstanceForMultiLineEditor) {
39 sInstanceForMultiLineEditor = new NativeKeyBindings();
40 sInstanceForMultiLineEditor->Init(aType);
42 return sInstanceForMultiLineEditor;
44 MOZ_CRASH("Not implemented");
50 void NativeKeyBindings::Shutdown() {
51 delete sInstanceForSingleLineEditor;
52 sInstanceForSingleLineEditor = nullptr;
53 delete sInstanceForMultiLineEditor;
54 sInstanceForMultiLineEditor = nullptr;
57 NativeKeyBindings::NativeKeyBindings() {}
59 inline objc_selector* ToObjcSelectorPtr(SEL aSel) {
60 return reinterpret_cast<objc_selector*>(aSel);
62 #define SEL_TO_COMMAND(aSel, aCommand) \
63 mSelectorToCommand.InsertOrUpdate(ToObjcSelectorPtr(@selector(aSel)), \
66 void NativeKeyBindings::Init(NativeKeyBindingsType aType) {
67 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
68 ("%p NativeKeyBindings::Init", this));
70 // Many selectors have a one-to-one mapping to a Gecko command. Those mappings
71 // are registered in mSelectorToCommand.
73 // Selectors from NSResponder's "Responding to Action Messages" section and
74 // from NSText's "Action Methods for Editing" section
76 // TODO: Improves correctness of left / right meaning
77 // TODO: Add real paragraph motions
79 // SEL_TO_COMMAND(cancelOperation:, );
80 // SEL_TO_COMMAND(capitalizeWord:, );
81 // SEL_TO_COMMAND(centerSelectionInVisibleArea:, );
82 // SEL_TO_COMMAND(changeCaseOfLetter:, );
83 // SEL_TO_COMMAND(complete:, );
84 SEL_TO_COMMAND(copy:, Command::Copy);
85 // SEL_TO_COMMAND(copyFont:, );
86 // SEL_TO_COMMAND(copyRuler:, );
87 SEL_TO_COMMAND(cut:, Command::Cut);
88 SEL_TO_COMMAND(delete:, Command::Delete);
89 SEL_TO_COMMAND(deleteBackward:, Command::DeleteCharBackward);
90 // SEL_TO_COMMAND(deleteBackwardByDecomposingPreviousCharacter:, );
91 SEL_TO_COMMAND(deleteForward:, Command::DeleteCharForward);
93 // TODO: deleteTo* selectors are also supposed to add text to a kill buffer
94 SEL_TO_COMMAND(deleteToBeginningOfLine:, Command::DeleteToBeginningOfLine);
95 SEL_TO_COMMAND(deleteToBeginningOfParagraph:,
96 Command::DeleteToBeginningOfLine);
97 SEL_TO_COMMAND(deleteToEndOfLine:, Command::DeleteToEndOfLine);
98 SEL_TO_COMMAND(deleteToEndOfParagraph:, Command::DeleteToEndOfLine);
99 // SEL_TO_COMMAND(deleteToMark:, );
101 SEL_TO_COMMAND(deleteWordBackward:, Command::DeleteWordBackward);
102 SEL_TO_COMMAND(deleteWordForward:, Command::DeleteWordForward);
103 // SEL_TO_COMMAND(indent:, );
104 // SEL_TO_COMMAND(insertBacktab:, );
105 // SEL_TO_COMMAND(insertContainerBreak:, );
106 // SEL_TO_COMMAND(insertLineBreak:, );
107 // SEL_TO_COMMAND(insertNewline:, );
108 // SEL_TO_COMMAND(insertNewlineIgnoringFieldEditor:, );
109 // SEL_TO_COMMAND(insertParagraphSeparator:, );
110 // SEL_TO_COMMAND(insertTab:, );
111 // SEL_TO_COMMAND(insertTabIgnoringFieldEditor:, );
112 // SEL_TO_COMMAND(insertDoubleQuoteIgnoringSubstitution:, );
113 // SEL_TO_COMMAND(insertSingleQuoteIgnoringSubstitution:, );
114 // SEL_TO_COMMAND(lowercaseWord:, );
115 SEL_TO_COMMAND(moveBackward:, Command::CharPrevious);
116 SEL_TO_COMMAND(moveBackwardAndModifySelection:, Command::SelectCharPrevious);
117 if (aType == NativeKeyBindingsType::SingleLineEditor) {
118 SEL_TO_COMMAND(moveDown:, Command::EndLine);
120 SEL_TO_COMMAND(moveDown:, Command::LineNext);
122 SEL_TO_COMMAND(moveDownAndModifySelection:, Command::SelectLineNext);
123 SEL_TO_COMMAND(moveForward:, Command::CharNext);
124 SEL_TO_COMMAND(moveForwardAndModifySelection:, Command::SelectCharNext);
125 SEL_TO_COMMAND(moveLeft:, Command::CharPrevious);
126 SEL_TO_COMMAND(moveLeftAndModifySelection:, Command::SelectCharPrevious);
127 SEL_TO_COMMAND(moveParagraphBackwardAndModifySelection:,
128 Command::SelectBeginLine);
129 SEL_TO_COMMAND(moveParagraphForwardAndModifySelection:,
130 Command::SelectEndLine);
131 SEL_TO_COMMAND(moveRight:, Command::CharNext);
132 SEL_TO_COMMAND(moveRightAndModifySelection:, Command::SelectCharNext);
133 SEL_TO_COMMAND(moveToBeginningOfDocument:, Command::MoveTop);
134 SEL_TO_COMMAND(moveToBeginningOfDocumentAndModifySelection:,
136 SEL_TO_COMMAND(moveToBeginningOfLine:, Command::BeginLine);
137 SEL_TO_COMMAND(moveToBeginningOfLineAndModifySelection:,
138 Command::SelectBeginLine);
139 SEL_TO_COMMAND(moveToBeginningOfParagraph:, Command::BeginLine);
140 SEL_TO_COMMAND(moveToBeginningOfParagraphAndModifySelection:,
141 Command::SelectBeginLine);
142 SEL_TO_COMMAND(moveToEndOfDocument:, Command::MoveBottom);
143 SEL_TO_COMMAND(moveToEndOfDocumentAndModifySelection:, Command::SelectBottom);
144 SEL_TO_COMMAND(moveToEndOfLine:, Command::EndLine);
145 SEL_TO_COMMAND(moveToEndOfLineAndModifySelection:, Command::SelectEndLine);
146 SEL_TO_COMMAND(moveToEndOfParagraph:, Command::EndLine);
147 SEL_TO_COMMAND(moveToEndOfParagraphAndModifySelection:,
148 Command::SelectEndLine);
149 SEL_TO_COMMAND(moveToLeftEndOfLine:, Command::BeginLine);
150 SEL_TO_COMMAND(moveToLeftEndOfLineAndModifySelection:,
151 Command::SelectBeginLine);
152 SEL_TO_COMMAND(moveToRightEndOfLine:, Command::EndLine);
153 SEL_TO_COMMAND(moveToRightEndOfLineAndModifySelection:,
154 Command::SelectEndLine);
155 if (aType == NativeKeyBindingsType::SingleLineEditor) {
156 SEL_TO_COMMAND(moveUp:, Command::BeginLine);
158 SEL_TO_COMMAND(moveUp:, Command::LinePrevious);
160 SEL_TO_COMMAND(moveUpAndModifySelection:, Command::SelectLinePrevious);
161 SEL_TO_COMMAND(moveWordBackward:, Command::WordPrevious);
162 SEL_TO_COMMAND(moveWordBackwardAndModifySelection:,
163 Command::SelectWordPrevious);
164 SEL_TO_COMMAND(moveWordForward:, Command::WordNext);
165 SEL_TO_COMMAND(moveWordForwardAndModifySelection:, Command::SelectWordNext);
166 SEL_TO_COMMAND(moveWordLeft:, Command::WordPrevious);
167 SEL_TO_COMMAND(moveWordLeftAndModifySelection:, Command::SelectWordPrevious);
168 SEL_TO_COMMAND(moveWordRight:, Command::WordNext);
169 SEL_TO_COMMAND(moveWordRightAndModifySelection:, Command::SelectWordNext);
170 SEL_TO_COMMAND(pageDown:, Command::MovePageDown);
171 SEL_TO_COMMAND(pageDownAndModifySelection:, Command::SelectPageDown);
172 SEL_TO_COMMAND(pageUp:, Command::MovePageUp);
173 SEL_TO_COMMAND(pageUpAndModifySelection:, Command::SelectPageUp);
174 SEL_TO_COMMAND(paste:, Command::Paste);
175 // SEL_TO_COMMAND(pasteFont:, );
176 // SEL_TO_COMMAND(pasteRuler:, );
177 SEL_TO_COMMAND(scrollLineDown:, Command::ScrollLineDown);
178 SEL_TO_COMMAND(scrollLineUp:, Command::ScrollLineUp);
179 SEL_TO_COMMAND(scrollPageDown:, Command::ScrollPageDown);
180 SEL_TO_COMMAND(scrollPageUp:, Command::ScrollPageUp);
181 SEL_TO_COMMAND(scrollToBeginningOfDocument:, Command::ScrollTop);
182 SEL_TO_COMMAND(scrollToEndOfDocument:, Command::ScrollBottom);
183 SEL_TO_COMMAND(selectAll:, Command::SelectAll);
184 // selectLine: is complex, see KeyDown
185 if (aType == NativeKeyBindingsType::SingleLineEditor) {
186 SEL_TO_COMMAND(selectParagraph:, Command::SelectAll);
188 // SEL_TO_COMMAND(selectToMark:, );
189 // selectWord: is complex, see KeyDown
190 // SEL_TO_COMMAND(setMark:, );
191 // SEL_TO_COMMAND(showContextHelp:, );
192 // SEL_TO_COMMAND(supplementalTargetForAction:sender:, );
193 // SEL_TO_COMMAND(swapWithMark:, );
194 // SEL_TO_COMMAND(transpose:, );
195 // SEL_TO_COMMAND(transposeWords:, );
196 // SEL_TO_COMMAND(uppercaseWord:, );
197 // SEL_TO_COMMAND(yank:, );
200 #undef SEL_TO_COMMAND
202 void NativeKeyBindings::GetEditCommands(const WidgetKeyboardEvent& aEvent,
203 const Maybe<WritingMode>& aWritingMode,
204 nsTArray<CommandInt>& aCommands) {
205 MOZ_ASSERT(!aEvent.mFlags.mIsSynthesizedForTests);
206 MOZ_ASSERT(aCommands.IsEmpty());
208 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
209 ("%p NativeKeyBindings::GetEditCommands", this));
211 // Recover the current event, which should always be the key down we are
214 NSEvent* cocoaEvent = reinterpret_cast<NSEvent*>(aEvent.mNativeKeyEvent);
216 if (!cocoaEvent || [cocoaEvent type] != NSEventTypeKeyDown) {
217 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
218 ("%p NativeKeyBindings::GetEditCommands, no Cocoa key down event",
224 if (aWritingMode.isSome() && aEvent.NeedsToRemapNavigationKey() &&
225 aWritingMode.ref().IsVertical()) {
226 NSEvent* originalEvent = cocoaEvent;
228 // TODO: Use KeyNameIndex rather than legacy keyCode.
229 uint32_t remappedGeckoKeyCode =
230 aEvent.GetRemappedKeyCode(aWritingMode.ref());
231 uint32_t remappedCocoaKeyCode = 0;
232 switch (remappedGeckoKeyCode) {
234 remappedCocoaKeyCode = kVK_UpArrow;
237 remappedCocoaKeyCode = kVK_DownArrow;
240 remappedCocoaKeyCode = kVK_LeftArrow;
243 remappedCocoaKeyCode = kVK_RightArrow;
246 MOZ_ASSERT_UNREACHABLE("Add a case for the new remapped key");
250 nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(remappedGeckoKeyCode);
251 NSString* chars = [[[NSString alloc] initWithCharacters:&ch
252 length:1] autorelease];
253 cocoaEvent = [NSEvent keyEventWithType:[originalEvent type]
254 location:[originalEvent locationInWindow]
255 modifierFlags:[originalEvent modifierFlags]
256 timestamp:[originalEvent timestamp]
257 windowNumber:[originalEvent windowNumber]
260 charactersIgnoringModifiers:chars
261 isARepeat:[originalEvent isARepeat]
262 keyCode:remappedCocoaKeyCode];
265 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
266 ("%p NativeKeyBindings::GetEditCommands, interpreting", this));
268 AutoTArray<KeyBindingsCommand, 2> bindingCommands;
269 nsCocoaUtils::GetCommandsFromKeyEvent(cocoaEvent, bindingCommands);
271 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
272 ("%p NativeKeyBindings::GetEditCommands, bindingCommands=%zu", this,
273 bindingCommands.Length()));
275 for (uint32_t i = 0; i < bindingCommands.Length(); i++) {
276 SEL selector = bindingCommands[i].selector;
278 if (MOZ_LOG_TEST(gNativeKeyBindingsLog, LogLevel::Info)) {
279 NSString* selectorString = NSStringFromSelector(selector);
280 nsAutoString nsSelectorString;
281 nsCocoaUtils::GetStringForNSString(selectorString, nsSelectorString);
283 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
284 ("%p NativeKeyBindings::GetEditCommands, selector=%s", this,
285 NS_LossyConvertUTF16toASCII(nsSelectorString).get()));
288 AppendEditCommandsForSelector(ToObjcSelectorPtr(selector), aCommands);
291 LogEditCommands(aCommands, "NativeKeyBindings::GetEditCommands");
294 void NativeKeyBindings::AppendEditCommandsForSelector(
295 objc_selector* aSelector, nsTArray<CommandInt>& aCommands) const {
296 // Try to find a simple mapping in the hashtable
297 Command geckoCommand = Command::DoNothing;
298 if (mSelectorToCommand.Get(aSelector, &geckoCommand) &&
299 geckoCommand != Command::DoNothing) {
300 aCommands.AppendElement(static_cast<CommandInt>(geckoCommand));
301 } else if (aSelector == ToObjcSelectorPtr(@selector(selectLine:))) {
302 // This is functional, but Cocoa's version is direction-less in that
303 // selection direction is not determined until some future directed action
304 // is taken. See bug 282097, comment 79 for more details.
305 aCommands.AppendElement(static_cast<CommandInt>(Command::BeginLine));
306 aCommands.AppendElement(static_cast<CommandInt>(Command::SelectEndLine));
307 } else if (aSelector == ToObjcSelectorPtr(@selector(selectWord:))) {
308 // This is functional, but Cocoa's version is direction-less in that
309 // selection direction is not determined until some future directed action
310 // is taken. See bug 282097, comment 79 for more details.
311 aCommands.AppendElement(static_cast<CommandInt>(Command::WordPrevious));
312 aCommands.AppendElement(static_cast<CommandInt>(Command::SelectWordNext));
316 void NativeKeyBindings::LogEditCommands(const nsTArray<CommandInt>& aCommands,
317 const char* aDescription) const {
318 if (!MOZ_LOG_TEST(gNativeKeyBindingsLog, LogLevel::Info)) {
322 if (aCommands.IsEmpty()) {
323 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
324 ("%p %s, no edit commands", this, aDescription));
328 for (CommandInt commandInt : aCommands) {
329 Command geckoCommand = static_cast<Command>(commandInt);
330 MOZ_LOG(gNativeKeyBindingsLog, LogLevel::Info,
331 ("%p %s, command=%s", this, aDescription,
332 WidgetKeyboardEvent::GetCommandStr(geckoCommand)));
337 void NativeKeyBindings::GetEditCommandsForTests(
338 NativeKeyBindingsType aType, const WidgetKeyboardEvent& aEvent,
339 const Maybe<WritingMode>& aWritingMode, nsTArray<CommandInt>& aCommands) {
340 MOZ_DIAGNOSTIC_ASSERT(aEvent.IsTrusted());
342 // The following mapping is checked on Big Sur. Some of them are defined in:
343 // https://support.apple.com/en-us/HT201236#text
344 NativeKeyBindings* instance = NativeKeyBindings::GetInstance(aType);
345 if (NS_WARN_IF(!instance)) {
348 switch (aWritingMode.isSome()
349 ? aEvent.GetRemappedKeyNameIndex(aWritingMode.ref())
350 : aEvent.mKeyNameIndex) {
351 case KEY_NAME_INDEX_USE_STRING:
352 if (!aEvent.IsControl() || aEvent.IsAlt() || aEvent.IsMeta()) {
355 switch (aEvent.PseudoCharCode()) {
358 instance->AppendEditCommandsForSelector(
360 ? ToObjcSelectorPtr(@selector(moveToBeginningOfParagraph:))
361 : ToObjcSelectorPtr(@selector(
362 moveToBeginningOfParagraphAndModifySelection:)),
367 instance->AppendEditCommandsForSelector(
368 !aEvent.IsShift() ? ToObjcSelectorPtr(@selector(moveBackward:))
369 : ToObjcSelectorPtr(@selector(
370 moveBackwardAndModifySelection:)),
375 if (!aEvent.IsShift()) {
376 instance->AppendEditCommandsForSelector(
377 ToObjcSelectorPtr(@selector(deleteForward:)), aCommands);
382 instance->AppendEditCommandsForSelector(
384 ? ToObjcSelectorPtr(@selector(moveToEndOfParagraph:))
386 @selector(moveToEndOfParagraphAndModifySelection:)),
391 instance->AppendEditCommandsForSelector(
392 !aEvent.IsShift() ? ToObjcSelectorPtr(@selector(moveForward:))
393 : ToObjcSelectorPtr(@selector(
394 moveForwardAndModifySelection:)),
399 if (!aEvent.IsShift()) {
400 instance->AppendEditCommandsForSelector(
401 ToObjcSelectorPtr(@selector(deleteBackward:)), aCommands);
406 if (!aEvent.IsShift()) {
407 instance->AppendEditCommandsForSelector(
408 ToObjcSelectorPtr(@selector(deleteToEndOfParagraph:)),
414 instance->AppendEditCommandsForSelector(
416 ? ToObjcSelectorPtr(@selector(moveDown:))
417 : ToObjcSelectorPtr(@selector(moveDownAndModifySelection:)),
422 instance->AppendEditCommandsForSelector(
424 ? ToObjcSelectorPtr(@selector(moveUp:))
425 : ToObjcSelectorPtr(@selector(moveUpAndModifySelection:)),
432 case KEY_NAME_INDEX_Backspace:
433 if (aEvent.IsMeta()) {
434 if (aEvent.IsAlt() || aEvent.IsControl()) {
438 instance->AppendEditCommandsForSelector(
439 ToObjcSelectorPtr(@selector(deleteToBeginningOfLine:)), aCommands);
442 if (aEvent.IsAlt()) {
443 // Shift and Control are ignored.
444 instance->AppendEditCommandsForSelector(
445 ToObjcSelectorPtr(@selector(deleteWordBackward:)), aCommands);
448 if (aEvent.IsControl()) {
449 if (aEvent.IsShift()) {
450 instance->AppendEditCommandsForSelector(
452 @selector(deleteBackwardByDecomposingPreviousCharacter:)),
458 instance->AppendEditCommandsForSelector(
459 ToObjcSelectorPtr(@selector(deleteBackward:)), aCommands);
461 case KEY_NAME_INDEX_Delete:
462 if (aEvent.IsControl() || aEvent.IsMeta()) {
465 if (aEvent.IsAlt()) {
467 instance->AppendEditCommandsForSelector(
468 ToObjcSelectorPtr(@selector(deleteWordForward:)), aCommands);
472 instance->AppendEditCommandsForSelector(
473 ToObjcSelectorPtr(@selector(deleteForward:)), aCommands);
475 case KEY_NAME_INDEX_PageDown:
476 if (aEvent.IsControl() || aEvent.IsMeta()) {
479 if (aEvent.IsAlt()) {
481 instance->AppendEditCommandsForSelector(
482 ToObjcSelectorPtr(@selector(pageDown:)), aCommands);
485 instance->AppendEditCommandsForSelector(
487 ? ToObjcSelectorPtr(@selector(scrollPageDown:))
488 : ToObjcSelectorPtr(@selector(pageDownAndModifySelection:)),
491 case KEY_NAME_INDEX_PageUp:
492 if (aEvent.IsControl() || aEvent.IsMeta()) {
495 if (aEvent.IsAlt()) {
497 instance->AppendEditCommandsForSelector(
498 ToObjcSelectorPtr(@selector(pageUp:)), aCommands);
501 instance->AppendEditCommandsForSelector(
503 ? ToObjcSelectorPtr(@selector(scrollPageUp:))
504 : ToObjcSelectorPtr(@selector(pageUpAndModifySelection:)),
507 case KEY_NAME_INDEX_Home:
508 if (aEvent.IsAlt() || aEvent.IsControl() || aEvent.IsMeta()) {
511 instance->AppendEditCommandsForSelector(
513 ? ToObjcSelectorPtr(@selector(scrollToBeginningOfDocument:))
515 @selector(moveToBeginningOfDocumentAndModifySelection:)),
518 case KEY_NAME_INDEX_End:
519 if (aEvent.IsAlt() || aEvent.IsControl() || aEvent.IsMeta()) {
522 instance->AppendEditCommandsForSelector(
524 ? ToObjcSelectorPtr(@selector(scrollToEndOfDocument:))
525 : ToObjcSelectorPtr(@selector
526 (moveToEndOfDocumentAndModifySelection:)),
529 case KEY_NAME_INDEX_ArrowLeft:
530 if (aEvent.IsAlt()) {
533 if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
534 instance->AppendEditCommandsForSelector(
536 ? ToObjcSelectorPtr(@selector(moveToLeftEndOfLine:))
537 : ToObjcSelectorPtr(@selector
538 (moveToLeftEndOfLineAndModifySelection:)),
542 if (aEvent.IsControl()) {
545 instance->AppendEditCommandsForSelector(
547 ? ToObjcSelectorPtr(@selector(moveLeft:))
548 : ToObjcSelectorPtr(@selector(moveLeftAndModifySelection:)),
551 case KEY_NAME_INDEX_ArrowRight:
552 if (aEvent.IsAlt()) {
555 if (aEvent.IsMeta() || (aEvent.IsControl() && aEvent.IsShift())) {
556 instance->AppendEditCommandsForSelector(
558 ? ToObjcSelectorPtr(@selector(moveToRightEndOfLine:))
559 : ToObjcSelectorPtr(@selector
560 (moveToRightEndOfLineAndModifySelection:)),
564 if (aEvent.IsControl()) {
567 instance->AppendEditCommandsForSelector(
569 ? ToObjcSelectorPtr(@selector(moveRight:))
570 : ToObjcSelectorPtr(@selector(moveRightAndModifySelection:)),
573 case KEY_NAME_INDEX_ArrowUp:
574 if (aEvent.IsControl()) {
577 if (aEvent.IsMeta()) {
578 if (aEvent.IsAlt()) {
581 instance->AppendEditCommandsForSelector(
583 ? ToObjcSelectorPtr(@selector(moveToBeginningOfDocument:))
585 @selector(moveToBegginingOfDocumentAndModifySelection:)),
589 if (aEvent.IsAlt()) {
590 if (!aEvent.IsShift()) {
591 instance->AppendEditCommandsForSelector(
592 ToObjcSelectorPtr(@selector(moveBackward:)), aCommands);
593 instance->AppendEditCommandsForSelector(
594 ToObjcSelectorPtr(@selector(moveToBeginningOfParagraph:)),
598 instance->AppendEditCommandsForSelector(
599 ToObjcSelectorPtr(@selector
600 (moveParagraphBackwardAndModifySelection:)),
604 instance->AppendEditCommandsForSelector(
606 ? ToObjcSelectorPtr(@selector(moveUp:))
607 : ToObjcSelectorPtr(@selector(moveUpAndModifySelection:)),
610 case KEY_NAME_INDEX_ArrowDown:
611 if (aEvent.IsControl()) {
614 if (aEvent.IsMeta()) {
615 if (aEvent.IsAlt()) {
618 instance->AppendEditCommandsForSelector(
620 ? ToObjcSelectorPtr(@selector(moveToEndOfDocument:))
621 : ToObjcSelectorPtr(@selector
622 (moveToEndOfDocumentAndModifySelection:)),
626 if (aEvent.IsAlt()) {
627 if (!aEvent.IsShift()) {
628 instance->AppendEditCommandsForSelector(
629 ToObjcSelectorPtr(@selector(moveForward:)), aCommands);
630 instance->AppendEditCommandsForSelector(
631 ToObjcSelectorPtr(@selector(moveToEndOfParagraph:)), aCommands);
634 instance->AppendEditCommandsForSelector(
635 ToObjcSelectorPtr(@selector
636 (moveParagraphForwardAndModifySelection:)),
640 instance->AppendEditCommandsForSelector(
642 ? ToObjcSelectorPtr(@selector(moveDown:))
643 : ToObjcSelectorPtr(@selector(moveDownAndModifySelection:)),
650 instance->LogEditCommands(aCommands,
651 "NativeKeyBindings::GetEditCommandsForTests");
654 } // namespace widget
655 } // namespace mozilla