Bug 917322 part.7 TextEventDispatcher should manage if it has composition r=smaug

This commit is contained in:
Masayuki Nakano 2015-01-28 15:27:31 +09:00
Родитель cdcbe304ef
Коммит dd277f3277
19 изменённых файлов: 116 добавлений и 51 удалений

Просмотреть файл

@ -340,35 +340,14 @@ TextComposition::RequestToCommit(nsIWidget* aWidget, bool aDiscard)
mIsRequestingCancel = false;
mIsRequestingCommit = true;
}
if (!mIsSynthesizedForTests) {
// FYI: CompositionEvents caused by a call of NotifyIME() may be
// discarded by PresShell if it's not safe to dispatch the event.
nsresult rv =
aWidget->NotifyIME(IMENotification(aDiscard ?
REQUEST_TO_CANCEL_COMPOSITION :
REQUEST_TO_COMMIT_COMPOSITION));
if (rv == NS_ERROR_NOT_IMPLEMENTED) {
return rv;
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
} else {
// Emulates to commit or cancel the composition
// FYI: These events may be discarded by PresShell if it's not safe to
// dispatch the event.
nsCOMPtr<nsIWidget> widget(aWidget);
nsAutoString commitData(aDiscard ? EmptyString() : lastData);
bool isChanging = commitData != mLastData;
uint32_t message =
isChanging ? NS_COMPOSITION_COMMIT : NS_COMPOSITION_COMMIT_AS_IS;
WidgetCompositionEvent commitEvent(true, message, widget);
if (commitEvent.message == NS_COMPOSITION_COMMIT) {
commitEvent.mData = commitData;
}
commitEvent.mFlags.mIsSynthesizedForTests = true;
nsEventStatus status = nsEventStatus_eIgnore;
widget->DispatchEvent(&commitEvent, status);
// FYI: CompositionEvents caused by a call of NotifyIME() may be
// discarded by PresShell if it's not safe to dispatch the event.
nsresult rv =
aWidget->NotifyIME(IMENotification(aDiscard ?
REQUEST_TO_CANCEL_COMPOSITION :
REQUEST_TO_COMMIT_COMPOSITION));
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
}

Просмотреть файл

@ -428,8 +428,8 @@ PuppetWidget::IMEEndComposition(bool aCancel)
return NS_OK;
}
NS_IMETHODIMP
PuppetWidget::NotifyIME(const IMENotification& aIMENotification)
nsresult
PuppetWidget::NotifyIMEInternal(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:

Просмотреть файл

@ -163,7 +163,6 @@ public:
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
bool* aAllowRetaining = nullptr) MOZ_OVERRIDE;
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) MOZ_OVERRIDE;
NS_IMETHOD_(InputContext) GetInputContext() MOZ_OVERRIDE;
@ -204,6 +203,9 @@ protected:
bool mEnabled;
bool mVisible;
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
private:
nsresult Paint();

Просмотреть файл

@ -23,6 +23,7 @@ TextEventDispatcher::TextEventDispatcher(nsIWidget* aWidget)
: mWidget(aWidget)
, mInitialized(false)
, mForTests(false)
, mIsComposing(false)
{
MOZ_RELEASE_ASSERT(mWidget, "aWidget must not be nullptr");
}
@ -33,6 +34,7 @@ TextEventDispatcher::Init()
if (mInitialized) {
return NS_ERROR_ALREADY_INITIALIZED;
}
MOZ_ASSERT(!mIsComposing, "There should not be active composition");
mInitialized = true;
mForTests = false;
return NS_OK;
@ -44,6 +46,7 @@ TextEventDispatcher::InitForTests()
if (mInitialized) {
return NS_ERROR_ALREADY_INITIALIZED;
}
MOZ_ASSERT(!mIsComposing, "There should not be active composition");
mInitialized = true;
mForTests = true;
return NS_OK;
@ -85,6 +88,11 @@ TextEventDispatcher::StartComposition(nsEventStatus& aStatus)
return rv;
}
if (NS_WARN_IF(mIsComposing)) {
return NS_ERROR_FAILURE;
}
mIsComposing = true;
nsCOMPtr<nsIWidget> widget(mWidget);
WidgetCompositionEvent compositionStartEvent(true, NS_COMPOSITION_START,
widget);
@ -108,6 +116,10 @@ TextEventDispatcher::CommitComposition(nsEventStatus& aStatus,
return rv;
}
// End current composition and make this free for other IMEs.
mIsComposing = false;
mInitialized = false;
nsCOMPtr<nsIWidget> widget(mWidget);
uint32_t message = aCommitString ? NS_COMPOSITION_COMMIT :
NS_COMPOSITION_COMMIT_AS_IS;
@ -124,6 +136,27 @@ TextEventDispatcher::CommitComposition(nsEventStatus& aStatus,
return NS_OK;
}
nsresult
TextEventDispatcher::NotifyIME(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION: {
NS_ASSERTION(mIsComposing, "Why is this requested without composition?");
nsEventStatus status = nsEventStatus_eIgnore;
CommitComposition(status);
return NS_OK;
}
case REQUEST_TO_CANCEL_COMPOSITION: {
NS_ASSERTION(mIsComposing, "Why is this requested without composition?");
nsEventStatus status = nsEventStatus_eIgnore;
CommitComposition(status, &EmptyString());
return NS_OK;
}
default:
return NS_ERROR_NOT_IMPLEMENTED;
}
}
/******************************************************************************
* TextEventDispatcher::PendingComposition
*****************************************************************************/

Просмотреть файл

@ -17,6 +17,8 @@ class nsIWidget;
namespace mozilla {
namespace widget {
struct IMENotification;
/**
* TextEventDispatcher is a helper class for dispatching widget events defined
* in TextEvents.h. Currently, this is a helper for dispatching
@ -63,6 +65,12 @@ public:
*/
nsresult GetState() const;
/**
* IsComposing() returns true after calling StartComposition() and before
* calling CommitComposition().
*/
bool IsComposing() const { return mIsComposing; }
/**
* StartComposition() starts composition explicitly.
*/
@ -135,6 +143,11 @@ public:
return mPendingComposition.Flush(this, aStatus);
}
/**
* @see nsIWidget::NotifyIME()
*/
nsresult NotifyIME(const IMENotification& aIMENotification);
private:
// mWidget is owner of the instance. When this is created, this is set.
// And when mWidget is released, this is cleared by OnDestroyWidget().
@ -168,6 +181,8 @@ private:
bool mInitialized;
bool mForTests;
// See IsComposing().
bool mIsComposing;
/**
* InitEvent() initializes aEvent. This must be called before dispatching

Просмотреть файл

@ -2047,8 +2047,8 @@ nsWindow::UserActivity()
}
}
NS_IMETHODIMP
nsWindow::NotifyIME(const IMENotification& aIMENotification)
nsresult
nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:

Просмотреть файл

@ -132,7 +132,6 @@ public:
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction);
NS_IMETHOD_(InputContext) GetInputContext();
@ -228,6 +227,9 @@ protected:
InputContext mInputContext;
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
static void DumpWindows();
static void DumpWindows(const nsTArray<nsWindow*>& wins, int indent = 0);
static void LogWindow(nsWindow *win, int index, int indent);

Просмотреть файл

@ -425,7 +425,6 @@ public:
NS_IMETHOD ActivateNativeMenuItemAt(const nsAString& indexString) MOZ_OVERRIDE;
NS_IMETHOD ForceUpdateNativeMenuAt(const nsAString& indexString) MOZ_OVERRIDE;
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) MOZ_OVERRIDE;
NS_IMETHOD_(InputContext) GetInputContext() MOZ_OVERRIDE;
@ -568,6 +567,9 @@ protected:
nsIWidget* GetWidgetForListenerEvents();
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
protected:
NSView<mozView>* mView; // my parallel cocoa view (ChildView or NativeScrollbarView), [STRONG]

Просмотреть файл

@ -1579,8 +1579,8 @@ bool nsChildView::HasPendingInputEvent()
#pragma mark -
NS_IMETHODIMP
nsChildView::NotifyIME(const IMENotification& aIMENotification)
nsresult
nsChildView::NotifyIMEInternal(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:

Просмотреть файл

@ -330,7 +330,6 @@ public:
void SetMenuBar(nsMenuBarX* aMenuBar);
nsMenuBarX *GetMenuBar();
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD_(void) SetInputContext(
const InputContext& aContext,
const InputContextAction& aAction) MOZ_OVERRIDE;
@ -381,6 +380,9 @@ protected:
return widget.forget();
}
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
nsIWidget* mParent; // if we're a popup, this is our parent [WEAK]
BaseWindow* mWindow; // our cocoa window [STRONG]
WindowDelegate* mDelegate; // our delegate for processing window msgs [STRONG]

Просмотреть файл

@ -2111,8 +2111,8 @@ void nsCocoaWindow::SetPopupWindowLevel()
}
}
NS_IMETHODIMP
nsCocoaWindow::NotifyIME(const IMENotification& aIMENotification)
nsresult
nsCocoaWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case NOTIFY_IME_OF_FOCUS:

Просмотреть файл

@ -5977,8 +5977,8 @@ nsChildWindow::~nsChildWindow()
{
}
NS_IMETHODIMP
nsWindow::NotifyIME(const IMENotification& aIMENotification)
nsresult
nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
{
if (MOZ_UNLIKELY(!mIMModule)) {
return NS_ERROR_NOT_AVAILABLE;

Просмотреть файл

@ -260,7 +260,6 @@ public:
bool DispatchKeyDownEvent(GdkEventKey *aEvent,
bool *aIsCancelled);
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) MOZ_OVERRIDE;
NS_IMETHOD_(InputContext) GetInputContext() MOZ_OVERRIDE;
@ -318,6 +317,10 @@ protected:
GtkWidget* aNewContainer,
GdkWindow* aNewParentWindow,
GtkWidget* aOldContainer);
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
nsCOMPtr<nsIWidget> mParent;
// Is this a toplevel window?
bool mIsTopLevel;

Просмотреть файл

@ -73,6 +73,7 @@ nsIRollupListener* nsBaseWidget::gRollupListener = nullptr;
using namespace mozilla::layers;
using namespace mozilla::ipc;
using namespace mozilla::widget;
using namespace mozilla;
using base::Thread;
@ -1585,6 +1586,25 @@ nsBaseWidget::NotifyUIStateChanged(UIStateChangeType aShowAccelerators,
}
}
NS_IMETHODIMP
nsBaseWidget::NotifyIME(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:
case REQUEST_TO_CANCEL_COMPOSITION:
// Currently, if native IME handler doesn't use TextEventDispatcher,
// the request may be notified to mTextEventDispatcher or native IME
// directly. Therefore, if mTextEventDispatcher has a composition,
// the request should be handled by the mTextEventDispatcher.
if (mTextEventDispatcher && mTextEventDispatcher->IsComposing()) {
return mTextEventDispatcher->NotifyIME(aIMENotification);
}
// Otherwise, call NotifyIMEInternal() for native IME handlers.
default:
return NotifyIMEInternal(aIMENotification);
}
}
NS_IMETHODIMP_(nsIWidget::TextEventDispatcher*)
nsBaseWidget::GetTextEventDispatcher()
{

Просмотреть файл

@ -195,7 +195,7 @@ public:
NS_IMETHOD BeginMoveDrag(mozilla::WidgetMouseEvent* aEvent) MOZ_OVERRIDE;
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE MOZ_FINAL;
NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
NativeKeyBindingsType aType,
@ -358,6 +358,9 @@ protected:
uint32_t aPointerOrientation) MOZ_OVERRIDE
{ return NS_ERROR_UNEXPECTED; }
virtual nsresult NotifyIMEInternal(const IMENotification& aIMENotification)
{ return NS_ERROR_NOT_IMPLEMENTED; }
protected:
// Stores the clip rectangles in aRects into mClipRects. Returns true
// if the new rectangles are different from the old rectangles.

Просмотреть файл

@ -6703,8 +6703,8 @@ nsWindow::OnSysColorChanged()
**************************************************************
**************************************************************/
NS_IMETHODIMP
nsWindow::NotifyIME(const IMENotification& aIMENotification)
nsresult
nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
{
return IMEHandler::NotifyIME(this, aIMENotification);
}

Просмотреть файл

@ -175,7 +175,6 @@ public:
double aDeltaZ,
uint32_t aModifierFlags,
uint32_t aAdditionalFlags);
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction);
NS_IMETHOD_(InputContext) GetInputContext();
@ -282,6 +281,9 @@ protected:
virtual void WindowUsesOMTC() MOZ_OVERRIDE;
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
// A magic number to identify the FAKETRACKPOINTSCROLLABLE window created
// when the trackpoint hack is enabled.
enum { eFakeTrackPointScrollableID = 0x46545053 };

Просмотреть файл

@ -1527,8 +1527,8 @@ MetroWidget::GetInputContext()
return mInputContext;
}
NS_IMETHODIMP
MetroWidget::NotifyIME(const IMENotification& aIMENotification)
nsresult
MetroWidget::NotifyIMEInternal(const IMENotification& aIMENotification)
{
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:

Просмотреть файл

@ -160,7 +160,6 @@ public:
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction);
NS_IMETHOD_(nsIWidget::InputContext) GetInputContext();
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE;
NS_IMETHOD GetToggledKeyState(uint32_t aKeyCode, bool* aLEDState);
virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE;
@ -252,6 +251,9 @@ protected:
void RemoveSubclass();
nsIWidgetListener* GetPaintListener();
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) MOZ_OVERRIDE;
// Async event dispatching
void DispatchAsyncScrollEvent(DispatchMsg* aEvent);
void DeliverNextScrollEvent();