зеркало из https://github.com/mozilla/gecko-dev.git
Bug 788943: Allow TabParents to capture event series for faster dispatch to subprocesses. Implements capturing of touch-event series. r=smaug sr=roc
This commit is contained in:
Родитель
b3325f556e
Коммит
ec4f0b7652
|
@ -1576,6 +1576,42 @@ nsEventStateManager::IsRemoteTarget(nsIContent* target) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nsEventStateManager::MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader,
|
||||
nsEvent* aEvent)
|
||||
{
|
||||
// The "toplevel widget" in child processes is always at position
|
||||
// 0,0. Map the event coordinates to match that.
|
||||
nsIFrame* targetFrame = aFrameLoader->GetPrimaryFrameOfOwningContent();
|
||||
if (!targetFrame) {
|
||||
return;
|
||||
}
|
||||
nsPresContext* presContext = targetFrame->PresContext();
|
||||
|
||||
if (aEvent->eventStructType != NS_TOUCH_EVENT) {
|
||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
|
||||
targetFrame);
|
||||
aEvent->refPoint = pt.ToNearestPixels(presContext->AppUnitsPerDevPixel());
|
||||
} else {
|
||||
aEvent->refPoint = nsIntPoint();
|
||||
// Find out how far we're offset from the nearest widget.
|
||||
nsPoint offset =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, targetFrame);
|
||||
nsIntPoint intOffset =
|
||||
offset.ToNearestPixels(presContext->AppUnitsPerDevPixel());
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
// Then offset all the touch points by that distance, to put them
|
||||
// in the space where top-left is 0,0.
|
||||
const nsTArray<nsCOMPtr<nsIDOMTouch> >& touches = touchEvent->touches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
nsIDOMTouch* touch = touches[i];
|
||||
if (touch) {
|
||||
touch->mRefPoint += intOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CrossProcessSafeEvent(const nsEvent& aEvent)
|
||||
{
|
||||
|
@ -1689,32 +1725,7 @@ nsEventStateManager::HandleCrossProcessEvent(nsEvent *aEvent,
|
|||
continue;
|
||||
}
|
||||
|
||||
// The "toplevel widget" in content processes is always at position
|
||||
// 0,0. Map the event coordinates to match that.
|
||||
if (aEvent->eventStructType != NS_TOUCH_EVENT) {
|
||||
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
|
||||
aTargetFrame);
|
||||
aEvent->refPoint =
|
||||
pt.ToNearestPixels(mPresContext->AppUnitsPerDevPixel());
|
||||
} else {
|
||||
nsIFrame* targetFrame = frameLoader->GetPrimaryFrameOfOwningContent();
|
||||
aEvent->refPoint = nsIntPoint();
|
||||
// Find out how far we're offset from the nearest widget.
|
||||
nsPoint offset =
|
||||
nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, targetFrame);
|
||||
nsIntPoint intOffset =
|
||||
offset.ToNearestPixels(mPresContext->AppUnitsPerDevPixel());
|
||||
nsTouchEvent* touchEvent = static_cast<nsTouchEvent*>(aEvent);
|
||||
// Then offset all the touch points by that distance, to put them
|
||||
// in the space where top-left is 0,0.
|
||||
const nsTArray<nsCOMPtr<nsIDOMTouch> >& touches = touchEvent->touches;
|
||||
for (uint32_t i = 0; i < touches.Length(); ++i) {
|
||||
nsIDOMTouch* touch = touches[i];
|
||||
if (touch) {
|
||||
touch->mRefPoint += intOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
MapEventCoordinatesForChildProcess(frameLoader, aEvent);
|
||||
|
||||
dispatched |= DispatchCrossProcessEvent(aEvent, frameLoader, aStatus);
|
||||
}
|
||||
|
|
|
@ -204,6 +204,9 @@ public:
|
|||
|
||||
static bool IsRemoteTarget(nsIContent* aTarget);
|
||||
|
||||
static void MapEventCoordinatesForChildProcess(nsFrameLoader* aFrameLoader,
|
||||
nsEvent* aEvent);
|
||||
|
||||
// Holds the point in screen coords that a mouse event was dispatched to,
|
||||
// before we went into pointer lock mode. This is constantly updated while
|
||||
// the pointer is not locked, but we don't update it while the pointer is
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsContentUtils.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsEventStateManager.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsFrameLoader.h"
|
||||
#include "nsIContent.h"
|
||||
|
@ -66,6 +67,8 @@ using namespace mozilla::dom::indexedDB;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
TabParent* sEventCapturer;
|
||||
|
||||
TabParent *TabParent::mIMETabParent = nullptr;
|
||||
|
||||
NS_IMPL_ISUPPORTS3(TabParent, nsITabParent, nsIAuthPromptProvider, nsISecureBrowserUI)
|
||||
|
@ -79,6 +82,7 @@ TabParent::TabParent(mozIApplication* aApp, bool aIsBrowserElement)
|
|||
, mIMECompositionEnding(false)
|
||||
, mIMECompositionStart(0)
|
||||
, mIMESeqno(0)
|
||||
, mEventCaptureDepth(0)
|
||||
, mDPI(0)
|
||||
, mActive(false)
|
||||
, mIsBrowserElement(aIsBrowserElement)
|
||||
|
@ -121,8 +125,12 @@ TabParent::Recv__delete__()
|
|||
void
|
||||
TabParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (mIMETabParent == this)
|
||||
if (sEventCapturer == this) {
|
||||
sEventCapturer = nullptr;
|
||||
}
|
||||
if (mIMETabParent == this) {
|
||||
mIMETabParent = nullptr;
|
||||
}
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
if (frameLoader) {
|
||||
frameLoader->DestroyChild();
|
||||
|
@ -361,21 +369,72 @@ bool TabParent::SendRealKeyEvent(nsKeyEvent& event)
|
|||
|
||||
bool TabParent::SendRealTouchEvent(nsTouchEvent& event)
|
||||
{
|
||||
if (event.message == NS_TOUCH_START) {
|
||||
MOZ_ASSERT((!sEventCapturer && mEventCaptureDepth == 0) ||
|
||||
(sEventCapturer == this && mEventCaptureDepth > 0));
|
||||
// We want to capture all remaining touch events in this series
|
||||
// for fast-path dispatch.
|
||||
sEventCapturer = this;
|
||||
++mEventCaptureDepth;
|
||||
}
|
||||
|
||||
nsTouchEvent e(event);
|
||||
// PresShell::HandleEventInternal adds touches on touch end/cancel.
|
||||
// PresShell::HandleEventInternal adds touches on touch end/cancel,
|
||||
// when we're not capturing raw events from the widget backend.
|
||||
// This hack filters those out. Bug 785554
|
||||
if (event.message == NS_TOUCH_END || event.message == NS_TOUCH_CANCEL) {
|
||||
if (sEventCapturer != this &&
|
||||
(event.message == NS_TOUCH_END || event.message == NS_TOUCH_CANCEL)) {
|
||||
for (int i = e.touches.Length() - 1; i >= 0; i--) {
|
||||
if (!e.touches[i]->mChanged)
|
||||
e.touches.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
MaybeForwardEventToRenderFrame(event, &e);
|
||||
return (e.message == NS_TOUCH_MOVE) ?
|
||||
PBrowserParent::SendRealTouchMoveEvent(e) :
|
||||
PBrowserParent::SendRealTouchEvent(e);
|
||||
}
|
||||
|
||||
/*static*/ TabParent*
|
||||
TabParent::GetEventCapturer()
|
||||
{
|
||||
return sEventCapturer;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::TryCapture(const nsGUIEvent& aEvent)
|
||||
{
|
||||
MOZ_ASSERT(sEventCapturer == this && mEventCaptureDepth > 0);
|
||||
|
||||
if (aEvent.eventStructType != NS_TOUCH_EVENT) {
|
||||
// Only capture of touch events is implemented, for now.
|
||||
return false;
|
||||
}
|
||||
|
||||
nsTouchEvent event(static_cast<const nsTouchEvent&>(aEvent));
|
||||
|
||||
bool isTouchPointUp = (event.message == NS_TOUCH_END ||
|
||||
event.message == NS_TOUCH_CANCEL);
|
||||
if (event.message == NS_TOUCH_START || isTouchPointUp) {
|
||||
// Let the DOM see touch start/end events so that its touch-point
|
||||
// state stays consistent.
|
||||
if (isTouchPointUp && 0 == --mEventCaptureDepth) {
|
||||
// All event series are un-captured, don't try to catch any
|
||||
// more.
|
||||
sEventCapturer = nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Adjust the widget coordinates to be relative to our frame.
|
||||
nsRefPtr<nsFrameLoader> frameLoader = GetFrameLoader();
|
||||
nsEventStateManager::MapEventCoordinatesForChildProcess(frameLoader, &event);
|
||||
|
||||
SendRealTouchEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabParent::RecvSyncMessage(const nsString& aMessage,
|
||||
const ClonedMessageData& aData,
|
||||
|
|
|
@ -66,6 +66,30 @@ public:
|
|||
mozIApplication* GetApp() { return mApp; }
|
||||
bool IsBrowserElement() { return mIsBrowserElement; }
|
||||
|
||||
/**
|
||||
* Return the TabParent that has decided it wants to capture an
|
||||
* event series for fast-path dispatch to its subprocess, if one
|
||||
* has.
|
||||
*
|
||||
* DOM event dispatch and widget are free to ignore capture
|
||||
* requests from TabParents; the end result wrt remote content is
|
||||
* (must be) always the same, albeit usually slower without
|
||||
* subprocess capturing. This allows frontends/widget backends to
|
||||
* "opt in" to faster cross-process dispatch.
|
||||
*/
|
||||
static TabParent* GetEventCapturer();
|
||||
/**
|
||||
* If this is the current event capturer, give this a chance to
|
||||
* capture the event. If it was captured, return true, false
|
||||
* otherwise. Un-captured events should follow normal DOM
|
||||
* dispatch; captured events should result in no further
|
||||
* processing from the caller of TryCapture().
|
||||
*
|
||||
* It's an error to call TryCapture() if this isn't the event
|
||||
* capturer.
|
||||
*/
|
||||
bool TryCapture(const nsGUIEvent& aEvent);
|
||||
|
||||
void Destroy();
|
||||
|
||||
virtual bool RecvMoveFocus(const bool& aForward);
|
||||
|
@ -246,6 +270,9 @@ protected:
|
|||
uint32_t mIMECompositionStart;
|
||||
uint32_t mIMESeqno;
|
||||
|
||||
// The number of event series we're currently capturing.
|
||||
int32_t mEventCaptureDepth;
|
||||
|
||||
float mDPI;
|
||||
bool mActive;
|
||||
bool mIsBrowserElement;
|
||||
|
|
|
@ -154,7 +154,7 @@ addDOMTouch(UserInputData& data, nsTouchEvent& event, int i)
|
|||
}
|
||||
|
||||
static nsEventStatus
|
||||
sendTouchEvent(UserInputData& data)
|
||||
sendTouchEvent(UserInputData& data, bool* captured)
|
||||
{
|
||||
uint32_t msg;
|
||||
int32_t action = data.action & AMOTION_EVENT_ACTION_MASK;
|
||||
|
@ -190,7 +190,7 @@ sendTouchEvent(UserInputData& data)
|
|||
addDOMTouch(data, event, i);
|
||||
}
|
||||
|
||||
return nsWindow::DispatchInputEvent(event);
|
||||
return nsWindow::DispatchInputEvent(event, captured);
|
||||
}
|
||||
|
||||
static nsEventStatus
|
||||
|
@ -435,7 +435,11 @@ GeckoInputDispatcher::dispatchOnce()
|
|||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
if ((data.action & AMOTION_EVENT_ACTION_MASK) !=
|
||||
AMOTION_EVENT_ACTION_HOVER_MOVE) {
|
||||
status = sendTouchEvent(data);
|
||||
bool captured;
|
||||
status = sendTouchEvent(data, &captured);
|
||||
if (captured) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t msg;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "android/log.h"
|
||||
#include "ui/FramebufferNativeWindow.h"
|
||||
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/FileUtils.h"
|
||||
|
@ -283,15 +284,30 @@ nsWindow::DoDraw(void)
|
|||
}
|
||||
|
||||
nsEventStatus
|
||||
nsWindow::DispatchInputEvent(nsGUIEvent &aEvent)
|
||||
nsWindow::DispatchInputEvent(nsGUIEvent &aEvent, bool* aWasCaptured)
|
||||
{
|
||||
if (!gFocusedWindow)
|
||||
if (aWasCaptured) {
|
||||
*aWasCaptured = false;
|
||||
}
|
||||
if (!gFocusedWindow) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
gFocusedWindow->UserActivity();
|
||||
|
||||
nsEventStatus status;
|
||||
aEvent.widget = gFocusedWindow;
|
||||
|
||||
if (TabParent* capturer = TabParent::GetEventCapturer()) {
|
||||
bool captured = capturer->TryCapture(aEvent);
|
||||
if (aWasCaptured) {
|
||||
*aWasCaptured = captured;
|
||||
}
|
||||
if (captured) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus status;
|
||||
gFocusedWindow->DispatchEvent(&aEvent, status);
|
||||
return status;
|
||||
}
|
||||
|
|
|
@ -46,7 +46,8 @@ public:
|
|||
virtual ~nsWindow();
|
||||
|
||||
static void DoDraw(void);
|
||||
static nsEventStatus DispatchInputEvent(nsGUIEvent &aEvent);
|
||||
static nsEventStatus DispatchInputEvent(nsGUIEvent &aEvent,
|
||||
bool* aWasCaptured = nullptr);
|
||||
|
||||
NS_IMETHOD Create(nsIWidget *aParent,
|
||||
void *aNativeParent,
|
||||
|
|
Загрузка…
Ссылка в новой задаче