mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-17 06:09:19 +00:00
Bug 1403759 - part 1: Make TextInputHandler::InsertNewline() treat other commands r=m_kato
Currently, we handle insertNewline: of NSResponder with TextInputHandler::InsertNewline(). However, its implementation is useful for handling some other commands. So, let's rename it to HandleCommand() and make it take Command as its argument for handling specific behavior of each command. MozReview-Commit-ID: GgzQdTlVtYl --HG-- extra : rebase_source : e1d1c8617897d29eb10ba62708e3549a77c6ee59
This commit is contained in:
parent
4bed737a12
commit
d7ecd695d3
@ -22,6 +22,8 @@ NS_DEFINE_COMMAND(DeleteToEndOfLine, cmd_deleteToEndOfLine)
|
||||
NS_DEFINE_COMMAND(DeleteWordBackward, cmd_deleteWordBackward)
|
||||
NS_DEFINE_COMMAND(DeleteWordForward, cmd_deleteWordForward)
|
||||
NS_DEFINE_COMMAND(EndLine, cmd_endLine)
|
||||
NS_DEFINE_COMMAND(InsertParagraph, cmd_insertParagraph)
|
||||
NS_DEFINE_COMMAND(InsertLineBreak, cmd_insertLineBreak)
|
||||
NS_DEFINE_COMMAND(LineNext, cmd_lineNext)
|
||||
NS_DEFINE_COMMAND(LinePrevious, cmd_linePrevious)
|
||||
NS_DEFINE_COMMAND(MoveBottom, cmd_moveBottom)
|
||||
|
@ -124,6 +124,8 @@ enum Command : CommandInt
|
||||
};
|
||||
#undef NS_DEFINE_COMMAND
|
||||
|
||||
const char* ToChar(Command aCommand);
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
|
@ -85,6 +85,28 @@ ToString(CodeNameIndex aCodeNameIndex)
|
||||
return NS_ConvertUTF16toUTF8(codeName);
|
||||
}
|
||||
|
||||
const char*
|
||||
ToChar(Command aCommand)
|
||||
{
|
||||
if (aCommand == CommandDoNothing) {
|
||||
return "CommandDoNothing";
|
||||
}
|
||||
|
||||
switch (aCommand) {
|
||||
|
||||
#define NS_DEFINE_COMMAND(aName, aCommandStr) \
|
||||
case Command##aName: \
|
||||
return "Command" #aName;
|
||||
|
||||
#include "mozilla/CommandList.h"
|
||||
|
||||
#undef NS_DEFINE_COMMAND
|
||||
|
||||
default:
|
||||
return "illegal command value";
|
||||
}
|
||||
}
|
||||
|
||||
const nsCString
|
||||
GetDOMKeyCodeName(uint32_t aKeyCode)
|
||||
{
|
||||
|
@ -1160,13 +1160,9 @@ public:
|
||||
NSRange* aReplacementRange = nullptr);
|
||||
|
||||
/**
|
||||
* Handles "insertNewline:" command. Due to bug 1350541, this always
|
||||
* dispatches a keypress event of Enter key unless there is composition.
|
||||
* If it's handling Enter key event, this dispatches "actual" Enter
|
||||
* keypress event. Otherwise, dispatches "fake" Enter keypress event
|
||||
* whose code value is unidentified.
|
||||
* Handles aCommand. This may cause dispatching an eKeyPress event.
|
||||
*/
|
||||
void InsertNewline();
|
||||
void HandleCommand(Command aCommand);
|
||||
|
||||
/**
|
||||
* doCommandBySelector event handler.
|
||||
|
@ -2351,7 +2351,7 @@ TextInputHandler::InsertText(NSAttributedString* aAttrString,
|
||||
}
|
||||
|
||||
void
|
||||
TextInputHandler::InsertNewline()
|
||||
TextInputHandler::HandleCommand(Command aCommand)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
@ -2362,11 +2362,11 @@ TextInputHandler::InsertNewline()
|
||||
KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
|
||||
|
||||
MOZ_LOG(gLog, LogLevel::Info,
|
||||
("%p TextInputHandler::InsertNewline, "
|
||||
"IsIMEComposing()=%s, "
|
||||
("%p TextInputHandler::HandleCommand, "
|
||||
"aCommand=%s, IsIMEComposing()=%s, "
|
||||
"keyevent=%p, keydownHandled=%s, keypressDispatched=%s, "
|
||||
"causedOtherKeyEvents=%s, compositionDispatched=%s",
|
||||
this, TrueOrFalse(IsIMEComposing()),
|
||||
this, ToChar(aCommand), TrueOrFalse(IsIMEComposing()),
|
||||
currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
|
||||
currentKeyEvent ?
|
||||
TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
|
||||
@ -2383,68 +2383,90 @@ TextInputHandler::InsertNewline()
|
||||
}
|
||||
|
||||
// If it's in composition, we cannot dispatch keypress event.
|
||||
// Therefore, we should insert '\n' as committing composition.
|
||||
// Therefore, we should use different approach or give up to handle
|
||||
// the command.
|
||||
if (IsIMEComposing()) {
|
||||
NSAttributedString* lineBreaker =
|
||||
[[NSAttributedString alloc] initWithString:@"\n"];
|
||||
InsertTextAsCommittingComposition(lineBreaker, nullptr);
|
||||
if (currentKeyEvent) {
|
||||
currentKeyEvent->mCompositionDispatched = true;
|
||||
switch (aCommand) {
|
||||
case CommandInsertLineBreak:
|
||||
case CommandInsertParagraph: {
|
||||
// Insert '\n' as committing composition.
|
||||
// Otherwise, we need to dispatch keypress event because HTMLEditor
|
||||
// doesn't treat "\n" in composition string as a line break unless
|
||||
// the whitespace is treated as pre (see bug 1350541). In strictly
|
||||
// speaking, we should dispatch keypress event as-is if it's handling
|
||||
// NSKeyDown event or should insert it with committing composition.
|
||||
NSAttributedString* lineBreaker =
|
||||
[[NSAttributedString alloc] initWithString:@"\n"];
|
||||
InsertTextAsCommittingComposition(lineBreaker, nullptr);
|
||||
if (currentKeyEvent) {
|
||||
currentKeyEvent->mCompositionDispatched = true;
|
||||
}
|
||||
[lineBreaker release];
|
||||
return;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
[lineBreaker release];
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we need to dispatch keypress event because HTMLEditor doesn't
|
||||
// treat "\n" in composition string as a line break unless the whitespace is
|
||||
// treated as pre (see bug 1350541). In strictly speaking, we should
|
||||
// dispatch keypress event as-is if it's handling NSKeyDown event or
|
||||
// should insert it with committing composition.
|
||||
|
||||
RefPtr<nsChildView> widget(mWidget);
|
||||
nsresult rv = mDispatcher->BeginNativeInputTransaction();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
MOZ_LOG(gLog, LogLevel::Error,
|
||||
("%p, IMEInputHandler::InsertNewline, "
|
||||
("%p, IMEInputHandler::HandleCommand, "
|
||||
"FAILED, due to BeginNativeInputTransaction() failure", this));
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: If it's not Enter keypress but user customized the OS settings
|
||||
// to insert a line breaker with other key, we should just set
|
||||
// TODO: If it's not appropriate keypress but user customized the OS
|
||||
// settings to do the command with other key, we should just set
|
||||
// command to the keypress event and it should be handled as
|
||||
// Enter key press in editor.
|
||||
// the key press in editor.
|
||||
|
||||
// If it's handling actual Enter key event and hasn't cause any composition
|
||||
// If it's handling actual key event and hasn't cause any composition
|
||||
// events nor other key events, we should expose actual modifier state.
|
||||
// Otherwise, we should remove Control, Option and Command state since
|
||||
// editor may behave differently if some of them are active. Although,
|
||||
// Shift+Enter and Enter are work differently in HTML editor, we should
|
||||
// expose actual Shift state if it's caused by Enter key for compatibility
|
||||
// with Chromium. Chromium breaks line in HTML editor with default pargraph
|
||||
// separator when Enter is pressed, with <br> element when Shift+Enter.
|
||||
// Safari breaks line in HTML editor with default paragraph separator when
|
||||
// Enter, Shift+Enter or Option+Enter. So, we should not change Shift+Enter
|
||||
// meaning when there was composition string or not.
|
||||
// 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->CanDispatchKeyPressEvent());
|
||||
|
||||
WidgetKeyboardEvent keypressEvent(true, eKeyPress, widget);
|
||||
if (!dispatchFakeKeyPress) {
|
||||
// If we're acutally handling an Enter key press, we should dispatch
|
||||
// Enter keypress event as-is.
|
||||
// If we're acutally handling a key press, we should dispatch
|
||||
// the keypress event as-is.
|
||||
currentKeyEvent->InitKeyEvent(this, keypressEvent);
|
||||
} else {
|
||||
// Otherwise, we should dispatch "fake" Enter keypress event.
|
||||
// In this case, we shouldn't set code value to "Enter".
|
||||
NSEvent* keyEvent = currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr;
|
||||
nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent);
|
||||
keypressEvent.mKeyCode = NS_VK_RETURN;
|
||||
keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_Enter;
|
||||
keypressEvent.mModifiers &= ~(MODIFIER_CONTROL |
|
||||
MODIFIER_ALT |
|
||||
MODIFIER_META);
|
||||
// Otherwise, we should dispatch "fake" keypress event.
|
||||
switch (aCommand) {
|
||||
case CommandInsertLineBreak:
|
||||
case CommandInsertParagraph: {
|
||||
// Although, Shift+Enter and Enter are work differently in HTML
|
||||
// editor, we should expose actual Shift state if it's caused by
|
||||
// Enter key for compatibility with Chromium. Chromium breaks
|
||||
// line in HTML editor with default pargraph separator when Enter
|
||||
// is pressed, with <br> element when Shift+Enter. Safari breaks
|
||||
// line in HTML editor with default paragraph separator when
|
||||
// Enter, Shift+Enter or Option+Enter. So, we should not change
|
||||
// Shift+Enter meaning when there was composition string or not.
|
||||
NSEvent* keyEvent =
|
||||
currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr;
|
||||
nsCocoaUtils::InitInputEvent(keypressEvent, keyEvent);
|
||||
keypressEvent.mKeyCode = NS_VK_RETURN;
|
||||
keypressEvent.mKeyNameIndex = KEY_NAME_INDEX_Enter;
|
||||
keypressEvent.mModifiers &= ~(MODIFIER_CONTROL |
|
||||
MODIFIER_ALT |
|
||||
MODIFIER_META);
|
||||
if (aCommand == CommandInsertLineBreak) {
|
||||
// In default settings, Ctrl + Enter causes insertLineBreak command.
|
||||
// So, let's make Ctrl state active of the keypress event.
|
||||
keypressEvent.mModifiers |= MODIFIER_CONTROL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
|
@ -5587,7 +5587,15 @@ GetIntegerDeltaForEvent(NSEvent* aEvent)
|
||||
- (void)insertNewline:(id)sender
|
||||
{
|
||||
if (mTextInputHandler) {
|
||||
mTextInputHandler->InsertNewline();
|
||||
mTextInputHandler->HandleCommand(CommandInsertParagraph);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)insertLineBreak:(id)sender
|
||||
{
|
||||
// Ctrl + Enter in the default settings.
|
||||
if (mTextInputHandler) {
|
||||
mTextInputHandler->HandleCommand(CommandInsertLineBreak);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user