зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1887435 - Ensure the `isPrimary` property of `PointerEvent` is correctly set for touch input; r=smaug
Differential Revision: https://phabricator.services.mozilla.com/D207017
This commit is contained in:
Родитель
657e7dfb94
Коммит
e7c1812c97
|
@ -2278,8 +2278,8 @@ void EventStateManager::MaybeFirePointerCancel(WidgetInputEvent* aEvent) {
|
|||
WidgetPointerEvent event(aTouchEvent->IsTrusted(), ePointerCancel,
|
||||
aTouchEvent->mWidget);
|
||||
|
||||
PointerEventHandler::InitPointerEventFromTouch(
|
||||
event, *aTouchEvent, *aTouchEvent->mTouches[0], true);
|
||||
PointerEventHandler::InitPointerEventFromTouch(event, *aTouchEvent,
|
||||
*aTouchEvent->mTouches[0]);
|
||||
|
||||
event.convertToPointer = false;
|
||||
presShell->HandleEventWithTarget(&event, targetFrame, content, &status);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/BrowserParent.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/DocumentInlines.h"
|
||||
#include "mozilla/dom/MouseEventBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -80,7 +81,8 @@ void PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent,
|
|||
// In this case we have to know information about available mouse pointers
|
||||
sActivePointersIds->InsertOrUpdate(
|
||||
aEvent->pointerId,
|
||||
MakeUnique<PointerInfo>(false, aEvent->mInputSource, true, nullptr));
|
||||
MakeUnique<PointerInfo>(false, aEvent->mInputSource, true, false,
|
||||
nullptr));
|
||||
|
||||
MaybeCacheSpoofedPointerID(aEvent->mInputSource, aEvent->pointerId);
|
||||
break;
|
||||
|
@ -94,6 +96,7 @@ void PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent,
|
|||
pointerEvent->pointerId,
|
||||
MakeUnique<PointerInfo>(
|
||||
true, pointerEvent->mInputSource, pointerEvent->mIsPrimary,
|
||||
pointerEvent->mFromTouchEvent,
|
||||
aTargetContent ? aTargetContent->OwnerDoc() : nullptr));
|
||||
MaybeCacheSpoofedPointerID(pointerEvent->mInputSource,
|
||||
pointerEvent->pointerId);
|
||||
|
@ -112,7 +115,8 @@ void PointerEventHandler::UpdateActivePointerState(WidgetMouseEvent* aEvent,
|
|||
sActivePointersIds->InsertOrUpdate(
|
||||
pointerEvent->pointerId,
|
||||
MakeUnique<PointerInfo>(false, pointerEvent->mInputSource,
|
||||
pointerEvent->mIsPrimary, nullptr));
|
||||
pointerEvent->mIsPrimary,
|
||||
pointerEvent->mFromTouchEvent, nullptr));
|
||||
} else {
|
||||
sActivePointersIds->Remove(pointerEvent->pointerId);
|
||||
}
|
||||
|
@ -314,7 +318,7 @@ void PointerEventHandler::ProcessPointerCaptureForTouch(
|
|||
continue;
|
||||
}
|
||||
WidgetPointerEvent event(aEvent->IsTrusted(), eVoidEvent, aEvent->mWidget);
|
||||
InitPointerEventFromTouch(event, *aEvent, *touch, i == 0);
|
||||
InitPointerEventFromTouch(event, *aEvent, *touch);
|
||||
CheckPointerCaptureState(&event);
|
||||
}
|
||||
}
|
||||
|
@ -548,7 +552,7 @@ void PointerEventHandler::InitPointerEventFromMouse(
|
|||
/* static */
|
||||
void PointerEventHandler::InitPointerEventFromTouch(
|
||||
WidgetPointerEvent& aPointerEvent, const WidgetTouchEvent& aTouchEvent,
|
||||
const mozilla::dom::Touch& aTouch, bool aIsPrimary) {
|
||||
const mozilla::dom::Touch& aTouch) {
|
||||
// Use mButton/mButtons only when mButton got a value (from pen input)
|
||||
int16_t button = aTouchEvent.mMessage == eTouchMove ? MouseButton::eNotPressed
|
||||
: aTouchEvent.mButton != MouseButton::eNotPressed
|
||||
|
@ -560,7 +564,10 @@ void PointerEventHandler::InitPointerEventFromTouch(
|
|||
? aTouchEvent.mButtons
|
||||
: MouseButtonsFlag::ePrimaryFlag;
|
||||
|
||||
aPointerEvent.mIsPrimary = aIsPrimary;
|
||||
// Only the first touch would be the primary pointer.
|
||||
aPointerEvent.mIsPrimary = aTouchEvent.mMessage == eTouchStart
|
||||
? !HasActiveTouchPointer()
|
||||
: GetPointerPrimaryState(aTouch.Identifier());
|
||||
aPointerEvent.pointerId = aTouch.Identifier();
|
||||
aPointerEvent.mRefPoint = aTouch.mRefPoint;
|
||||
aPointerEvent.mModifiers = aTouchEvent.mModifiers;
|
||||
|
@ -681,7 +688,7 @@ void PointerEventHandler::DispatchPointerFromMouseOrTouch(
|
|||
WidgetPointerEvent event(touchEvent->IsTrusted(), pointerMessage,
|
||||
touchEvent->mWidget);
|
||||
|
||||
InitPointerEventFromTouch(event, *touchEvent, *touch, i == 0);
|
||||
InitPointerEventFromTouch(event, *touchEvent, *touch);
|
||||
event.convertToPointer = touch->convertToPointer = false;
|
||||
event.mCoalescedWidgetEvents = touch->mCoalescedWidgetEvents;
|
||||
if (aMouseOrTouchEvent->mMessage == eTouchStart) {
|
||||
|
@ -741,6 +748,15 @@ void PointerEventHandler::NotifyDestroyPresContext(
|
|||
iter.Remove();
|
||||
}
|
||||
}
|
||||
// Clean up active pointer info
|
||||
for (auto iter = sActivePointersIds->Iter(); !iter.Done(); iter.Next()) {
|
||||
PointerInfo* data = iter.UserData();
|
||||
MOZ_ASSERT(data, "how could we have a null PointerInfo here?");
|
||||
if (data->mActiveDocument &&
|
||||
data->mActiveDocument->GetPresContext() == aPresContext) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PointerEventHandler::IsDragAndDropEnabled(WidgetMouseEvent& aEvent) {
|
||||
|
@ -772,6 +788,16 @@ bool PointerEventHandler::GetPointerPrimaryState(uint32_t aPointerId) {
|
|||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool PointerEventHandler::HasActiveTouchPointer() {
|
||||
for (auto iter = sActivePointersIds->ConstIter(); !iter.Done(); iter.Next()) {
|
||||
if (iter.Data()->mFromTouchEvent) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void PointerEventHandler::DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent,
|
||||
|
|
|
@ -50,13 +50,16 @@ class PointerInfo final {
|
|||
uint16_t mPointerType;
|
||||
bool mActiveState;
|
||||
bool mPrimaryState;
|
||||
bool mFromTouchEvent;
|
||||
bool mPreventMouseEventByContent;
|
||||
WeakPtr<dom::Document> mActiveDocument;
|
||||
explicit PointerInfo(bool aActiveState, uint16_t aPointerType,
|
||||
bool aPrimaryState, dom::Document* aActiveDocument)
|
||||
bool aPrimaryState, bool aFromTouchEvent,
|
||||
dom::Document* aActiveDocument)
|
||||
: mPointerType(aPointerType),
|
||||
mActiveState(aActiveState),
|
||||
mPrimaryState(aPrimaryState),
|
||||
mFromTouchEvent(aFromTouchEvent),
|
||||
mPreventMouseEventByContent(false),
|
||||
mActiveDocument(aActiveDocument) {}
|
||||
};
|
||||
|
@ -208,8 +211,7 @@ class PointerEventHandler final {
|
|||
|
||||
static void InitPointerEventFromTouch(WidgetPointerEvent& aPointerEvent,
|
||||
const WidgetTouchEvent& aTouchEvent,
|
||||
const mozilla::dom::Touch& aTouch,
|
||||
bool aIsPrimary);
|
||||
const mozilla::dom::Touch& aTouch);
|
||||
|
||||
static bool ShouldGeneratePointerEventFromMouse(WidgetGUIEvent* aEvent) {
|
||||
return aEvent->mMessage == eMouseDown || aEvent->mMessage == eMouseUp ||
|
||||
|
@ -250,6 +252,10 @@ class PointerEventHandler final {
|
|||
// event with pointerId
|
||||
static bool GetPointerPrimaryState(uint32_t aPointerId);
|
||||
|
||||
// HasActiveTouchPointer returns true if there is active pointer event that is
|
||||
// generated from touch event.
|
||||
static bool HasActiveTouchPointer();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
static void DispatchGotOrLostPointerCaptureEvent(
|
||||
bool aIsGotCapture, const WidgetPointerEvent* aPointerEvent,
|
||||
|
|
|
@ -25,8 +25,7 @@ void CoalescedTouchData::CreateCoalescedTouchEvent(
|
|||
WidgetPointerEvent* event =
|
||||
touch->mCoalescedWidgetEvents->mEvents.AppendElement(WidgetPointerEvent(
|
||||
aEvent.IsTrusted(), ePointerMove, aEvent.mWidget));
|
||||
PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch,
|
||||
i == 0);
|
||||
PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch);
|
||||
event->mFlags.mBubbles = false;
|
||||
event->mFlags.mCancelable = false;
|
||||
}
|
||||
|
@ -63,8 +62,7 @@ void CoalescedTouchData::Coalesce(const WidgetTouchEvent& aEvent,
|
|||
sameTouch->mCoalescedWidgetEvents->mEvents.AppendElement(
|
||||
WidgetPointerEvent(aEvent.IsTrusted(), ePointerMove,
|
||||
aEvent.mWidget));
|
||||
PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch,
|
||||
i == 0);
|
||||
PointerEventHandler::InitPointerEventFromTouch(*event, aEvent, *touch);
|
||||
event->mFlags.mBubbles = false;
|
||||
event->mFlags.mCancelable = false;
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
[pointerevent_pointermove_isprimary_same_as_pointerdown.html]
|
||||
expected:
|
||||
if (os == "android") and fission: [OK, TIMEOUT]
|
|
@ -6,6 +6,8 @@
|
|||
<link rel="author" title="Microsoft" href="http://www.microsoft.com/"/>
|
||||
<meta name="assert" content="The isPrimary attribute of a pointermove event must have the same value as the isPrimary attribute of the last pointerdown event with the same pointerId attribute."/>
|
||||
<link rel="stylesheet" type="text/css" href="pointerevent_styles.css">
|
||||
<meta name="variant" content="?mouse">
|
||||
<meta name="variant" content="?touch">
|
||||
<!-- /resources/testharness.js -->
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
@ -22,45 +24,82 @@
|
|||
// will fail unless the async_test is created with the var name "test_pointerEvent".
|
||||
add_completion_callback(showPointerTypes);
|
||||
|
||||
var pointermove_event = null;
|
||||
var pointerdown_event = null;
|
||||
var pointermove_events = new Map();
|
||||
var pointerdown_events = new Map();
|
||||
|
||||
function run() {
|
||||
var target0 = document.getElementById("target0");
|
||||
var actions_promise;
|
||||
|
||||
on_event(target0, "pointermove", function (event) {
|
||||
if (pointerdown_event != null) {
|
||||
let pointerdown_event = pointerdown_events.get(event.pointerId);
|
||||
if (pointerdown_event) {
|
||||
test_pointerEvent.step(function () {
|
||||
assert_equals(event.pointerId, pointerdown_event.pointerId, "pointermove.pointerId should be the same as pointerdown.pointerId.");
|
||||
assert_equals(event.isPrimary, pointerdown_event.isPrimary, "pointermove.isPrimary should be the same as pointerdown.isPrimary.");
|
||||
});
|
||||
pointermove_event = event;
|
||||
pointermove_events.set(event.pointerId, event);
|
||||
}
|
||||
});
|
||||
|
||||
on_event(target0, "pointerdown", function (event) {
|
||||
pointerdown_event = event;
|
||||
assert_equals(event.isPrimary, !!(pointerdown_events.size == 0), "pointerdown.isPrimary should only be true for first pointer.");
|
||||
pointerdown_events.set(event.pointerId, event);
|
||||
detected_pointertypes[event.pointerType] = true;
|
||||
});
|
||||
|
||||
on_event(target0, "pointerup", function (event) {
|
||||
let pointerdown_event = pointerdown_events.get(event.pointerId);
|
||||
test_pointerEvent.step(function () {
|
||||
assert_not_equals(pointermove_event, null, "pointermove event was never received: ");
|
||||
});
|
||||
// Make sure the test finishes after all the input actions are completed.
|
||||
actions_promise.then( () => {
|
||||
test_pointerEvent.done();
|
||||
assert_true(!!pointerdown_event, "pointerdown event was received.");
|
||||
assert_true(!!pointermove_events.size, "pointermove event was received.");
|
||||
assert_equals(event.pointerId, pointerdown_event.pointerId, "pointerup.pointerId should be the same as pointerdown.pointerId.");
|
||||
assert_equals(event.isPrimary, pointerdown_event.isPrimary, "pointerup.isPrimary should be the same as pointerdown.isPrimary.");
|
||||
});
|
||||
pointermove_events.delete(event.pointerId);
|
||||
pointerdown_events.delete(event.pointerId);
|
||||
if (pointerdown_events.size == 0) {
|
||||
// Make sure the test finishes after all the input actions are completed.
|
||||
actions_promise.then(() => {
|
||||
test_pointerEvent.done();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Dispatch a mouse drag in target0.
|
||||
actions_promise = new test_driver.Actions()
|
||||
.pointerMove(0, 0, {origin: target0})
|
||||
.pointerDown()
|
||||
.pointerMove(3, 3, {origin: target0})
|
||||
.pointerUp()
|
||||
.send();
|
||||
// Dispatch a mouse/touch drag in target0.
|
||||
var pointerType = location.search.substring(1);
|
||||
switch (pointerType) {
|
||||
case "mouse":
|
||||
actions_promise = new test_driver.Actions()
|
||||
.pointerMove(0, 0, {origin: target0})
|
||||
.pointerDown()
|
||||
.pointerMove(3, 3, {origin: target0})
|
||||
.pointerUp()
|
||||
.send();
|
||||
break;
|
||||
case "touch":
|
||||
actions_promise = new test_driver.Actions()
|
||||
.addPointer("touchPointer1", "touch")
|
||||
.pointerMove(0, 0, {origin: target0, sourceName: "touchPointer1"})
|
||||
.pointerDown({sourceName: "touchPointer1"})
|
||||
.pointerMove(3, 3, {origin: target0, sourceName: "touchPointer1"})
|
||||
.addPointer("touchPointer2", "touch")
|
||||
.pointerMove(0, 0, {origin: target0, sourceName: "touchPointer2"})
|
||||
.pointerDown({sourceName: "touchPointer2"})
|
||||
.pointerMove(5, 5, {origin: target0, sourceName: "touchPointer2"})
|
||||
.addPointer("touchPointer3", "touch")
|
||||
.pointerMove(0, 0, {origin: target0, sourceName: "touchPointer3"})
|
||||
.pointerDown({sourceName: "touchPointer3"})
|
||||
.pointerMove(7, 7, {origin: target0, sourceName: "touchPointer3"})
|
||||
.pointerUp({sourceName: "touchPointer3"})
|
||||
.pointerUp({sourceName: "touchPointer1"})
|
||||
.pointerUp({sourceName: "touchPointer2"})
|
||||
.send();
|
||||
break;
|
||||
default:
|
||||
assert_true(false, `does support testing ${pointerType} input`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
|
|
Загрузка…
Ссылка в новой задаче