mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1208944 - Part 10-b. Call DefaultProc When CompositionEvent isn't handled correctly by plugin. r=masayuki
This commit is contained in:
parent
3317a4cbfe
commit
648e3da9ac
@ -62,6 +62,7 @@ using mozilla::DefaultXDisplay;
|
||||
#include "nsPIWindowRoot.h"
|
||||
#include "mozilla/IMEStateManager.h"
|
||||
#include "mozilla/TextComposition.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
|
||||
#include "nsContentCID.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
@ -368,6 +369,11 @@ nsPluginInstanceOwner::nsPluginInstanceOwner()
|
||||
mFullScreen = false;
|
||||
mJavaView = nullptr;
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
mGotCompositionData = false;
|
||||
mSentStartComposition = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsPluginInstanceOwner::~nsPluginInstanceOwner()
|
||||
@ -799,6 +805,9 @@ nsPluginInstanceOwner::GetCompositionString(uint32_t aType,
|
||||
nsTArray<uint8_t>* aDist,
|
||||
int32_t* aLength)
|
||||
{
|
||||
// Mark pkugin calls ImmGetCompositionStringW correctly
|
||||
mGotCompositionData = true;
|
||||
|
||||
RefPtr<TextComposition> composition = GetTextComposition();
|
||||
if (NS_WARN_IF(!composition)) {
|
||||
return false;
|
||||
@ -1660,10 +1669,10 @@ nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent)
|
||||
if (theEvent) {
|
||||
WidgetGUIEvent focusEvent(theEvent->mFlags.mIsTrusted, theEvent->mMessage,
|
||||
nullptr);
|
||||
nsEventStatus rv = ProcessEvent(focusEvent);
|
||||
if (nsEventStatus_eConsumeNoDefault == rv) {
|
||||
nsEventStatus status = ProcessEvent(focusEvent);
|
||||
if (nsEventStatus_eConsumeNoDefault == status) {
|
||||
aFocusEvent->PreventDefault();
|
||||
aFocusEvent->StopPropagation();
|
||||
aFocusEvent->StopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1775,6 +1784,28 @@ nsresult nsPluginInstanceOwner::DispatchMouseToPlugin(nsIDOMEvent* aMouseEvent,
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
void
|
||||
nsPluginInstanceOwner::CallDefaultProc(const WidgetGUIEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetContainingWidgetIfOffset();
|
||||
if (!widget) {
|
||||
widget = GetRootWidgetForPluginFrame(mPluginFrame);
|
||||
if (NS_WARN_IF(!widget)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const NPEvent* npEvent =
|
||||
static_cast<const NPEvent*>(aEvent->mPluginEvent);
|
||||
if (NS_WARN_IF(!npEvent)) {
|
||||
return;
|
||||
}
|
||||
|
||||
WidgetPluginEvent pluginEvent(true, ePluginInputEvent, widget);
|
||||
pluginEvent.mPluginEvent.Copy(*npEvent);
|
||||
widget->DefaultProcOfPluginEvent(pluginEvent);
|
||||
}
|
||||
|
||||
already_AddRefed<TextComposition>
|
||||
nsPluginInstanceOwner::GetTextComposition()
|
||||
{
|
||||
@ -1824,13 +1855,79 @@ nsPluginInstanceOwner::DispatchCompositionToPlugin(nsIDOMEvent* aEvent)
|
||||
compositionChangeEventHandlingMarker(composition, compositionEvent);
|
||||
}
|
||||
|
||||
// Protected mode Flash returns noDefault by NPP_HandleEvent, but
|
||||
// composition information into plugin is invalid because plugin's bug.
|
||||
// So if plugin doesn't get composition data by WM_IME_COMPOSITION, we
|
||||
// recongnize it isn't handled
|
||||
AutoRestore<bool> restore(mGotCompositionData);
|
||||
mGotCompositionData = false;
|
||||
|
||||
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();
|
||||
aEvent->StopImmediatePropagation();
|
||||
|
||||
// Composition event isn't handled by plugin, so we have to call default proc.
|
||||
const NPEvent* pPluginEvent =
|
||||
static_cast<const NPEvent*>(compositionEvent->mPluginEvent);
|
||||
if (NS_WARN_IF(!pPluginEvent)) {
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pPluginEvent->event == WM_IME_STARTCOMPOSITION) {
|
||||
// Flash's protected mode lies that composition event is handled, but it
|
||||
// cannot do it well. So even if handled, we should post this message when
|
||||
// no IMM API calls during WM_IME_COMPOSITION.
|
||||
if (nsEventStatus_eConsumeNoDefault != rv) {
|
||||
CallDefaultProc(compositionEvent);
|
||||
mSentStartComposition = true;
|
||||
} else {
|
||||
mSentStartComposition = false;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (pPluginEvent->event == WM_IME_ENDCOMPOSITION) {
|
||||
// Always post WM_END_COMPOSITION to default proc. Because Flash may lie
|
||||
// that it doesn't handle composition well, but event is handled.
|
||||
// Even if posting this message, default proc do nothing if unnecessary.
|
||||
CallDefaultProc(compositionEvent);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (pPluginEvent->event == WM_IME_COMPOSITION && !mGotCompositionData) {
|
||||
nsCOMPtr<nsIWidget> widget = GetContainingWidgetIfOffset();
|
||||
if (!widget) {
|
||||
widget = GetRootWidgetForPluginFrame(mPluginFrame);
|
||||
}
|
||||
|
||||
if (pPluginEvent->lParam & GCS_RESULTSTR) {
|
||||
// GCS_RESULTSTR's default proc will generate WM_CHAR. So emulate it.
|
||||
for (size_t i = 0; i < compositionEvent->mData.Length(); i++) {
|
||||
WidgetPluginEvent charEvent(true, ePluginInputEvent, widget);
|
||||
NPEvent event;
|
||||
event.event = WM_CHAR;
|
||||
event.wParam = compositionEvent->mData[i];
|
||||
event.lParam = 0;
|
||||
charEvent.mPluginEvent.Copy(event);
|
||||
ProcessEvent(charEvent);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
if (!mSentStartComposition) {
|
||||
// We post WM_IME_COMPOSITION to default proc, but
|
||||
// WM_IME_STARTCOMPOSITION isn't post yet. We should post it at first.
|
||||
WidgetPluginEvent event(true, ePluginInputEvent, widget);
|
||||
NPEvent npevent;
|
||||
npevent.event = WM_IME_STARTCOMPOSITION;
|
||||
npevent.wParam = 0;
|
||||
npevent.lParam = 0;
|
||||
event.mPluginEvent.Copy(npevent);
|
||||
CallDefaultProc(&event);
|
||||
mSentStartComposition = true;
|
||||
}
|
||||
|
||||
CallDefaultProc(compositionEvent);
|
||||
}
|
||||
#endif // #ifdef XP_WIN
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -289,6 +289,9 @@ private:
|
||||
#if defined(XP_WIN)
|
||||
nsIWidget* GetContainingWidgetIfOffset();
|
||||
already_AddRefed<mozilla::TextComposition> GetTextComposition();
|
||||
|
||||
bool mGotCompositionData;
|
||||
bool mSentStartComposition;
|
||||
#endif
|
||||
|
||||
nsPluginNativeWindow *mPluginWindow;
|
||||
@ -342,6 +345,10 @@ private:
|
||||
nsresult DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent);
|
||||
nsresult DispatchCompositionToPlugin(nsIDOMEvent* aEvent);
|
||||
|
||||
#ifdef XP_WIN
|
||||
void CallDefaultProc(const mozilla::WidgetGUIEvent* aEvent);
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
static NPBool ConvertPointPuppet(PuppetWidget *widget, nsPluginFrame* pluginFrame,
|
||||
double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
|
||||
|
@ -1088,11 +1088,10 @@ IMMHandler::OnChar(nsWindow* aWindow,
|
||||
* message handlers for plug-in
|
||||
****************************************************************************/
|
||||
|
||||
bool
|
||||
void
|
||||
IMMHandler::OnIMEStartCompositionOnPlugin(nsWindow* aWindow,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
MSGResult& aResult)
|
||||
LPARAM lParam)
|
||||
{
|
||||
MOZ_LOG(gIMMLog, LogLevel::Info,
|
||||
("IMM: OnIMEStartCompositionOnPlugin, hWnd=%08x, mIsComposingOnPlugin=%s",
|
||||
@ -1104,17 +1103,12 @@ IMMHandler::OnIMEStartCompositionOnPlugin(nsWindow* aWindow,
|
||||
// On widnowless plugin, we should assume that the focused editor is always
|
||||
// in horizontal writing mode.
|
||||
AdjustCompositionFont(aWindow, context, WritingMode());
|
||||
aResult.mConsumed =
|
||||
aWindow->DispatchPluginEvent(WM_IME_STARTCOMPOSITION, wParam, lParam,
|
||||
false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
IMMHandler::OnIMECompositionOnPlugin(nsWindow* aWindow,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
MSGResult& aResult)
|
||||
LPARAM lParam)
|
||||
{
|
||||
MOZ_LOG(gIMMLog, LogLevel::Info,
|
||||
("IMM: OnIMECompositionOnPlugin, hWnd=%08x, lParam=%08x, "
|
||||
@ -1128,6 +1122,7 @@ IMMHandler::OnIMECompositionOnPlugin(nsWindow* aWindow,
|
||||
if (IS_COMMITTING_LPARAM(lParam)) {
|
||||
mIsComposingOnPlugin = false;
|
||||
mComposingWindow = nullptr;
|
||||
return;
|
||||
}
|
||||
// Continue composition if there is still a string being composed.
|
||||
if (IS_COMPOSING_LPARAM(lParam)) {
|
||||
@ -1136,16 +1131,12 @@ IMMHandler::OnIMECompositionOnPlugin(nsWindow* aWindow,
|
||||
IMEContext context(aWindow);
|
||||
SetIMERelatedWindowsPosOnPlugin(aWindow, context);
|
||||
}
|
||||
aResult.mConsumed =
|
||||
aWindow->DispatchPluginEvent(WM_IME_COMPOSITION, wParam, lParam, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
IMMHandler::OnIMEEndCompositionOnPlugin(nsWindow* aWindow,
|
||||
WPARAM wParam,
|
||||
LPARAM lParam,
|
||||
MSGResult& aResult)
|
||||
LPARAM lParam)
|
||||
{
|
||||
MOZ_LOG(gIMMLog, LogLevel::Info,
|
||||
("IMM: OnIMEEndCompositionOnPlugin, hWnd=%08x, mIsComposingOnPlugin=%s",
|
||||
@ -1158,11 +1149,6 @@ IMMHandler::OnIMEEndCompositionOnPlugin(nsWindow* aWindow,
|
||||
::DestroyCaret();
|
||||
mNativeCaretIsCreated = false;
|
||||
}
|
||||
|
||||
aResult.mConsumed =
|
||||
aWindow->DispatchPluginEvent(WM_IME_ENDCOMPOSITION, wParam, lParam,
|
||||
false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1231,6 +1217,12 @@ IMMHandler::OnCharOnPlugin(nsWindow* aWindow,
|
||||
LPARAM lParam,
|
||||
MSGResult& aResult)
|
||||
{
|
||||
NS_WARNING("OnCharOnPlugin");
|
||||
if (mIsComposing) {
|
||||
aWindow->NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
|
||||
return true;
|
||||
}
|
||||
|
||||
// We should never consume char message on windowless plugin.
|
||||
aResult.mConsumed = false;
|
||||
if (IsIMECharRecordsEmpty()) {
|
||||
@ -2757,6 +2749,33 @@ IMMHandler::SetCandidateWindow(nsWindow* aWindow, CANDIDATEFORM* aForm)
|
||||
ImmSetCandidateWindow(context.get(), aForm);
|
||||
}
|
||||
|
||||
// staitc
|
||||
void
|
||||
IMMHandler::DefaultProcOfPluginEvent(nsWindow* aWindow, const NPEvent* aEvent)
|
||||
{
|
||||
switch (aEvent->event) {
|
||||
case WM_IME_STARTCOMPOSITION:
|
||||
EnsureHandlerInstance();
|
||||
gIMMHandler->OnIMEStartCompositionOnPlugin(aWindow, aEvent->wParam,
|
||||
aEvent->lParam);
|
||||
break;
|
||||
|
||||
case WM_IME_COMPOSITION:
|
||||
if (gIMMHandler) {
|
||||
gIMMHandler->OnIMECompositionOnPlugin(aWindow, aEvent->wParam,
|
||||
aEvent->lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_IME_ENDCOMPOSITION:
|
||||
if (gIMMHandler) {
|
||||
gIMMHandler->OnIMEEndCompositionOnPlugin(aWindow, aEvent->wParam,
|
||||
aEvent->lParam);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* IMMHandler::Selection
|
||||
******************************************************************************/
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "nsRect.h"
|
||||
#include "WritingModes.h"
|
||||
#include "npapi.h"
|
||||
|
||||
class nsWindow;
|
||||
|
||||
@ -151,6 +152,8 @@ public:
|
||||
static nsresult OnMouseButtonEvent(nsWindow* aWindow,
|
||||
const IMENotification& aIMENotification);
|
||||
static void SetCandidateWindow(nsWindow* aWindow, CANDIDATEFORM* aForm);
|
||||
static void DefaultProcOfPluginEvent(nsWindow* aWindow,
|
||||
const NPEvent* aEvent);
|
||||
|
||||
protected:
|
||||
static void EnsureHandlerInstance();
|
||||
@ -192,16 +195,15 @@ protected:
|
||||
MSGResult& aResult);
|
||||
|
||||
bool OnIMEStartComposition(nsWindow* aWindow, MSGResult& aResult);
|
||||
bool OnIMEStartCompositionOnPlugin(nsWindow* aWindow,
|
||||
WPARAM wParam, LPARAM lParam,
|
||||
MSGResult& aResult);
|
||||
void OnIMEStartCompositionOnPlugin(nsWindow* aWindow,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
bool OnIMEComposition(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
|
||||
MSGResult& aResult);
|
||||
bool OnIMECompositionOnPlugin(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
|
||||
MSGResult& aResult);
|
||||
void OnIMECompositionOnPlugin(nsWindow* aWindow, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
bool OnIMEEndComposition(nsWindow* aWindow, MSGResult& aResult);
|
||||
bool OnIMEEndCompositionOnPlugin(nsWindow* aWindow, WPARAM wParam,
|
||||
LPARAM lParam, MSGResult& aResult);
|
||||
void OnIMEEndCompositionOnPlugin(nsWindow* aWindow, WPARAM wParam,
|
||||
LPARAM lParam);
|
||||
bool OnIMERequest(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
|
||||
MSGResult& aResult);
|
||||
bool OnIMECharOnPlugin(nsWindow* aWindow, WPARAM wParam, LPARAM lParam,
|
||||
|
@ -959,5 +959,16 @@ IMEHandler::SetCandidateWindow(nsWindow* aWindow, CANDIDATEFORM* aForm)
|
||||
IMMHandler::SetCandidateWindow(aWindow, aForm);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
IMEHandler::DefaultProcOfPluginEvent(nsWindow* aWindow,
|
||||
const NPEvent* aPluginEvent)
|
||||
{
|
||||
if (!sPluginHasFocus) {
|
||||
return;
|
||||
}
|
||||
IMMHandler::DefaultProcOfPluginEvent(aWindow, aPluginEvent);
|
||||
}
|
||||
|
||||
} // namespace widget
|
||||
} // namespace mozilla
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "npapi.h"
|
||||
#include <windows.h>
|
||||
#include <inputscope.h>
|
||||
|
||||
@ -108,6 +109,12 @@ public:
|
||||
*/
|
||||
static void SetCandidateWindow(nsWindow* aWindow, CANDIDATEFORM* aForm);
|
||||
|
||||
/*
|
||||
* For WM_IME_*COMPOSITION messages and e10s with windowless plugin
|
||||
*/
|
||||
static void DefaultProcOfPluginEvent(nsWindow* aWindow,
|
||||
const NPEvent* aPluginEvent);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Returns true when current keyboard layout has IME. Otherwise, false.
|
||||
|
@ -7777,6 +7777,9 @@ nsWindow::DefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
|
||||
return;
|
||||
}
|
||||
|
||||
// For WM_IME_*COMPOSITION
|
||||
IMEHandler::DefaultProcOfPluginEvent(this, pPluginEvent);
|
||||
|
||||
CallWindowProcW(GetPrevWindowProc(), mWnd, pPluginEvent->event,
|
||||
pPluginEvent->wParam, pPluginEvent->lParam);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user