Bug 1257759 part.5 PluginInstanceChild should post received native key event to chrome process if the key combination may be a shortcut key r=jimm

When PluginInstanceChild receives native key events, it should post the events to the chrome process first for checking if the key combination is reserved.  However, posting all key events to the chrome process may make damage to the performance of text input.  Therefore, this patch starts to post a key event whose key combination may be a shortcut key.  However, for avoiding to shuffle the event order, it posts following key events until all posted key events are handled by the chrome process.

For receiving response from widget, this patch defines nsIKeyEventInPluginCallback.  It's specified by nsIWidget::OnWindowedPluginKeyEvent() for ensuring the caller will receive the reply.  Basically, the caller of nsIWidget::OnWindowedPluginKeyEvent() should reply to the child process.  However, if the widget is a PuppetWidget, it cannot return the result synchronously.  Therefore, PuppetWidget::OnWindowedPluginKeyEvent() returns NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY and stores the callback to mKeyEventInPluginCallbacks.  Then, TabParent::HandledWindowedPluginKeyEvent() will call PuppetWidget::HandledWindowedPluginKeyEvent().

MozReview-Commit-ID: G6brOU26NwQ
This commit is contained in:
Masayuki Nakano
2016-04-19 20:09:37 +09:00
parent a42732a6b2
commit bbce223b06
31 changed files with 674 additions and 7 deletions

View File

@@ -67,6 +67,7 @@ using mozilla::EventMessage from "mozilla/EventForwards.h";
using nsEventStatus from "mozilla/EventForwards.h";
using nsSizeMode from "nsIWidgetListener.h";
using mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
using class mozilla::NativeEventData from "ipc/nsGUIEventIPC.h";
namespace mozilla {
namespace dom {
@@ -283,6 +284,16 @@ parent:
*/
async SetCandidateWindowForPlugin(CandidateWindowPosition aPosition);
/**
* Notifies the parent process of native key event data received in a
* plugin process directly.
*
* aKeyEventData The native key event data. The actual type copied into
* NativeEventData depending on the caller. Please check
* PluginInstanceChild.
*/
prio(urgent) async OnWindowedPluginKeyEvent(NativeEventData aKeyEventData);
/**
* When plugin event isn't consumed, call this
*/
@@ -732,6 +743,18 @@ child:
*/
async SetUseGlobalHistory(bool aUse);
/**
* HandledWindowedPluginKeyEvent() is always called after posting a native
* key event with OnWindowedPluginKeyEvent().
*
* @param aKeyEventData The key event which was posted to the parent
* process.
* @param aIsConsumed true if aKeyEventData is consumed in the
* parent process. Otherwise, false.
*/
async HandledWindowedPluginKeyEvent(NativeEventData aKeyEventData,
bool aIsConsumed);
/*
* FIXME: write protocol!

View File

@@ -2483,6 +2483,18 @@ TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNaviga
return true;
}
bool
TabChild::RecvHandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
const bool& aIsConsumed)
{
if (NS_WARN_IF(!mPuppetWidget)) {
return true;
}
mPuppetWidget->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
return true;
}
PRenderFrameChild*
TabChild::AllocPRenderFrameChild()
{

View File

@@ -575,6 +575,10 @@ public:
virtual bool RecvSetUseGlobalHistory(const bool& aUse) override;
virtual bool RecvHandledWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
const bool& aIsConsumed) override;
/**
* Native widget remoting protocol for use with windowed plugins with e10s.
*/

View File

@@ -1899,6 +1899,44 @@ TabParent::RecvOnEventNeedingAckHandled(const EventMessage& aMessage)
return true;
}
void
TabParent::HandledWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
bool aIsConsumed)
{
bool ok = SendHandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
NS_WARN_IF(!ok);
}
bool
TabParent::RecvOnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData)
{
nsCOMPtr<nsIWidget> widget = GetWidget();
if (NS_WARN_IF(!widget)) {
// Notifies the plugin process of the key event being not consumed by us.
HandledWindowedPluginKeyEvent(aKeyEventData, false);
return true;
}
nsresult rv = widget->OnWindowedPluginKeyEvent(aKeyEventData, this);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Notifies the plugin process of the key event being not consumed by us.
HandledWindowedPluginKeyEvent(aKeyEventData, false);
return true;
}
// If the key event is posted to another process, we need to wait a call
// of HandledWindowedPluginKeyEvent(). So, nothing to do here in this case.
if (rv == NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY) {
return true;
}
// Otherwise, the key event is handled synchronously. Let's notify the
// plugin process of the key event's result.
bool consumed = (rv == NS_SUCCESS_EVENT_CONSUMED);
HandledWindowedPluginKeyEvent(aKeyEventData, consumed);
return true;
}
bool
TabParent::RecvRequestFocus(const bool& aCanRaise)
{

View File

@@ -22,6 +22,7 @@
#include "nsIAuthPromptProvider.h"
#include "nsIBrowserDOMWindow.h"
#include "nsIDOMEventListener.h"
#include "nsIKeyEventInPluginCallback.h"
#include "nsISecureBrowserUI.h"
#include "nsITabParent.h"
#include "nsIWebBrowserPersistable.h"
@@ -82,6 +83,7 @@ class TabParent final : public PBrowserParent
, public nsITabParent
, public nsIAuthPromptProvider
, public nsISecureBrowserUI
, public nsIKeyEventInPluginCallback
, public nsSupportsWeakReference
, public TabContext
, public nsAPostRefreshObserver
@@ -255,6 +257,15 @@ public:
const int32_t& aCause,
const int32_t& aFocusChange) override;
// See nsIKeyEventInPluginCallback
virtual void HandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
bool aIsConsumed) override;
virtual bool RecvOnWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData) override;
virtual bool RecvRequestFocus(const bool& aCanRaise) override;
virtual bool

View File

@@ -334,4 +334,17 @@ PluginPRLibrary::UpdateScrollState(NPP aInstance, bool aIsScrolling)
}
#endif
nsresult
PluginPRLibrary::HandledWindowedPluginKeyEvent(
NPP aInstance,
const NativeEventData& aNativeKeyData,
bool aIsConsumed)
{
nsNPAPIPluginInstance* instance = (nsNPAPIPluginInstance*)aInstance->ndata;
if (NS_WARN_IF(!instance)) {
return NS_ERROR_NULL_POINTER;
}
return NS_OK;
}
} // namespace mozilla

View File

@@ -129,6 +129,10 @@ public:
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) override;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling) override;
#endif
virtual nsresult HandledWindowedPluginKeyEvent(
NPP aInstance,
const mozilla::NativeEventData& aNativeKeyData,
bool aIsCOnsumed) override;
private:
NP_InitializeFunc mNP_Initialize;

View File

@@ -1170,6 +1170,23 @@ nsNPAPIPluginInstance::UpdateScrollState(bool aIsScrolling)
}
#endif
nsresult
nsNPAPIPluginInstance::HandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
bool aIsConsumed)
{
if (NS_WARN_IF(!mPlugin)) {
return NS_ERROR_FAILURE;
}
PluginLibrary* library = mPlugin->GetLibrary();
if (NS_WARN_IF(!library)) {
return NS_ERROR_FAILURE;
}
return library->HandledWindowedPluginKeyEvent(&mNPP, aKeyEventData,
aIsConsumed);
}
void
nsNPAPIPluginInstance::DidComposite()
{

View File

@@ -28,6 +28,7 @@
class PluginEventRunnable;
#endif
#include "mozilla/EventForwards.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/PluginLibrary.h"
#include "mozilla/WeakPtr.h"
@@ -125,6 +126,9 @@ public:
nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer **aContainer);
nsresult UpdateScrollState(bool aIsScrolling);
#endif
nsresult HandledWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
bool aIsConsumed);
nsPluginInstanceOwner* GetOwner();
void SetOwner(nsPluginInstanceOwner *aOwner);
void DidComposite();

View File

@@ -418,6 +418,7 @@ NS_IMPL_ISUPPORTS(nsPluginInstanceOwner,
nsIPluginInstanceOwner,
nsIDOMEventListener,
nsIPrivacyTransitionObserver,
nsIKeyEventInPluginCallback,
nsISupportsWeakReference)
nsresult
@@ -993,8 +994,58 @@ nsPluginInstanceOwner::RequestCommitOrCancel(bool aCommitted)
}
return true;
}
#endif // #ifdef XP_WIN
void
nsPluginInstanceOwner::HandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
bool aIsConsumed)
{
if (NS_WARN_IF(!mInstance)) {
return;
}
nsresult rv =
mInstance->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
NS_WARN_IF(NS_FAILED(rv));
}
void
nsPluginInstanceOwner::OnWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData)
{
if (NS_WARN_IF(!mPluginFrame)) {
// Notifies the plugin process of the key event being not consumed by us.
HandledWindowedPluginKeyEvent(aKeyEventData, false);
return;
}
nsCOMPtr<nsIWidget> widget = mPluginFrame->PresContext()->GetRootWidget();
if (NS_WARN_IF(!widget)) {
// Notifies the plugin process of the key event being not consumed by us.
HandledWindowedPluginKeyEvent(aKeyEventData, false);
return;
}
nsresult rv = widget->OnWindowedPluginKeyEvent(aKeyEventData, this);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Notifies the plugin process of the key event being not consumed by us.
HandledWindowedPluginKeyEvent(aKeyEventData, false);
return;
}
// If the key event is posted to another process, we need to wait a call
// of HandledWindowedPluginKeyEvent(). So, nothing to do here in this case.
if (rv == NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY) {
return;
}
// Otherwise, the key event is handled synchronously. Let's notify the
// plugin process of the key event's result.
bool consumed = (rv == NS_SUCCESS_EVENT_CONSUMED);
HandledWindowedPluginKeyEvent(aKeyEventData, consumed);
}
NS_IMETHODIMP nsPluginInstanceOwner::SetEventModel(int32_t eventModel)
{
#ifdef XP_MACOSX

View File

@@ -10,6 +10,7 @@
#include "mozilla/Attributes.h"
#include "npapi.h"
#include "nsCOMPtr.h"
#include "nsIKeyEventInPluginCallback.h"
#include "nsIPluginInstanceOwner.h"
#include "nsIPrivacyTransitionObserver.h"
#include "nsIDOMEventListener.h"
@@ -52,10 +53,11 @@ using mozilla::widget::PuppetWidget;
#endif
#endif
class nsPluginInstanceOwner final : public nsIPluginInstanceOwner,
public nsIDOMEventListener,
public nsIPrivacyTransitionObserver,
public nsSupportsWeakReference
class nsPluginInstanceOwner final : public nsIPluginInstanceOwner
, public nsIDOMEventListener
, public nsIPrivacyTransitionObserver
, public nsIKeyEventInPluginCallback
, public nsSupportsWeakReference
{
public:
typedef mozilla::gfx::DrawTarget DrawTarget;
@@ -278,6 +280,21 @@ public:
const mozilla::widget::CandidateWindowPosition& aPosition);
bool RequestCommitOrCancel(bool aCommitted);
// See nsIKeyEventInPluginCallback
virtual void HandledWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
bool aIsConsumed) override;
/**
* OnWindowedPluginKeyEvent() is called when the plugin process receives
* native key event directly.
*
* @param aNativeKeyData The key event which was received by the
* plugin process directly.
*/
void OnWindowedPluginKeyEvent(
const mozilla::NativeEventData& aNativeKeyData);
void GetCSSZoomFactor(float *result);
private:
virtual ~nsPluginInstanceOwner();

View File

@@ -32,6 +32,7 @@ using nsIntRect from "nsRect.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
using struct DxgiAdapterDesc from "mozilla/D3DMessageUtils.h";
using struct mozilla::widget::CandidateWindowPosition from "ipc/nsGUIEventIPC.h";
using class mozilla::NativeEventData from "ipc/nsGUIEventIPC.h";
namespace mozilla {
namespace plugins {
@@ -140,6 +141,16 @@ child:
intr NPP_Destroy()
returns (NPError rv);
// HandledWindowedPluginKeyEvent() is always called after posting a native
// key event with OnWindowedPluginKeyEvent().
//
// @param aKeyEventData The key event which was posted to the parent
// process.
// @param aIsConsumed true if aKeyEventData is consumed in the
// parent process. Otherwise, false.
async HandledWindowedPluginKeyEvent(NativeEventData aKeyEventData,
bool aIsConsumed);
parent:
intr NPN_GetValue_NPNVWindowNPObject()
returns (nullable PPluginScriptableObject value, NPError result);
@@ -271,6 +282,13 @@ parent:
async SetCandidateWindow(CandidateWindowPosition aPosition);
async RequestCommitOrCancel(bool aCommitted);
// Notifies the parent process of a plugin instance receiving key event
// directly.
//
// @param aKeyEventData The native key event which will be sent to
// plugin from native event handler.
async OnWindowedPluginKeyEvent(NativeEventData aKeyEventData);
both:
async PPluginScriptableObject();

View File

@@ -32,6 +32,7 @@ using mozilla::gfx::SharedDIBSurface;
#include "gfxAlphaRecovery.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/BasicEvents.h"
#include "mozilla/ipc/MessageChannel.h"
#include "mozilla/AutoRestore.h"
#include "mozilla/StaticPtr.h"
@@ -43,6 +44,7 @@ using mozilla::ipc::ProcessChild;
using namespace mozilla::plugins;
using namespace mozilla::layers;
using namespace mozilla::gfx;
using namespace mozilla::widget;
using namespace std;
#ifdef MOZ_WIDGET_GTK
@@ -61,6 +63,8 @@ using namespace std;
#include <windowsx.h>
#include "mozilla/widget/WinMessages.h"
#include "mozilla/widget/WinModifierKeyState.h"
#include "mozilla/widget/WinNativeEventData.h"
#include "nsWindowsDllInterceptor.h"
typedef BOOL (WINAPI *User32TrackPopupMenu)(HMENU hMenu,
@@ -149,6 +153,7 @@ PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
#if defined(XP_DARWIN)
, mContentsScaleFactor(1.0)
#endif
, mPostingKeyEvents(0)
, mDrawingModel(kDefaultDrawingModel)
, mCurrentDirectSurface(nullptr)
, mAsyncInvalidateMutex("PluginInstanceChild::mAsyncInvalidateMutex")
@@ -1430,6 +1435,61 @@ PluginInstanceChild::Initialize()
return true;
}
bool
PluginInstanceChild::RecvHandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
const bool& aIsConsumed)
{
// Unknown key input shouldn't be sent to plugin for security.
// XXX Is this possible if a plugin process which posted the message
// already crashed and this plugin process is recreated?
if (NS_WARN_IF(!mPostingKeyEvents)) {
return true;
}
mPostingKeyEvents--;
if (aIsConsumed) {
return true;
}
#if defined(OS_WIN)
const WinNativeKeyEventData* eventData =
static_cast<const WinNativeKeyEventData*>(aKeyEventData);
UINT message = 0;
switch (eventData->mMessage) {
case WM_KEYDOWN:
message = MOZ_WM_KEYDOWN;
break;
case WM_SYSKEYDOWN:
message = MOZ_WM_SYSKEYDOWN;
break;
case WM_KEYUP:
message = MOZ_WM_KEYUP;
break;
case WM_SYSKEYUP:
message = MOZ_WM_SYSKEYUP;
break;
case WM_CHAR:
message = MOZ_WM_CHAR;
break;
case WM_SYSCHAR:
message = MOZ_WM_SYSCHAR;
break;
case WM_DEADCHAR:
message = MOZ_WM_DEADCHAR;
break;
case WM_SYSDEADCHAR:
message = MOZ_WM_SYSDEADCHAR;
break;
default:
MOZ_CRASH("Needs to handle all messages posted to the parent");
}
PluginWindowProcInternal(mPluginWindowHWND, message,
eventData->mWParam, eventData->mLParam);
#endif
return true;
}
#if defined(OS_WIN)
static const TCHAR kWindowClassName[] = TEXT("GeckoPluginWindow");
@@ -1588,6 +1648,51 @@ PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
break;
}
case WM_SETFOCUS:
// If this gets focus, ensure that there is no pending key events.
// Even if there were, we should ignore them for performance reason.
// Although, such case shouldn't occur.
NS_WARN_IF(self->mPostingKeyEvents > 0);
self->mPostingKeyEvents = 0;
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
if (self->MaybePostKeyMessage(message, wParam, lParam)) {
// If PreHandleKeyMessage() posts the message to the parent
// process, we need to wait RecvOnKeyEventHandledBeforePlugin()
// to be called.
return 0; // Consume current message temporarily.
}
break;
case MOZ_WM_KEYDOWN:
message = WM_KEYDOWN;
break;
case MOZ_WM_SYSKEYDOWN:
message = WM_SYSKEYDOWN;
break;
case MOZ_WM_KEYUP:
message = WM_KEYUP;
break;
case MOZ_WM_SYSKEYUP:
message = WM_SYSKEYUP;
break;
case MOZ_WM_CHAR:
message = WM_CHAR;
break;
case MOZ_WM_SYSCHAR:
message = WM_SYSCHAR;
break;
case MOZ_WM_DEADCHAR:
message = WM_DEADCHAR;
break;
case MOZ_WM_SYSDEADCHAR:
message = WM_SYSDEADCHAR;
break;
// The plugin received keyboard focus, let the parent know so the dom
// is up to date.
case WM_MOUSEACTIVATE:
@@ -1651,6 +1756,87 @@ PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
return res;
}
bool
PluginInstanceChild::ShouldPostKeyMessage(UINT message,
WPARAM wParam,
LPARAM lParam)
{
// If there are some pending keyboard events which are not handled in
// the parent process, we should post the message for avoiding to shuffle
// the key event order.
if (mPostingKeyEvents) {
return true;
}
// If we are not waiting calls of RecvOnKeyEventHandledBeforePlugin(),
// we don't need to post WM_*CHAR messages.
switch (message) {
case WM_CHAR:
case WM_SYSCHAR:
case WM_DEADCHAR:
case WM_SYSDEADCHAR:
return false;
}
// Otherwise, we should post key message which might match with a
// shortcut key.
ModifierKeyState modifierState;
if (!modifierState.MaybeMatchShortcutKey()) {
// For better UX, we shouldn't use IPC when user tries to
// input character(s).
return false;
}
// Ignore modifier key events and keys already handled by IME.
switch (wParam) {
case VK_SHIFT:
case VK_CONTROL:
case VK_MENU:
case VK_LWIN:
case VK_RWIN:
case VK_CAPITAL:
case VK_NUMLOCK:
case VK_SCROLL:
// Following virtual keycodes shouldn't come with WM_(SYS)KEY* message
// but check it for avoiding unnecessary cross process communication.
case VK_LSHIFT:
case VK_RSHIFT:
case VK_LCONTROL:
case VK_RCONTROL:
case VK_LMENU:
case VK_RMENU:
case VK_PROCESSKEY:
case VK_PACKET:
case 0xFF: // 0xFF could be sent with unidentified key by the layout.
return false;
default:
break;
}
return true;
}
bool
PluginInstanceChild::MaybePostKeyMessage(UINT message,
WPARAM wParam,
LPARAM lParam)
{
if (!ShouldPostKeyMessage(message, wParam, lParam)) {
return false;
}
ModifierKeyState modifierState;
WinNativeKeyEventData winNativeKeyData(message, wParam, lParam,
modifierState);
NativeEventData nativeKeyData;
nativeKeyData.Copy(winNativeKeyData);
if (NS_WARN_IF(!SendOnWindowedPluginKeyEvent(nativeKeyData))) {
return false;
}
mPostingKeyEvents++;
return true;
}
/* set window long ptr hook for flash */
/*

View File

@@ -7,6 +7,7 @@
#ifndef dom_plugins_PluginInstanceChild_h
#define dom_plugins_PluginInstanceChild_h 1
#include "mozilla/EventForwards.h"
#include "mozilla/plugins/PPluginInstanceChild.h"
#include "mozilla/plugins/PluginScriptableObjectChild.h"
#include "mozilla/plugins/StreamNotifyChild.h"
@@ -272,6 +273,11 @@ public:
void NPN_SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed);
void DoAsyncRedraw();
virtual bool RecvHandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
const bool& aIsConsumed) override;
private:
friend class PluginModuleChild;
@@ -394,7 +400,9 @@ private:
bool mWindowed;
};
#endif
bool ShouldPostKeyMessage(UINT message, WPARAM wParam, LPARAM lParam);
bool MaybePostKeyMessage(UINT message, WPARAM wParam, LPARAM lParam);
#endif // #if defined(OS_WIN)
const NPPluginFuncs* mPluginIface;
nsCString mMimeType;
uint16_t mMode;
@@ -406,6 +414,7 @@ private:
double mContentsScaleFactor;
#endif
double mCSSZoomFactor;
uint32_t mPostingKeyEvents;
int16_t mDrawingModel;
NPAsyncSurface* mCurrentDirectSurface;

View File

@@ -7,6 +7,7 @@
#include "mozilla/DebugOnly.h"
#include <stdint.h> // for intptr_t
#include "mozilla/BasicEvents.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "PluginInstanceParent.h"
@@ -2662,6 +2663,33 @@ PluginInstanceParent::RecvRequestCommitOrCancel(const bool& aCommitted)
return true;
}
nsresult
PluginInstanceParent::HandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
bool aIsConsumed)
{
if (NS_WARN_IF(!SendHandledWindowedPluginKeyEvent(aKeyEventData,
aIsConsumed))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
bool
PluginInstanceParent::RecvOnWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData)
{
nsPluginInstanceOwner* owner = GetOwner();
if (NS_WARN_IF(!owner)) {
// Notifies the plugin process of the key event being not consumed
// by us.
HandledWindowedPluginKeyEvent(aKeyEventData, false);
return true;
}
owner->OnWindowedPluginKeyEvent(aKeyEventData);
return true;
}
void
PluginInstanceParent::RecordDrawingModel()
{

View File

@@ -25,6 +25,7 @@
#include "PluginDataResolver.h"
#include "mozilla/unused.h"
#include "mozilla/EventForwards.h"
class gfxASurface;
class gfxContext;
@@ -356,6 +357,14 @@ public:
virtual bool
RecvRequestCommitOrCancel(const bool& aCommitted) override;
// for reserved shortcut key handling with windowed plugin on Windows
nsresult HandledWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
bool aIsConsumed);
virtual bool
RecvOnWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData) override;
private:
// Create an appropriate platform surface for a background of size
// |aSize|. Return true if successful.

View File

@@ -91,6 +91,10 @@ public:
virtual nsresult GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) = 0;
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling) = 0;
#endif
virtual nsresult HandledWindowedPluginKeyEvent(
NPP aInstance,
const mozilla::NativeEventData& aNativeKeyData,
bool aIsCOnsumed) = 0;
/**
* The next three methods are the third leg in the trip to

View File

@@ -2014,6 +2014,19 @@ PluginModuleParent::UpdateScrollState(NPP aInstance, bool aIsScrolling)
}
#endif
nsresult
PluginModuleParent::HandledWindowedPluginKeyEvent(
NPP aInstance,
const NativeEventData& aNativeKeyData,
bool aIsConsumed)
{
PluginInstanceParent* parent = PluginInstanceParent::Cast(aInstance);
if (NS_WARN_IF(!parent)) {
return NS_ERROR_FAILURE;
}
return parent->HandledWindowedPluginKeyEvent(aNativeKeyData, aIsConsumed);
}
void
PluginModuleParent::OnInitFailure()
{

View File

@@ -266,6 +266,11 @@ protected:
virtual nsresult UpdateScrollState(NPP aInstance, bool aIsScrolling);
#endif
virtual nsresult HandledWindowedPluginKeyEvent(
NPP aInstance,
const mozilla::NativeEventData& aNativeKeyData,
bool aIsConsumed) override;
#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK)
virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) override;
#else

View File

@@ -1459,5 +1459,34 @@ PuppetWidget::HasPendingInputEvent()
return ret;
}
void
PuppetWidget::HandledWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
bool aIsConsumed)
{
if (NS_WARN_IF(mKeyEventInPluginCallbacks.IsEmpty())) {
return;
}
nsCOMPtr<nsIKeyEventInPluginCallback> callback =
mKeyEventInPluginCallbacks[0];
MOZ_ASSERT(callback);
mKeyEventInPluginCallbacks.RemoveElementAt(0);
callback->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed);
}
nsresult
PuppetWidget::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback)
{
if (NS_WARN_IF(!mTabChild)) {
return NS_ERROR_NOT_AVAILABLE;
}
if (NS_WARN_IF(!mTabChild->SendOnWindowedPluginKeyEvent(aKeyEventData))) {
return NS_ERROR_FAILURE;
}
mKeyEventInPluginCallbacks.AppendElement(aCallback);
return NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY;
}
} // namespace widget
} // namespace mozilla

View File

@@ -19,6 +19,8 @@
#include "mozilla/RefPtr.h"
#include "nsBaseScreen.h"
#include "nsBaseWidget.h"
#include "nsCOMArray.h"
#include "nsIKeyEventInPluginCallback.h"
#include "nsIScreenManager.h"
#include "nsThreadUtils.h"
#include "mozilla/Attributes.h"
@@ -262,6 +264,12 @@ public:
virtual bool HasPendingInputEvent() override;
void HandledWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
bool aIsConsumed);
virtual nsresult OnWindowedPluginKeyEvent(
const NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback) override;
protected:
virtual nsresult NotifyIMEInternal(
const IMENotification& aIMENotification) override;
@@ -348,6 +356,8 @@ private:
nsCOMPtr<imgIContainer> mCustomCursor;
uint32_t mCursorHotspotX, mCursorHotspotY;
nsCOMArray<nsIKeyEventInPluginCallback> mKeyEventInPluginCallbacks;
protected:
bool mEnabled;
bool mVisible;

View File

@@ -96,6 +96,7 @@ EXPORTS += [
'nsBaseWidget.h',
'nsDeviceContextSpecProxy.h',
'nsIDeviceContextSpec.h',
'nsIKeyEventInPluginCallback.h',
'nsIPluginWidget.h',
'nsIRollupListener.h',
'nsIWidget.h',

View File

@@ -18,6 +18,7 @@
#include "nsGfxCIID.h"
#include "nsWidgetsCID.h"
#include "nsServiceManagerUtils.h"
#include "nsIKeyEventInPluginCallback.h"
#include "nsIScreenManager.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsISimpleEnumerator.h"
@@ -2140,6 +2141,13 @@ nsIWidget::GetNativeIMEContext()
return NativeIMEContext(this);
}
nsresult
nsIWidget::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
namespace mozilla {
namespace widget {

View File

@@ -0,0 +1,42 @@
/* -*- Mode: C++; tab-width: 40; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 nsIKeyEventInPluginCallback_h_
#define nsIKeyEventInPluginCallback_h_
#include "mozilla/EventForwards.h"
#include "nsISupports.h"
#define NS_IKEYEVENTINPLUGINCALLBACK_IID \
{ 0x543c5a8a, 0xc50e, 0x4cf9, \
{ 0xa6, 0xba, 0x29, 0xa1, 0xc5, 0xa5, 0x47, 0x07 } }
class nsIKeyEventInPluginCallback : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_IKEYEVENTINPLUGINCALLBACK_IID)
/**
* HandledWindowedPluginKeyEvent() is a callback method of
* nsIWidget::OnWindowedPluginKeyEvent(). When it returns
* NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY, it should call this method
* when the key event is handled.
*
* @param aKeyEventData The key event which was posted to the parent
* process from a plugin process.
* @param aIsConsumed true if aKeyEventData is consumed in the
* parent process. Otherwise, false.
*/
virtual void HandledWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
bool aIsConsumed) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsIKeyEventInPluginCallback,
NS_IKEYEVENTINPLUGINCALLBACK_IID)
#endif // #ifndef nsIKeyEventInPluginCallback_h_

View File

@@ -39,6 +39,7 @@ class nsIContent;
class ViewWrapper;
class nsIScreen;
class nsIRunnable;
class nsIKeyEventInPluginCallback;
namespace mozilla {
class CompositorVsyncDispatcher;
@@ -2054,6 +2055,28 @@ public:
const CSSRect& aRect,
const uint32_t& aFlags) = 0;
/**
* OnWindowedPluginKeyEvent() is called when native key event is
* received in the focused plugin process directly in PluginInstanceChild.
*
* @param aKeyEventData The native key event data. The actual type
* copied into NativeEventData depends on the
* caller. Please check PluginInstanceChild.
* @param aCallback Callback interface. When this returns
* NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY,
* the event handler has to call this callback.
* Otherwise, the caller should do that instead.
* @return NS_ERROR_* if this fails to handle the event.
* NS_SUCCESS_EVENT_CONSUMED if the key event is
* consumed.
* NS_OK if the key event isn't consumed.
* NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY if the
* key event will be handled asynchronously.
*/
virtual nsresult OnWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback);
protected:
/**
* Like GetDefaultScale, but taking into account only the system settings

View File

@@ -34,6 +34,17 @@
// Internal message used for hiding the on-screen keyboard
#define MOZ_WM_DISMISS_ONSCREEN_KEYBOARD (WM_APP+0x0317)
// Following MOZ_WM_*KEY* messages are used by PluginInstanceChild internally.
// (never posted to the queue)
#define MOZ_WM_KEYDOWN (WM_APP+0x0318)
#define MOZ_WM_KEYUP (WM_APP+0x0319)
#define MOZ_WM_SYSKEYDOWN (WM_APP+0x031A)
#define MOZ_WM_SYSKEYUP (WM_APP+0x031B)
#define MOZ_WM_CHAR (WM_APP+0x031C)
#define MOZ_WM_SYSCHAR (WM_APP+0x031D)
#define MOZ_WM_DEADCHAR (WM_APP+0x031E)
#define MOZ_WM_SYSDEADCHAR (WM_APP+0x031F)
// Internal message for ensuring the file picker is visible on multi monitor
// systems, and when the screen resolution changes.
#define MOZ_WM_ENSUREVISIBLE (WM_APP+0x374F)

View File

@@ -0,0 +1,56 @@
/* -*- 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 mozilla_widget_WinNativeEventData_h_
#define mozilla_widget_WinNativeEventData_h_
#include <windows.h>
#include "mozilla/EventForwards.h"
#include "mozilla/widget/WinModifierKeyState.h"
namespace mozilla {
namespace widget {
/**
* WinNativeKeyEventData is used by nsIWidget::OnWindowedPluginKeyEvent() and
* related IPC methods. This class cannot hold any pointers and references
* since which are not available in different process.
*/
class WinNativeKeyEventData final
{
public:
UINT mMessage;
WPARAM mWParam;
LPARAM mLParam;
Modifiers mModifiers;
private:
uintptr_t mKeyboardLayout;
public:
WinNativeKeyEventData(UINT aMessage,
WPARAM aWParam,
LPARAM aLParam,
const ModifierKeyState& aModifierKeyState)
: mMessage(aMessage)
, mWParam(aWParam)
, mLParam(aLParam)
, mModifiers(aModifierKeyState.GetModifiers())
, mKeyboardLayout(reinterpret_cast<uintptr_t>(::GetKeyboardLayout(0)))
{
}
HKL GetKeyboardLayout() const
{
return reinterpret_cast<HKL>(mKeyboardLayout);
}
};
} // namespace widget
} // namespace mozilla
#endif // #ifndef mozilla_widget_WinNativeEventData_h_

View File

@@ -16,6 +16,7 @@ EXPORTS.mozilla.widget += [
'AudioSession.h',
'WinMessages.h',
'WinModifierKeyState.h',
'WinNativeEventData.h',
]
UNIFIED_SOURCES += [

View File

@@ -86,6 +86,7 @@
#include "nsIAppShell.h"
#include "nsISupportsPrimitives.h"
#include "nsIDOMMouseEvent.h"
#include "nsIKeyEventInPluginCallback.h"
#include "nsITheme.h"
#include "nsIObserverService.h"
#include "nsIScreenManager.h"
@@ -7869,6 +7870,14 @@ nsWindow::DefaultProcOfPluginEvent(const WidgetPluginEvent& aEvent)
pPluginEvent->wParam, pPluginEvent->lParam);
}
nsresult
nsWindow::OnWindowedPluginKeyEvent(const NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback)
{
// TODO: Implement in the following patch.
return NS_ERROR_NOT_IMPLEMENTED;
}
/**************************************************************
**************************************************************
**

View File

@@ -311,6 +311,9 @@ public:
aPosition) override;
virtual void DefaultProcOfPluginEvent(
const mozilla::WidgetPluginEvent& aEvent) override;
virtual nsresult OnWindowedPluginKeyEvent(
const mozilla::NativeEventData& aKeyEventData,
nsIKeyEventInPluginCallback* aCallback) override;
protected:
virtual ~nsWindow();

View File

@@ -118,9 +118,17 @@
/* 4: NS_ERROR_MODULE_WIDGET */
/* ======================================================================= */
#define MODULE NS_ERROR_MODULE_WIDGET
/* Used by nsIWidget::NotifyIME(). Returned when the notification is handled
* and the notified event is consumed by IME. */
/* Used by:
* - nsIWidget::NotifyIME()
* - nsIWidget::OnWindowedPluginKeyEvent()
* Returned when the notification or the event is handled and it's consumed
* by somebody. */
ERROR(NS_SUCCESS_EVENT_CONSUMED, SUCCESS(1)),
/* Used by:
* - nsIWidget::OnWindowedPluginKeyEvent()
* Returned when the event is handled correctly but the result will be
* notified asynchronously. */
ERROR(NS_SUCCESS_EVENT_HANDLED_ASYNCHRONOUSLY, SUCCESS(2)),
#undef MODULE