Bug 968647 - Part 1. Add position change notification for IME. r=roc

This commit is contained in:
Makoto Kato 2014-02-28 16:45:01 +09:00
parent 9f33df0dac
commit 4d1a05b05d
8 changed files with 174 additions and 4 deletions

View File

@ -37,6 +37,7 @@ XPIDL_MODULE = 'docshell'
EXPORTS += [
'nsDocShellLoadTypes.h',
'nsILinkHandler.h',
'nsIScrollObserver.h',
'nsIWebShellServices.h',
'SerializedLoadContext.h',
]

View File

@ -67,6 +67,7 @@
#include "nsITimedChannel.h"
#include "nsIPrivacyTransitionObserver.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
#include "nsIDocShellTreeItem.h"
#include "nsIChannel.h"
#include "IHistory.h"
@ -2857,6 +2858,39 @@ nsDocShell::GetCurrentDocChannel()
return nullptr;
}
NS_IMETHODIMP
nsDocShell::AddWeakScrollObserver(nsIScrollObserver* aObserver)
{
nsWeakPtr weakObs = do_GetWeakReference(aObserver);
if (!weakObs) {
return NS_ERROR_FAILURE;
}
return mScrollObservers.AppendElement(weakObs) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocShell::RemoveWeakScrollObserver(nsIScrollObserver* aObserver)
{
nsWeakPtr obs = do_GetWeakReference(aObserver);
return mScrollObservers.RemoveElement(obs) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDocShell::NotifyScrollObservers()
{
nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
while (iter.HasMore()) {
nsWeakPtr ref = iter.GetNext();
nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
if (obs) {
obs->ScrollPositionChanged();
} else {
mScrollObservers.RemoveElement(ref);
}
}
return NS_OK;
}
//*****************************************************************************
// nsDocShell::nsIDocShellTreeItem
//*****************************************************************************

View File

@ -900,6 +900,7 @@ private:
nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
nsTObserverArray<nsWeakPtr> mReflowObservers;
nsTObserverArray<nsWeakPtr> mScrollObservers;
nsCString mOriginalUriString;
// Separate function to do the actual name (i.e. not _top, _self etc.)

View File

@ -41,10 +41,11 @@ interface nsIWebBrowserPrint;
interface nsIVariant;
interface nsIPrivacyTransitionObserver;
interface nsIReflowObserver;
interface nsIScrollObserver;
typedef unsigned long nsLoadFlags;
[scriptable, builtinclass, uuid(d0eaef67-4234-47de-b05a-9c7b324eb4f4)]
[scriptable, builtinclass, uuid(e46d924d-c20f-4add-8cf5-1e1c817b2181)]
interface nsIDocShell : nsIDocShellTreeItem
{
/**
@ -667,6 +668,24 @@ interface nsIDocShell : nsIDocShellTreeItem
in DOMHighResTimeStamp start,
in DOMHighResTimeStamp end);
/**
* Add an observer to the list of parties to be notified when scroll position
* of some elements is changed.
*/
[noscript] void addWeakScrollObserver(in nsIScrollObserver obs);
/**
* Add an observer to the list of parties to be notified when scroll position
* of some elements is changed.
*/
[noscript] void removeWeakScrollObserver(in nsIScrollObserver obs);
/**
* Notify all attached observers that the scroll position of some element
* has changed.
*/
[noscript] void notifyScrollObservers();
/**
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
* (<iframe mozapp mozbrowser> is not considered a browser.)

View File

@ -0,0 +1,28 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsIScrollObserver_h___
#define nsIScrollObserver_h___
#include "nsISupports.h"
#define NS_ISCROLLOBSERVER_IID \
{ 0x7c1a8b63, 0xe322, 0x4827, \
{ 0xa4, 0xb1, 0x3b, 0x6e, 0x59, 0x03, 0x47, 0x7e } }
class nsIScrollObserver : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLOBSERVER_IID)
/**
* Called when the scroll position of some element has changed.
*/
virtual void ScrollPositionChanged() = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScrollObserver, NS_ISCROLLOBSERVER_IID)
#endif /* nsIScrollObserver_h___ */

View File

@ -35,6 +35,10 @@
#include "TextComposition.h"
#include "mozilla/Preferences.h"
#include "nsAsyncDOMEvent.h"
#include "nsIDocShell.h"
#include "nsIReflowObserver.h"
#include "nsIScrollObserver.h"
#include "nsWeakReference.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -46,7 +50,10 @@ using namespace mozilla::widget;
// sTextStateObserver is null if there is no focused editor
class nsTextStateManager MOZ_FINAL : public nsISelectionListener,
public nsStubMutationObserver
public nsStubMutationObserver,
public nsIReflowObserver,
public nsIScrollObserver,
public nsSupportsWeakReference
{
public:
nsTextStateManager()
@ -61,6 +68,10 @@ public:
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
NS_DECL_NSIREFLOWOBSERVER
// nsIScrollObserver
virtual void ScrollPositionChanged() MOZ_OVERRIDE;
void Init(nsIWidget* aWidget,
nsPresContext* aPresContext,
@ -82,6 +93,7 @@ private:
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
void ObserveEditableNode();
nsCOMPtr<nsIDocShell> mDocShell;
nsIMEUpdatePreference mUpdatePreference;
uint32_t mPreAttrChangeLength;
};
@ -752,6 +764,8 @@ nsTextStateManager::Init(nsIWidget* aWidget,
return;
}
mDocShell = aPresContext->GetDocShell();
ObserveEditableNode();
}
@ -774,6 +788,13 @@ nsTextStateManager::ObserveEditableNode()
// add text change observer
mRootContent->AddMutationObserver(this);
}
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
// Add scroll position listener and reflow observer to detect position and
// size changes
mDocShell->AddWeakScrollObserver(this);
mDocShell->AddWeakReflowObserver(this);
}
}
void
@ -800,8 +821,13 @@ nsTextStateManager::Destroy(void)
if (mUpdatePreference.WantTextChange() && mRootContent) {
mRootContent->RemoveMutationObserver(this);
}
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
mDocShell->RemoveWeakScrollObserver(this);
mDocShell->RemoveWeakReflowObserver(this);
}
mRootContent = nullptr;
mEditableNode = nullptr;
mDocShell = nullptr;
mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
}
@ -833,9 +859,12 @@ nsTextStateManager::IsEditorHandlingEventForComposition() const
return composition->IsEditorHandlingEvent();
}
NS_IMPL_ISUPPORTS2(nsTextStateManager,
NS_IMPL_ISUPPORTS5(nsTextStateManager,
nsIMutationObserver,
nsISelectionListener)
nsISelectionListener,
nsIReflowObserver,
nsIScrollObserver,
nsISupportsWeakReference)
// Helper class, used for selection change notification
class SelectionChangeEvent : public nsRunnable {
@ -917,6 +946,54 @@ private:
bool mCausedByComposition;
};
class PositionChangeEvent MOZ_FINAL : public nsRunnable
{
public:
PositionChangeEvent(nsTextStateManager* aDispatcher)
: mDispatcher(aDispatcher) {
MOZ_ASSERT(mDispatcher);
}
NS_IMETHOD Run() {
if (mDispatcher->mWidget) {
mDispatcher->mWidget->NotifyIME(
IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
}
return NS_OK;
}
private:
nsRefPtr<nsTextStateManager> mDispatcher;
};
void
nsTextStateManager::ScrollPositionChanged()
{
if (mWidget) {
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
}
}
NS_IMETHODIMP
nsTextStateManager::Reflow(DOMHighResTimeStamp aStart,
DOMHighResTimeStamp aEnd)
{
if (mWidget) {
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
}
return NS_OK;
}
NS_IMETHODIMP
nsTextStateManager::ReflowInterruptible(DOMHighResTimeStamp aStart,
DOMHighResTimeStamp aEnd)
{
if (mWidget) {
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
}
return NS_OK;
}
void
nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
nsIContent* aContent,

View File

@ -2085,6 +2085,8 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
for (uint32_t i = 0; i < mListeners.Length(); i++) {
mListeners[i]->ScrollPositionDidChange(pt.x, pt.y);
}
presContext->GetDocShell()->NotifyScrollObservers();
}
static void

View File

@ -226,6 +226,7 @@ struct nsIMEUpdatePreference {
NOTIFY_NOTHING = 0,
NOTIFY_SELECTION_CHANGE = 1 << 0,
NOTIFY_TEXT_CHANGE = 1 << 1,
NOTIFY_POSITION_CHANGE = 1 << 2,
// Following values indicate when widget needs or doesn't need notification.
NOTIFY_CHANGES_CAUSED_BY_COMPOSITION = 1 << 6,
// NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
@ -264,6 +265,11 @@ struct nsIMEUpdatePreference {
return !!(mWantUpdates & NOTIFY_TEXT_CHANGE);
}
bool WantPositionChanged() const
{
return !!(mWantUpdates & NOTIFY_POSITION_CHANGE);
}
bool WantChanges() const
{
return WantSelectionChange() || WantTextChange();
@ -492,6 +498,8 @@ enum IMEMessage MOZ_ENUM_TYPE(int8_t)
NOTIFY_IME_OF_TEXT_CHANGE,
// Composition string has been updated
NOTIFY_IME_OF_COMPOSITION_UPDATE,
// Position or size of focused element may be changed.
NOTIFY_IME_OF_POSITION_CHANGE,
// Request to commit current composition to IME
// (some platforms may not support)
REQUEST_TO_COMMIT_COMPOSITION,