Bug 1211352 part.1 IMEContentObserver should be created when a plugin has focus r=smaug

This commit is contained in:
Masayuki Nakano 2015-10-10 10:21:01 +09:00
parent 2814f667b7
commit 27b1c48ce9
3 changed files with 151 additions and 63 deletions

View File

@ -218,8 +218,6 @@ IMEContentObserver::Init(nsIWidget* aWidget,
nsIContent* aContent,
nsIEditor* aEditor)
{
MOZ_ASSERT(aEditor, "aEditor must not be null");
State state = GetState();
if (NS_WARN_IF(state == eState_Observing)) {
return; // Nothing to do.
@ -231,10 +229,7 @@ IMEContentObserver::Init(nsIWidget* aWidget,
// should be registered again for simpler implementation.
UnregisterObservers();
// Clear members which may not be initialized again.
mRootContent = nullptr;
mEditor = nullptr;
mSelection = nullptr;
mDocShell = nullptr;
Clear();
}
mESM = aPresContext->EventStateManager();
@ -242,51 +237,17 @@ IMEContentObserver::Init(nsIWidget* aWidget,
mWidget = aWidget;
mEditableNode =
IMEStateManager::GetRootEditableNode(aPresContext, aContent);
if (!mEditableNode) {
return;
}
mEditor = aEditor;
nsIPresShell* presShell = aPresContext->PresShell();
// get selection and root content
nsCOMPtr<nsISelectionController> selCon;
if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) {
nsIFrame* frame =
static_cast<nsIContent*>(mEditableNode.get())->GetPrimaryFrame();
NS_ENSURE_TRUE_VOID(frame);
frame->GetSelectionController(aPresContext,
getter_AddRefs(selCon));
if (aWidget->GetInputContext().mIMEState.mEnabled == IMEState::PLUGIN) {
if (!InitWithPlugin(aPresContext, aContent)) {
Clear();
return;
}
} else {
// mEditableNode is a document
selCon = do_QueryInterface(presShell);
if (!InitWithEditor(aPresContext, aContent, aEditor)) {
Clear();
return;
}
}
NS_ENSURE_TRUE_VOID(selCon);
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(mSelection));
NS_ENSURE_TRUE_VOID(mSelection);
nsCOMPtr<nsIDOMRange> selDomRange;
if (NS_SUCCEEDED(mSelection->GetRangeAt(0, getter_AddRefs(selDomRange)))) {
nsRange* selRange = static_cast<nsRange*>(selDomRange.get());
NS_ENSURE_TRUE_VOID(selRange && selRange->GetStartParent());
mRootContent = selRange->GetStartParent()->
GetSelectionRootContent(presShell);
} else {
mRootContent = mEditableNode->GetSelectionRootContent(presShell);
}
if (!mRootContent && mEditableNode->IsNodeOfType(nsINode::eDOCUMENT)) {
// The document node is editable, but there are no contents, this document
// is not editable.
return;
}
NS_ENSURE_TRUE_VOID(mRootContent);
if (firstInitialization) {
MaybeNotifyIMEOfFocusSet();
@ -307,8 +268,6 @@ IMEContentObserver::Init(nsIWidget* aWidget,
}
}
mDocShell = aPresContext->GetDocShell();
ObserveEditableNode();
// Some change events may wait to notify IME because this was being
@ -316,16 +275,138 @@ IMEContentObserver::Init(nsIWidget* aWidget,
FlushMergeableNotifications();
}
bool
IMEContentObserver::InitWithEditor(nsPresContext* aPresContext,
nsIContent* aContent,
nsIEditor* aEditor)
{
MOZ_ASSERT(aEditor);
mEditableNode =
IMEStateManager::GetRootEditableNode(aPresContext, aContent);
if (NS_WARN_IF(!mEditableNode)) {
return false;
}
mEditor = aEditor;
if (NS_WARN_IF(!mEditor)) {
return false;
}
nsIPresShell* presShell = aPresContext->PresShell();
// get selection and root content
nsCOMPtr<nsISelectionController> selCon;
if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) {
nsIFrame* frame =
static_cast<nsIContent*>(mEditableNode.get())->GetPrimaryFrame();
if (NS_WARN_IF(!frame)) {
return false;
}
frame->GetSelectionController(aPresContext,
getter_AddRefs(selCon));
} else {
// mEditableNode is a document
selCon = do_QueryInterface(presShell);
}
if (NS_WARN_IF(!selCon)) {
return false;
}
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(mSelection));
if (NS_WARN_IF(!mSelection)) {
return false;
}
nsCOMPtr<nsIDOMRange> selDomRange;
if (NS_SUCCEEDED(mSelection->GetRangeAt(0, getter_AddRefs(selDomRange)))) {
nsRange* selRange = static_cast<nsRange*>(selDomRange.get());
if (NS_WARN_IF(!selRange) || NS_WARN_IF(!selRange->GetStartParent())) {
return false;
}
mRootContent = selRange->GetStartParent()->
GetSelectionRootContent(presShell);
} else {
mRootContent = mEditableNode->GetSelectionRootContent(presShell);
}
if (!mRootContent && mEditableNode->IsNodeOfType(nsINode::eDOCUMENT)) {
// The document node is editable, but there are no contents, this document
// is not editable.
return false;
}
if (NS_WARN_IF(!mRootContent)) {
return false;
}
mDocShell = aPresContext->GetDocShell();
if (NS_WARN_IF(!mDocShell)) {
return false;
}
return true;
}
bool
IMEContentObserver::InitWithPlugin(nsPresContext* aPresContext,
nsIContent* aContent)
{
if (NS_WARN_IF(!aContent) ||
NS_WARN_IF(aContent->GetDesiredIMEState().mEnabled != IMEState::PLUGIN)) {
return false;
}
nsIFrame* frame = aContent->GetPrimaryFrame();
if (NS_WARN_IF(!frame)) {
return false;
}
nsCOMPtr<nsISelectionController> selCon;
frame->GetSelectionController(aPresContext, getter_AddRefs(selCon));
if (NS_WARN_IF(!selCon)) {
return false;
}
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
getter_AddRefs(mSelection));
if (NS_WARN_IF(!mSelection)) {
return false;
}
mEditor = nullptr;
mEditableNode = aContent;
mRootContent = aContent;
mDocShell = aPresContext->GetDocShell();
if (NS_WARN_IF(!mDocShell)) {
return false;
}
return true;
}
void
IMEContentObserver::Clear()
{
mEditor = nullptr;
mSelection = nullptr;
mEditableNode = nullptr;
mRootContent = nullptr;
mDocShell = nullptr;
}
void
IMEContentObserver::ObserveEditableNode()
{
MOZ_RELEASE_ASSERT(mEditor);
MOZ_RELEASE_ASSERT(mSelection);
MOZ_RELEASE_ASSERT(mRootContent);
MOZ_RELEASE_ASSERT(GetState() != eState_Observing);
mIsObserving = true;
mEditor->AddEditorObserver(this);
if (mEditor) {
mEditor->AddEditorObserver(this);
}
mUpdatePreference = mWidget->GetIMEUpdatePreference();
if (mUpdatePreference.WantSelectionChange()) {
@ -430,13 +511,9 @@ IMEContentObserver::Destroy()
NotifyIMEOfBlur();
UnregisterObservers();
Clear();
mEditor = nullptr;
mWidget = nullptr;
mSelection = nullptr;
mRootContent = nullptr;
mEditableNode = nullptr;
mDocShell = nullptr;
mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
if (mESM) {
@ -492,8 +569,10 @@ bool
IMEContentObserver::IsObservingContent(nsPresContext* aPresContext,
nsIContent* aContent) const
{
return mEditableNode == IMEStateManager::GetRootEditableNode(aPresContext,
aContent);
return IsInitializedWithPlugin() ?
mRootContent == aContent && mRootContent != nullptr :
mEditableNode == IMEStateManager::GetRootEditableNode(aPresContext,
aContent);
}
bool

View File

@ -113,6 +113,11 @@ private:
eState_Observing
};
State GetState() const;
bool InitWithEditor(nsPresContext* aPresContext, nsIContent* aContent,
nsIEditor* aEditor);
bool InitWithPlugin(nsPresContext* aPresContext, nsIContent* aContent);
bool IsInitializedWithPlugin() const { return !mEditor; }
void Clear();
bool IsObservingContent(nsPresContext* aPresContext,
nsIContent* aContent) const;
bool IsReflowLocked() const;

View File

@ -510,8 +510,12 @@ IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
sPresContext = aPresContext;
sContent = aContent;
// Don't call CreateIMEContentObserver() here, it should be called from
// focus event handler of editor.
// Don't call CreateIMEContentObserver() here except when a plugin gets
// focus because it will be called from the focus event handler of focused
// editor.
if (newState.mEnabled == IMEState::PLUGIN) {
CreateIMEContentObserver(nullptr);
}
return NS_OK;
}
@ -1515,7 +1519,7 @@ IMEStateManager::GetRootEditableNode(nsPresContext* aPresContext,
bool
IMEStateManager::IsIMEObserverNeeded(const IMEState& aState)
{
return aState.IsEditable();
return aState.MaybeEditable();
}
// static