diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 325837923ad7..98c2bd9634a2 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -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; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index e256da2dd6f0..d55e536f685c 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1253,9 +1253,10 @@ public: nsCOMPtr mPendingContent; nsCOMPtr 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* 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* 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 diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index bf37e35e8850..b1fb8b77eda1 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -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 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 event; event = PointerEvent::Constructor(aCaptureTarget, aIsGotCapture diff --git a/layout/base/tests/bug977003_inner_1.html b/layout/base/tests/bug977003_inner_1.html index dee6f124fdbd..c4c7f2d84aba 100644 --- a/layout/base/tests/bug977003_inner_1.html +++ b/layout/base/tests/bug977003_inner_1.html @@ -3,10 +3,11 @@ - Test for Bugs 977003, 1094913 + Test for Bugs 977003, 1094913, 1098139 @@ -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 Mozilla Bug 977003 Test 1
Mozilla Bug 1094913 +
Mozilla Bug 1098139

diff --git a/layout/base/tests/bug977003_inner_5.html b/layout/base/tests/bug977003_inner_5.html index b505d9cdda2e..2bd12291a46c 100644 --- a/layout/base/tests/bug977003_inner_5.html +++ b/layout/base/tests/bug977003_inner_5.html @@ -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 --> - Test for Bugs 977003, 1073563, 1094913 + Test for Bugs 977003, 1073563, 1094913, 1098139 @@ -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 Mozilla Bug 977003 Test 5
Mozilla Bug 1073563
Mozilla Bug 1094913 +
Mozilla Bug 1098139

diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js index 4028bbae2fcd..36bd4be9dca7 100644 --- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -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);