Bug 968647 - Part 1. Add postion change notification for IME. r=roc
This commit is contained in:
@@ -37,6 +37,7 @@ XPIDL_MODULE = 'docshell'
|
|||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'nsDocShellLoadTypes.h',
|
'nsDocShellLoadTypes.h',
|
||||||
'nsILinkHandler.h',
|
'nsILinkHandler.h',
|
||||||
|
'nsIScrollObserver.h',
|
||||||
'nsIWebShellServices.h',
|
'nsIWebShellServices.h',
|
||||||
'SerializedLoadContext.h',
|
'SerializedLoadContext.h',
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
#include "nsITimedChannel.h"
|
#include "nsITimedChannel.h"
|
||||||
#include "nsIPrivacyTransitionObserver.h"
|
#include "nsIPrivacyTransitionObserver.h"
|
||||||
#include "nsIReflowObserver.h"
|
#include "nsIReflowObserver.h"
|
||||||
|
#include "nsIScrollObserver.h"
|
||||||
#include "nsIDocShellTreeItem.h"
|
#include "nsIDocShellTreeItem.h"
|
||||||
#include "nsIChannel.h"
|
#include "nsIChannel.h"
|
||||||
#include "IHistory.h"
|
#include "IHistory.h"
|
||||||
@@ -2857,6 +2858,39 @@ nsDocShell::GetCurrentDocChannel()
|
|||||||
return nullptr;
|
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
|
// nsDocShell::nsIDocShellTreeItem
|
||||||
//*****************************************************************************
|
//*****************************************************************************
|
||||||
|
|||||||
@@ -900,6 +900,7 @@ private:
|
|||||||
nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
|
nsCOMPtr<nsIPrincipal> mParentCharsetPrincipal;
|
||||||
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
nsTObserverArray<nsWeakPtr> mPrivacyObservers;
|
||||||
nsTObserverArray<nsWeakPtr> mReflowObservers;
|
nsTObserverArray<nsWeakPtr> mReflowObservers;
|
||||||
|
nsTObserverArray<nsWeakPtr> mScrollObservers;
|
||||||
nsCString mOriginalUriString;
|
nsCString mOriginalUriString;
|
||||||
|
|
||||||
// Separate function to do the actual name (i.e. not _top, _self etc.)
|
// Separate function to do the actual name (i.e. not _top, _self etc.)
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ interface nsIWebBrowserPrint;
|
|||||||
interface nsIVariant;
|
interface nsIVariant;
|
||||||
interface nsIPrivacyTransitionObserver;
|
interface nsIPrivacyTransitionObserver;
|
||||||
interface nsIReflowObserver;
|
interface nsIReflowObserver;
|
||||||
|
interface nsIScrollObserver;
|
||||||
|
|
||||||
typedef unsigned long nsLoadFlags;
|
typedef unsigned long nsLoadFlags;
|
||||||
|
|
||||||
@@ -667,6 +668,24 @@ interface nsIDocShell : nsIDocShellTreeItem
|
|||||||
in DOMHighResTimeStamp start,
|
in DOMHighResTimeStamp start,
|
||||||
in DOMHighResTimeStamp end);
|
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>.
|
* Returns true if this docshell corresponds to an <iframe mozbrowser>.
|
||||||
* (<iframe mozapp mozbrowser> is not considered a browser.)
|
* (<iframe mozapp mozbrowser> is not considered a browser.)
|
||||||
|
|||||||
28
docshell/base/nsIScrollObserver.h
Normal file
28
docshell/base/nsIScrollObserver.h
Normal 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___ */
|
||||||
@@ -35,6 +35,10 @@
|
|||||||
#include "TextComposition.h"
|
#include "TextComposition.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "nsAsyncDOMEvent.h"
|
#include "nsAsyncDOMEvent.h"
|
||||||
|
#include "nsIDocShell.h"
|
||||||
|
#include "nsIReflowObserver.h"
|
||||||
|
#include "nsIScrollObserver.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::dom;
|
using namespace mozilla::dom;
|
||||||
@@ -46,7 +50,10 @@ using namespace mozilla::widget;
|
|||||||
// sTextStateObserver is null if there is no focused editor
|
// sTextStateObserver is null if there is no focused editor
|
||||||
|
|
||||||
class nsTextStateManager MOZ_FINAL : public nsISelectionListener,
|
class nsTextStateManager MOZ_FINAL : public nsISelectionListener,
|
||||||
public nsStubMutationObserver
|
public nsStubMutationObserver,
|
||||||
|
public nsIReflowObserver,
|
||||||
|
public nsIScrollObserver,
|
||||||
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsTextStateManager()
|
nsTextStateManager()
|
||||||
@@ -61,6 +68,10 @@ public:
|
|||||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
|
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
|
||||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||||
|
NS_DECL_NSIREFLOWOBSERVER
|
||||||
|
|
||||||
|
// nsIScrollObserver
|
||||||
|
virtual void ScrollPositionChanged() MOZ_OVERRIDE;
|
||||||
|
|
||||||
void Init(nsIWidget* aWidget,
|
void Init(nsIWidget* aWidget,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
@@ -82,6 +93,7 @@ private:
|
|||||||
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
|
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
|
||||||
void ObserveEditableNode();
|
void ObserveEditableNode();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDocShell> mDocShell;
|
||||||
nsIMEUpdatePreference mUpdatePreference;
|
nsIMEUpdatePreference mUpdatePreference;
|
||||||
uint32_t mPreAttrChangeLength;
|
uint32_t mPreAttrChangeLength;
|
||||||
};
|
};
|
||||||
@@ -752,6 +764,8 @@ nsTextStateManager::Init(nsIWidget* aWidget,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mDocShell = aPresContext->GetDocShell();
|
||||||
|
|
||||||
ObserveEditableNode();
|
ObserveEditableNode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,6 +788,13 @@ nsTextStateManager::ObserveEditableNode()
|
|||||||
// add text change observer
|
// add text change observer
|
||||||
mRootContent->AddMutationObserver(this);
|
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
|
void
|
||||||
@@ -800,8 +821,13 @@ nsTextStateManager::Destroy(void)
|
|||||||
if (mUpdatePreference.WantTextChange() && mRootContent) {
|
if (mUpdatePreference.WantTextChange() && mRootContent) {
|
||||||
mRootContent->RemoveMutationObserver(this);
|
mRootContent->RemoveMutationObserver(this);
|
||||||
}
|
}
|
||||||
|
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
|
||||||
|
mDocShell->RemoveWeakScrollObserver(this);
|
||||||
|
mDocShell->RemoveWeakReflowObserver(this);
|
||||||
|
}
|
||||||
mRootContent = nullptr;
|
mRootContent = nullptr;
|
||||||
mEditableNode = nullptr;
|
mEditableNode = nullptr;
|
||||||
|
mDocShell = nullptr;
|
||||||
mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
|
mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,9 +859,12 @@ nsTextStateManager::IsEditorHandlingEventForComposition() const
|
|||||||
return composition->IsEditorHandlingEvent();
|
return composition->IsEditorHandlingEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS2(nsTextStateManager,
|
NS_IMPL_ISUPPORTS5(nsTextStateManager,
|
||||||
nsIMutationObserver,
|
nsIMutationObserver,
|
||||||
nsISelectionListener)
|
nsISelectionListener,
|
||||||
|
nsIReflowObserver,
|
||||||
|
nsIScrollObserver,
|
||||||
|
nsISupportsWeakReference)
|
||||||
|
|
||||||
// Helper class, used for selection change notification
|
// Helper class, used for selection change notification
|
||||||
class SelectionChangeEvent : public nsRunnable {
|
class SelectionChangeEvent : public nsRunnable {
|
||||||
@@ -917,6 +946,54 @@ private:
|
|||||||
bool mCausedByComposition;
|
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
|
void
|
||||||
nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
|
nsTextStateManager::CharacterDataChanged(nsIDocument* aDocument,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
|
|||||||
@@ -2085,6 +2085,8 @@ ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange, nsIAtom* aOri
|
|||||||
for (uint32_t i = 0; i < mListeners.Length(); i++) {
|
for (uint32_t i = 0; i < mListeners.Length(); i++) {
|
||||||
mListeners[i]->ScrollPositionDidChange(pt.x, pt.y);
|
mListeners[i]->ScrollPositionDidChange(pt.x, pt.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
presContext->GetDocShell()->NotifyScrollObservers();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -226,6 +226,7 @@ struct nsIMEUpdatePreference {
|
|||||||
NOTIFY_NOTHING = 0,
|
NOTIFY_NOTHING = 0,
|
||||||
NOTIFY_SELECTION_CHANGE = 1 << 0,
|
NOTIFY_SELECTION_CHANGE = 1 << 0,
|
||||||
NOTIFY_TEXT_CHANGE = 1 << 1,
|
NOTIFY_TEXT_CHANGE = 1 << 1,
|
||||||
|
NOTIFY_POSITION_CHANGE = 1 << 2,
|
||||||
// Following values indicate when widget needs or doesn't need notification.
|
// Following values indicate when widget needs or doesn't need notification.
|
||||||
NOTIFY_CHANGES_CAUSED_BY_COMPOSITION = 1 << 6,
|
NOTIFY_CHANGES_CAUSED_BY_COMPOSITION = 1 << 6,
|
||||||
// NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
|
// NOTE: NOTIFY_DURING_DEACTIVE isn't supported in environments where two
|
||||||
@@ -264,6 +265,11 @@ struct nsIMEUpdatePreference {
|
|||||||
return !!(mWantUpdates & NOTIFY_TEXT_CHANGE);
|
return !!(mWantUpdates & NOTIFY_TEXT_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WantPositionChanged() const
|
||||||
|
{
|
||||||
|
return !!(mWantUpdates & NOTIFY_POSITION_CHANGE);
|
||||||
|
}
|
||||||
|
|
||||||
bool WantChanges() const
|
bool WantChanges() const
|
||||||
{
|
{
|
||||||
return WantSelectionChange() || WantTextChange();
|
return WantSelectionChange() || WantTextChange();
|
||||||
@@ -492,6 +498,8 @@ enum IMEMessage MOZ_ENUM_TYPE(int8_t)
|
|||||||
NOTIFY_IME_OF_TEXT_CHANGE,
|
NOTIFY_IME_OF_TEXT_CHANGE,
|
||||||
// Composition string has been updated
|
// Composition string has been updated
|
||||||
NOTIFY_IME_OF_COMPOSITION_UPDATE,
|
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
|
// Request to commit current composition to IME
|
||||||
// (some platforms may not support)
|
// (some platforms may not support)
|
||||||
REQUEST_TO_COMMIT_COMPOSITION,
|
REQUEST_TO_COMMIT_COMPOSITION,
|
||||||
|
|||||||
Reference in New Issue
Block a user