Bug 993714 - [e10s] Cache native key bindings in tests (r=masayuki,sr=roc)

This commit is contained in:
Bill McCloskey 2014-04-21 13:40:09 -07:00
parent 516d6336f0
commit 204c0f3633
12 changed files with 160 additions and 24 deletions

View File

@ -353,6 +353,9 @@ parent:
ReplyKeyEvent(WidgetKeyboardEvent event);
sync RequestNativeKeyBindings(WidgetKeyboardEvent event)
returns (MaybeNativeKeyBinding bindings);
child:
/**
* Notify the remote browser that it has been Show()n on this

View File

@ -1,4 +1,4 @@
/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*- */
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- */
/* vim: set sw=2 sts=2 ts=8 et tw=80 : */
/* 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
@ -2027,19 +2027,40 @@ TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent,
return RecvRealTouchEvent(aEvent, aGuid);
}
void
TabChild::RequestNativeKeyBindings(AutoCacheNativeKeyCommands* aAutoCache,
WidgetKeyboardEvent* aEvent)
{
MaybeNativeKeyBinding maybeBindings;
if (!SendRequestNativeKeyBindings(*aEvent, &maybeBindings)) {
return;
}
if (maybeBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
const NativeKeyBinding& bindings = maybeBindings;
aAutoCache->Cache(bindings.singleLineCommands(),
bindings.multiLineCommands(),
bindings.richTextCommands());
} else {
aAutoCache->CacheNoCommands();
}
}
bool
TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
const MaybeNativeKeyBinding& aBindings)
{
{
PuppetWidget* widget = static_cast<PuppetWidget*>(mWidget.get());
AutoCacheNativeKeyCommands autoCache(widget);
if (event.message == NS_KEY_PRESS) {
PuppetWidget* widget = static_cast<PuppetWidget*>(mWidget.get());
if (aBindings.type() == MaybeNativeKeyBinding::TNativeKeyBinding) {
const NativeKeyBinding& bindings = aBindings;
widget->CacheNativeKeyCommands(bindings.singleLineCommands(),
bindings.multiLineCommands(),
bindings.richTextCommands());
autoCache.Cache(bindings.singleLineCommands(),
bindings.multiLineCommands(),
bindings.richTextCommands());
} else {
widget->ClearNativeKeyCommands();
autoCache.CacheNoCommands();
}
}
// If content code called preventDefault() on a keydown event, then we don't

View File

@ -46,6 +46,10 @@ namespace layers {
class ActiveElementManager;
}
namespace widget {
struct AutoCacheNativeKeyCommands;
}
namespace dom {
class TabChild;
@ -393,6 +397,8 @@ public:
void NotifyPainted();
void RequestNativeKeyBindings(mozilla::widget::AutoCacheNativeKeyCommands* aAutoCache,
WidgetKeyboardEvent* aEvent);
/** Return a boolean indicating if the page has called preventDefault on
* the event.

View File

@ -791,6 +791,41 @@ DoCommandCallback(mozilla::Command aCommand, void* aData)
static_cast<InfallibleTArray<mozilla::CommandInt>*>(aData)->AppendElement(aCommand);
}
bool
TabParent::RecvRequestNativeKeyBindings(const WidgetKeyboardEvent& aEvent,
MaybeNativeKeyBinding* aBindings)
{
AutoInfallibleTArray<mozilla::CommandInt, 4> singleLine;
AutoInfallibleTArray<mozilla::CommandInt, 4> multiLine;
AutoInfallibleTArray<mozilla::CommandInt, 4> richText;
*aBindings = mozilla::void_t();
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return true;
}
WidgetKeyboardEvent localEvent(aEvent);
if (NS_FAILED(widget->AttachNativeKeyEvent(localEvent))) {
return true;
}
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForSingleLineEditor,
localEvent, DoCommandCallback, &singleLine);
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForMultiLineEditor,
localEvent, DoCommandCallback, &multiLine);
widget->ExecuteNativeKeyBinding(nsIWidget::NativeKeyBindingsForRichTextEditor,
localEvent, DoCommandCallback, &richText);
if (!singleLine.IsEmpty() || !multiLine.IsEmpty() || !richText.IsEmpty()) {
*aBindings = NativeKeyBinding(singleLine, multiLine, richText);
}
return true;
}
bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event)
{
if (mIsDestroyed) {

View File

@ -222,6 +222,9 @@ public:
void MapEventCoordinatesForChildProcess(const LayoutDeviceIntPoint& aOffset,
mozilla::WidgetEvent* aEvent);
virtual bool RecvRequestNativeKeyBindings(const mozilla::WidgetKeyboardEvent& aEvent,
MaybeNativeKeyBinding* aBindings) MOZ_OVERRIDE;
void SendMouseEvent(const nsAString& aType, float aX, float aY,
int32_t aButton, int32_t aClickCount,
int32_t aModifiers, bool aIgnoreRootScrollFrame);

View File

@ -8905,6 +8905,7 @@ PresShell::DelayedKeyEvent::DelayedKeyEvent(WidgetKeyboardEvent* aEvent) :
aEvent->message,
aEvent->widget);
keyEvent->AssignKeyEventData(*aEvent, false);
keyEvent->mFlags.mIsSynthesizedForTests = aEvent->mFlags.mIsSynthesizedForTests;
mEvent = keyEvent;
}

View File

@ -521,6 +521,7 @@ public:
NS_IMETHOD_(void) SetInputContext(const InputContext& aContext,
const InputContextAction& aAction);
NS_IMETHOD_(InputContext) GetInputContext();
NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent);
NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,

View File

@ -1942,6 +1942,13 @@ nsChildView::GetInputContext()
return mInputContext;
}
NS_IMETHODIMP
nsChildView::AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent)
{
NS_ENSURE_TRUE(mTextInputHandler, NS_ERROR_NOT_AVAILABLE);
return mTextInputHandler->AttachNativeKeyEvent(aEvent);
}
NS_IMETHODIMP_(bool)
nsChildView::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
const WidgetKeyboardEvent& aEvent,

View File

@ -100,8 +100,8 @@ typedef void* nsNativeWidget;
#endif
#define NS_IWIDGET_IID \
{ 0x8e081187, 0xf123, 0x4572, \
{ 0x82, 0xc6, 0x4c, 0xcd, 0xc2, 0x0e, 0xbd, 0xf9 } }
{ 0x87d80888, 0x9917, 0x4bfb, \
{ 0x81, 0xa9, 0x1c, 0x5e, 0x30, 0x9c, 0x78, 0xb4 } }
/*
* Window shadow styles
@ -1811,6 +1811,14 @@ public:
*/
NS_IMETHOD_(InputContext) GetInputContext() = 0;
/*
* Given a WidgetKeyboardEvent, this method synthesizes a corresponding
* native (OS-level) event for it. This method allows tests to simulate
* keystrokes that trigger native key bindings (which require a native
* event).
*/
NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) = 0;
/*
* Execute native key bindings for aType.
*/

View File

@ -79,6 +79,7 @@ PuppetWidget::PuppetWidget(TabChild* aTabChild)
: mTabChild(aTabChild)
, mDPI(-1)
, mDefaultScale(-1)
, mNativeKeyCommandsValid(false)
{
MOZ_COUNT_CTOR(PuppetWidget);
@ -275,6 +276,14 @@ PuppetWidget::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
NS_ABORT_IF_FALSE(!mChild || mChild->mWindowType == eWindowType_popup,
"Unexpected event dispatch!");
AutoCacheNativeKeyCommands autoCache(this);
if (event->mFlags.mIsSynthesizedForTests && !mNativeKeyCommandsValid) {
WidgetKeyboardEvent* keyEvent = event->AsKeyboardEvent();
if (keyEvent) {
mTabChild->RequestNativeKeyBindings(&autoCache, keyEvent);
}
}
aStatus = nsEventStatus_eIgnore;
if (event->message == NS_COMPOSITION_START) {
@ -319,6 +328,12 @@ PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
DoCommandCallback aCallback,
void* aCallbackData)
{
// B2G doesn't have native key bindings.
#ifdef MOZ_B2G
return false;
#else // #ifdef MOZ_B2G
MOZ_ASSERT(mNativeKeyCommandsValid);
nsTArray<mozilla::CommandInt>& commands = mSingleLineCommands;
switch (aType) {
case nsIWidget::NativeKeyBindingsForSingleLineEditor:
@ -340,6 +355,7 @@ PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
aCallback(static_cast<mozilla::Command>(commands[i]), aCallbackData);
}
return true;
#endif
}
LayerManager*

View File

@ -33,6 +33,8 @@ class TabChild;
namespace widget {
class AutoCacheNativeKeyCommands;
class PuppetWidget : public nsBaseWidget, public nsSupportsWeakReference
{
typedef mozilla::dom::TabChild TabChild;
@ -136,21 +138,7 @@ public:
DoCommandCallback aCallback,
void* aCallbackData) MOZ_OVERRIDE;
void CacheNativeKeyCommands(const InfallibleTArray<mozilla::CommandInt>& aSingleLineCommands,
const InfallibleTArray<mozilla::CommandInt>& aMultiLineCommands,
const InfallibleTArray<mozilla::CommandInt>& aRichTextCommands)
{
mSingleLineCommands = aSingleLineCommands;
mMultiLineCommands = aMultiLineCommands;
mRichTextCommands = aRichTextCommands;
}
void ClearNativeKeyCommands()
{
mSingleLineCommands.Clear();
mMultiLineCommands.Clear();
mRichTextCommands.Clear();
}
friend class AutoCacheNativeKeyCommands;
//
// nsBaseWidget methods we override
@ -250,11 +238,57 @@ private:
double mDefaultScale;
// Precomputed answers for ExecuteNativeKeyBinding
bool mNativeKeyCommandsValid;
InfallibleTArray<mozilla::CommandInt> mSingleLineCommands;
InfallibleTArray<mozilla::CommandInt> mMultiLineCommands;
InfallibleTArray<mozilla::CommandInt> mRichTextCommands;
};
struct AutoCacheNativeKeyCommands
{
AutoCacheNativeKeyCommands(PuppetWidget* aWidget)
: mWidget(aWidget)
{
mSavedValid = mWidget->mNativeKeyCommandsValid;
mSavedSingleLine = mWidget->mSingleLineCommands;
mSavedMultiLine = mWidget->mMultiLineCommands;
mSavedRichText = mWidget->mRichTextCommands;
}
void Cache(const InfallibleTArray<mozilla::CommandInt>& aSingleLineCommands,
const InfallibleTArray<mozilla::CommandInt>& aMultiLineCommands,
const InfallibleTArray<mozilla::CommandInt>& aRichTextCommands)
{
mWidget->mNativeKeyCommandsValid = true;
mWidget->mSingleLineCommands = aSingleLineCommands;
mWidget->mMultiLineCommands = aMultiLineCommands;
mWidget->mRichTextCommands = aRichTextCommands;
}
void CacheNoCommands()
{
mWidget->mNativeKeyCommandsValid = true;
mWidget->mSingleLineCommands.Clear();
mWidget->mMultiLineCommands.Clear();
mWidget->mRichTextCommands.Clear();
}
~AutoCacheNativeKeyCommands()
{
mWidget->mNativeKeyCommandsValid = mSavedValid;
mWidget->mSingleLineCommands = mSavedSingleLine;
mWidget->mMultiLineCommands = mSavedMultiLine;
mWidget->mRichTextCommands = mSavedRichText;
}
private:
PuppetWidget* mWidget;
bool mSavedValid;
InfallibleTArray<mozilla::CommandInt> mSavedSingleLine;
InfallibleTArray<mozilla::CommandInt> mSavedMultiLine;
InfallibleTArray<mozilla::CommandInt> mSavedRichText;
};
class PuppetScreen : public nsBaseScreen
{
public:

View File

@ -181,6 +181,7 @@ public:
virtual nsresult ActivateNativeMenuItemAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
virtual nsresult ForceUpdateNativeMenuAt(const nsAString& indexString) { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD NotifyIME(const IMENotification& aIMENotification) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; }
NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
NativeKeyBindingsType aType,
const mozilla::WidgetKeyboardEvent& aEvent,