зеркало из https://github.com/mozilla/gecko-dev.git
Bug 796275 - Context menu fires on wrong target out of process. r=cjones
This commit is contained in:
Родитель
fa73294e7c
Коммит
8dde3fc959
|
@ -307,6 +307,13 @@ child:
|
|||
*/
|
||||
HandleSingleTap(nsIntPoint point);
|
||||
|
||||
/**
|
||||
* Requests handling of a long tap. |point| is in CSS pixels, relative to
|
||||
* the scroll offset. This message is expected to send a "contextmenu"
|
||||
* events at this point.
|
||||
*/
|
||||
HandleLongTap(nsIntPoint point);
|
||||
|
||||
/**
|
||||
* Sending an activate message moves focus to the child.
|
||||
*/
|
||||
|
|
|
@ -1250,6 +1250,22 @@ TabChild::RecvHandleSingleTap(const nsIntPoint& aPoint)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvHandleLongTap(const nsIntPoint& aPoint)
|
||||
{
|
||||
if (!mCx || !mTabChildGlobal) {
|
||||
return true;
|
||||
}
|
||||
|
||||
RecvMouseEvent(NS_LITERAL_STRING("contextmenu"), aPoint.x, aPoint.y,
|
||||
2 /* Right button */,
|
||||
1 /* Click count */,
|
||||
0 /* Modifiers */,
|
||||
false /* Ignore root scroll frame */);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvActivate()
|
||||
{
|
||||
|
|
|
@ -200,6 +200,7 @@ public:
|
|||
virtual bool RecvUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
||||
virtual bool RecvHandleDoubleTap(const nsIntPoint& aPoint);
|
||||
virtual bool RecvHandleSingleTap(const nsIntPoint& aPoint);
|
||||
virtual bool RecvHandleLongTap(const nsIntPoint& aPoint);
|
||||
virtual bool RecvActivate();
|
||||
virtual bool RecvDeactivate();
|
||||
virtual bool RecvMouseEvent(const nsString& aType,
|
||||
|
|
|
@ -266,6 +266,11 @@ void TabParent::HandleSingleTap(const nsIntPoint& aPoint)
|
|||
unused << SendHandleSingleTap(aPoint);
|
||||
}
|
||||
|
||||
void TabParent::HandleLongTap(const nsIntPoint& aPoint)
|
||||
{
|
||||
unused << SendHandleLongTap(aPoint);
|
||||
}
|
||||
|
||||
void
|
||||
TabParent::Activate()
|
||||
{
|
||||
|
|
|
@ -162,6 +162,7 @@ public:
|
|||
void UpdateFrame(const layers::FrameMetrics& aFrameMetrics);
|
||||
void HandleDoubleTap(const nsIntPoint& aPoint);
|
||||
void HandleSingleTap(const nsIntPoint& aPoint);
|
||||
void HandleLongTap(const nsIntPoint& aPoint);
|
||||
void Activate();
|
||||
void Deactivate();
|
||||
|
||||
|
|
|
@ -537,7 +537,17 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
|||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
|
||||
// XXX: Implement this.
|
||||
if (mGeckoContentController) {
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
|
||||
gfxFloat resolution = CalculateResolution(mFrameMetrics).width;
|
||||
gfx::Point point = WidgetSpaceToCompensatedViewportSpace(
|
||||
gfx::Point(aEvent.mPoint.x, aEvent.mPoint.y),
|
||||
resolution);
|
||||
mGeckoContentController->HandleLongTap(nsIntPoint(NS_lround(point.x),
|
||||
NS_lround(point.y)));
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,12 @@ public:
|
|||
*/
|
||||
virtual void HandleSingleTap(const nsIntPoint& aPoint) = 0;
|
||||
|
||||
/**
|
||||
* Requests handling a long tap. |aPoint| is in CSS pixels, relative to the
|
||||
* current scroll offset.
|
||||
*/
|
||||
virtual void HandleLongTap(const nsIntPoint& aPoint) = 0;
|
||||
|
||||
GeckoContentController() {}
|
||||
virtual ~GeckoContentController() {}
|
||||
};
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "GestureEventListener.h"
|
||||
#include "AsyncPanZoomController.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
|
@ -47,6 +49,11 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||
}
|
||||
|
||||
const MultiTouchInput& event = static_cast<const MultiTouchInput&>(aEvent);
|
||||
|
||||
// Cache the current event since it may become the single or long tap that we
|
||||
// send.
|
||||
mLastTouchInput = event;
|
||||
|
||||
switch (event.mType)
|
||||
{
|
||||
case MultiTouchInput::MULTITOUCH_START:
|
||||
|
@ -75,6 +82,14 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||
mTouchStartPosition = event.mTouches[0].mScreenPoint;
|
||||
if (mState == GESTURE_NONE) {
|
||||
mState = GESTURE_WAITING_SINGLE_TAP;
|
||||
|
||||
mLongTapTimeoutTask =
|
||||
NewRunnableMethod(this, &GestureEventListener::TimeoutLongTap);
|
||||
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
FROM_HERE,
|
||||
mLongTapTimeoutTask,
|
||||
Preferences::GetInt("ui.click_hold_context_menus.delay", 500));
|
||||
}
|
||||
} else if (length == 2) {
|
||||
// Another finger has been added; it can't be a tap anymore.
|
||||
|
@ -129,6 +144,8 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||
HandleDoubleTap(event);
|
||||
mState = GESTURE_NONE;
|
||||
} else if (mState == GESTURE_WAITING_SINGLE_TAP) {
|
||||
mLongTapTimeoutTask->Cancel();
|
||||
|
||||
HandleSingleTapUpEvent(event);
|
||||
|
||||
// We were not waiting for anything but a single tap has happened that
|
||||
|
@ -136,10 +153,6 @@ nsEventStatus GestureEventListener::HandleInputEvent(const InputData& aEvent)
|
|||
// a double tap, send a single tap instead.
|
||||
mState = GESTURE_WAITING_DOUBLE_TAP;
|
||||
|
||||
// Cache the current event since it may become the single tap that we
|
||||
// send.
|
||||
mLastTouchInput = event;
|
||||
|
||||
mDoubleTapTimeoutTask =
|
||||
NewRunnableMethod(this, &GestureEventListener::TimeoutDoubleTap);
|
||||
|
||||
|
@ -260,6 +273,12 @@ nsEventStatus GestureEventListener::HandleSingleTapConfirmedEvent(const MultiTou
|
|||
return mAsyncPanZoomController->ReceiveInputEvent(tapEvent);
|
||||
}
|
||||
|
||||
nsEventStatus GestureEventListener::HandleLongTapEvent(const MultiTouchInput& aEvent)
|
||||
{
|
||||
TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG, aEvent.mTime, aEvent.mTouches[0].mScreenPoint);
|
||||
return mAsyncPanZoomController->ReceiveInputEvent(tapEvent);
|
||||
}
|
||||
|
||||
nsEventStatus GestureEventListener::HandleTapCancel(const MultiTouchInput& aEvent)
|
||||
{
|
||||
mTapStartTime = 0;
|
||||
|
@ -267,6 +286,10 @@ nsEventStatus GestureEventListener::HandleTapCancel(const MultiTouchInput& aEven
|
|||
switch (mState)
|
||||
{
|
||||
case GESTURE_WAITING_SINGLE_TAP:
|
||||
mLongTapTimeoutTask->Cancel();
|
||||
mState = GESTURE_NONE;
|
||||
break;
|
||||
|
||||
case GESTURE_WAITING_DOUBLE_TAP:
|
||||
mState = GESTURE_NONE;
|
||||
break;
|
||||
|
@ -294,6 +317,16 @@ void GestureEventListener::TimeoutDoubleTap()
|
|||
}
|
||||
}
|
||||
|
||||
void GestureEventListener::TimeoutLongTap()
|
||||
{
|
||||
// If the tap has not been released, this is a long press.
|
||||
if (mState == GESTURE_WAITING_SINGLE_TAP) {
|
||||
mState = GESTURE_NONE;
|
||||
|
||||
HandleLongTapEvent(mLastTouchInput);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncPanZoomController* GestureEventListener::GetAsyncPanZoomController() {
|
||||
return mAsyncPanZoomController;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,12 @@ protected:
|
|||
*/
|
||||
nsEventStatus HandleSingleTapConfirmedEvent(const MultiTouchInput& aEvent);
|
||||
|
||||
/**
|
||||
* Attempts to handle a long tap confirmation. This is what will use
|
||||
* for context menu.
|
||||
*/
|
||||
nsEventStatus HandleLongTapEvent(const MultiTouchInput& aEvent);
|
||||
|
||||
/**
|
||||
* Attempts to handle a tap event cancellation. This happens when we think
|
||||
* something was a tap but it actually wasn't. In general, this will not
|
||||
|
@ -130,6 +136,11 @@ protected:
|
|||
* has time to tap again (to make a double tap).
|
||||
*/
|
||||
void TimeoutDoubleTap();
|
||||
/**
|
||||
* Times out a long tap. This should be called a 'long' time after a single
|
||||
* tap is detected.
|
||||
*/
|
||||
void TimeoutLongTap();
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> mAsyncPanZoomController;
|
||||
|
||||
|
@ -183,6 +194,13 @@ protected:
|
|||
*/
|
||||
CancelableTask *mDoubleTapTimeoutTask;
|
||||
|
||||
/**
|
||||
* Task used to timeout a long tap. This gets posted to the UI thread such
|
||||
* that it runs a time when a single tap happens. We cache it so that
|
||||
* we can cancel it if any other touch event happens.
|
||||
*/
|
||||
CancelableTask *mLongTapTimeoutTask;
|
||||
|
||||
/**
|
||||
* Position of the last touch starting. This is only valid during an attempt
|
||||
* to determine if a touch is a tap. This means that it is used in both the
|
||||
|
|
|
@ -538,6 +538,23 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
virtual void HandleLongTap(const nsIntPoint& aPoint) MOZ_OVERRIDE
|
||||
{
|
||||
if (MessageLoop::current() != mUILoop) {
|
||||
// We have to send this message from the "UI thread" (main
|
||||
// thread).
|
||||
mUILoop->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &RemoteContentController::HandleLongTap,
|
||||
aPoint));
|
||||
return;
|
||||
}
|
||||
if (mRenderFrame) {
|
||||
TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
|
||||
browser->HandleLongTap(aPoint);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearRenderFrame() { mRenderFrame = nullptr; }
|
||||
|
||||
private:
|
||||
|
|
Загрузка…
Ссылка в новой задаче