diff --git a/widget/CommandList.h b/widget/CommandList.h index d54feb17fec3..7fcea8713af8 100644 --- a/widget/CommandList.h +++ b/widget/CommandList.h @@ -4,9 +4,12 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /** - * Define NS_DEFIVE_COMMAND(aName, aCommandStr) before including this. + * Define NS_DEFINE_COMMAND(aName, aCommandStr) before including this. * @param aName The name useful in C++ of the command. * @param aCommandStr The command string in JS. + * + * Define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) before including this. + * @param aName The name useful in C++ of the command. */ NS_DEFINE_COMMAND(BeginLine, cmd_beginLine) @@ -52,3 +55,8 @@ NS_DEFINE_COMMAND(SelectWordNext, cmd_selectWordNext) NS_DEFINE_COMMAND(SelectWordPrevious, cmd_selectWordPrevious) NS_DEFINE_COMMAND(WordNext, cmd_wordNext) NS_DEFINE_COMMAND(WordPrevious, cmd_wordPrevious) + +NS_DEFINE_COMMAND_NO_EXEC_COMMAND(CancelOperation) +NS_DEFINE_COMMAND_NO_EXEC_COMMAND(Complete) +NS_DEFINE_COMMAND_NO_EXEC_COMMAND(InsertBacktab) +NS_DEFINE_COMMAND_NO_EXEC_COMMAND(InsertTab) diff --git a/widget/EventForwards.h b/widget/EventForwards.h index 11c39bb42043..ed2496750b0d 100644 --- a/widget/EventForwards.h +++ b/widget/EventForwards.h @@ -114,6 +114,7 @@ enum CodeNameIndex : CodeNameIndexType const nsCString ToString(CodeNameIndex aCodeNameIndex); #define NS_DEFINE_COMMAND(aName, aCommandStr) , Command##aName +#define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) , Command##aName typedef int8_t CommandInt; enum Command : CommandInt @@ -123,6 +124,7 @@ enum Command : CommandInt #include "mozilla/CommandList.h" }; #undef NS_DEFINE_COMMAND +#undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND const char* ToChar(Command aCommand); diff --git a/widget/WidgetEventImpl.cpp b/widget/WidgetEventImpl.cpp index 7fcb985e8a1e..bff041c88685 100644 --- a/widget/WidgetEventImpl.cpp +++ b/widget/WidgetEventImpl.cpp @@ -97,10 +97,14 @@ ToChar(Command aCommand) #define NS_DEFINE_COMMAND(aName, aCommandStr) \ case Command##aName: \ return "Command" #aName; +#define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) \ + case Command##aName: \ + return "Command" #aName; #include "mozilla/CommandList.h" #undef NS_DEFINE_COMMAND +#undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND default: return "illegal command value"; @@ -1164,11 +1168,13 @@ WidgetKeyboardEvent::GetCodeNameIndex(const nsAString& aCodeValue) WidgetKeyboardEvent::GetCommandStr(Command aCommand) { #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr +#define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) static const char* const kCommands[] = { "" // CommandDoNothing #include "mozilla/CommandList.h" }; #undef NS_DEFINE_COMMAND +#undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND MOZ_RELEASE_ASSERT(static_cast(aCommand) < ArrayLength(kCommands), "Illegal command enumeration value"); diff --git a/widget/cocoa/TextInputHandler.h b/widget/cocoa/TextInputHandler.h index 9002f87014d6..1e41c3752822 100644 --- a/widget/cocoa/TextInputHandler.h +++ b/widget/cocoa/TextInputHandler.h @@ -627,14 +627,141 @@ protected: return !mKeyDownHandled && !mKeyPressHandled; } - bool IsEnterKeyEvent() const + bool IsProperKeyEvent(Command aCommand) const { if (NS_WARN_IF(!mKeyEvent)) { return false; } KeyNameIndex keyNameIndex = TISInputSourceWrapper::ComputeGeckoKeyNameIndex([mKeyEvent keyCode]); - return keyNameIndex == KEY_NAME_INDEX_Enter; + Modifiers modifiers = + nsCocoaUtils::ModifiersForEvent(mKeyEvent) & (MODIFIER_SHIFT | + MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + switch (aCommand) { + case CommandInsertLineBreak: + return keyNameIndex == KEY_NAME_INDEX_Enter && + modifiers == MODIFIER_CONTROL; + case CommandInsertParagraph: + return keyNameIndex == KEY_NAME_INDEX_Enter && + modifiers == MODIFIER_NONE; + case CommandDeleteCharBackward: + return keyNameIndex == KEY_NAME_INDEX_Backspace && + modifiers == MODIFIER_NONE; + case CommandDeleteToBeginningOfLine: + return keyNameIndex == KEY_NAME_INDEX_Backspace && + modifiers == MODIFIER_META; + case CommandDeleteWordBackward: + return keyNameIndex == KEY_NAME_INDEX_Backspace && + modifiers == MODIFIER_ALT; + case CommandDeleteCharForward: + return keyNameIndex == KEY_NAME_INDEX_Delete && + modifiers == MODIFIER_NONE; + case CommandDeleteWordForward: + return keyNameIndex == KEY_NAME_INDEX_Delete && + modifiers == MODIFIER_ALT; + case CommandInsertTab: + return keyNameIndex == KEY_NAME_INDEX_Tab && + modifiers == MODIFIER_NONE; + case CommandInsertBacktab: + return keyNameIndex == KEY_NAME_INDEX_Tab && + modifiers == MODIFIER_SHIFT; + case CommandCharNext: + return keyNameIndex == KEY_NAME_INDEX_ArrowRight && + modifiers == MODIFIER_NONE; + case CommandSelectCharNext: + return keyNameIndex == KEY_NAME_INDEX_ArrowRight && + modifiers == MODIFIER_SHIFT; + case CommandWordNext: + return keyNameIndex == KEY_NAME_INDEX_ArrowRight && + modifiers == MODIFIER_ALT; + case CommandSelectWordNext: + return keyNameIndex == KEY_NAME_INDEX_ArrowRight && + modifiers == (MODIFIER_ALT | MODIFIER_SHIFT); + case CommandEndLine: + return keyNameIndex == KEY_NAME_INDEX_ArrowRight && + modifiers == MODIFIER_META; + case CommandSelectEndLine: + return keyNameIndex == KEY_NAME_INDEX_ArrowRight && + modifiers == (MODIFIER_META | MODIFIER_SHIFT); + case CommandCharPrevious: + return keyNameIndex == KEY_NAME_INDEX_ArrowLeft && + modifiers == MODIFIER_NONE; + case CommandSelectCharPrevious: + return keyNameIndex == KEY_NAME_INDEX_ArrowLeft && + modifiers == MODIFIER_SHIFT; + case CommandWordPrevious: + return keyNameIndex == KEY_NAME_INDEX_ArrowLeft && + modifiers == MODIFIER_ALT; + case CommandSelectWordPrevious: + return keyNameIndex == KEY_NAME_INDEX_ArrowLeft && + modifiers == (MODIFIER_ALT | MODIFIER_SHIFT); + case CommandBeginLine: + return keyNameIndex == KEY_NAME_INDEX_ArrowLeft && + modifiers == MODIFIER_META; + case CommandSelectBeginLine: + return keyNameIndex == KEY_NAME_INDEX_ArrowLeft && + modifiers == (MODIFIER_META | MODIFIER_SHIFT); + case CommandLinePrevious: + return keyNameIndex == KEY_NAME_INDEX_ArrowUp && + modifiers == MODIFIER_NONE; + case CommandSelectLinePrevious: + return keyNameIndex == KEY_NAME_INDEX_ArrowUp && + modifiers == MODIFIER_SHIFT; + case CommandMoveTop: + return keyNameIndex == KEY_NAME_INDEX_ArrowUp && + modifiers == MODIFIER_META; + case CommandSelectTop: + return (keyNameIndex == KEY_NAME_INDEX_ArrowUp && + modifiers == (MODIFIER_META | MODIFIER_SHIFT)) || + (keyNameIndex == KEY_NAME_INDEX_Home && + modifiers == MODIFIER_SHIFT); + case CommandLineNext: + return keyNameIndex == KEY_NAME_INDEX_ArrowDown && + modifiers == MODIFIER_NONE; + case CommandSelectLineNext: + return keyNameIndex == KEY_NAME_INDEX_ArrowDown && + modifiers == MODIFIER_SHIFT; + case CommandMoveBottom: + return keyNameIndex == KEY_NAME_INDEX_ArrowDown && + modifiers == MODIFIER_META; + case CommandSelectBottom: + return (keyNameIndex == KEY_NAME_INDEX_ArrowDown && + modifiers == (MODIFIER_META | MODIFIER_SHIFT)) || + (keyNameIndex == KEY_NAME_INDEX_End && + modifiers == MODIFIER_SHIFT); + case CommandScrollPageUp: + return keyNameIndex == KEY_NAME_INDEX_PageUp && + modifiers == MODIFIER_NONE; + case CommandSelectPageUp: + return keyNameIndex == KEY_NAME_INDEX_PageUp && + modifiers == MODIFIER_SHIFT; + case CommandScrollPageDown: + return keyNameIndex == KEY_NAME_INDEX_PageDown && + modifiers == MODIFIER_NONE; + case CommandSelectPageDown: + return keyNameIndex == KEY_NAME_INDEX_PageDown && + modifiers == MODIFIER_SHIFT; + case CommandScrollBottom: + return keyNameIndex == KEY_NAME_INDEX_End && + modifiers == MODIFIER_NONE; + case CommandScrollTop: + return keyNameIndex == KEY_NAME_INDEX_Home && + modifiers == MODIFIER_NONE; + case CommandCancelOperation: + return (keyNameIndex == KEY_NAME_INDEX_Escape && + (modifiers == MODIFIER_NONE || + modifiers == MODIFIER_SHIFT)) || + ([mKeyEvent keyCode] == kVK_ANSI_Period && + modifiers == MODIFIER_META); + case CommandComplete: + return keyNameIndex == KEY_NAME_INDEX_Escape && + (modifiers == MODIFIER_ALT || + modifiers == (MODIFIER_ALT | MODIFIER_SHIFT)); + default: + return false; + } } void InitKeyEvent(TextInputHandlerBase* aHandler, @@ -1161,8 +1288,12 @@ public: /** * Handles aCommand. This may cause dispatching an eKeyPress event. + * + * @param aCommand The command which receives from Cocoa. + * @return true if this handles the command even if it does + * nothing actually. Otherwise, false. */ - void HandleCommand(Command aCommand); + bool HandleCommand(Command aCommand); /** * doCommandBySelector event handler. diff --git a/widget/cocoa/TextInputHandler.mm b/widget/cocoa/TextInputHandler.mm index 27c503c2ad47..2ca14287b954 100644 --- a/widget/cocoa/TextInputHandler.mm +++ b/widget/cocoa/TextInputHandler.mm @@ -2350,13 +2350,13 @@ TextInputHandler::InsertText(NSAttributedString* aAttrString, NS_OBJC_END_TRY_ABORT_BLOCK; } -void +bool TextInputHandler::HandleCommand(Command aCommand) { - NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN; if (Destroyed()) { - return; + return false; } KeyEventState* currentKeyEvent = GetCurrentKeyEvent(); @@ -2377,9 +2377,9 @@ TextInputHandler::HandleCommand(Command aCommand) currentKeyEvent ? TrueOrFalse(currentKeyEvent->mCompositionDispatched) : "N/A")); - // If "insertNewline:" command shouldn't be handled, let's ignore it. + // The command shouldn't be handled, let's ignore it. if (currentKeyEvent && !currentKeyEvent->CanHandleCommand()) { - return; + return false; } // If it's in composition, we cannot dispatch keypress event. @@ -2402,8 +2402,52 @@ TextInputHandler::HandleCommand(Command aCommand) currentKeyEvent->mCompositionDispatched = true; } [lineBreaker release]; - return; + return true; } + case CommandDeleteCharBackward: + case CommandDeleteCharForward: + case CommandDeleteToBeginningOfLine: + case CommandDeleteWordBackward: + case CommandDeleteWordForward: + // Don't remove any contents during composition. + return false; + case CommandInsertTab: + case CommandInsertBacktab: + // Don't move focus during composition. + return false; + case CommandCharNext: + case CommandSelectCharNext: + case CommandWordNext: + case CommandSelectWordNext: + case CommandEndLine: + case CommandSelectEndLine: + case CommandCharPrevious: + case CommandSelectCharPrevious: + case CommandWordPrevious: + case CommandSelectWordPrevious: + case CommandBeginLine: + case CommandSelectBeginLine: + case CommandLinePrevious: + case CommandSelectLinePrevious: + case CommandMoveTop: + case CommandLineNext: + case CommandSelectLineNext: + case CommandMoveBottom: + case CommandSelectBottom: + case CommandSelectPageUp: + case CommandSelectPageDown: + case CommandScrollBottom: + case CommandScrollTop: + // Don't move selection during composition. + return false; + case CommandCancelOperation: + case CommandComplete: + // Don't handle Escape key by ourselves during composition. + return false; + case CommandScrollPageUp: + case CommandScrollPageDown: + // Allow to scroll. + break; default: break; } @@ -2415,7 +2459,7 @@ TextInputHandler::HandleCommand(Command aCommand) MOZ_LOG(gLog, LogLevel::Error, ("%p, IMEInputHandler::HandleCommand, " "FAILED, due to BeginNativeInputTransaction() failure", this)); - return; + return false; } // TODO: If it's not appropriate keypress but user customized the OS @@ -2428,7 +2472,7 @@ TextInputHandler::HandleCommand(Command aCommand) // Otherwise, we should adjust Control, Option and Command state since // editor may behave differently if some of them are active. bool dispatchFakeKeyPress = - !(currentKeyEvent && currentKeyEvent->IsEnterKeyEvent() && + !(currentKeyEvent && currentKeyEvent->IsProperKeyEvent(aCommand) && currentKeyEvent->CanDispatchKeyPressEvent()); WidgetKeyboardEvent keypressEvent(true, eKeyPress, widget); @@ -2464,8 +2508,205 @@ TextInputHandler::HandleCommand(Command aCommand) } break; } + case CommandDeleteCharBackward: + case CommandDeleteToBeginningOfLine: + case CommandDeleteWordBackward: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_BACK; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_Backspace; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandDeleteToBeginningOfLine) { + keypressEvent.mModifiers |= MODIFIER_META; + } else if (aCommand == CommandDeleteWordBackward) { + keypressEvent.mModifiers |= MODIFIER_ALT; + } + break; + } + case CommandDeleteCharForward: + case CommandDeleteWordForward: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_DELETE; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_Delete; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandDeleteWordForward) { + keypressEvent.mModifiers |= MODIFIER_ALT; + } + break; + } + case CommandCharNext: + case CommandSelectCharNext: + case CommandWordNext: + case CommandSelectWordNext: + case CommandEndLine: + case CommandSelectEndLine: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_RIGHT; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_ArrowRight; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandSelectCharNext || + aCommand == CommandSelectWordNext || + aCommand == CommandSelectEndLine) { + keypressEvent.mModifiers |= MODIFIER_SHIFT; + } + if (aCommand == CommandWordNext || + aCommand == CommandSelectWordNext) { + keypressEvent.mModifiers |= MODIFIER_ALT; + } + if (aCommand == CommandEndLine || + aCommand == CommandSelectEndLine) { + keypressEvent.mModifiers |= MODIFIER_META; + } + break; + } + case CommandCharPrevious: + case CommandSelectCharPrevious: + case CommandWordPrevious: + case CommandSelectWordPrevious: + case CommandBeginLine: + case CommandSelectBeginLine: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_LEFT; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_ArrowLeft; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandSelectCharPrevious || + aCommand == CommandSelectWordPrevious || + aCommand == CommandSelectBeginLine) { + keypressEvent.mModifiers |= MODIFIER_SHIFT; + } + if (aCommand == CommandWordPrevious || + aCommand == CommandSelectWordPrevious) { + keypressEvent.mModifiers |= MODIFIER_ALT; + } + if (aCommand == CommandBeginLine || + aCommand == CommandSelectBeginLine) { + keypressEvent.mModifiers |= MODIFIER_META; + } + break; + } + case CommandLinePrevious: + case CommandSelectLinePrevious: + case CommandMoveTop: + case CommandSelectTop: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_UP; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_ArrowUp; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandSelectLinePrevious || + aCommand == CommandSelectTop) { + keypressEvent.mModifiers |= MODIFIER_SHIFT; + } + if (aCommand == CommandMoveTop || + aCommand == CommandSelectTop) { + keypressEvent.mModifiers |= MODIFIER_META; + } + break; + } + case CommandLineNext: + case CommandSelectLineNext: + case CommandMoveBottom: + case CommandSelectBottom: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_DOWN; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_ArrowDown; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandSelectLineNext || + aCommand == CommandSelectBottom) { + keypressEvent.mModifiers |= MODIFIER_SHIFT; + } + if (aCommand == CommandMoveBottom || + aCommand == CommandSelectBottom) { + keypressEvent.mModifiers |= MODIFIER_META; + } + break; + } + case CommandScrollPageUp: + case CommandSelectPageUp: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_PAGE_UP; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_PageUp; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandSelectPageUp) { + keypressEvent.mModifiers |= MODIFIER_SHIFT; + } + break; + } + case CommandScrollPageDown: + case CommandSelectPageDown: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_PAGE_DOWN; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_PageDown; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandSelectPageDown) { + keypressEvent.mModifiers |= MODIFIER_SHIFT; + } + break; + } + case CommandScrollBottom: + case CommandScrollTop: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + if (aCommand == CommandScrollBottom) { + keypressEvent.mKeyCode = NS_VK_END; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_End; + } else { + keypressEvent.mKeyCode = NS_VK_HOME; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_Home; + } + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + break; + } + case CommandCancelOperation: + case CommandComplete: { + NSEvent* keyEvent = + currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr; + nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent); + keypressEvent.mKeyCode = NS_VK_ESCAPE; + keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_Escape; + keypressEvent.mModifiers &= ~(MODIFIER_CONTROL | + MODIFIER_ALT | + MODIFIER_META); + if (aCommand == CommandComplete) { + keypressEvent.mModifiers |= MODIFIER_ALT; + } + break; + } default: - return; + return false; } } @@ -2486,20 +2727,26 @@ TextInputHandler::HandleCommand(Command aCommand) currentKeyEvent->mKeyPressHandled = keyPressHandled; currentKeyEvent->mKeyPressDispatched = keyPressDispatched; } - return; + return true; } // If keypress event isn't dispatched as expected, we should fallback to // using composition events. - NSAttributedString* lineBreaker = - [[NSAttributedString alloc] initWithString:@"\n"]; - InsertTextAsCommittingComposition(lineBreaker, nullptr); - if (currentKeyEvent) { - currentKeyEvent->mCompositionDispatched = true; + if (aCommand == CommandInsertLineBreak || + aCommand == CommandInsertParagraph) { + NSAttributedString* lineBreaker = + [[NSAttributedString alloc] initWithString:@"\n"]; + InsertTextAsCommittingComposition(lineBreaker, nullptr); + if (currentKeyEvent) { + currentKeyEvent->mCompositionDispatched = true; + } + [lineBreaker release]; + return true; } - [lineBreaker release]; - NS_OBJC_END_TRY_ABORT_BLOCK; + return false; + + NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false); } bool @@ -2567,7 +2814,26 @@ TextInputHandler::DoCommandBySelector(const char* aSelector) // Korean IME sends "insertNewline:" when committing existing composition // with Enter key press. In such case, the key operation has been consumed // by the committing composition but we still need to handle the command. - return Destroyed() || !currentKeyEvent->CanHandleCommand(); + if (Destroyed() || !currentKeyEvent->CanHandleCommand()) { + return true; + } + + // cancelOperation: command is fired after Escape or Command + Period. + // However, if ChildView implements cancelOperation:, calling + // [[ChildView super] doCommandBySelector:aSelector] when Command + Period + // causes only a call of [ChildView cancelOperation:sender]. I.e., + // [ChildView keyDown:theEvent] becomes to be never called. For avoiding + // this odd behavior, we need to handle the command before super class of + // ChildView only when current key event is proper event to fire Escape + // keypress event. + if (!strcmp(aSelector, "cancelOperatiorn:") && currentKeyEvent && + currentKeyEvent->IsProperKeyEvent(CommandCancelOperation)) { + return HandleCommand(CommandCancelOperation); + } + + // Otherwise, we've not handled the command yet. Propagate the command + // to the super class of ChildView. + return false; } diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 1ced0c467c7d..6de61a1c8dfe 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -5599,6 +5599,290 @@ GetIntegerDeltaForEvent(NSEvent* aEvent) } } +- (void) deleteBackward:(id)sender +{ + // Backspace in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandDeleteCharBackward); + } +} + +- (void) deleteBackwardByDecomposingPreviousCharacter:(id)sender +{ + // Ctrl + Backspace in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandDeleteCharBackward); + } +} + +- (void) deleteWordBackward:(id)sender +{ + // Alt + Backspace in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandDeleteWordBackward); + } +} + +- (void) deleteToBeginningOfBackward:(id)sender +{ + // Command + Backspace in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandDeleteToBeginningOfLine); + } +} + +- (void) deleteForward:(id)sender +{ + // Delete in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandDeleteCharForward); + } +} + +- (void) deleteWordForward:(id)sender +{ + // Alt + Delete in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandDeleteWordForward); + } +} + +- (void) insertTab:(id)sender +{ + // Tab in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandInsertTab); + } +} + +- (void) insertBacktab:(id)sender +{ + // Shift + Tab in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandInsertBacktab); + } +} + +- (void) moveRight:(id)sender +{ + // RightArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandCharNext); + } +} + +- (void) moveRightAndModifySelection:(id)sender +{ + // Shift + RightArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectCharNext); + } +} + +- (void) moveWordRight:(id)sender +{ + // Alt + RightArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandWordNext); + } +} + +- (void) moveWordRightAndModifySelection:(id)sender +{ + // Alt + Shift + RightArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectWordNext); + } +} + +- (void) moveToRightEndOfLine:(id)sender +{ + // Command + RightArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandEndLine); + } +} + +- (void) moveToRightEndOfLineAndModifySelection:(id)sender +{ + // Command + Shift + RightArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectEndLine); + } +} + +- (void) moveLeft:(id)sender +{ + // LeftArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandCharPrevious); + } +} + +- (void) moveLeftAndModifySelection:(id)sender +{ + // Shift + LeftArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectCharPrevious); + } +} + +- (void) moveWordLeft:(id)sender +{ + // Alt + LeftArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandWordPrevious); + } +} + +- (void) moveWordLeftAndModifySelection:(id)sender +{ + // Alt + Shift + LeftArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectWordPrevious); + } +} + +- (void) moveToLeftEndOfLine:(id)sender +{ + // Command + LeftArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandBeginLine); + } +} + +- (void) moveToLeftEndOfLineAndModifySelection:(id)sender +{ + // Command + Shift + LeftArrow in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectBeginLine); + } +} + +- (void) moveUp:(id)sender +{ + // ArrowUp in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandLinePrevious); + } +} + +- (void) moveUpAndModifySelection:(id)sender +{ + // Shift + ArrowUp in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectLinePrevious); + } +} + +- (void) moveToBeginningOfDocument:(id)sender +{ + // Command + ArrowUp in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandMoveTop); + } +} + +- (void) moveToBeginningOfDocumentAndModifySelection:(id)sender +{ + // Command + Shift + ArrowUp or Shift + Home in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectTop); + } +} + +- (void) moveDown:(id)sender +{ + // ArrowDown in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandLineNext); + } +} + +- (void) moveDownAndModifySelection:(id)sender +{ + // Shift + ArrowDown in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectLineNext); + } +} + +- (void) moveToEndOfDocument:(id)sender +{ + // Command + ArrowDown in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandMoveBottom); + } +} + +- (void) moveToEndOfDocumentAndModifySelection:(id)sender +{ + // Command + Shift + ArrowDown or Shift + End in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectBottom); + } +} + +- (void) scrollPageUp:(id)sender +{ + // PageUp in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandScrollPageUp); + } +} + +- (void) pageUpAndModifySelection:(id)sender +{ + // Shift + PageUp in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectPageUp); + } +} + +- (void) scrollPageDown:(id)sender +{ + // PageDown in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandScrollPageDown); + } +} + +- (void) pageDownAndModifySelection:(id)sender +{ + // Shift + PageDown in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandSelectPageDown); + } +} + +- (void) scrollToEndOfDocument:(id)sender +{ + // End in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandScrollBottom); + } +} + +- (void) scrollToBeginningOfDocument:(id)sender +{ + // Home in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandScrollTop); + } +} + +// XXX Don't decleare nor implement calcelOperation: because it +// causes not calling keyDown: for Command + Period. +// We need to handle it from doCommandBySelector:. + +- (void) complete:(id)sender +{ + // Alt + Escape or Alt + Shift + Escape in the default settings. + if (mTextInputHandler) { + mTextInputHandler->HandleCommand(CommandComplete); + } +} + - (void)flagsChanged:(NSEvent*)theEvent { NS_OBJC_BEGIN_TRY_ABORT_BLOCK;