зеркало из https://github.com/mozilla/gecko-dev.git
Bug 968647 - Part 1. Add postion change notification for IME. r=roc
This commit is contained in:
Родитель
0134c520ed
Коммит
9857fbb5f0
|
@ -37,6 +37,7 @@ XPIDL_MODULE = 'docshell'
|
|||
EXPORTS += [
|
||||
'nsDocShellLoadTypes.h',
|
||||
'nsILinkHandler.h',
|
||||
'nsIScrollObserver.h',
|
||||
'nsIWebShellServices.h',
|
||||
'SerializedLoadContext.h',
|
||||
]
|
||||
|
|
|
@ -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
|
||||
//*****************************************************************************
|
||||
|
|
|
@ -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.)
|
||||
|
|
|
@ -41,6 +41,7 @@ interface nsIWebBrowserPrint;
|
|||
interface nsIVariant;
|
||||
interface nsIPrivacyTransitionObserver;
|
||||
interface nsIReflowObserver;
|
||||
interface nsIScrollObserver;
|
||||
|
||||
typedef unsigned long nsLoadFlags;
|
||||
|
||||
|
@ -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.)
|
||||
|
|
|
@ -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 "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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче