WIP bug 1419091 draft
authorTimothy Guan-tin Chien <timdream@gmail.com>
Tue, 27 Feb 2018 12:02:02 -0800
changeset 763383 348e4dfe31c85f8ff875afc8dacfd4fc50ad4465
parent 762291 5410375734d6ca8be3ff06acdc1c951d87d644ee
push id101443
push usertimdream@gmail.com
push dateMon, 05 Mar 2018 22:16:14 +0000
bugs1419091
milestone60.0a1
WIP bug 1419091 MozReview-Commit-ID: BWVIxE36vIg
dom/html/HTMLInputElement.cpp
dom/html/HTMLInputElement.h
dom/xbl/builtin/input-fields-base.inc
dom/xbl/builtin/mac/platformHTMLBindings.xml
dom/xbl/builtin/unix/platformHTMLBindings.xml
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -26,16 +26,17 @@
 #include "HTMLFormSubmissionConstants.h"
 #include "mozilla/Telemetry.h"
 #include "nsIControllers.h"
 #include "nsIStringBundle.h"
 #include "nsFocusManager.h"
 #include "nsColorControlFrame.h"
 #include "nsNumberControlFrame.h"
 #include "nsPIDOMWindow.h"
+#include "nsPIWindowRoot.h"
 #include "nsRepeatService.h"
 #include "nsContentCID.h"
 #include "nsIComponentManager.h"
 #include "mozilla/dom/ProgressEvent.h"
 #include "nsGkAtoms.h"
 #include "nsStyleConsts.h"
 #include "nsPresContext.h"
 #include "nsMappedAttributes.h"
@@ -211,16 +212,51 @@ const Decimal HTMLInputElement::kStepAny
 const double HTMLInputElement::kMinimumYear = 1;
 const double HTMLInputElement::kMaximumYear = 275760;
 const double HTMLInputElement::kMaximumWeekInMaximumYear = 37;
 const double HTMLInputElement::kMaximumDayInMaximumYear = 13;
 const double HTMLInputElement::kMaximumMonthInMaximumYear = 9;
 const double HTMLInputElement::kMaximumWeekInYear = 53;
 const double HTMLInputElement::kMsPerDay = 24 * 60 * 60 * 1000;
 
+static const CommandKeyMapInfo sCommandKeyTable[] = {
+// These command keys are shared across all platforms.
+  { NS_VK_C, true, MODIFIER_NONE, "cmd_copy" },
+  { NS_VK_X, true, MODIFIER_NONE, "cmd_cut" },
+  { NS_VK_V, true, MODIFIER_NONE, "cmd_paste" },
+  { NS_VK_Z, true, MODIFIER_NONE, "cmd_undo" },
+  { NS_VK_RIGHT, false, MODIFIER_NONE, "cmd_moveRight" },
+  { NS_VK_Z, true, MODIFIER_SHIFT, "cmd_redo" },
+#ifdef XP_WIN
+#endif
+#ifdef MOZ_WIDGET_COCOA
+  { NS_VK_A, true, MODIFIER_NONE, "cmd_selectAll" },
+#endif
+#ifndef MOZ_WIDGET_COCOA
+  { NS_VK_LEFT, false, MODIFIER_SHIFT, "cmd_selectLeft" },
+  { NS_VK_LEFT, false, MODIFIER_NONE, "cmd_moveLeft" },
+  { NS_VK_RIGHT, false, MODIFIER_SHIFT, "cmd_selectRight" },
+  { NS_VK_RIGHT, false, MODIFIER_NONE, "cmd_moveRight" },
+  { NS_VK_UP, false, MODIFIER_SHIFT, "cmd_selectUp" },
+  { NS_VK_UP, false, MODIFIER_NONE, "cmd_moveUp" },
+  { NS_VK_DOWN, false, MODIFIER_SHIFT, "cmd_selectDown" },
+  { NS_VK_DOWN, false, MODIFIER_NONE, "cmd_moveDown" },
+#endif
+#ifdef MOZ_WIDGET_ANDROID
+#endif
+#ifdef MOZ_WIDGET_GTK
+  { NS_VK_A, true, MODIFIER_NONE, "cmd_selectAll" },
+  { NS_VK_A, false, MODIFIER_ALT, "cmd_selectAll" },
+  { NS_VK_Y, true, MODIFIER_NONE, "cmd_undo" },
+#endif
+#if !defined(XP_WIN) && !defined(MOZ_WIDGET_COCOA) && !defined(MOZ_WIDGET_ANDROID) && !defined(MOZ_WIDGET_GTK)
+// "emacs" command keys
+#endif
+};
+
 #define NS_INPUT_ELEMENT_STATE_IID                 \
 { /* dc3b3d14-23e2-4479-b513-7b369343e3a0 */       \
   0xdc3b3d14,                                      \
   0x23e2,                                          \
   0x4479,                                          \
   {0xb5, 0x13, 0x7b, 0x36, 0x93, 0x43, 0xe3, 0xa0} \
 }
 
@@ -4427,16 +4463,68 @@ HTMLInputElement::PostHandleEvent(EventC
                 mType == NS_FORM_INPUT_NUMBER ||
                 IsExperimentalMobileType(mType) ||
                 IsDateTimeInputType(mType))) {
             FireChangeEventIfNeeded();
             rv = MaybeSubmitForm(aVisitor.mPresContext);
             NS_ENSURE_SUCCESS(rv, rv);
           }
 
+          /*
+           * Trigger command if the key and the modifiers matches.
+           */
+          if (aVisitor.mEvent->mMessage == eKeyPress &&
+              !aVisitor.mEvent->DefaultPrevented() &&
+              !aVisitor.mEvent->PropagationStopped() &&
+              mType != NS_FORM_INPUT_HIDDEN &&
+              mType != NS_FORM_INPUT_IMAGE &&
+              mType != NS_FORM_INPUT_FILE &&
+              mType != NS_FORM_INPUT_COLOR &&
+              mType != NS_FORM_INPUT_RESET &&
+              mType != NS_FORM_INPUT_BUTTON &&
+              mType != NS_FORM_INPUT_SUBMIT) {
+
+            const char* cmd = nullptr;
+            uint32_t code = keyEvent->mCharCode ?
+              ToUpperCase(keyEvent->mCharCode) : keyEvent->mKeyCode;
+            IgnoreModifierState ignore = IgnoreModifierState();
+            Modifiers modifiersToMatch = keyEvent->mModifiers &
+              (ignore.mShift ? ~MODIFIER_SHIFT : ~MODIFIER_NONE) &
+              (ignore.mOS ? ~MODIFIER_OS : ~MODIFIER_NONE);
+            const Modifiers sAccelKey = WidgetInputEvent::AccelModifier();
+
+            for (uint32_t i = 0 ; i < ArrayLength(sCommandKeyTable) ; i++) {
+              Modifiers modifiers = sCommandKeyTable[i].accelKey ?
+                sCommandKeyTable[i].modifiers ^ sAccelKey :
+                sCommandKeyTable[i].modifiers;
+              if (sCommandKeyTable[i].code == code &&
+                  modifiers == modifiersToMatch) {
+                cmd = sCommandKeyTable[i].cmd;
+                break;
+              }
+            }
+
+            if (cmd) {
+              // We are the default action for this command.
+              // Stop any other default action from executing.
+              aVisitor.mDOMEvent->PreventDefault();
+
+              nsCOMPtr<nsPIDOMWindowOuter> window = OwnerDoc()->GetWindow();
+              MOZ_ASSERT(window);
+              nsCOMPtr<nsPIWindowRoot> root = window->GetTopWindowRoot();
+              MOZ_ASSERT(root);
+              nsCOMPtr<nsIController> controller;
+              root->GetControllerForCommand(cmd, true, getter_AddRefs(controller));
+              if (!controller) {
+                break;
+              }
+              controller->DoCommand(cmd);
+            }
+          }
+
           if (aVisitor.mEvent->mMessage == eKeyPress &&
               mType == NS_FORM_INPUT_RANGE && !keyEvent->IsAlt() &&
               !keyEvent->IsControl() && !keyEvent->IsMeta() &&
               (keyEvent->mKeyCode == NS_VK_LEFT ||
                keyEvent->mKeyCode == NS_VK_RIGHT ||
                keyEvent->mKeyCode == NS_VK_UP ||
                keyEvent->mKeyCode == NS_VK_DOWN ||
                keyEvent->mKeyCode == NS_VK_PAGE_UP ||
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -46,16 +46,23 @@ static constexpr size_t INPUT_TYPE_SIZE 
                    MonthInputType, DateTimeLocalInputType, FileInputType,
                    ColorInputType, HiddenInputType> );
 
 class InputType;
 struct DoNotDelete;
 class nsIRadioGroupContainer;
 class nsIRadioVisitor;
 
+struct CommandKeyMapInfo {
+  const uint32_t code;
+  const bool accelKey;
+  const mozilla::Modifiers modifiers;
+  const char* cmd;
+};
+
 namespace mozilla {
 
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 
 namespace dom {
 
 class AfterSetFilesOrDirectoriesRunnable;
--- a/dom/xbl/builtin/input-fields-base.inc
+++ b/dom/xbl/builtin/input-fields-base.inc
@@ -1,17 +1,19 @@
+<!--
     <handler event="keypress" keycode="VK_LEFT" command="cmd_moveLeft"/>
     <handler event="keypress" keycode="VK_RIGHT" command="cmd_moveRight"/>
     <handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectLeft"/>
     <handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectRight"/>
 
     <handler event="keypress" keycode="VK_UP" command="cmd_moveUp"/>
     <handler event="keypress" keycode="VK_DOWN" command="cmd_moveDown"/>
     <handler event="keypress" keycode="VK_UP" modifiers="shift" command="cmd_selectUp"/>
     <handler event="keypress" keycode="VK_DOWN" modifiers="shift" command="cmd_selectDown"/>
-
+-->
     <!-- Cut/copy/paste/undo -->
+<!--
     <handler event="keypress" key="c" modifiers="accel" command="cmd_copy"/>
     <handler event="keypress" key="x" modifiers="accel" command="cmd_cut"/>
     <handler event="keypress" key="v" modifiers="accel" command="cmd_paste"/>
     <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
     <handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo" />
-
+-->
--- a/dom/xbl/builtin/mac/platformHTMLBindings.xml
+++ b/dom/xbl/builtin/mac/platformHTMLBindings.xml
@@ -5,22 +5,22 @@
 
 
 <bindings id="htmlBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="inputFields" bindToUntrustedContent="true">
     <handlers>
-      <handler event="keypress" key="c" modifiers="accel" command="cmd_copy"/>
+<!--       <handler event="keypress" key="c" modifiers="accel" command="cmd_copy"/>
       <handler event="keypress" key="x" modifiers="accel" command="cmd_cut"/>
       <handler event="keypress" key="v" modifiers="accel" command="cmd_paste"/>
       <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
       <handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
-      <handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/>
+      <handler event="keypress" key="a" modifiers="accel" command="cmd_selectAll"/> -->
     </handlers>
   </binding>
 
   <binding id="textAreas" bindToUntrustedContent="true">
     <handlers>
       <handler event="keypress" key="c" modifiers="accel" command="cmd_copy"/>
       <handler event="keypress" key="x" modifiers="accel" command="cmd_cut"/>
       <handler event="keypress" key="v" modifiers="accel" command="cmd_paste"/>
@@ -30,18 +30,18 @@
     </handlers>
   </binding>
 
   <binding id="browser">
     <handlers>
 #include ../browser-base.inc
       <handler event="keypress" keycode="VK_PAGE_UP" command="cmd_scrollPageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_scrollPageDown"/>
-      <handler event="keypress" keycode="VK_HOME" command="cmd_scrollTop" /> 
-      <handler event="keypress" keycode="VK_END"  command="cmd_scrollBottom" /> 
+      <handler event="keypress" keycode="VK_HOME" command="cmd_scrollTop" />
+      <handler event="keypress" keycode="VK_END"  command="cmd_scrollBottom" />
 
       <handler event="keypress" keycode="VK_LEFT" modifiers="alt" command="cmd_moveLeft2" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="alt" command="cmd_moveRight2" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="alt,shift" command="cmd_selectLeft2" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="alt,shift" command="cmd_selectRight2" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectLeft" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectRight" />
       <handler event="keypress" keycode="VK_UP" modifiers="alt,shift" command="cmd_selectUp2" />
--- a/dom/xbl/builtin/unix/platformHTMLBindings.xml
+++ b/dom/xbl/builtin/unix/platformHTMLBindings.xml
@@ -2,26 +2,26 @@
 <!-- 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/. -->
 
 
 <bindings id="htmlBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
- 
+
   <binding id="inputFields" bindToUntrustedContent="true">
     <handlers>
-#include ../input-fields-base.inc
+<!-- #include ../input-fields-base.inc
     <handler event="keypress" key="a" modifiers="alt"
         command="cmd_selectAll"/>
     <handler event="keypress" key="y" modifiers="accel"
         command="cmd_redo"/>
     <handler event="keypress" key="z" modifiers="accel,shift" command="cmd_redo"/>
-    <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/>
+    <handler event="keypress" key="z" modifiers="accel" command="cmd_undo"/> -->
     </handlers>
   </binding>
 
   <binding id="textAreas" bindToUntrustedContent="true">
     <handlers>
 #include ../textareas-base.inc
     <handler event="keypress" key="a" modifiers="alt"
         command="cmd_selectAll"/>
@@ -35,27 +35,27 @@
   <binding id="browser">
     <handlers>
 #include ../browser-base.inc
       <handler event="keypress" keycode="VK_PAGE_UP" command="cmd_movePageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" command="cmd_movePageDown"/>
       <handler event="keypress" keycode="VK_PAGE_UP" modifiers="shift" command="cmd_selectPageUp"/>
       <handler event="keypress" keycode="VK_PAGE_DOWN" modifiers="shift" command="cmd_selectPageDown"/>
 
-      <handler event="keypress" keycode="VK_DELETE" modifiers="shift" command="cmd_cut" /> 
-      <handler event="keypress" keycode="VK_DELETE" modifiers="control" command="cmd_copy" /> 
-      <handler event="keypress" keycode="VK_INSERT" modifiers="control" command="cmd_copy" /> 
+      <handler event="keypress" keycode="VK_DELETE" modifiers="shift" command="cmd_cut" />
+      <handler event="keypress" keycode="VK_DELETE" modifiers="control" command="cmd_copy" />
+      <handler event="keypress" keycode="VK_INSERT" modifiers="control" command="cmd_copy" />
       <handler event="keypress" keycode="VK_HOME" command="cmd_beginLine"/>
       <handler event="keypress" keycode="VK_END" command="cmd_endLine"/>
       <handler event="keypress" keycode="VK_HOME" modifiers="shift" command="cmd_selectBeginLine" />
       <handler event="keypress" keycode="VK_END" modifiers="shift" command="cmd_selectEndLine" />
       <handler event="keypress" keycode="VK_HOME" modifiers="control" command="cmd_moveTop"/>
       <handler event="keypress" keycode="VK_END" modifiers="control" command="cmd_moveBottom"/>
-      <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" /> 
-      <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" /> 
+      <handler event="keypress" keycode="VK_HOME" modifiers="shift,control" command="cmd_selectTop" />
+      <handler event="keypress" keycode="VK_END" modifiers="shift,control" command="cmd_selectBottom" />
 
       <handler event="keypress" keycode="VK_LEFT" modifiers="shift" command="cmd_selectLeft" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="shift" command="cmd_selectRight" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="control" command="cmd_moveLeft2" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="control" command="cmd_moveRight2" />
       <handler event="keypress" keycode="VK_LEFT" modifiers="control,shift" command="cmd_selectLeft2" />
       <handler event="keypress" keycode="VK_RIGHT" modifiers="control,shift" command="cmd_selectRight2" />