зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1388647 - part2: Make IMEInputHandler of Cocoa widget handle request to commit/cancel composition synchronously r=m_kato
When Gecko started to support Cocoa widget, we needed to use NSInputManager. That allowed applications to access only focused IME context. Therefore, commit composition request handler for Cocoa is designed as handling asynchronosly if it's requested when the window is not active or is being inactivated. Additionally, the asynchronous handling isn't perfect. We hit some MOZ_ASSERT() now in some places. E.g., in SelectedRange(), it doesn't assume that it's called during deactive. On the other hand, NSInputManager was alreay obsolete and we already stopped using it (bug 810225). Instead, we're using NSTextInputContext and it allows applications to access IME anytime. Therefore, if we make IMEInputHandler handles commit/cancel composition requests synchronsly, that behaves same as the other platforms. So, we can get rid of macOS specific issue completely. MozReview-Commit-ID: X7aWmGq95x --HG-- extra : rebase_source : a472a03e3ef6f424fe73c2d438b8326bed80278d
This commit is contained in:
Родитель
9467d56cf9
Коммит
5345065a53
|
@ -917,14 +917,6 @@ public:
|
|||
bool IsASCIICapableOnly() { return mIsASCIICapableOnly; }
|
||||
bool IgnoreIMECommit() { return mIgnoreIMECommit; }
|
||||
|
||||
bool IgnoreIMEComposition()
|
||||
{
|
||||
// Ignore the IME composition events when we're pending to discard the
|
||||
// composition and we are not to handle the IME composition now.
|
||||
return (mPendingMethods & kDiscardIMEComposition) &&
|
||||
(mIsInFocusProcessing || !IsFocused());
|
||||
}
|
||||
|
||||
void CommitIMEComposition();
|
||||
void CancelIMEComposition();
|
||||
|
||||
|
@ -951,8 +943,7 @@ protected:
|
|||
nsCOMPtr<nsITimer> mTimer;
|
||||
enum {
|
||||
kNotifyIMEOfFocusChangeInGecko = 1,
|
||||
kDiscardIMEComposition = 2,
|
||||
kSyncASCIICapableOnly = 4
|
||||
kSyncASCIICapableOnly = 2
|
||||
};
|
||||
uint32_t mPendingMethods;
|
||||
|
||||
|
@ -990,11 +981,6 @@ private:
|
|||
bool mIsIMEEnabled;
|
||||
bool mIsASCIICapableOnly;
|
||||
bool mIgnoreIMECommit;
|
||||
// This flag is enabled by OnFocusChangeInGecko, and will be cleared by
|
||||
// ExecutePendingMethods. When this is true, IsFocus() returns TRUE. At
|
||||
// that time, the focus processing in Gecko might not be finished yet. So,
|
||||
// you cannot use WidgetQueryContentEvent or something.
|
||||
bool mIsInFocusProcessing;
|
||||
bool mIMEHasFocus;
|
||||
|
||||
void KillIMEComposition();
|
||||
|
@ -1003,7 +989,6 @@ private:
|
|||
|
||||
// Pending methods
|
||||
void NotifyIMEOfFocusChangeInGecko();
|
||||
void DiscardIMEComposition();
|
||||
void SyncASCIICapableOnly();
|
||||
|
||||
static bool sStaticMembersInitialized;
|
||||
|
|
|
@ -2185,13 +2185,13 @@ TextInputHandler::InsertText(NSAttributedString* aAttrString,
|
|||
MOZ_LOG(gLog, LogLevel::Info,
|
||||
("%p TextInputHandler::InsertText, aAttrString=\"%s\", "
|
||||
"aReplacementRange=%p { location=%lu, length=%lu }, "
|
||||
"IsIMEComposing()=%s, IgnoreIMEComposition()=%s, "
|
||||
"IsIMEComposing()=%s, "
|
||||
"keyevent=%p, keydownHandled=%s, keypressDispatched=%s, "
|
||||
"causedOtherKeyEvents=%s, compositionDispatched=%s",
|
||||
this, GetCharacters([aAttrString string]), aReplacementRange,
|
||||
static_cast<unsigned long>(aReplacementRange ? aReplacementRange->location : 0),
|
||||
static_cast<unsigned long>(aReplacementRange ? aReplacementRange->length : 0),
|
||||
TrueOrFalse(IsIMEComposing()), TrueOrFalse(IgnoreIMEComposition()),
|
||||
TrueOrFalse(IsIMEComposing()),
|
||||
currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
|
||||
currentKeyEvent ?
|
||||
TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
|
||||
|
@ -2202,10 +2202,6 @@ TextInputHandler::InsertText(NSAttributedString* aAttrString,
|
|||
currentKeyEvent ?
|
||||
TrueOrFalse(currentKeyEvent->mCompositionDispatched) : "N/A"));
|
||||
|
||||
if (IgnoreIMEComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
InputContext context = mWidget->GetInputContext();
|
||||
bool isEditable = (context.mIMEState.mEnabled == IMEState::ENABLED ||
|
||||
context.mIMEState.mEnabled == IMEState::PASSWORD);
|
||||
|
@ -2367,10 +2363,10 @@ TextInputHandler::InsertNewline()
|
|||
|
||||
MOZ_LOG(gLog, LogLevel::Info,
|
||||
("%p TextInputHandler::InsertNewline, "
|
||||
"IsIMEComposing()=%s, IgnoreIMEComposition()=%s, "
|
||||
"IsIMEComposing()=%s, "
|
||||
"keyevent=%p, keydownHandled=%s, keypressDispatched=%s, "
|
||||
"causedOtherKeyEvents=%s, compositionDispatched=%s",
|
||||
this, TrueOrFalse(IsIMEComposing()), TrueOrFalse(IgnoreIMEComposition()),
|
||||
this, TrueOrFalse(IsIMEComposing()),
|
||||
currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
|
||||
currentKeyEvent ?
|
||||
TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
|
||||
|
@ -2381,10 +2377,6 @@ TextInputHandler::InsertNewline()
|
|||
currentKeyEvent ?
|
||||
TrueOrFalse(currentKeyEvent->mCompositionDispatched) : "N/A"));
|
||||
|
||||
if (IgnoreIMEComposition()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If "insertNewline:" command shouldn't be handled, let's ignore it.
|
||||
if (currentKeyEvent && !currentKeyEvent->CanHandleCommand()) {
|
||||
return;
|
||||
|
@ -2870,37 +2862,6 @@ IMEInputHandler::NotifyIMEOfFocusChangeInGecko()
|
|||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
void
|
||||
IMEInputHandler::DiscardIMEComposition()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
MOZ_LOG(gLog, LogLevel::Info,
|
||||
("%p IMEInputHandler::DiscardIMEComposition, "
|
||||
"Destroyed()=%s, IsFocused()=%s, mView=%p, inputContext=%p",
|
||||
this, TrueOrFalse(Destroyed()), TrueOrFalse(IsFocused()),
|
||||
mView, mView ? [mView inputContext] : nullptr));
|
||||
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsFocused()) {
|
||||
// retry at next focus event
|
||||
mPendingMethods |= kDiscardIMEComposition;
|
||||
return;
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE_VOID(mView);
|
||||
NSTextInputContext* inputContext = [mView inputContext];
|
||||
NS_ENSURE_TRUE_VOID(inputContext);
|
||||
mIgnoreIMECommit = true;
|
||||
[inputContext discardMarkedText];
|
||||
mIgnoreIMECommit = false;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK
|
||||
}
|
||||
|
||||
void
|
||||
IMEInputHandler::SyncASCIICapableOnly()
|
||||
{
|
||||
|
@ -2974,7 +2935,6 @@ IMEInputHandler::ExecutePendingMethods()
|
|||
}
|
||||
|
||||
if (![[NSApplication sharedApplication] isActive]) {
|
||||
mIsInFocusProcessing = false;
|
||||
// If we're not active, we should retry at focus event
|
||||
return;
|
||||
}
|
||||
|
@ -2984,16 +2944,12 @@ IMEInputHandler::ExecutePendingMethods()
|
|||
// run now, they can reentry to the pending flags by theirselves.
|
||||
mPendingMethods = 0;
|
||||
|
||||
if (pendingMethods & kDiscardIMEComposition)
|
||||
DiscardIMEComposition();
|
||||
if (pendingMethods & kSyncASCIICapableOnly)
|
||||
SyncASCIICapableOnly();
|
||||
if (pendingMethods & kNotifyIMEOfFocusChangeInGecko) {
|
||||
NotifyIMEOfFocusChangeInGecko();
|
||||
}
|
||||
|
||||
mIsInFocusProcessing = false;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
|
@ -3417,7 +3373,7 @@ IMEInputHandler::SetMarkedText(NSAttributedString* aAttrString,
|
|||
("%p IMEInputHandler::SetMarkedText, "
|
||||
"aAttrString=\"%s\", aSelectedRange={ location=%lu, length=%lu }, "
|
||||
"aReplacementRange=%p { location=%lu, length=%lu }, "
|
||||
"Destroyed()=%s, IgnoreIMEComposition()=%s, IsIMEComposing()=%s, "
|
||||
"Destroyed()=%s, IsIMEComposing()=%s, "
|
||||
"mMarkedRange={ location=%lu, length=%lu }, keyevent=%p, "
|
||||
"keydownHandled=%s, keypressDispatched=%s, causedOtherKeyEvents=%s, "
|
||||
"compositionDispatched=%s",
|
||||
|
@ -3426,8 +3382,7 @@ IMEInputHandler::SetMarkedText(NSAttributedString* aAttrString,
|
|||
static_cast<unsigned long>(aSelectedRange.length), aReplacementRange,
|
||||
static_cast<unsigned long>(aReplacementRange ? aReplacementRange->location : 0),
|
||||
static_cast<unsigned long>(aReplacementRange ? aReplacementRange->length : 0),
|
||||
TrueOrFalse(Destroyed()), TrueOrFalse(IgnoreIMEComposition()),
|
||||
TrueOrFalse(IsIMEComposing()),
|
||||
TrueOrFalse(Destroyed()), TrueOrFalse(IsIMEComposing()),
|
||||
static_cast<unsigned long>(mMarkedRange.location),
|
||||
static_cast<unsigned long>(mMarkedRange.length),
|
||||
currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
|
||||
|
@ -3447,7 +3402,7 @@ IMEInputHandler::SetMarkedText(NSAttributedString* aAttrString,
|
|||
currentKeyEvent->mCompositionDispatched = true;
|
||||
}
|
||||
|
||||
if (Destroyed() || IgnoreIMEComposition()) {
|
||||
if (Destroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3912,7 +3867,6 @@ IMEInputHandler::IMEInputHandler(nsChildView* aWidget,
|
|||
, mIsIMEEnabled(true)
|
||||
, mIsASCIICapableOnly(false)
|
||||
, mIgnoreIMECommit(false)
|
||||
, mIsInFocusProcessing(false)
|
||||
, mIMEHasFocus(false)
|
||||
{
|
||||
InitStaticMembers();
|
||||
|
@ -3958,7 +3912,6 @@ IMEInputHandler::OnFocusChangeInGecko(bool aFocus)
|
|||
}
|
||||
|
||||
sFocusedIMEHandler = this;
|
||||
mIsInFocusProcessing = true;
|
||||
|
||||
// We need to notify IME of focus change in Gecko as native focus change
|
||||
// because the window level of the focused element in Gecko may be changed.
|
||||
|
@ -4051,26 +4004,15 @@ IMEInputHandler::KillIMEComposition()
|
|||
TrueOrFalse(mIsIMEComposing), TrueOrFalse(Destroyed()),
|
||||
TrueOrFalse(IsFocused())));
|
||||
|
||||
if (Destroyed()) {
|
||||
if (Destroyed() || NS_WARN_IF(!mView)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsFocused()) {
|
||||
NS_ENSURE_TRUE_VOID(mView);
|
||||
NSTextInputContext* inputContext = [mView inputContext];
|
||||
NS_ENSURE_TRUE_VOID(inputContext);
|
||||
[inputContext discardMarkedText];
|
||||
NSTextInputContext* inputContext = [mView inputContext];
|
||||
if (NS_WARN_IF(!inputContext)) {
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_LOG(gLog, LogLevel::Info,
|
||||
("%p IMEInputHandler::KillIMEComposition, Pending...", this));
|
||||
|
||||
// Commit the composition internally.
|
||||
SendCommittedText(mIMECompositionString);
|
||||
NS_ASSERTION(!mIsIMEComposing, "We're still in a composition");
|
||||
// The pending method will be fired by the next focus event.
|
||||
mPendingMethods |= kDiscardIMEComposition;
|
||||
[inputContext discardMarkedText];
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче