Bug 1137572 part.2 Add nsIWidget::GetNativeTextEventDispatcherListener() for TextEventDispatcher::NotifyIME() r=smaug, sr=smaug

This commit is contained in:
Masayuki Nakano 2016-03-16 13:47:47 +09:00
parent 13c20e8b89
commit 3a5c26cf72
6 changed files with 107 additions and 35 deletions

View File

@ -631,8 +631,11 @@ TextInputProcessor::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
const IMENotification& aNotification)
{
// If This is called while this is being initialized, ignore the call.
// In such case, this method should return NS_ERROR_NOT_IMPLEMENTED because
// we can say, TextInputProcessor doesn't implement any handlers of the
// requests and notifications.
if (!mDispatcher) {
return NS_ERROR_NOT_AVAILABLE;
return NS_ERROR_NOT_IMPLEMENTED;
}
MOZ_ASSERT(aTextEventDispatcher == mDispatcher,
"Wrong TextEventDispatcher notifies this");

View File

@ -55,10 +55,17 @@ TextEventDispatcher::BeginTestInputTransaction(
}
nsresult
TextEventDispatcher::BeginNativeInputTransaction(
TextEventDispatcherListener* aListener)
TextEventDispatcher::BeginNativeInputTransaction()
{
return BeginInputTransactionInternal(aListener, eNativeInputTransaction);
if (NS_WARN_IF(!mWidget)) {
return NS_ERROR_FAILURE;
}
RefPtr<TextEventDispatcherListener> listener =
mWidget->GetNativeTextEventDispatcherListener();
if (NS_WARN_IF(!listener)) {
return NS_ERROR_FAILURE;
}
return BeginInputTransactionInternal(listener, eNativeInputTransaction);
}
nsresult
@ -308,18 +315,50 @@ TextEventDispatcher::CommitComposition(nsEventStatus& aStatus,
nsresult
TextEventDispatcher::NotifyIME(const IMENotification& aIMENotification)
{
nsresult rv = NS_ERROR_NOT_IMPLEMENTED;
// First, send the notification to current input transaction's listener.
nsCOMPtr<TextEventDispatcherListener> listener = do_QueryReferent(mListener);
if (!listener) {
return NS_ERROR_NOT_IMPLEMENTED;
if (listener) {
rv = listener->NotifyIME(this, aIMENotification);
}
nsresult rv = listener->NotifyIME(this, aIMENotification);
// If the listener isn't available, it means that it cannot handle the
// notification or request for now. In this case, we should return
// NS_ERROR_NOT_IMPLEMENTED because it's not implemented at such moment.
if (rv == NS_ERROR_NOT_AVAILABLE) {
return NS_ERROR_NOT_IMPLEMENTED;
if (mInputTransactionType == eNativeInputTransaction || !mWidget) {
return rv;
}
// If current input transaction isn't for native event handler, we should
// send the notification to the native text event dispatcher listener
// since native event handler may need to do something from
// TextEventDispatcherListener::NotifyIME() even before there is no
// input transaction yet. For example, native IME handler may need to
// create new context at receiving NOTIFY_IME_OF_FOCUS. In this case,
// mListener may not be initialized since input transaction should be
// initialized immediately before dispatching every WidgetKeyboardEvent
// and WidgetCompositionEvent (dispatching events always occurs after
// focus move).
nsCOMPtr<TextEventDispatcherListener> nativeListener =
mWidget->GetNativeTextEventDispatcherListener();
if (!nativeListener) {
return rv;
}
switch (aIMENotification.mMessage) {
case REQUEST_TO_COMMIT_COMPOSITION:
case REQUEST_TO_CANCEL_COMPOSITION:
// It's not necessary to notify native IME of requests.
return rv;
default: {
// Even if current input transaction's listener returns NS_OK or
// something, we need to notify native IME of notifications because
// when user typing after TIP does something, the changed information
// is necessary for them.
nsresult rv2 =
nativeListener->NotifyIME(this, aIMENotification);
// But return the result from current listener except when the
// notification isn't handled.
return rv == NS_ERROR_NOT_IMPLEMENTED ? rv2 : rv;
}
}
return rv;
}
bool

View File

@ -57,7 +57,7 @@ public:
*/
nsresult BeginInputTransaction(TextEventDispatcherListener* aListener);
nsresult BeginTestInputTransaction(TextEventDispatcherListener* aListener);
nsresult BeginNativeInputTransaction(TextEventDispatcherListener* aListener);
nsresult BeginNativeInputTransaction();
/**
* EndInputTransaction() should be called when the listener stops using
@ -72,6 +72,8 @@ public:
*/
void OnDestroyWidget();
nsIWidget* GetWidget() const { return mWidget; }
/**
* GetState() returns current state of this class.
*

View File

@ -6,6 +6,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/TextEventDispatcher.h"
#include "mozilla/TextEventDispatcherListener.h"
#include "mozilla/layers/CompositorChild.h"
#include "mozilla/layers/CompositorParent.h"
@ -1750,39 +1751,51 @@ nsBaseWidget::NotifyIME(const IMENotification& aIMENotification)
}
// Otherwise, it should be handled by native IME.
return NotifyIMEInternal(aIMENotification);
case NOTIFY_IME_OF_FOCUS:
mIMEHasFocus = true;
// We should notify TextEventDispatcher of focus notification, first.
// After that, notify native IME too.
if (mTextEventDispatcher) {
mTextEventDispatcher->NotifyIME(aIMENotification);
default: {
if (aIMENotification.mMessage == NOTIFY_IME_OF_FOCUS) {
mIMEHasFocus = true;
}
return NotifyIMEInternal(aIMENotification);
case NOTIFY_IME_OF_BLUR: {
// We should notify TextEventDispatcher of blur notification, first.
// After that, notify native IME too.
if (mTextEventDispatcher) {
mTextEventDispatcher->NotifyIME(aIMENotification);
EnsureTextEventDispatcher();
// If the platform specific widget uses TextEventDispatcher for handling
// native IME and keyboard events, IME event handler should be notified
// of the notification via TextEventDispatcher. Otherwise, on the other
// platforms which have not used TextEventDispatcher yet, IME event
// handler should be notified by the old path (NotifyIMEInternal).
nsresult rv = mTextEventDispatcher->NotifyIME(aIMENotification);
nsresult rv2 = NotifyIMEInternal(aIMENotification);
if (aIMENotification.mMessage == NOTIFY_IME_OF_BLUR) {
mIMEHasFocus = false;
}
nsresult rv = NotifyIMEInternal(aIMENotification);
mIMEHasFocus = false;
return rv;
return rv2 == NS_ERROR_NOT_IMPLEMENTED ? rv : rv2;
}
default:
// Otherwise, notify only native IME for now.
return NotifyIMEInternal(aIMENotification);
}
}
void
nsBaseWidget::EnsureTextEventDispatcher()
{
if (mTextEventDispatcher) {
return;
}
mTextEventDispatcher = new TextEventDispatcher(this);
}
NS_IMETHODIMP_(nsIWidget::TextEventDispatcher*)
nsBaseWidget::GetTextEventDispatcher()
{
if (!mTextEventDispatcher) {
mTextEventDispatcher = new TextEventDispatcher(this);
}
EnsureTextEventDispatcher();
return mTextEventDispatcher;
}
NS_IMETHODIMP_(TextEventDispatcherListener*)
nsBaseWidget::GetNativeTextEventDispatcherListener()
{
// TODO: If all platforms supported use of TextEventDispatcher for handling
// native IME and keyboard events, this method should be removed since
// in such case, this is overridden by all the subclasses.
return nullptr;
}
void
nsBaseWidget::ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,

View File

@ -249,6 +249,8 @@ public:
virtual nsIWidgetListener* GetPreviouslyAttachedWidgetListener() override;
virtual void SetPreviouslyAttachedWidgetListener(nsIWidgetListener* aListener) override;
NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() override final;
NS_IMETHOD_(TextEventDispatcherListener*)
GetNativeTextEventDispatcherListener() override;
virtual void ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,
@ -483,6 +485,8 @@ protected:
nsIDocument* GetDocument() const;
void EnsureTextEventDispatcher();
// Notify the compositor that a device reset has occurred.
void OnRenderingDeviceReset();

View File

@ -64,6 +64,7 @@ class SourceSurface;
} // namespace gfx
namespace widget {
class TextEventDispatcher;
class TextEventDispatcherListener;
} // namespace widget
} // namespace mozilla
@ -342,6 +343,8 @@ class nsIWidget : public nsISupports {
typedef mozilla::widget::NativeIMEContext NativeIMEContext;
typedef mozilla::widget::SizeConstraints SizeConstraints;
typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
typedef mozilla::widget::TextEventDispatcherListener
TextEventDispatcherListener;
typedef mozilla::CompositorVsyncDispatcher CompositorVsyncDispatcher;
typedef mozilla::LayoutDeviceIntMargin LayoutDeviceIntMargin;
typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint;
@ -2042,6 +2045,14 @@ public:
*/
NS_IMETHOD_(TextEventDispatcher*) GetTextEventDispatcher() = 0;
/**
* GetNativeTextEventDispatcherListener() returns a
* TextEventDispatcherListener instance which is used when the widget
* instance handles native IME and/or keyboard events.
*/
NS_IMETHOD_(TextEventDispatcherListener*)
GetNativeTextEventDispatcherListener() = 0;
virtual void ZoomToRect(const uint32_t& aPresShellId,
const FrameMetrics::ViewID& aViewId,
const CSSRect& aRect,