Bug 1090906, no context menu when pointer is locked, r=masayuki
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 30 Oct 2014 13:24:08 +0200
changeset 213176 b0b71ab4cd59d49889157c0edbe360af99a5d308
parent 213175 5dcc6258e024571a90c7814cdd70c5740036936e
child 213177 374ebf41e67c6f30851c861bdf6e3ca821cc06f8
push id27742
push userryanvm@gmail.com
push dateThu, 30 Oct 2014 20:15:35 +0000
treeherdermozilla-central@e0b505a37b1c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki
bugs1090906
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1090906, no context menu when pointer is locked, r=masayuki
dom/events/EventStateManager.cpp
dom/tests/mochitest/pointerlock/file_pointerlock-api.html
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -524,16 +524,21 @@ EventStateManager::PreHandleEvent(nsPres
     ++gMouseOrKeyboardEventCounter;
   }
 
   *aStatus = nsEventStatus_eIgnore;
 
   WheelTransaction::OnEvent(aEvent);
 
   switch (aEvent->message) {
+  case NS_CONTEXTMENU:
+    if (sIsPointerLocked) {
+      return NS_ERROR_DOM_INVALID_STATE_ERR;
+    }
+    break;
   case NS_MOUSE_BUTTON_DOWN: {
     switch (mouseEvent->button) {
     case WidgetMouseEvent::eLeftButton:
       BeginTrackingDragGesture(aPresContext, mouseEvent, aTargetFrame);
       mLClickCount = mouseEvent->clickCount;
       SetClickCount(aPresContext, mouseEvent, aStatus);
       sNormalLMouseEventInProcess = true;
       break;
@@ -1268,18 +1273,21 @@ EventStateManager::HandleCrossProcessEve
 // is a one-shot that will be cancelled when the user moves enough to fire
 // a drag.
 //
 void
 EventStateManager::CreateClickHoldTimer(nsPresContext* inPresContext,
                                         nsIFrame* inDownFrame,
                                         WidgetGUIEvent* inMouseDownEvent)
 {
-  if (!inMouseDownEvent->mFlags.mIsTrusted || IsRemoteTarget(mGestureDownContent))
+  if (!inMouseDownEvent->mFlags.mIsTrusted ||
+      IsRemoteTarget(mGestureDownContent) ||
+      sIsPointerLocked) {
     return;
+  }
 
   // just to be anal (er, safe)
   if (mClickHoldTimer) {
     mClickHoldTimer->Cancel();
     mClickHoldTimer = nullptr;
   }
 
   // if content clicked on has a popup, don't even start the timer
@@ -1351,17 +1359,17 @@ EventStateManager::sClickHoldCallback(ns
 // means that someone either ate the event or put up a context menu. This is our cue
 // to stop tracking the drag gesture. If we always did this, draggable items w/out
 // a context menu wouldn't be draggable after a certain length of time, which is
 // _not_ what we want.
 //
 void
 EventStateManager::FireContextClick()
 {
-  if (!mGestureDownContent || !mPresContext) {
+  if (!mGestureDownContent || !mPresContext || sIsPointerLocked) {
     return;
   }
 
 #ifdef XP_MACOSX
   // Hack to ensure that we don't show a context menu when the user
   // let go of the mouse after a long cpu-hogging operation prevented
   // us from handling any OS events. See bug 117589.
   if (!CGEventSourceButtonState(kCGEventSourceStateCombinedSessionState, kCGMouseButtonLeft))
--- a/dom/tests/mochitest/pointerlock/file_pointerlock-api.html
+++ b/dom/tests/mochitest/pointerlock/file_pointerlock-api.html
@@ -29,26 +29,28 @@
         hasRequestPointerLock = false,
         pointerLockChangeEventFired = false,
         pointerUnlocked = false,
         pointerLocked = false,
         hasExitPointerLock = false,
         pointerLockElement = false,
         hasMovementX = false,
         hasMovementY = false;
+        gotContextMenuEvent = false;
 
       function runTests () {
         ok(hasRequestPointerLock, "Element should have mozRequestPointerLock.");
         ok(pointerLockChangeEventFired, "pointerlockchange event should fire.");
         ok(pointerUnlocked, "Should be able to unlock pointer locked element.");
         ok(pointerLocked, "Requested element should be able to lock.");
         ok(hasExitPointerLock, "Document should have mozExitPointerLock");
         ok(pointerLockElement, "Document should keep track of correct pointer locked element");
         ok(hasMovementX, "Mouse Event should have mozMovementX.");
         ok(hasMovementY, "Mouse Event should have mozMovementY.");
+        ok(!gotContextMenuEvent, "Shouldn't have got a contextmenu event.");
       }
 
       function mouseMoveHandler(e) {
         document.removeEventListener("mousemove", mouseMoveHandler, false);
 
         hasMovementX = "mozMovementX" in e;
         hasMovementY = "mozMovementY" in e;
 
@@ -57,16 +59,24 @@
       }
 
       document.addEventListener("mozpointerlockchange", function (e) {
         pointerLockChangeEventFired = true;
 
         if (document.mozPointerLockElement) {
           pointerLocked = true;
           pointerLockElement = document.mozPointerLockElement === div;
+ 
+          window.addEventListener("contextmenu",
+                                  function() { gotContextMenuEvent = true; },
+                                  true);
+          synthesizeMouse(document.body, 4, 4,
+                          { type: "contextmenu", button: 2 },
+                          window);
+
           document.addEventListener("mousemove", mouseMoveHandler, false);
           synthesizeMouseAtCenter(div, {type: "mousemove"}, window);
         } else {
           pointerUnlocked = true;
           document.mozCancelFullScreen();
         }
       }, false);