Bug 1098139 - Add attribute isPrimary detection for got/lostpointercapture events. r=smaug

This commit is contained in:
Lebedev Maksim 2014-11-18 01:13:00 +01:00
parent 0095fc6678
commit 22d1368cd8
6 changed files with 73 additions and 29 deletions

View File

@ -866,7 +866,7 @@ nsDOMWindowUtils::SendPointerEventCommon(const nsAString& aType,
event.height = aHeight;
event.tiltX = aTiltX;
event.tiltY = aTiltY;
event.isPrimary = aIsPrimary;
event.isPrimary = (nsIDOMMouseEvent::MOZ_SOURCE_MOUSE == aInputSourceArg) ? true : aIsPrimary;
event.clickCount = aClickCount;
event.time = PR_IntervalNow();
event.mFlags.mIsSynthesizedForTests = aOptionalArgCount >= 10 ? aIsSynthesized : true;

View File

@ -1253,9 +1253,10 @@ public:
nsCOMPtr<nsIContent> mPendingContent;
nsCOMPtr<nsIContent> mOverrideContent;
bool mReleaseContent;
bool mPrimaryState;
explicit PointerCaptureInfo(nsIContent* aPendingContent) :
mPendingContent(aPendingContent), mReleaseContent(false)
explicit PointerCaptureInfo(nsIContent* aPendingContent, bool aPrimaryState) :
mPendingContent(aPendingContent), mReleaseContent(false), mPrimaryState(aPrimaryState)
{
MOZ_COUNT_CTOR(PointerCaptureInfo);
}
@ -1273,27 +1274,29 @@ public:
// Keeps a map between pointerId and element that currently capturing pointer
// with such pointerId. If pointerId is absent in this map then nobody is
// capturing it. Additionally keep information about pending capturing content.
// Additionally keep information about primaryState of pointer event.
static nsClassHashtable<nsUint32HashKey, PointerCaptureInfo>* gPointerCaptureList;
struct PointerInfo
{
bool mActiveState;
uint16_t mPointerType;
PointerInfo(bool aActiveState, uint16_t aPointerType) :
mActiveState(aActiveState), mPointerType(aPointerType) {}
bool mPrimaryState;
PointerInfo(bool aActiveState, uint16_t aPointerType, bool aPrimaryState) :
mActiveState(aActiveState), mPointerType(aPointerType), mPrimaryState(aPrimaryState) {}
};
// Keeps information about pointers such as pointerId, activeState, pointerType
// Keeps information about pointers such as pointerId, activeState, pointerType, primaryState
static nsClassHashtable<nsUint32HashKey, PointerInfo>* gActivePointersIds;
static void DispatchGotOrLostPointerCaptureEvent(bool aIsGotCapture,
uint32_t aPointerId,
uint16_t aPointerType,
bool aIsPrimary,
nsIContent* aCaptureTarget);
static void SetPointerCapturingContent(uint32_t aPointerId, nsIContent* aContent);
static void ReleasePointerCapturingContent(uint32_t aPointerId, nsIContent* aContent);
static nsIContent* GetPointerCapturingContent(uint32_t aPointerId);
static uint16_t GetPointerType(uint32_t aPointerId);
// CheckPointerCaptureState checks cases, when got/lostpointercapture events should be fired.
// Function returns true, if any of events was fired; false, if no one event was fired.
static bool CheckPointerCaptureState(uint32_t aPointerId);
@ -1302,6 +1305,12 @@ public:
// aActiveState is additional information, which shows state of pointer like button state for mouse.
static bool GetPointerInfo(uint32_t aPointerId, bool& aActiveState);
// GetPointerType returns pointer type like mouse, pen or touch for pointer event with pointerId
static uint16_t GetPointerType(uint32_t aPointerId);
// GetPointerPrimaryState returns state of attribute isPrimary for pointer event with pointerId
static bool GetPointerPrimaryState(uint32_t aPointerId);
/**
* When capturing content is set, it traps all mouse events and retargets
* them at this content node. If capturing is not allowed

View File

@ -6411,7 +6411,8 @@ nsIPresShell::SetPointerCapturingContent(uint32_t aPointerId, nsIContent* aConte
if (pointerCaptureInfo) {
pointerCaptureInfo->mPendingContent = aContent;
} else {
gPointerCaptureList->Put(aPointerId, new PointerCaptureInfo(aContent));
gPointerCaptureList->Put(aPointerId,
new PointerCaptureInfo(aContent, GetPointerPrimaryState(aPointerId)));
}
}
@ -6442,16 +6443,6 @@ nsIPresShell::GetPointerCapturingContent(uint32_t aPointerId)
return nullptr;
}
/* static */ uint16_t
nsIPresShell::GetPointerType(uint32_t aPointerId)
{
PointerInfo* pointerInfo = nullptr;
if (gActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
return pointerInfo->mPointerType;
}
return nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
}
/* static */ bool
nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId)
{
@ -6463,6 +6454,7 @@ nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId)
if (pointerCaptureInfo->mPendingContent || pointerCaptureInfo->mReleaseContent) {
if (pointerCaptureInfo->mOverrideContent) {
uint16_t pointerType = GetPointerType(aPointerId);
bool isPrimary = pointerCaptureInfo->mPrimaryState;
nsCOMPtr<nsIContent> content;
pointerCaptureInfo->mOverrideContent.swap(content);
if (pointerCaptureInfo->mReleaseContent) {
@ -6471,7 +6463,7 @@ nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId)
if (pointerCaptureInfo->Empty()) {
gPointerCaptureList->Remove(aPointerId);
}
DispatchGotOrLostPointerCaptureEvent(false, aPointerId, pointerType, content);
DispatchGotOrLostPointerCaptureEvent(false, aPointerId, pointerType, isPrimary, content);
didDispatchEvent = true;
} else if (pointerCaptureInfo->mPendingContent && pointerCaptureInfo->mReleaseContent) {
// If anybody calls element.releasePointerCapture
@ -6489,6 +6481,7 @@ nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId)
pointerCaptureInfo->mReleaseContent = false;
DispatchGotOrLostPointerCaptureEvent(true, aPointerId,
GetPointerType(aPointerId),
pointerCaptureInfo->mPrimaryState,
pointerCaptureInfo->mOverrideContent);
didDispatchEvent = true;
}
@ -6496,6 +6489,26 @@ nsIPresShell::CheckPointerCaptureState(uint32_t aPointerId)
return didDispatchEvent;
}
/* static */ uint16_t
nsIPresShell::GetPointerType(uint32_t aPointerId)
{
PointerInfo* pointerInfo = nullptr;
if (gActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
return pointerInfo->mPointerType;
}
return nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN;
}
/* static */ bool
nsIPresShell::GetPointerPrimaryState(uint32_t aPointerId)
{
PointerInfo* pointerInfo = nullptr;
if (gActivePointersIds->Get(aPointerId, &pointerInfo) && pointerInfo) {
return pointerInfo->mPrimaryState;
}
return false;
}
/* static */ bool
nsIPresShell::GetPointerInfo(uint32_t aPointerId, bool& aActiveState)
{
@ -6514,20 +6527,23 @@ PresShell::UpdateActivePointerState(WidgetGUIEvent* aEvent)
case NS_MOUSE_ENTER:
// In this case we have to know information about available mouse pointers
if (WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent()) {
gActivePointersIds->Put(mouseEvent->pointerId, new PointerInfo(false, mouseEvent->inputSource));
gActivePointersIds->Put(mouseEvent->pointerId,
new PointerInfo(false, mouseEvent->inputSource, true));
}
break;
case NS_POINTER_DOWN:
// In this case we switch pointer to active state
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
gActivePointersIds->Put(pointerEvent->pointerId, new PointerInfo(true, pointerEvent->inputSource));
gActivePointersIds->Put(pointerEvent->pointerId,
new PointerInfo(true, pointerEvent->inputSource, pointerEvent->isPrimary));
}
break;
case NS_POINTER_UP:
// In this case we remove information about pointer or turn off active state
if (WidgetPointerEvent* pointerEvent = aEvent->AsPointerEvent()) {
if(pointerEvent->inputSource != nsIDOMMouseEvent::MOZ_SOURCE_TOUCH) {
gActivePointersIds->Put(pointerEvent->pointerId, new PointerInfo(false, pointerEvent->inputSource));
gActivePointersIds->Put(pointerEvent->pointerId,
new PointerInfo(false, pointerEvent->inputSource, pointerEvent->isPrimary));
} else {
gActivePointersIds->Remove(pointerEvent->pointerId);
}
@ -8245,12 +8261,14 @@ void
nsIPresShell::DispatchGotOrLostPointerCaptureEvent(bool aIsGotCapture,
uint32_t aPointerId,
uint16_t aPointerType,
bool aIsPrimary,
nsIContent* aCaptureTarget)
{
PointerEventInit init;
init.mPointerId = aPointerId;
init.mBubbles = true;
ConvertPointerTypeToString(aPointerType, init.mPointerType);
init.mIsPrimary = aIsPrimary;
nsRefPtr<mozilla::dom::PointerEvent> event;
event = PointerEvent::Constructor(aCaptureTarget,
aIsGotCapture

View File

@ -3,10 +3,11 @@
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=977003
https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
-->
<head>
<meta charset="utf-8">
<title>Test for Bugs 977003, 1094913</title>
<title>Test for Bugs 977003, 1094913, 1098139</title>
<meta name="author" content="Maksim Lebedev" />
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
@ -19,9 +20,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
var test_send_got = 0;
var test_got_async = 0;
var test_got_type = "";
var test_got_primary = false;
var test_send_lost = 0;
var test_lost_async = 0;
var test_lost_type = "";
var test_lost_primary = false;
function DownHandler(event) {
logger("Receive event: " + event.type);
@ -35,6 +38,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
if(test_send_got)
test_got_async++;
test_got_type = event.pointerType;
test_got_primary = event.isPrimary;
logger("Send releasePointerCapture from target");
target.releasePointerCapture(event.pointerId);
logger("releasePointerCapture was executed");
@ -45,6 +49,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
if(test_send_lost)
test_lost_async++;
test_lost_type = event.pointerType;
test_lost_primary = event.isPrimary;
}
function logger(message) {
console.log(message);
@ -71,9 +76,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
parent.is(test_send_got, 1, "Part 1: gotpointercapture event should be sent once");
parent.is(test_got_async, 1, "Part 1: gotpointercapture event should be asynchronous");
parent.is(test_got_type, "mouse", "Part 1: gotpointercapture event should have pointerType mouse");
parent.is(test_got_primary, true, "Part 1: gotpointercapture event should have isPrimary as true");
parent.is(test_send_lost, 1, "Part 1: lostpointercapture event should be sent once");
parent.is(test_lost_async, 1, "Part 1: lostpointercapture event should be asynchronous");
parent.is(test_lost_type, "mouse", "Part 1: lostpointercapture event should have pointerType mouse");
parent.is(test_lost_primary, true, "Part 1: lostpointercapture event should have isPrimary as true");
logger("finishTest");
parent.finishTest();
}
@ -82,6 +89,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
<body onload="prepareTest()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 1</a>
<br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094913">Mozilla Bug 1094913</a>
<br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1098139">Mozilla Bug 1098139</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>

View File

@ -4,10 +4,11 @@
https://bugzilla.mozilla.org/show_bug.cgi?id=977003
https://bugzilla.mozilla.org/show_bug.cgi?id=1073563
https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
https://bugzilla.mozilla.org/show_bug.cgi?id=1098139
-->
<head>
<meta charset="utf-8">
<title>Test for Bugs 977003, 1073563, 1094913</title>
<title>Test for Bugs 977003, 1073563, 1094913, 1098139</title>
<meta name="author" content="Maksim Lebedev" />
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
@ -21,9 +22,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
var test_down_target = false;
var test_got_listener = false;
var test_got_type = "";
var test_got_primary = false;
var test_lost_listener = false;
var test_lost_type = "";
var test_listener = false;
var test_lost_primary = false;
function TargetDownHandler(event) {
logger("Target receive event: " + event.type);
@ -37,11 +40,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
listener.releasePointerCapture(event.pointerId);
test_got_listener = true;
test_got_type = event.pointerType;
test_got_primary = event.isPrimary;
}
function ListenerLostPCHandler(event) {
logger("Receive event on Listener: " + event.type + "(" + event.pointerType + ")");
test_lost_listener = true;
test_lost_type = event.pointerType;
test_lost_primary = event.isPrimary;
}
function ListenerHandler(event) {
logger("Receive event on Listener: " + event.type);
@ -69,17 +74,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
listener.addEventListener("pointerup", ListenerHandler, false);
listener.addEventListener("pointerout", ListenerHandler, false);
var rect = target.getBoundingClientRect();
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown", inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove", inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup", inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerdown", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointermove", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
synthesizePointer(target, rect.width/2, rect.height/2, {type: "pointerup", isPrimary: true, inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH});
finishTest();
}
function finishTest() {
parent.is(test_down_target, true, "Part 5: pointerdown event should be received by target");
parent.is(test_got_listener, true, "Part 5: listener should receive gotpointercapture event");
parent.is(test_got_type, "touch", "Part 5: gotpointercapture event should have pointerType touch");
parent.is(test_got_primary, true, "Part 5: gotpointercapture event should have isPrimary as true");
parent.is(test_lost_listener, true, "Part 5: listener should receive lostpointercapture event");
parent.is(test_lost_type, "touch", "Part 5: lostpointercapture event should have pointerType touch");
parent.is(test_lost_primary, true, "Part 5: lostpointercapture event should have isPrimary as true");
parent.is(test_listener, false, "Part 5: listener should not receive any other events");
logger("finishTest");
parent.finishTest();
@ -90,6 +97,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1094913
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=977003">Mozilla Bug 977003 Test 5</a>
<br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1073563">Mozilla Bug 1073563</a>
<br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1094913">Mozilla Bug 1094913</a>
<br><a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1098139">Mozilla Bug 1098139</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>

View File

@ -305,12 +305,13 @@ function synthesizePointerAtPoint(left, top, aEvent, aWindow)
var pressure = ("pressure" in aEvent) ? aEvent.pressure : 0;
var inputSource = ("inputSource" in aEvent) ? aEvent.inputSource : 0;
var synthesized = ("isSynthesized" in aEvent) ? aEvent.isSynthesized : true;
var isPrimary = ("isPrimary" in aEvent) ? aEvent.isPrimary : false;
if (("type" in aEvent) && aEvent.type) {
defaultPrevented = utils.sendPointerEventToWindow(aEvent.type, left, top, button,
clickCount, modifiers, false,
pressure, inputSource,
synthesized);
synthesized, 0, 0, 0, 0, isPrimary);
}
else {
utils.sendPointerEventToWindow("pointerdown", left, top, button, clickCount, modifiers, false, pressure, inputSource);