mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 944938 - Add event structs and APZ event handling for pan gesture events that can be used for Mac touchpad scrolling. r=kats
This commit is contained in:
parent
3a6289bbd6
commit
a986c2df8c
@ -445,6 +445,27 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
||||
}
|
||||
}
|
||||
break;
|
||||
} case PANGESTURE_INPUT: {
|
||||
const PanGestureInput& panInput = aEvent.AsPanGestureInput();
|
||||
bool inOverscrolledApzc = false;
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(panInput.mPanStartPoint,
|
||||
&inOverscrolledApzc);
|
||||
if (apzc) {
|
||||
if (panInput.mType == PanGestureInput::PANGESTURE_START ||
|
||||
panInput.mType == PanGestureInput::PANGESTURE_MOMENTUMSTART) {
|
||||
BuildOverscrollHandoffChain(apzc);
|
||||
}
|
||||
apzc->GetGuid(aOutTargetGuid);
|
||||
GetInputTransforms(apzc, transformToApzc, transformToGecko);
|
||||
PanGestureInput inputForApzc(panInput);
|
||||
ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc);
|
||||
result = apzc->ReceiveInputEvent(inputForApzc);
|
||||
if (panInput.mType == PanGestureInput::PANGESTURE_END ||
|
||||
panInput.mType == PanGestureInput::PANGESTURE_MOMENTUMEND) {
|
||||
ClearOverscrollHandoffChain();
|
||||
}
|
||||
}
|
||||
break;
|
||||
} case PINCHGESTURE_INPUT: {
|
||||
const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
|
||||
bool inOverscrolledApzc = false;
|
||||
|
@ -714,6 +714,21 @@ nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PANGESTURE_INPUT: {
|
||||
const PanGestureInput& panGestureInput = aEvent.AsPanGestureInput();
|
||||
switch (panGestureInput.mType) {
|
||||
case PanGestureInput::PANGESTURE_MAYSTART: rv = OnPanMayBegin(panGestureInput); break;
|
||||
case PanGestureInput::PANGESTURE_CANCELLED: rv = OnPanCancelled(panGestureInput); break;
|
||||
case PanGestureInput::PANGESTURE_START: rv = OnPanBegin(panGestureInput); break;
|
||||
case PanGestureInput::PANGESTURE_PAN: rv = OnPan(panGestureInput, true); break;
|
||||
case PanGestureInput::PANGESTURE_END: rv = OnPanEnd(panGestureInput); break;
|
||||
case PanGestureInput::PANGESTURE_MOMENTUMSTART: rv = OnPanMomentumStart(panGestureInput); break;
|
||||
case PanGestureInput::PANGESTURE_MOMENTUMPAN: rv = OnPan(panGestureInput, false); break;
|
||||
case PanGestureInput::PANGESTURE_MOMENTUMEND: rv = OnPanMomentumEnd(panGestureInput); break;
|
||||
default: NS_WARNING("Unhandled pan gesture"); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: NS_WARNING("Unhandled input event"); break;
|
||||
}
|
||||
|
||||
@ -1085,6 +1100,93 @@ AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut
|
||||
return false;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState);
|
||||
|
||||
mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime);
|
||||
mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime);
|
||||
CancelAnimation();
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPanCancelled(const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-cancelled in state %d\n", this, mState);
|
||||
|
||||
mX.CancelTouch();
|
||||
mY.CancelTouch();
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPanBegin(const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-begin in state %d\n", this, mState);
|
||||
|
||||
mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime);
|
||||
mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime);
|
||||
|
||||
if (GetAxisLockMode() == FREE) {
|
||||
SetState(PANNING);
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
float dx = aEvent.mPanDisplacement.x, dy = aEvent.mPanDisplacement.y;
|
||||
double angle = atan2(dy, dx); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
||||
HandlePanning(angle);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool aFingersOnTouchpad) {
|
||||
APZC_LOG("%p got a pan-pan in state %d\n", this, mState);
|
||||
|
||||
// We need to update the axis velocity in order to get a useful display port
|
||||
// size and position. We need to do so even if this is a momentum pan (i.e.
|
||||
// aFingersOnTouchpad == false); in that case the "with touch" part is not
|
||||
// really appropriate, so we may want to rethink this at some point.
|
||||
mX.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.x, aEvent.mTime);
|
||||
mY.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.y, aEvent.mTime);
|
||||
|
||||
HandlePanningUpdate(aEvent.mPanDisplacement.x, aEvent.mPanDisplacement.y);
|
||||
|
||||
CallDispatchScroll(aEvent.mPanStartPoint, aEvent.mPanStartPoint + aEvent.mPanDisplacement, 0);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-end in state %d\n", this, mState);
|
||||
|
||||
mX.EndTouch(aEvent.mTime);
|
||||
mY.EndTouch(aEvent.mTime);
|
||||
RequestContentRepaint();
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPanMomentumStart(const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-momentumstart in state %d\n", this, mState);
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnPanMomentumEnd(const PanGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a pan-momentumend in state %d\n", this, mState);
|
||||
|
||||
// We need to reset the velocity to zero. We don't really have a "touch"
|
||||
// here because the touch has already ended long before the momentum
|
||||
// animation started, but I guess it doesn't really matter for now.
|
||||
mX.CancelTouch();
|
||||
mY.CancelTouch();
|
||||
|
||||
RequestContentRepaint();
|
||||
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
|
||||
APZC_LOG("%p got a long-press in state %d\n", this, mState);
|
||||
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
@ -1235,6 +1337,7 @@ void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle, TouchBe
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::HandlePanning(double aAngle) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
if (!gfxPrefs::APZCrossSlideEnabled() && (!mX.CanScrollNow() || !mY.CanScrollNow())) {
|
||||
SetState(PANNING);
|
||||
} else if (IsCloseToHorizontal(aAngle, AXIS_LOCK_ANGLE)) {
|
||||
@ -1258,6 +1361,31 @@ void AsyncPanZoomController::HandlePanning(double aAngle) {
|
||||
}
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::HandlePanningUpdate(float aDX, float aDY) {
|
||||
// If we're axis-locked, check if the user is trying to break the lock
|
||||
if (GetAxisLockMode() == STICKY && !mPanDirRestricted) {
|
||||
|
||||
double angle = atan2(aDY, aDX); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
||||
float breakThreshold = AXIS_BREAKOUT_THRESHOLD * APZCTreeManager::GetDPI();
|
||||
|
||||
if (fabs(aDX) > breakThreshold || fabs(aDY) > breakThreshold) {
|
||||
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
|
||||
if (!IsCloseToHorizontal(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mY.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
|
||||
if (!IsCloseToVertical(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mX.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) {
|
||||
ReentrantMonitorAutoEnter lock(mMonitor);
|
||||
|
||||
@ -1435,31 +1563,9 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) {
|
||||
ScreenIntPoint prevTouchPoint(mX.GetPos(), mY.GetPos());
|
||||
ScreenIntPoint touchPoint = GetFirstTouchScreenPoint(aEvent);
|
||||
|
||||
// If we're axis-locked, check if the user is trying to break the lock
|
||||
if (GetAxisLockMode() == STICKY && !mPanDirRestricted) {
|
||||
ScreenIntPoint point = GetFirstTouchScreenPoint(aEvent);
|
||||
float dx = mX.PanDistance(point.x);
|
||||
float dy = mY.PanDistance(point.y);
|
||||
|
||||
double angle = atan2(dy, dx); // range [-pi, pi]
|
||||
angle = fabs(angle); // range [0, pi]
|
||||
|
||||
float breakThreshold = AXIS_BREAKOUT_THRESHOLD * APZCTreeManager::GetDPI();
|
||||
|
||||
if (fabs(dx) > breakThreshold || fabs(dy) > breakThreshold) {
|
||||
if (mState == PANNING_LOCKED_X || mState == CROSS_SLIDING_X) {
|
||||
if (!IsCloseToHorizontal(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mY.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
} else if (mState == PANNING_LOCKED_Y || mState == CROSS_SLIDING_Y) {
|
||||
if (!IsCloseToVertical(angle, AXIS_BREAKOUT_ANGLE)) {
|
||||
mX.SetAxisLocked(false);
|
||||
SetState(PANNING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
float dx = mX.PanDistance(touchPoint.x);
|
||||
float dy = mY.PanDistance(touchPoint.y);
|
||||
HandlePanningUpdate(dx, dy);
|
||||
|
||||
UpdateWithTouchAtDevicePoint(aEvent);
|
||||
|
||||
|
@ -387,6 +387,17 @@ protected:
|
||||
*/
|
||||
nsEventStatus OnScaleEnd(const PinchGestureInput& aEvent);
|
||||
|
||||
/**
|
||||
* Helper methods for handling pan events.
|
||||
*/
|
||||
nsEventStatus OnPanMayBegin(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPanCancelled(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPanBegin(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPan(const PanGestureInput& aEvent, bool aFingersOnTouchpad);
|
||||
nsEventStatus OnPanEnd(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPanMomentumStart(const PanGestureInput& aEvent);
|
||||
nsEventStatus OnPanMomentumEnd(const PanGestureInput& aEvent);
|
||||
|
||||
/**
|
||||
* Helper methods for long press gestures.
|
||||
*/
|
||||
@ -471,6 +482,11 @@ protected:
|
||||
*/
|
||||
void HandlePanning(double angle);
|
||||
|
||||
/**
|
||||
* Update the panning state and axis locks.
|
||||
*/
|
||||
void HandlePanningUpdate(float aDX, float aDY);
|
||||
|
||||
/**
|
||||
* Sets up anything needed for panning. This takes us out of the "TOUCHING"
|
||||
* state and starts actually panning us.
|
||||
|
@ -19,11 +19,13 @@ namespace mozilla {
|
||||
enum InputType
|
||||
{
|
||||
MULTITOUCH_INPUT,
|
||||
PANGESTURE_INPUT,
|
||||
PINCHGESTURE_INPUT,
|
||||
TAPGESTURE_INPUT
|
||||
};
|
||||
|
||||
class MultiTouchInput;
|
||||
class PanGestureInput;
|
||||
class PinchGestureInput;
|
||||
class TapGestureInput;
|
||||
|
||||
@ -56,6 +58,7 @@ public:
|
||||
Modifiers modifiers;
|
||||
|
||||
INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PanGestureInput, PANGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT)
|
||||
INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT)
|
||||
|
||||
@ -184,6 +187,79 @@ public:
|
||||
nsTArray<SingleTouchData> mTouches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for pan events, can be used off-main-thread.
|
||||
* These events are currently only used for scrolling on desktop.
|
||||
*/
|
||||
class PanGestureInput : public InputData
|
||||
{
|
||||
public:
|
||||
enum PanGestureType
|
||||
{
|
||||
// MayStart: Dispatched before any actual panning has occurred but when a
|
||||
// pan gesture is probably about to start, for example when the user
|
||||
// starts touching the touchpad. Should interrupt any ongoing APZ
|
||||
// animation and can be used to trigger scrollability indicators (e.g.
|
||||
// flashing overlay scrollbars).
|
||||
PANGESTURE_MAYSTART,
|
||||
|
||||
// Cancelled: Dispatched after MayStart when no pan gesture is going to
|
||||
// happen after all, for example when the user lifts their fingers from a
|
||||
// touchpad without having done any scrolling.
|
||||
PANGESTURE_CANCELLED,
|
||||
|
||||
// Start: A pan gesture is starting.
|
||||
// For devices that do not support the MayStart event type, this event can
|
||||
// be used to interrupt ongoing APZ animations.
|
||||
PANGESTURE_START,
|
||||
|
||||
// Pan: The actual pan motion by mPanDisplacement.
|
||||
PANGESTURE_PAN,
|
||||
|
||||
// End: The pan gesture has ended, for example because the user has lifted
|
||||
// their fingers from a touchpad after scrolling.
|
||||
// Any potential momentum events fire after this event.
|
||||
PANGESTURE_END,
|
||||
|
||||
// The following momentum event types are used in order to control the pan
|
||||
// momentum animation. Using these instead of our own animation ensures
|
||||
// that the animation curve is OS native and that the animation stops
|
||||
// reliably if it is cancelled by the user.
|
||||
|
||||
// MomentumStart: Dispatched between the End event of the actual
|
||||
// user-controlled pan, and the first MomentumPan event of the momentum
|
||||
// animation.
|
||||
PANGESTURE_MOMENTUMSTART,
|
||||
|
||||
// MomentumPan: The actual momentum motion by mPanDisplacement.
|
||||
PANGESTURE_MOMENTUMPAN,
|
||||
|
||||
// MomentumEnd: The momentum animation has ended, for example because the
|
||||
// momentum velocity has gone below the stopping threshold, or because the
|
||||
// user has stopped the animation by putting their fingers on a touchpad.
|
||||
PANGESTURE_MOMENTUMEND
|
||||
};
|
||||
|
||||
PanGestureInput(PanGestureType aType,
|
||||
uint32_t aTime,
|
||||
TimeStamp aTimeStamp,
|
||||
const ScreenPoint& aPanStartPoint,
|
||||
const ScreenPoint& aPanDisplacement,
|
||||
Modifiers aModifiers)
|
||||
: InputData(PANGESTURE_INPUT, aTime, aTimeStamp, aModifiers),
|
||||
mType(aType),
|
||||
mPanStartPoint(aPanStartPoint),
|
||||
mPanDisplacement(aPanDisplacement)
|
||||
{
|
||||
}
|
||||
|
||||
PanGestureType mType;
|
||||
ScreenPoint mPanStartPoint;
|
||||
|
||||
// Only non-zero if mType is PANGESTURE_PAN or PANGESTURE_MOMENTUMPAN.
|
||||
ScreenPoint mPanDisplacement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encapsulation class for pinch events. In general, these will be generated by
|
||||
* a gesture listener by looking at SingleTouchData/MultiTouchInput instances and
|
||||
|
Loading…
Reference in New Issue
Block a user