Bug 1351783 part 3 - Add a KeyboardScrollAction type. r=kats,masayuki draft
authorRyan Hunt <rhunt@eqrion.net>
Mon, 05 Jun 2017 18:17:30 -0500
changeset 599267 2db52d99287df29483ada0edc0fc739dd045d147
parent 599266 50d92b62f7eb4eef807eec565cb1ad15578ebf01
child 599268 6e7da49e9459a91cd2cb43bf172ad290c2583a71
push id65466
push userbmo:rhunt@eqrion.net
push dateThu, 22 Jun 2017 22:16:51 +0000
reviewerskats, masayuki
bugs1351783
milestone56.0a1
Bug 1351783 part 3 - Add a KeyboardScrollAction type. r=kats,masayuki The different types of keyboard scrolls are represented as command strings that are dispatched to nsGlobalWindowCommands. This commit adds a class to represent these command strings, along with a function to find the keyboard scroll action corresponding to a command string. MozReview-Commit-ID: 20vvYdzlYYT
dom/base/nsGlobalWindowCommands.cpp
dom/base/nsGlobalWindowCommands.h
gfx/layers/apz/src/Keyboard.cpp
gfx/layers/apz/src/Keyboard.h
gfx/layers/ipc/LayersMessageUtils.h
gfx/layers/moz.build
--- a/dom/base/nsGlobalWindowCommands.cpp
+++ b/dom/base/nsGlobalWindowCommands.cpp
@@ -31,21 +31,23 @@
 #include "nsIClipboard.h"
 #include "ContentEventHandler.h"
 #include "nsContentUtils.h"
 #include "nsIWordBreaker.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/TextEvents.h"
 #include "mozilla/dom/Selection.h"
+#include "mozilla/layers/Keyboard.h"
 
 #include "nsIClipboardDragDropHooks.h"
 #include "nsIClipboardDragDropHookList.h"
 
 using namespace mozilla;
+using namespace mozilla::layers;
 
 constexpr const char * sSelectAllString = "cmd_selectAll";
 constexpr const char * sSelectNoneString = "cmd_selectNone";
 constexpr const char * sCopyImageLocationString = "cmd_copyImageLocation";
 constexpr const char * sCopyImageContentsString = "cmd_copyImageContents";
 constexpr const char * sCopyImageString = "cmd_copyImage";
 
 constexpr const char * sScrollTopString = "cmd_scrollTop";
@@ -266,43 +268,54 @@ IsCaretOnInWindow(nsPIDOMWindowOuter* aW
       }
     }
   }
   return caretOn;
 }
 
 static constexpr struct BrowseCommand {
   const char *reverse, *forward;
+  KeyboardScrollAction::KeyboardScrollActionType scrollAction;
   nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
   nsresult (NS_STDCALL nsISelectionController::*move)(bool, bool);
 } browseCommands[] = {
  { sScrollTopString, sScrollBottomString,
+   KeyboardScrollAction::eScrollComplete,
    &nsISelectionController::CompleteScroll },
  { sScrollPageUpString, sScrollPageDownString,
+   KeyboardScrollAction::eScrollPage,
    &nsISelectionController::ScrollPage },
  { sScrollLineUpString, sScrollLineDownString,
+   KeyboardScrollAction::eScrollLine,
    &nsISelectionController::ScrollLine },
  { sScrollLeftString, sScrollRightString,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter },
  { sMoveTopString, sMoveBottomString,
+   KeyboardScrollAction::eScrollComplete,
    &nsISelectionController::CompleteScroll,
    &nsISelectionController::CompleteMove },
  { sMovePageUpString, sMovePageDownString,
+   KeyboardScrollAction::eScrollPage,
    &nsISelectionController::ScrollPage,
    &nsISelectionController::PageMove },
  { sLinePreviousString, sLineNextString,
+   KeyboardScrollAction::eScrollLine,
    &nsISelectionController::ScrollLine,
    &nsISelectionController::LineMove },
  { sWordPreviousString, sWordNextString,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter,
    &nsISelectionController::WordMove },
  { sCharPreviousString, sCharNextString,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter,
    &nsISelectionController::CharacterMove },
  { sBeginLineString, sEndLineString,
+   KeyboardScrollAction::eScrollComplete,
    &nsISelectionController::CompleteScroll,
    &nsISelectionController::IntraLineMove }
 };
 
 nsresult
 nsSelectMoveScrollCommand::DoCommand(const char *aCommandName, nsISupports *aCommandContext)
 {
   nsCOMPtr<nsPIDOMWindowOuter> piWindow(do_QueryInterface(aCommandContext));
@@ -329,33 +342,42 @@ nsSelectMoveScrollCommand::DoCommand(con
 
 // XXX It's not clear to me yet how we should handle the "scroll" option
 // for these commands; for now, I'm mapping them back to ScrollCharacter,
 // ScrollLine, etc., as if for horizontal-mode content, but this may need
 // to be reconsidered once we have more experience with vertical content.
 static const struct PhysicalBrowseCommand {
   const char *command;
   int16_t direction, amount;
+  KeyboardScrollAction::KeyboardScrollActionType scrollAction;
   nsresult (NS_STDCALL nsISelectionController::*scroll)(bool);
 } physicalBrowseCommands[] = {
  { sMoveLeftString, nsISelectionController::MOVE_LEFT, 0,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter },
  { sMoveRightString, nsISelectionController::MOVE_RIGHT, 0,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter },
  { sMoveUpString, nsISelectionController::MOVE_UP, 0,
+   KeyboardScrollAction::eScrollLine,
    &nsISelectionController::ScrollLine },
  { sMoveDownString, nsISelectionController::MOVE_DOWN, 0,
+   KeyboardScrollAction::eScrollLine,
    &nsISelectionController::ScrollLine },
  { sMoveLeft2String, nsISelectionController::MOVE_LEFT, 1,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter },
  { sMoveRight2String, nsISelectionController::MOVE_RIGHT, 1,
+   KeyboardScrollAction::eScrollCharacter,
    &nsISelectionController::ScrollCharacter },
  { sMoveUp2String, nsISelectionController::MOVE_UP, 1,
+   KeyboardScrollAction::eScrollComplete,
    &nsISelectionController::CompleteScroll },
  { sMoveDown2String, nsISelectionController::MOVE_DOWN, 1,
+   KeyboardScrollAction::eScrollComplete,
    &nsISelectionController::CompleteScroll },
 };
 
 nsresult
 nsPhysicalSelectMoveScrollCommand::DoCommand(const char *aCommandName,
                                              nsISupports *aCommandContext)
 {
   nsCOMPtr<nsPIDOMWindowOuter> piWindow(do_QueryInterface(aCommandContext));
@@ -1257,8 +1279,41 @@ nsWindowCommandRegistration::RegisterWin
 #endif
 
   NS_REGISTER_ONE_COMMAND(nsClipboardDragDropHookCommand, "cmd_clipboardDragDropHook");
 
   NS_REGISTER_ONE_COMMAND(nsLookUpDictionaryCommand, "cmd_lookUpDictionary");
 
   return rv;
 }
+
+/* static */ bool
+nsGlobalWindowCommands::FindScrollCommand(const char* aCommandName,
+                                          KeyboardScrollAction* aOutAction)
+{
+  // Search for a keyboard scroll action to do for this command in browseCommands
+  // and physicalBrowseCommands. Each command exists in only one of them, so the
+  // order we examine browseCommands and physicalBrowseCommands doesn't matter.
+
+  for (size_t i = 0; i < ArrayLength(browseCommands); i++) {
+    const BrowseCommand& cmd = browseCommands[i];
+    bool forward = !strcmp(aCommandName, cmd.forward);
+    bool reverse = !strcmp(aCommandName, cmd.reverse);
+    if (forward || reverse) {
+      *aOutAction = KeyboardScrollAction(cmd.scrollAction, forward);
+      return true;
+    }
+  }
+
+  for (size_t i = 0; i < ArrayLength(physicalBrowseCommands); i++) {
+    const PhysicalBrowseCommand& cmd = physicalBrowseCommands[i];
+    if (!strcmp(aCommandName, cmd.command)) {
+      int16_t dir = cmd.direction;
+      bool forward = (dir == nsISelectionController::MOVE_RIGHT ||
+                      dir == nsISelectionController::MOVE_DOWN);
+
+      *aOutAction = KeyboardScrollAction(cmd.scrollAction, forward);
+      return true;
+    }
+  }
+
+  return false;
+}
--- a/dom/base/nsGlobalWindowCommands.h
+++ b/dom/base/nsGlobalWindowCommands.h
@@ -4,24 +4,46 @@
  * 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/. */
 
 #ifndef nsGlobalWindowCommands_h__
 #define nsGlobalWindowCommands_h__
 
 #include "nscore.h"
 
+namespace mozilla {
+namespace layers {
+struct KeyboardScrollAction;
+} // namespace layers
+} // namespace mozilla
+
 class nsIControllerCommandTable;
 
 class nsWindowCommandRegistration
 {
 public:
   static nsresult  RegisterWindowCommands(nsIControllerCommandTable *ccm);
 };
 
+class nsGlobalWindowCommands
+{
+public:
+  typedef mozilla::layers::KeyboardScrollAction KeyboardScrollAction;
+
+  /**
+   * Search through nsGlobalWindowCommands to find the keyboard scrolling action
+   * that would be done in response to a command.
+   *
+   * @param aCommandName the name of the command
+   * @param aOutAction the result of searching for this command, must not be null
+   * @returns whether a keyboard action was found or not
+   */
+  static bool FindScrollCommand(const char* aCommandName,
+                                KeyboardScrollAction* aOutAction);
+};
 
 // XXX find a better home for these
 #define NS_WINDOWCONTROLLER_CID        \
  { /* 7BD05C78-6A26-11D7-B16F-0003938A9D96 */       \
   0x7BD05C78, 0x6A26, 0x11D7, {0xB1, 0x6F, 0x00, 0x03, 0x93, 0x8A, 0x9D, 0x96} }
 
 #define NS_WINDOWCONTROLLER_CONTRACTID "@mozilla.org/dom/window-controller;1"
 
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/Keyboard.cpp
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 8; 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 "mozilla/layers/Keyboard.h"
+
+namespace mozilla {
+namespace layers {
+
+/* static */ nsIScrollableFrame::ScrollUnit
+KeyboardScrollAction::GetScrollUnit(KeyboardScrollAction::KeyboardScrollActionType aDeltaType)
+{
+  switch (aDeltaType) {
+    case KeyboardScrollAction::eScrollCharacter:
+      return nsIScrollableFrame::LINES;
+    case KeyboardScrollAction::eScrollLine:
+      return nsIScrollableFrame::LINES;
+    case KeyboardScrollAction::eScrollPage:
+      return nsIScrollableFrame::PAGES;
+    case KeyboardScrollAction::eScrollComplete:
+      return nsIScrollableFrame::WHOLE;
+    case KeyboardScrollAction::eSentinel:
+      MOZ_ASSERT_UNREACHABLE("Invalid KeyboardScrollActionType.");
+      return nsIScrollableFrame::WHOLE;
+  }
+}
+
+KeyboardScrollAction::KeyboardScrollAction()
+  : mType(KeyboardScrollAction::eScrollCharacter)
+  , mForward(false)
+{
+}
+
+KeyboardScrollAction::KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward)
+  : mType(aType)
+  , mForward(aForward)
+{
+}
+
+} // namespace layers
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/src/Keyboard.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 8; 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/. */
+
+#ifndef mozilla_layers_Keyboard_h
+#define mozilla_layers_Keyboard_h
+
+#include "nsIScrollableFrame.h" // for nsIScrollableFrame::ScrollUnit
+
+namespace mozilla {
+namespace layers {
+
+/**
+ * This class represents a scrolling action to be performed on a scrollable layer.
+ */
+struct KeyboardScrollAction final
+{
+public:
+  enum KeyboardScrollActionType : uint8_t
+  {
+    eScrollCharacter,
+    eScrollLine,
+    eScrollPage,
+    eScrollComplete,
+
+    // Used as an upper bound for ContiguousEnumSerializer
+    eSentinel,
+  };
+
+  static nsIScrollableFrame::ScrollUnit
+  GetScrollUnit(KeyboardScrollActionType aDeltaType);
+
+  KeyboardScrollAction();
+  KeyboardScrollAction(KeyboardScrollActionType aType, bool aForward);
+
+  // The type of scroll to perform for this action
+  KeyboardScrollActionType mType;
+  // Whether to scroll forward or backward along the axis of this action type
+  bool mForward;
+};
+
+} // namespace layers
+} // namespace mozilla
+
+#endif // mozilla_layers_Keyboard_h
--- a/gfx/layers/ipc/LayersMessageUtils.h
+++ b/gfx/layers/ipc/LayersMessageUtils.h
@@ -7,21 +7,23 @@
 #ifndef mozilla_layers_LayersMessageUtils
 #define mozilla_layers_LayersMessageUtils
 
 #include "FrameMetrics.h"
 #include "base/process_util.h"
 #include "chrome/common/ipc_message_utils.h"
 #include "gfxTelemetry.h"
 #include "ipc/IPCMessageUtils.h"
+#include "ipc/nsGUIEventIPC.h"
 #include "mozilla/GfxMessageUtils.h"
 #include "mozilla/layers/AsyncDragMetrics.h"
 #include "mozilla/layers/CompositorOptions.h"
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/GeckoContentController.h"
+#include "mozilla/layers/Keyboard.h"
 #include "mozilla/layers/LayerAttributes.h"
 #include "mozilla/layers/LayersTypes.h"
 
 #include <stdint.h>
 
 #ifdef _MSC_VER
 #pragma warning( disable : 4800 )
 #endif
@@ -410,16 +412,42 @@ struct ParamTraits<mozilla::layers::Even
     return (ReadParam(aMsg, aIter, &aResult->mHitRegion) &&
             ReadParam(aMsg, aIter, &aResult->mDispatchToContentHitRegion) &&
             ReadParam(aMsg, aIter, &aResult->mNoActionRegion) &&
             ReadParam(aMsg, aIter, &aResult->mHorizontalPanRegion) &&
             ReadParam(aMsg, aIter, &aResult->mVerticalPanRegion));
   }
 };
 
+template <>
+struct ParamTraits<mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType>
+  : public ContiguousEnumSerializer<
+             mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType,
+             mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType::eScrollCharacter,
+             mozilla::layers::KeyboardScrollAction::KeyboardScrollActionType::eSentinel>
+{};
+
+template <>
+struct ParamTraits<mozilla::layers::KeyboardScrollAction>
+{
+  typedef mozilla::layers::KeyboardScrollAction paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, aParam.mType);
+    WriteParam(aMsg, aParam.mForward);
+  }
+
+  static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
+  {
+    return ReadParam(aMsg, aIter, &aResult->mType) &&
+           ReadParam(aMsg, aIter, &aResult->mForward);
+  }
+};
+
 typedef mozilla::layers::GeckoContentController::TapType TapType;
 
 template <>
 struct ParamTraits<TapType>
   : public ContiguousEnumSerializer<
              TapType,
              TapType::eSingleTap,
              TapType::eSentinel>
--- a/gfx/layers/moz.build
+++ b/gfx/layers/moz.build
@@ -95,16 +95,17 @@ EXPORTS.mozilla.layers += [
     'apz/public/IAPZCTreeManager.h',
     'apz/public/MetricsSharingController.h',
     # exporting things from apz/src is temporary until we extract a
     # proper interface for the code there
     'apz/src/APZCTreeManager.h',
     'apz/src/APZUtils.h',
     'apz/src/AsyncDragMetrics.h',
     'apz/src/AsyncPanZoomAnimation.h',
+    'apz/src/Keyboard.h',
     'apz/src/TouchCounter.h',
     'apz/testutil/APZTestData.h',
     'apz/util/ActiveElementManager.h',
     'apz/util/APZCCallbackHelper.h',
     'apz/util/APZEventState.h',
     'apz/util/APZThreadUtils.h',
     'apz/util/ChromeProcessController.h',
     'apz/util/ContentProcessController.h',
@@ -276,16 +277,17 @@ UNIFIED_SOURCES += [
     'apz/src/AsyncPanZoomController.cpp',
     'apz/src/Axis.cpp',
     'apz/src/CheckerboardEvent.cpp',
     'apz/src/DragTracker.cpp',
     'apz/src/GestureEventListener.cpp',
     'apz/src/HitTestingTreeNode.cpp',
     'apz/src/InputBlockState.cpp',
     'apz/src/InputQueue.cpp',
+    'apz/src/Keyboard.cpp',
     'apz/src/OverscrollHandoffState.cpp',
     'apz/src/PotentialCheckerboardDurationTracker.cpp',
     'apz/src/QueuedInput.cpp',
     'apz/src/TouchCounter.cpp',
     'apz/src/WheelScrollAnimation.cpp',
     'apz/testutil/APZTestData.cpp',
     'apz/util/ActiveElementManager.cpp',
     'apz/util/APZCCallbackHelper.cpp',