зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1051842 - Part 2 - crash in -[ChildView keyDown:]. r=masayuki
In e10s, each nsFocusManger (main/chrome and content/tab) operates on its own content tree with its own InputContext. They also communicate their InputContexts with the OS widget (nsChildView on mac, nsWindow on Windows). Prior to this patch, the OS widgets didn't distinguish between main and content InputContexts. When GetInputContext was called on the OS widget, it would return whatever InputContext it had set last. This patch distinguishes between InputContexts in the widget.
This commit is contained in:
Родитель
645064d99a
Коммит
569529da16
|
@ -16,6 +16,7 @@
|
|||
#include "mozilla/TextComposition.h"
|
||||
#include "mozilla/TextEvents.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
|
||||
#include "HTMLInputElement.h"
|
||||
#include "IMEContentObserver.h"
|
||||
|
@ -388,6 +389,27 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
IMEState newState = GetNewIMEState(aPresContext, aContent);
|
||||
|
||||
// In e10s, remote content may have IME focus. The main process (i.e. this process)
|
||||
// would attempt to set state to DISABLED if, for example, the user clicks
|
||||
// some other remote content. The content process would later re-ENABLE IME, meaning
|
||||
// that all state-changes were unnecessary.
|
||||
// Here we filter the common case where the main process knows that the remote
|
||||
// process controls IME focus. The DISABLED->re-ENABLED progression can
|
||||
// still happen since remote content may be concurrently communicating its claim
|
||||
// on focus to the main process... but this cannot cause bugs like missed keypresses.
|
||||
// (It just means a lot of needless IPC.)
|
||||
if ((newState.mEnabled == IMEState::DISABLED) && TabParent::GetIMETabParent()) {
|
||||
PR_LOG(sISMLog, PR_LOG_DEBUG,
|
||||
("ISM: IMEStateManager::OnChangeFocusInternal(), "
|
||||
"Parent process cancels to set DISABLED state because the content process "
|
||||
"has IME focus and has already sets IME state"));
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"TabParent::GetIMETabParent() should never return non-null value "
|
||||
"in the content process");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!focusActuallyChanging) {
|
||||
// actual focus isn't changing, but if IME enabled state is changing,
|
||||
// we should do it.
|
||||
|
|
|
@ -2028,14 +2028,25 @@ TabParent::RecvSetInputContext(const int32_t& aIMEEnabled,
|
|||
const int32_t& aCause,
|
||||
const int32_t& aFocusChange)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget || !AllowContentIME()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
InputContext oldContext = widget->GetInputContext();
|
||||
|
||||
// Ignore if current widget IME setting is not DISABLED and didn't come
|
||||
// from remote content. Chrome content may have taken over.
|
||||
if (oldContext.mIMEState.mEnabled != IMEState::DISABLED &&
|
||||
oldContext.IsOriginMainProcess()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// mIMETabParent (which is actually static) tracks which if any TabParent has IMEFocus
|
||||
// When the input mode is set to anything but IMEState::DISABLED,
|
||||
// mIMETabParent should be set to this
|
||||
mIMETabParent =
|
||||
aIMEEnabled != static_cast<int32_t>(IMEState::DISABLED) ? this : nullptr;
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
if (!widget || !AllowContentIME())
|
||||
return true;
|
||||
|
||||
InputContext context;
|
||||
context.mIMEState.mEnabled = static_cast<IMEState::Enabled>(aIMEEnabled);
|
||||
|
@ -2043,6 +2054,8 @@ TabParent::RecvSetInputContext(const int32_t& aIMEEnabled,
|
|||
context.mHTMLInputType.Assign(aType);
|
||||
context.mHTMLInputInputmode.Assign(aInputmode);
|
||||
context.mActionHint.Assign(aActionHint);
|
||||
context.mOrigin = InputContext::ORIGIN_CONTENT;
|
||||
|
||||
InputContextAction action(
|
||||
static_cast<InputContextAction::Cause>(aCause),
|
||||
static_cast<InputContextAction::FocusChange>(aFocusChange));
|
||||
|
|
|
@ -410,6 +410,7 @@ struct IMEState {
|
|||
struct InputContext {
|
||||
InputContext()
|
||||
: mNativeIMEContext(nullptr)
|
||||
, mOrigin(XRE_IsParentProcess() ? ORIGIN_MAIN : ORIGIN_CONTENT)
|
||||
{}
|
||||
|
||||
bool IsPasswordEditor() const
|
||||
|
@ -433,6 +434,36 @@ struct InputContext {
|
|||
be nullptr. */
|
||||
void* mNativeIMEContext;
|
||||
|
||||
|
||||
/**
|
||||
* mOrigin indicates whether this focus event refers to main or remote content.
|
||||
*/
|
||||
enum Origin
|
||||
{
|
||||
// Adjusting focus of content on the main process
|
||||
ORIGIN_MAIN,
|
||||
// Adjusting focus of content in a remote process
|
||||
ORIGIN_CONTENT
|
||||
};
|
||||
Origin mOrigin;
|
||||
|
||||
bool IsOriginMainProcess() const
|
||||
{
|
||||
return mOrigin == ORIGIN_MAIN;
|
||||
}
|
||||
|
||||
bool IsOriginContentProcess() const
|
||||
{
|
||||
return mOrigin == ORIGIN_CONTENT;
|
||||
}
|
||||
|
||||
bool IsOriginCurrentProcess() const
|
||||
{
|
||||
if (XRE_IsParentProcess()) {
|
||||
return IsOriginMainProcess();
|
||||
}
|
||||
return IsOriginContentProcess();
|
||||
}
|
||||
};
|
||||
|
||||
struct InputContextAction {
|
||||
|
|
Загрузка…
Ссылка в новой задаче