Bug 1077515 - part 5 - Remap arrow keys for vertical writing-mode in the Cocoa key-bindings code. r=roc
authorJonathan Kew <jkew@mozilla.com>
Sat, 22 Nov 2014 14:39:03 +0000
changeset 241313 c873b373dc1d5793a21a295c57738982d077c773
parent 241312 b51ce3f8031115d228f3660d1456de7a31fd2167
child 241314 b45361b7aab2976453598b289f355f2dd7ac25f4
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1077515
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 1077515 - part 5 - Remap arrow keys for vertical writing-mode in the Cocoa key-bindings code. r=roc
widget/cocoa/NativeKeyBindings.mm
widget/cocoa/nsChildView.h
widget/cocoa/nsChildView.mm
--- a/widget/cocoa/NativeKeyBindings.mm
+++ b/widget/cocoa/NativeKeyBindings.mm
@@ -277,17 +277,17 @@ NativeKeyBindings::Execute(const WidgetK
     return false;
   }
 
   for (uint32_t i = 0; i < geckoCommands.Length(); i++) {
     Command geckoCommand = geckoCommands[i];
 
     PR_LOG(gNativeKeyBindingsLog, PR_LOG_ALWAYS,
       ("%p NativeKeyBindings::KeyPress, command=%s",
-       this, geckoCommand));
+       this, WidgetKeyboardEvent::GetCommandStr(geckoCommand)));
 
     // Execute the Gecko command
     aCallback(geckoCommand, aCallbackData);
   }
 
   PR_LOG(gNativeKeyBindingsLog, PR_LOG_ALWAYS,
     ("%p NativeKeyBindings::KeyPress, handled=true", this));
 
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -499,16 +499,23 @@ public:
                                     const InputContextAction& aAction);
   NS_IMETHOD_(InputContext) GetInputContext();
   NS_IMETHOD        AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent);
   NS_IMETHOD_(bool) ExecuteNativeKeyBinding(
                       NativeKeyBindingsType aType,
                       const mozilla::WidgetKeyboardEvent& aEvent,
                       DoCommandCallback aCallback,
                       void* aCallbackData) MOZ_OVERRIDE;
+  bool ExecuteNativeKeyBindingRemapped(
+                      NativeKeyBindingsType aType,
+                      const mozilla::WidgetKeyboardEvent& aEvent,
+                      DoCommandCallback aCallback,
+                      void* aCallbackData,
+                      uint32_t aGeckoKeyCode,
+                      uint32_t aCocoaKeyCode);
   virtual nsIMEUpdatePreference GetIMEUpdatePreference() MOZ_OVERRIDE;
   NS_IMETHOD        GetToggledKeyState(uint32_t aKeyCode,
                                        bool* aLEDState);
 
   // nsIPluginWidget
   // outClipRect and outOrigin are in display pixels (not device pixels)
   NS_IMETHOD        GetPluginClipRect(nsIntRect& outClipRect, nsIntPoint& outOrigin, bool& outWidgetVisible);
   NS_IMETHOD        StartDrawPlugin();
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -2029,22 +2029,106 @@ nsChildView::GetInputContext()
 
 NS_IMETHODIMP
 nsChildView::AttachNativeKeyEvent(mozilla::WidgetKeyboardEvent& aEvent)
 {
   NS_ENSURE_TRUE(mTextInputHandler, NS_ERROR_NOT_AVAILABLE);
   return mTextInputHandler->AttachNativeKeyEvent(aEvent);
 }
 
+bool
+nsChildView::ExecuteNativeKeyBindingRemapped(NativeKeyBindingsType aType,
+                                             const WidgetKeyboardEvent& aEvent,
+                                             DoCommandCallback aCallback,
+                                             void* aCallbackData,
+                                             uint32_t aGeckoKeyCode,
+                                             uint32_t aCocoaKeyCode)
+{
+  NSEvent *originalEvent = reinterpret_cast<NSEvent*>(aEvent.mNativeKeyEvent);
+
+  WidgetKeyboardEvent modifiedEvent(aEvent);
+  modifiedEvent.keyCode = aGeckoKeyCode;
+
+  unichar ch = nsCocoaUtils::ConvertGeckoKeyCodeToMacCharCode(aGeckoKeyCode);
+  NSString *chars =
+    [[[NSString alloc] initWithCharacters:&ch length:1] autorelease];
+
+  modifiedEvent.mNativeKeyEvent =
+    [NSEvent keyEventWithType:[originalEvent type]
+                     location:[originalEvent locationInWindow]
+                modifierFlags:[originalEvent modifierFlags]
+                    timestamp:[originalEvent timestamp]
+                 windowNumber:[originalEvent windowNumber]
+                      context:[originalEvent context]
+                   characters:chars
+  charactersIgnoringModifiers:chars
+                    isARepeat:[originalEvent isARepeat]
+                      keyCode:aCocoaKeyCode];
+
+  NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
+  return keyBindings->Execute(modifiedEvent, aCallback, aCallbackData);
+}
+
 NS_IMETHODIMP_(bool)
 nsChildView::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
                                      const WidgetKeyboardEvent& aEvent,
                                      DoCommandCallback aCallback,
                                      void* aCallbackData)
 {
+  // If the key is a cursor-movement arrow, and the current selection has
+  // vertical writing-mode, we'll remap so that the movement command
+  // generated (in terms of characters/lines) will be appropriate for
+  // the physical direction of the arrow.
+  if (aEvent.keyCode >= nsIDOMKeyEvent::DOM_VK_LEFT &&
+      aEvent.keyCode <= nsIDOMKeyEvent::DOM_VK_DOWN) {
+    WidgetQueryContentEvent query(true, NS_QUERY_SELECTED_TEXT, this);
+    DispatchWindowEvent(query);
+
+    if (query.mSucceeded && query.mReply.mWritingMode.IsVertical()) {
+      uint32_t geckoKey = 0;
+      uint32_t cocoaKey = 0;
+
+      switch (aEvent.keyCode) {
+      case nsIDOMKeyEvent::DOM_VK_LEFT:
+        if (query.mReply.mWritingMode.IsVerticalLR()) {
+          geckoKey = nsIDOMKeyEvent::DOM_VK_UP;
+          cocoaKey = kVK_UpArrow;
+        } else {
+          geckoKey = nsIDOMKeyEvent::DOM_VK_DOWN;
+          cocoaKey = kVK_DownArrow;
+        }
+        break;
+
+      case nsIDOMKeyEvent::DOM_VK_RIGHT:
+        if (query.mReply.mWritingMode.IsVerticalLR()) {
+          geckoKey = nsIDOMKeyEvent::DOM_VK_DOWN;
+          cocoaKey = kVK_DownArrow;
+        } else {
+          geckoKey = nsIDOMKeyEvent::DOM_VK_UP;
+          cocoaKey = kVK_UpArrow;
+        }
+        break;
+
+      case nsIDOMKeyEvent::DOM_VK_UP:
+        geckoKey = nsIDOMKeyEvent::DOM_VK_LEFT;
+        cocoaKey = kVK_LeftArrow;
+        break;
+
+      case nsIDOMKeyEvent::DOM_VK_DOWN:
+        geckoKey = nsIDOMKeyEvent::DOM_VK_RIGHT;
+        cocoaKey = kVK_RightArrow;
+        break;
+      }
+
+      return ExecuteNativeKeyBindingRemapped(aType, aEvent, aCallback,
+                                             aCallbackData,
+                                             geckoKey, cocoaKey);
+    }
+  }
+
   NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
   return keyBindings->Execute(aEvent, aCallback, aCallbackData);
 }
 
 nsIMEUpdatePreference
 nsChildView::GetIMEUpdatePreference()
 {
   return nsIMEUpdatePreference(nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE);