Bug 940843 Don't consume keydown event in content of print preview because following keypress event may be handled as access key or shortcut key r=mats+smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 27 Nov 2013 09:55:26 +0900
changeset 157697 f73da8ab5911e12d6e6586962f98e10b7a6f4d5a
parent 157696 b61e4769b8ed0c17b01481a607aaf9a91d2c3a0b
child 157698 1c77baa4ac3e8ea723207c924b152a283caf313e
push id25719
push usercbook@mozilla.com
push dateWed, 27 Nov 2013 09:57:23 +0000
treeherdermozilla-central@2e3d89ed5dc7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs940843
milestone28.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 940843 Don't consume keydown event in content of print preview because following keypress event may be handled as access key or shortcut key r=mats+smaug
layout/printing/nsPrintPreviewListener.cpp
--- a/layout/printing/nsPrintPreviewListener.cpp
+++ b/layout/printing/nsPrintPreviewListener.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsPrintPreviewListener.h"
 
+#include "mozilla/TextEvents.h"
 #include "mozilla/dom/Element.h"
 #include "nsDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMKeyEvent.h"
 #include "nsIDOMEvent.h"
 #include "nsIDocument.h"
@@ -53,16 +54,19 @@ nsPrintPreviewListener::AddListeners()
     mEventTarget->AddEventListener(NS_LITERAL_STRING("keydown"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("keypress"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("keyup"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseout"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseover"), this, true);
     mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseup"), this, true);
+
+    mEventTarget->AddSystemEventListener(NS_LITERAL_STRING("keydown"),
+                                         this, true);
   }
 
   return NS_OK;
 }
 
 
 //-------------------------------------------------------
 //
@@ -79,69 +83,82 @@ nsPrintPreviewListener::RemoveListeners(
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keydown"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keypress"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("keyup"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousedown"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseout"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseover"), this, true);
     mEventTarget->RemoveEventListener(NS_LITERAL_STRING("mouseup"), this, true);
+
+    mEventTarget->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"),
+                                            this, true);
   }
 
   return NS_OK;
 }
 
 //-------------------------------------------------------
 //
 // GetActionForEvent
 //
 // Helper function to let certain key events through
 //
 enum eEventAction {
   eEventAction_Tab,       eEventAction_ShiftTab,
-  eEventAction_Propagate, eEventAction_Suppress
+  eEventAction_Propagate, eEventAction_Suppress,
+  eEventAction_StopPropagation
 };
 
 static eEventAction
 GetActionForEvent(nsIDOMEvent* aEvent)
 {
+  WidgetKeyboardEvent* keyEvent =
+    aEvent->GetInternalNSEvent()->AsKeyboardEvent();
+  if (!keyEvent) {
+    return eEventAction_Suppress;
+  }
+
+  if (keyEvent->mFlags.mInSystemGroup) {
+    NS_ASSERTION(keyEvent->message == NS_KEY_DOWN,
+      "Assuming we're listening only keydown event in system group");
+    return eEventAction_StopPropagation;
+  }
+
+  if (keyEvent->IsAlt() || keyEvent->IsControl() || keyEvent->IsMeta()) {
+    // Don't consume keydown event because following keypress event may be
+    // handled as access key or shortcut key.
+    return (keyEvent->message == NS_KEY_DOWN) ? eEventAction_StopPropagation :
+                                                eEventAction_Suppress;
+  }
+
   static const uint32_t kOKKeyCodes[] = {
     nsIDOMKeyEvent::DOM_VK_PAGE_UP, nsIDOMKeyEvent::DOM_VK_PAGE_DOWN,
     nsIDOMKeyEvent::DOM_VK_UP,      nsIDOMKeyEvent::DOM_VK_DOWN, 
     nsIDOMKeyEvent::DOM_VK_HOME,    nsIDOMKeyEvent::DOM_VK_END 
   };
 
-  nsCOMPtr<nsIDOMKeyEvent> keyEvent(do_QueryInterface(aEvent));
-  if (keyEvent) {
-    bool b;
-    keyEvent->GetAltKey(&b);
-    if (b) return eEventAction_Suppress;
-    keyEvent->GetCtrlKey(&b);
-    if (b) return eEventAction_Suppress;
+  if (keyEvent->keyCode == nsIDOMKeyEvent::DOM_VK_TAB) {
+    return keyEvent->IsShift() ? eEventAction_ShiftTab : eEventAction_Tab;
+  }
 
-    keyEvent->GetShiftKey(&b);
+  if (keyEvent->charCode == ' ' || keyEvent->keyCode == NS_VK_SPACE) {
+    return eEventAction_Propagate;
+  }
 
-    uint32_t keyCode;
-    keyEvent->GetKeyCode(&keyCode);
-    if (keyCode == nsIDOMKeyEvent::DOM_VK_TAB)
-      return b ? eEventAction_ShiftTab : eEventAction_Tab;
+  if (keyEvent->IsShift()) {
+    return eEventAction_Suppress;
+  }
 
-    uint32_t charCode;
-    keyEvent->GetCharCode(&charCode);
-    if (charCode == ' ' || keyCode == nsIDOMKeyEvent::DOM_VK_SPACE)
+  for (uint32_t i = 0; i < ArrayLength(kOKKeyCodes); ++i) {
+    if (keyEvent->keyCode == kOKKeyCodes[i]) {
       return eEventAction_Propagate;
-
-    if (b) return eEventAction_Suppress;
-
-    for (uint32_t i = 0; i < sizeof(kOKKeyCodes)/sizeof(kOKKeyCodes[0]); ++i) {
-      if (keyCode == kOKKeyCodes[i]) {
-        return eEventAction_Propagate;
-      }
     }
   }
+
   return eEventAction_Suppress;
 }
 
 NS_IMETHODIMP
 nsPrintPreviewListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   nsCOMPtr<nsIContent> content = do_QueryInterface(
     aEvent ? aEvent->InternalDOMEvent()->GetOriginalTarget() : nullptr);
@@ -178,15 +195,18 @@ nsPrintPreviewListener::HandleEvent(nsID
           }
         }
       }
       // fall-through
       case eEventAction_Suppress:
         aEvent->StopPropagation();
         aEvent->PreventDefault();
         break;
+      case eEventAction_StopPropagation:
+        aEvent->StopPropagation();
+        break;
       case eEventAction_Propagate:
         // intentionally empty
         break;
     }
   }
   return NS_OK;
 }