Bug 1208944 - Part 2-a. Handle CompositionEvent on plugin. r=masayuki

This commit is contained in:
Makoto Kato 2015-12-29 22:57:37 +09:00
parent 069c0f8ad5
commit 42d7f2f96c
5 changed files with 125 additions and 4 deletions

View File

@ -10,6 +10,7 @@
#include "nsIEditor.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsPluginInstanceOwner.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/EventDispatcher.h"
#include "mozilla/IMEStateManager.h"
@ -118,11 +119,24 @@ TextComposition::CloneAndDispatchAs(
if (aMessage == eCompositionUpdate) {
mLastData = compositionEvent.mData;
}
EventDispatcher::Dispatch(mNode, mPresContext,
&compositionEvent, nullptr, status, aCallBack);
DispatchEvent(&compositionEvent, status, aCallBack, aCompositionEvent);
return compositionEvent.mFlags;
}
void
TextComposition::DispatchEvent(WidgetCompositionEvent* aDispatchEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallBack,
const WidgetCompositionEvent *aOriginalEvent)
{
nsPluginInstanceOwner::GeneratePluginEvent(aOriginalEvent,
aDispatchEvent);
EventDispatcher::Dispatch(mNode, mPresContext,
aDispatchEvent, nullptr, aStatus, aCallBack);
}
void
TextComposition::OnCompositionEventDiscarded(
WidgetCompositionEvent* aCompositionEvent)
@ -341,8 +355,7 @@ TextComposition::DispatchCompositionEvent(
CloneAndDispatchAs(aCompositionEvent, eCompositionChange,
aStatus, aCallBack);
} else {
EventDispatcher::Dispatch(mNode, mPresContext,
aCompositionEvent, nullptr, aStatus, aCallBack);
DispatchEvent(aCompositionEvent, aStatus, aCallBack);
}
} else {
*aStatus = nsEventStatus_eConsumeNoDefault;

View File

@ -293,6 +293,15 @@ private:
EventDispatchingCallback* aCallBack,
bool aIsSynthesized);
/**
* Simply calling EventDispatcher::Dispatch() with plugin event.
* If dispatching event has no orginal clone, aOriginalEvent can be null.
*/
void DispatchEvent(WidgetCompositionEvent* aDispatchEvent,
nsEventStatus* aStatus,
EventDispatchingCallback* aCallback,
const WidgetCompositionEvent *aOriginalEvent = nullptr);
/**
* HandleSelectionEvent() sends the selection event to ContentEventHandler
* or dispatches it to the focused child process.

View File

@ -1597,6 +1597,30 @@ nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
return NS_OK;
}
nsresult
nsPluginInstanceOwner::DispatchCompositionToPlugin(nsIDOMEvent* aEvent)
{
#ifdef XP_WIN
if (!mPluginWindow) {
// CompositionEvent isn't cancellable. So it is unnecessary to call
// PreventDefaults() to consume event
return NS_OK;
}
WidgetCompositionEvent* compositionEvent =
aEvent->GetInternalNSEvent()->AsCompositionEvent();
if (NS_WARN_IF(!compositionEvent)) {
return NS_ERROR_INVALID_ARG;
}
nsEventStatus rv = ProcessEvent(*compositionEvent);
// XXX This isn't e10s aware.
// If the event isn't consumed, we cannot post result to chrome process.
if (nsEventStatus_eConsumeNoDefault == rv) {
aEvent->StopImmediatePropagation();
}
#endif
return NS_OK;
}
nsresult
nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
{
@ -1651,6 +1675,11 @@ nsPluginInstanceOwner::HandleEvent(nsIDOMEvent* aEvent)
if (eventType.EqualsLiteral("keypress")) {
return ProcessKeyPress(aEvent);
}
if (eventType.EqualsLiteral("compositionstart") ||
eventType.EqualsLiteral("compositionend") ||
eventType.EqualsLiteral("text")) {
return DispatchCompositionToPlugin(aEvent);
}
nsCOMPtr<nsIDOMDragEvent> dragEvent(do_QueryInterface(aEvent));
if (dragEvent && mInstance) {
@ -2477,6 +2506,11 @@ nsPluginInstanceOwner::Destroy()
content->RemoveEventListener(NS_LITERAL_STRING("dragstart"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("draggesture"), this, true);
content->RemoveEventListener(NS_LITERAL_STRING("dragend"), this, true);
content->RemoveSystemEventListener(NS_LITERAL_STRING("compositionstart"),
this, true);
content->RemoveSystemEventListener(NS_LITERAL_STRING("compositionend"),
this, true);
content->RemoveSystemEventListener(NS_LITERAL_STRING("text"), this, true);
#if MOZ_WIDGET_ANDROID
RemovePluginView();
@ -2872,6 +2906,11 @@ nsresult nsPluginInstanceOwner::Init(nsIContent* aContent)
aContent->AddEventListener(NS_LITERAL_STRING("dragstart"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("draggesture"), this, true);
aContent->AddEventListener(NS_LITERAL_STRING("dragend"), this, true);
aContent->AddSystemEventListener(NS_LITERAL_STRING("compositionstart"),
this, true);
aContent->AddSystemEventListener(NS_LITERAL_STRING("compositionend"), this,
true);
aContent->AddSystemEventListener(NS_LITERAL_STRING("text"), this, true);
return NS_OK;
}
@ -3374,6 +3413,51 @@ already_AddRefed<nsIURI> nsPluginInstanceOwner::GetBaseURI() const
return content->GetBaseURI();
}
// static
void
nsPluginInstanceOwner::GeneratePluginEvent(
const WidgetCompositionEvent* aSrcCompositionEvent,
WidgetCompositionEvent* aDistCompositionEvent)
{
#ifdef XP_WIN
NPEvent newEvent;
switch (aDistCompositionEvent->mMessage) {
case eCompositionChange: {
newEvent.event = WM_IME_COMPOSITION;
newEvent.wParam = 0;
if (aSrcCompositionEvent &&
(aSrcCompositionEvent->mMessage == eCompositionCommit ||
aSrcCompositionEvent->mMessage == eCompositionCommitAsIs)) {
newEvent.lParam = GCS_RESULTSTR;
} else {
newEvent.lParam = GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE;
}
TextRangeArray* ranges = aDistCompositionEvent->mRanges;
if (ranges && ranges->HasCaret()) {
newEvent.lParam |= GCS_CURSORPOS;
}
break;
}
case eCompositionStart:
newEvent.event = WM_IME_STARTCOMPOSITION;
newEvent.wParam = 0;
newEvent.lParam = 0;
break;
case eCompositionEnd:
newEvent.event = WM_IME_ENDCOMPOSITION;
newEvent.wParam = 0;
newEvent.lParam = 0;
break;
default:
return;
}
aDistCompositionEvent->mPluginEvent.Copy(newEvent);
#endif
}
// nsPluginDOMContextMenuListener class implementation
nsPluginDOMContextMenuListener::nsPluginDOMContextMenuListener(nsIContent* aContent)

View File

@ -118,6 +118,10 @@ public:
nsEventStatus ProcessEvent(const mozilla::WidgetGUIEvent& anEvent);
static void GeneratePluginEvent(
const mozilla::WidgetCompositionEvent* aSrcCompositionEvent,
mozilla::WidgetCompositionEvent* aDistCompositionEvent);
#if defined(XP_WIN)
void SetWidgetWindowAsParent(HWND aWindowToAdopt);
nsresult SetNetscapeWindowAsParent(HWND aWindowToAdopt);
@ -329,6 +333,7 @@ private:
nsresult DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
bool aAllowPropagate = false);
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
nsresult DispatchCompositionToPlugin(nsIDOMEvent* aEvent);
#ifdef XP_MACOSX
static NPBool ConvertPointPuppet(PuppetWidget *widget, nsPluginFrame* pluginFrame,

View File

@ -256,6 +256,16 @@ public:
ElementAt(i).RemoveCharacter(aOffset);
}
}
bool HasCaret() const
{
for (const TextRange& range : *this) {
if (range.mRangeType == NS_TEXTRANGE_CARETPOSITION) {
return true;
}
}
return false;
}
};
} // namespace mozilla