Bug 1137557 - Part 1: Allow callee of TIP.keydown() to figure out preventDefault() of keydown and keypress event. r=masayuki, r+sr=smaug
authorTim Chien <timdream@gmail.com>
Wed, 05 Aug 2015 01:58:00 -0400
changeset 259089 1d47c8de65633109bd821654e873ad8abd418899
parent 259088 692a0e1e46a6805a266c86dd1de5cec2ede1b930
child 259090 e89f50c10fc263b6eda1672d81305b46232435d2
push id29268
push userryanvm@gmail.com
push dateTue, 25 Aug 2015 00:37:23 +0000
treeherdermozilla-central@08015770c9d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, r
bugs1137557
milestone43.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 1137557 - Part 1: Allow callee of TIP.keydown() to figure out preventDefault() of keydown and keypress event. r=masayuki, r+sr=smaug
dom/base/TextInputProcessor.cpp
dom/base/TextInputProcessor.h
dom/base/test/chrome/window_nsITextInputProcessor.xul
dom/interfaces/base/nsITextInputProcessor.idl
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -280,18 +280,21 @@ TextInputProcessor::MaybeDispatchKeydown
   // Modifier keys are not allowed because managing modifier state in this
   // method makes this messy.
   if (NS_WARN_IF(aKeyboardEvent->IsModifierKeyEvent())) {
     result.mResult = NS_ERROR_INVALID_ARG;
     result.mCanContinue = false;
     return result;
   }
 
+  uint32_t consumedFlags = 0;
+
   result.mResult = KeydownInternal(*aKeyboardEvent, aKeyFlags, false,
-                                   result.mDoDefault);
+                                   consumedFlags);
+  result.mDoDefault = !consumedFlags;
   if (NS_WARN_IF(NS_FAILED(result.mResult))) {
     result.mCanContinue = false;
     return result;
   }
 
   result.mCanContinue = NS_SUCCEEDED(IsValidStateForComposition());
   return result;
 }
@@ -750,32 +753,32 @@ TextInputProcessor::PrepareKeyboardEvent
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::Keydown(nsIDOMKeyEvent* aDOMKeyEvent,
                             uint32_t aKeyFlags,
                             uint8_t aOptionalArgc,
-                            bool* aDoDefault)
+                            uint32_t* aConsumedFlags)
 {
-  MOZ_RELEASE_ASSERT(aDoDefault, "aDoDefault must not be nullptr");
+  MOZ_RELEASE_ASSERT(aConsumedFlags, "aConsumedFlags must not be nullptr");
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   if (!aOptionalArgc) {
     aKeyFlags = 0;
   }
   if (NS_WARN_IF(!aDOMKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
   WidgetKeyboardEvent* originalKeyEvent =
     aDOMKeyEvent->GetInternalNSEvent()->AsKeyboardEvent();
   if (NS_WARN_IF(!originalKeyEvent)) {
     return NS_ERROR_INVALID_ARG;
   }
-  return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aDoDefault);
+  return KeydownInternal(*originalKeyEvent, aKeyFlags, true, *aConsumedFlags);
 }
 
 TextEventDispatcher::DispatchTo
 TextInputProcessor::GetDispatchTo() const
 {
   // Support asynchronous tests.
   if (mForTests) {
     return gfxPrefs::TestEventsAsyncEnabled() ?
@@ -789,28 +792,29 @@ TextInputProcessor::GetDispatchTo() cons
   // the current process.
   return TextEventDispatcher::eDispatchToCurrentProcess;
 }
 
 nsresult
 TextInputProcessor::KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                                     uint32_t aKeyFlags,
                                     bool aAllowToDispatchKeypress,
-                                    bool& aDoDefault)
+                                    uint32_t& aConsumedFlags)
 {
-  aDoDefault = false;
+  aConsumedFlags = KEYEVENT_NOT_CONSUMED;
 
   // We shouldn't modify the internal WidgetKeyboardEvent.
   WidgetKeyboardEvent keyEvent(aKeyboardEvent);
   nsresult rv = PrepareKeyboardEventToDispatch(keyEvent, aKeyFlags);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  aDoDefault = !(aKeyFlags & KEY_DEFAULT_PREVENTED);
+  aConsumedFlags = (aKeyFlags & KEY_DEFAULT_PREVENTED) ? KEYDOWN_IS_CONSUMED :
+                                                         KEYEVENT_NOT_CONSUMED;
 
   if (WidgetKeyboardEvent::GetModifierForKeyName(keyEvent.mKeyNameIndex)) {
     ModifierKeyData modifierKeyData(keyEvent);
     if (WidgetKeyboardEvent::IsLockableModifier(keyEvent.mKeyNameIndex)) {
       // If the modifier key is lockable modifier key such as CapsLock,
       // let's toggle modifier key state at keydown.
       ToggleModifierKey(modifierKeyData);
     } else {
@@ -827,30 +831,37 @@ TextInputProcessor::KeydownInternal(cons
   keyEvent.modifiers = GetActiveModifiers();
 
   nsRefPtr<TextEventDispatcher> kungfuDeathGrip(mDispatcher);
   rv = IsValidStateForComposition();
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  nsEventStatus status = aDoDefault ? nsEventStatus_eIgnore :
-                                      nsEventStatus_eConsumeNoDefault;
+  nsEventStatus status = aConsumedFlags ? nsEventStatus_eConsumeNoDefault :
+                                          nsEventStatus_eIgnore;
   if (!mDispatcher->DispatchKeyboardEvent(NS_KEY_DOWN, keyEvent, status,
                                           GetDispatchTo())) {
     // If keydown event isn't dispatched, we don't need to dispatch keypress
     // events.
     return NS_OK;
   }
 
-  if (aAllowToDispatchKeypress) {
-    mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status, GetDispatchTo());
+  aConsumedFlags |=
+    (status == nsEventStatus_eConsumeNoDefault) ? KEYDOWN_IS_CONSUMED :
+                                                  KEYEVENT_NOT_CONSUMED;
+
+  if (aAllowToDispatchKeypress &&
+      mDispatcher->MaybeDispatchKeypressEvents(keyEvent, status, 
+                                               GetDispatchTo())) {
+    aConsumedFlags |=
+      (status == nsEventStatus_eConsumeNoDefault) ? KEYPRESS_IS_CONSUMED :
+                                                    KEYEVENT_NOT_CONSUMED;
   }
 
-  aDoDefault = (status != nsEventStatus_eConsumeNoDefault);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TextInputProcessor::Keyup(nsIDOMKeyEvent* aDOMKeyEvent,
                           uint32_t aKeyFlags,
                           uint8_t aOptionalArgc,
                           bool* aDoDefault)
--- a/dom/base/TextInputProcessor.h
+++ b/dom/base/TextInputProcessor.h
@@ -52,17 +52,17 @@ private:
              const nsAString* aCommitString = nullptr,
              bool* aSucceeded = nullptr);
   nsresult CancelCompositionInternal(
              const WidgetKeyboardEvent* aKeyboardEvent = nullptr,
              uint32_t aKeyFlags = 0);
   nsresult KeydownInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                            uint32_t aKeyFlags,
                            bool aAllowToDispatchKeypress,
-                           bool& aDoDefault);
+                           uint32_t& aConsumedFlags);
   nsresult KeyupInternal(const WidgetKeyboardEvent& aKeyboardEvent,
                          uint32_t aKeyFlags,
                          bool& aDoDefault);
   TextEventDispatcher::DispatchTo GetDispatchTo() const;
   nsresult IsValidStateForComposition();
   void UnlinkFromTextEventDispatcher();
   nsresult PrepareKeyboardEventToDispatch(WidgetKeyboardEvent& aKeyboardEvent,
                                           uint32_t aKeyFlags);
--- a/dom/base/test/chrome/window_nsITextInputProcessor.xul
+++ b/dom/base/test/chrome/window_nsITextInputProcessor.xul
@@ -10,17 +10,17 @@
         src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
 <body  xmlns="http://www.w3.org/1999/xhtml">
 <p id="display">
 <input id="input" type="text"/><br/>
 <iframe id="iframe" width="300" height="150"
         src="data:text/html,&lt;textarea id='textarea' cols='20' rows='4'&gt;&lt;/textarea&gt;"></iframe><br/>
 </p>
 <div id="content" style="display: none">
-  
+
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script class="testbody" type="application/javascript">
 <![CDATA[
 
@@ -2335,18 +2335,18 @@ function runKeyTests()
 
   // Printable key test:
   // Emulates pressing 'a' key.
   var keyA = new KeyboardEvent("", { key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A });
 
   reset();
   var doDefaultKeydown = TIP.keydown(keyA);
 
-  ok(!doDefaultKeydown,
-     description + "TIP.keydown(keyA) should return false because the keypress event should be consumed by the input element");
+  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
+     description + "TIP.keydown(keyA) should return 0x02 because the keypress event should be consumed by the input element");
   is(events.length, 2,
      description + "TIP.keydown(keyA) should cause keydown and keypress event");
   checkKeyAttrs("TIP.keydown(keyA)", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0 });
   checkKeyAttrs("TIP.keydown(keyA)", events[1],
                 { type: "keypress", key: "a", code: "KeyA", keyCode: 0,                      charCode: "a".charCodeAt(0), defaultPrevented: true });
   is(input.value, "a",
      description + "input.value should be \"a\" which is inputted by TIP.keydown(keyA)");
@@ -2366,18 +2366,18 @@ function runKeyTests()
 
   // Non-printable key test:
   // Emulates pressing Enter key.
   var keyEnter = new KeyboardEvent("", { key: "Enter", code: "Enter" });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyEnter);
 
-  ok(doDefaultKeydown,
-     description + "TIP.keydown(keyEnter) should return true");
+  is(doDefaultKeydown, 0,
+     description + "TIP.keydown(keyEnter) should return 0");
   is(events.length, 2,
      description + "TIP.keydown(keyEnter) should cause keydown and keypress event");
   checkKeyAttrs("TIP.keydown(keyEnter)", events[0],
                 { type: "keydown",  key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
   checkKeyAttrs("TIP.keydown(keyEnter)", events[1],
                 { type: "keypress", key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
   is(input.value, "a",
      description + "input.value should stay \"a\" which was inputted by TIP.keydown(keyA)");
@@ -2397,18 +2397,18 @@ function runKeyTests()
 
   // KEY_DEFAULT_PREVENTED should cause defaultPrevented = true and not cause keypress event
   var keyB = new KeyboardEvent("", { key: "b", code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED);
   doDefaultKeyup   = TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED);
 
-  ok(!doDefaultKeydown,
-     description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) should return false because it's marked as consumed at dispatching the event");
+  is(doDefaultKeydown, TIP.KEYDOWN_IS_CONSUMED,
+     description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) should return 0x01 because it's marked as consumed at dispatching the event");
   ok(!doDefaultKeyup,
      description + "TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED) should return false because it's marked as consumed at dispatching the event");
   is(events.length, 2,
      description + "TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) and TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED) should cause keydown and keyup event");
   checkKeyAttrs("TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) and TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED)", events[0],
                 { type: "keydown", key: "b", code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B, defaultPrevented: true });
   checkKeyAttrs("TIP.keydown(keyB, TIP.KEY_DEFAULT_PREVENTED) and TIP.keyup(keyB, TIP.KEY_DEFAULT_PREVENTED)", events[1],
                 { type: "keyup",   key: "b", code: "KeyB", keyCode: KeyboardEvent.DOM_VK_B, defaultPrevented: true });
@@ -2418,17 +2418,17 @@ function runKeyTests()
   // Assume that KeyX causes inputting text "abc"
   input.value = "";
   var keyABC = new KeyboardEvent("", { key: "abc", code: "KeyX", keyCode: KeyboardEvent.DOM_VK_A });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyABC);
   doDefaultKeyup   = TIP.keyup(keyABC);
 
-  ok(!doDefaultKeydown,
+  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
      description + "TIP.keydown(keyABC) should return false because the keypress events should be consumed by the input element");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyABC) should return true");
   is(events.length, 5,
      description + "TIP.keydown(keyABC) and TIP.keyup(keyABC) should cause keydown, keypress, keypress, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyABC) and TIP.keyup(keyABC)", events[0],
                 { type: "keydown",  key: "abc",           code: "KeyX", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0,                   defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyABC) and TIP.keyup(keyABC)", events[1],
@@ -2445,18 +2445,18 @@ function runKeyTests()
   // If KEY_FORCE_PRINTABLE_KEY is specified, registered key names can be a printable key which inputs the specified value.
   input.value = "";
   var keyEnterPrintable = new KeyboardEvent("", { key: "Enter", code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY);
   doDefaultKeyup   = TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY);
 
-  ok(!doDefaultKeydown,
-     description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return false because the keypress events should be consumed by the input element");
+  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
+     description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return 0x02 because the keypress events should be consumed by the input element");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should return true");
   is(events.length, 7,
      description + "TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) and TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) should cause keydown, keypress, keypress, keypress, keypress, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) and TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY)", events[0],
                 { type: "keydown",  key: "Enter",           code: "Enter", keyCode: KeyboardEvent.DOM_VK_RETURN, charCode: 0,                    defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY) and TIP.keyup(keyEnterPrintable, TIP.KEY_FORCE_PRINTABLE_KEY)", events[1],
                 { type: "keypress", key: "Enter".charAt(0), code: "Enter", keyCode: 0,                           charCode: "Enter".charCodeAt(0), defaultPrevented: true });
@@ -2475,18 +2475,18 @@ function runKeyTests()
 
   // modifiers should be ignored.
   var keyWithModifiers = new KeyboardEvent("", { key: "Escape", code: "Escape", shiftKey: true, ctrlKey: true, altKey: true, metaKey: true });
 
   reset();
   doDefaultKeydown = TIP.keydown(keyWithModifiers);
   doDefaultKeyup   = TIP.keyup(keyWithModifiers);
 
-  ok(doDefaultKeydown,
-     description + "TIP.keydown(keyWithModifiers) should return true");
+  is(doDefaultKeydown, 0,
+     description + "TIP.keydown(keyWithModifiers) should return 0");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyWithModifiers) should return true");
   is(events.length, 3,
      description + "TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers) should cause keydown, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[0],
                 { type: "keydown",  key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
   checkKeyAttrs("TIP.keydown(keyWithModifiers) and TIP.keyup(keyWithModifiers)", events[1],
                 { type: "keypress", key: "Escape", code: "Escape", keyCode: KeyboardEvent.DOM_VK_ESCAPE });
@@ -2497,18 +2497,18 @@ function runKeyTests()
 
   // Call preventDefault() at keydown
   input.value = "";
   reset();
   doPreventDefaults = [ "keydown" ];
   doDefaultKeydown = TIP.keydown(keyA);
   doDefaultKeyup   = TIP.keyup(keyA);
 
-  ok(!doDefaultKeydown,
-     description + "TIP.keydown(keyA) should return false because keydown event's preventDefault should be called");
+  is(doDefaultKeydown, TIP.KEYDOWN_IS_CONSUMED,
+     description + "TIP.keydown(keyA) should return 0x01 because keydown event's preventDefault should be called");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyA) should return true");
   is(events.length, 2,
      description + "TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keydown should cause keydown and keyup event");
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keydown", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, defaultPrevented: true });
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keydown", events[1],
                 { type: "keyup",    key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, defaultPrevented: false });
@@ -2516,18 +2516,18 @@ function runKeyTests()
      description + "input.value shouldn't be modified by TIP.keyup(keyA) if the keydown event is consumed");
 
   // Call preventDefault() at keypress
   reset();
   doPreventDefaults = [ "keypress" ];
   doDefaultKeydown = TIP.keydown(keyA);
   doDefaultKeyup   = TIP.keyup(keyA);
 
-  ok(!doDefaultKeydown,
-     description + "TIP.keydown(keyA) should return false because keypress event's preventDefault should be called");
+  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
+     description + "TIP.keydown(keyA) should return 0x02 because keypress event's preventDefault should be called");
   ok(doDefaultKeyup,
      description + "TIP.keyup(keyA) should return true");
   is(events.length, 3,
      description + "TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keypress should cause keydown, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keypress", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0,                 defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keypress", events[1],
                 { type: "keypress", key: "a", code: "KeyA", keyCode: 0,                      charCode: "a".charCodeAt(0), defaultPrevented: true });
@@ -2538,18 +2538,18 @@ function runKeyTests()
 
   // Call preventDefault() at keyup
   input.value = "";
   reset();
   doPreventDefaults = [ "keyup" ];
   doDefaultKeydown = TIP.keydown(keyA);
   doDefaultKeyup   = TIP.keyup(keyA);
 
-  ok(!doDefaultKeydown,
-     description + "TIP.keydown(keyA) should return false because the key event should be consumed by the input element");
+  is(doDefaultKeydown, TIP.KEYPRESS_IS_CONSUMED,
+     description + "TIP.keydown(keyA) should return 0x02 because the key event should be consumed by the input element");
   ok(!doDefaultKeyup,
      description + "TIP.keyup(keyA) should return false because keyup event's preventDefault should be called");
   is(events.length, 3,
      description + "TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keyup should cause keydown, keypress and keyup event");
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keyup", events[0],
                 { type: "keydown",  key: "a", code: "KeyA", keyCode: KeyboardEvent.DOM_VK_A, charCode: 0,                 defaultPrevented: false });
   checkKeyAttrs("TIP.keydown(keyA) and TIP.keyup(keyA) with preventing default of keyup", events[1],
                 { type: "keypress", key: "a", code: "KeyA", keyCode: 0,                      charCode: "a".charCodeAt(0), defaultPrevented: true });
--- a/dom/interfaces/base/nsITextInputProcessor.idl
+++ b/dom/interfaces/base/nsITextInputProcessor.idl
@@ -249,17 +249,17 @@ interface nsITextInputProcessorCallback;
  *
  *   // keyup of one of shift key doesn't cause inactivating "Shift" state.
  *   TIP.keyup(rightShift);
  *
  *   // This causes inactivating "Shift" state completely.
  *   TIP.keyup(leftShift);
  */
 
-[scriptable, builtinclass, uuid(6617a9f6-3e16-4086-9e1e-c8a6c5d505c7)]
+[scriptable, builtinclass, uuid(581f6619-76ed-478c-905d-b8e6553a714a)]
 interface nsITextInputProcessor : nsISupports
 {
   /**
    * Returns true if this instance was dispatched compositionstart but hasn't
    * dispatched compositionend yet.
    */
   readonly attribute boolean hasComposition;
 
@@ -484,16 +484,22 @@ interface nsITextInputProcessor : nsISup
   // non-zero value, this flag causes throwing an exception.
   const unsigned long KEY_KEEP_KEYCODE_ZERO                        = 0x00000010;
   // If KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT is specified when the key event is
   // a modifier key's, keydown() and keyup() only modifies its modifier state
   // without dispatching key events.  This is useful for testing odd behavior
   // or emulating legacy API behavior.
   const unsigned long KEY_DONT_DISPATCH_MODIFIER_KEY_EVENT         = 0x00000020;
 
+  // These values can be used to do bitwise operation with the return value of
+  // the keydown() method.
+  const unsigned long KEYEVENT_NOT_CONSUMED                        = 0x00000000;
+  const unsigned long KEYDOWN_IS_CONSUMED                          = 0x00000001;
+  const unsigned long KEYPRESS_IS_CONSUMED                         = 0x00000002;
+
   /**
    * keydown() may dispatch a keydown event and some keypress events if
    * preceding keydown event isn't consumed and they are necessary.
    * Note that even if this is called during composition, key events may not
    * be dispatched.  In this case, this returns false.
    *
    * You should initialize at least .key value and .code value of the event.
    * Additionally, if you try to emulate a printable key, .keyCode value should
@@ -524,23 +530,30 @@ interface nsITextInputProcessor : nsISup
    *                        defined by any standards, use "" (empty string).
    *                        #4 .keyCode is guessed from .key value if the key
    *                        name is registered and .keyCode isn't initialized.
    *                        #5 modifier key states, e.g., .shiftKey, are
    *                        ignored.  Instead, modifier states are managed by
    *                        each instance and set automatically.
    * @param aKeyFlags       Special flags.  The values can be some of KEY_*
    *                        constants.
-   * @return                true if neither the keydown event or following
-   *                        keypress events is *not* consumed.
-   *                        Otherwise, i.e., preventDefault() is called, false.
+   * @return                KEYEVENT_NOT_CONSUMED, if the keydown event nor
+   *                        the following keypress event(s) are consumed.
+   *                        KEYDOWN_IS_CONSUMED, if the keydown event is
+   *                        consumed. No keypress event will be dispatched in
+   *                        this case.
+   *                        KEYPRESS_IS_CONSUMED, if the keypress event(s) is
+   *                        consumed when dispatched.
+   *                        Note that keypress event is always consumed by
+   *                        native code for the printable keys (indicating the
+   *                        default action has been taken).
    */
   [optional_argc]
-    boolean keydown(in nsIDOMKeyEvent aKeyboardEvent,
-                    [optional] in unsigned long aKeyFlags);
+    unsigned long keydown(in nsIDOMKeyEvent aKeyboardEvent,
+                          [optional] in unsigned long aKeyFlags);
 
   /**
    * Similar to keydown(), but this dispatches only a keyup event.
    */
   [optional_argc]
     boolean keyup(in nsIDOMKeyEvent aKeyboardEvent,
                   [optional] in unsigned long aKeyFlags);