Bug 1275473 - Implement CompositionEvent.ranges. r=masayuki, r=smaug
authorisangelawu <ywu@mozilla.com>
Tue, 26 Jul 2016 12:09:07 +0200
changeset 348781 493c726899561c8214ea70c8a6f699878d82fe2b
parent 348780 d9bbe09fe56179b84b5998b84ad726c630a1667b
child 348782 6e23273bf3508403aeacdb301d278c281528756c
push id1230
push userjlund@mozilla.com
push dateMon, 31 Oct 2016 18:13:35 +0000
treeherdermozilla-release@5e06e3766db2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmasayuki, smaug
bugs1275473
milestone50.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 1275473 - Implement CompositionEvent.ranges. r=masayuki, r=smaug
dom/events/CompositionEvent.cpp
dom/events/CompositionEvent.h
dom/events/TextClause.cpp
dom/events/TextClause.h
dom/events/moz.build
dom/webidl/CompositionEvent.webidl
dom/webidl/TextClause.webidl
dom/webidl/moz.build
widget/TextEvents.h
--- a/dom/events/CompositionEvent.cpp
+++ b/dom/events/CompositionEvent.cpp
@@ -64,16 +64,37 @@ CompositionEvent::InitCompositionEvent(c
                                        const nsAString& aData,
                                        const nsAString& aLocale)
 {
   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, 0);
   mData = aData;
   mLocale = aLocale;
 }
 
+void
+CompositionEvent::GetRanges(TextClauseArray& aRanges)
+{
+  // If the mRanges is not empty, we return the cached value.
+  if (!mRanges.IsEmpty()) {
+    aRanges = mRanges;
+    return;
+  }
+  RefPtr<TextRangeArray> textRangeArray = mEvent->AsCompositionEvent()->mRanges;
+  if (!textRangeArray) {
+    return;
+  }
+  nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(mOwner);
+  const TextRange* targetRange = textRangeArray->GetTargetClause();
+  for (size_t i = 0; i < textRangeArray->Length(); i++) {
+    const TextRange& range = textRangeArray->ElementAt(i);
+    mRanges.AppendElement(new TextClause(window, range, targetRange));
+  }
+  aRanges = mRanges;
+}
+
 } // namespace dom
 } // namespace mozilla
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 already_AddRefed<CompositionEvent>
 NS_NewDOMCompositionEvent(EventTarget* aOwner,
--- a/dom/events/CompositionEvent.h
+++ b/dom/events/CompositionEvent.h
@@ -3,22 +3,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/. */
 
 #ifndef mozilla_dom_CompositionEvent_h_
 #define mozilla_dom_CompositionEvent_h_
 
 #include "mozilla/dom/CompositionEventBinding.h"
+#include "mozilla/dom/TextClause.h"
+#include "mozilla/dom/TypedArray.h"
 #include "mozilla/dom/UIEvent.h"
 #include "mozilla/EventForwards.h"
 
 namespace mozilla {
 namespace dom {
 
+typedef nsTArray<RefPtr<TextClause>> TextClauseArray;
+
 class CompositionEvent : public UIEvent
 {
 public:
   CompositionEvent(EventTarget* aOwner,
                    nsPresContext* aPresContext,
                    WidgetCompositionEvent* aEvent);
 
   NS_DECL_ISUPPORTS_INHERITED
@@ -32,22 +36,24 @@ public:
   void InitCompositionEvent(const nsAString& aType,
                             bool aCanBubble,
                             bool aCancelable,
                             nsGlobalWindow* aView,
                             const nsAString& aData,
                             const nsAString& aLocale);
   void GetData(nsAString&) const;
   void GetLocale(nsAString&) const;
+  void GetRanges(TextClauseArray& aRanges);
 
 protected:
   ~CompositionEvent() {}
 
   nsString mData;
   nsString mLocale;
+  TextClauseArray mRanges;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 already_AddRefed<mozilla::dom::CompositionEvent>
 NS_NewDOMCompositionEvent(mozilla::dom::EventTarget* aOwner,
                           nsPresContext* aPresContext,
new file mode 100644
--- /dev/null
+++ b/dom/events/TextClause.cpp
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/dom/TextClause.h"
+#include "mozilla/dom/TextClauseBinding.h"
+#include "mozilla/TextEvents.h"
+
+namespace mozilla {
+namespace dom {
+
+// Only needed for refcounted objects.
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(TextClause)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(TextClause)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(TextClause)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TextClause)
+NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+TextClause::TextClause(nsPIDOMWindowInner* aOwner, const TextRange& aRange,
+                       const TextRange* aTargetRange)
+  : mOwner(aOwner)
+  , mIsTargetClause(false)
+{
+  MOZ_ASSERT(aOwner);
+  mStartOffset = aRange.mStartOffset;
+  mEndOffset = aRange.mEndOffset;
+  if (aRange.IsClause()) {
+    mIsCaret = false;
+    if (aTargetRange && aTargetRange->mStartOffset == mStartOffset) {
+      mIsTargetClause = true;
+    }
+  } else {
+    mIsCaret = true;
+  }
+}
+
+JSObject*
+TextClause::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+  return TextClauseBinding::Wrap(aCx, this, aGivenProto);
+}
+
+TextClause::~TextClause() {}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/events/TextClause.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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_dom_TextClause_h
+#define mozilla_dom_TextClause_h
+
+#include "js/TypeDecls.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "nsCycleCollectionParticipant.h"
+#include "nsWrapperCache.h"
+
+namespace mozilla {
+namespace dom {
+
+class TextClause final : public nsISupports
+                       , public nsWrapperCache
+{
+public:
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(TextClause)
+
+  nsPIDOMWindowInner* GetParentObject() const { return mOwner; }
+
+  TextClause(nsPIDOMWindowInner* aWindow, const TextRange& aRange,
+             const TextRange* targetRange);
+
+  virtual JSObject* WrapObject(JSContext* aCx,
+                               JS::Handle<JSObject*> aGivenProto) override;
+
+  inline uint32_t StartOffset() const { return mStartOffset; }
+
+  inline uint32_t EndOffset() const { return mEndOffset; }
+
+  inline bool IsCaret() const { return mIsCaret; }
+
+  inline bool IsTargetClause() const { return mIsTargetClause; }
+
+private:
+  ~TextClause();
+  nsCOMPtr<nsPIDOMWindowInner> mOwner;
+
+  // Following members, please take look at widget/TextRange.h.
+  uint32_t mStartOffset;
+  uint32_t mEndOffset;
+  bool mIsCaret;
+  bool mIsTargetClause;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_TextClause_h
--- a/dom/events/moz.build
+++ b/dom/events/moz.build
@@ -59,16 +59,17 @@ EXPORTS.mozilla.dom += [
     'MouseScrollEvent.h',
     'MutationEvent.h',
     'NotifyPaintEvent.h',
     'PaintRequest.h',
     'PointerEvent.h',
     'ScrollAreaEvent.h',
     'SimpleGestureEvent.h',
     'StorageEvent.h',
+    'TextClause.h',
     'Touch.h',
     'TouchEvent.h',
     'TransitionEvent.h',
     'UIEvent.h',
     'WheelEvent.h',
     'XULCommandEvent.h',
 ]
 
@@ -107,16 +108,17 @@ UNIFIED_SOURCES += [
     'MouseScrollEvent.cpp',
     'MutationEvent.cpp',
     'NotifyPaintEvent.cpp',
     'PaintRequest.cpp',
     'PointerEvent.cpp',
     'ScrollAreaEvent.cpp',
     'SimpleGestureEvent.cpp',
     'StorageEvent.cpp',
+    'TextClause.cpp',
     'TextComposition.cpp',
     'Touch.cpp',
     'TouchEvent.cpp',
     'TransitionEvent.cpp',
     'UIEvent.cpp',
     'WheelEvent.cpp',
     'WheelHandlingHelper.cpp',
     'XULCommandEvent.cpp',
--- a/dom/webidl/CompositionEvent.webidl
+++ b/dom/webidl/CompositionEvent.webidl
@@ -8,16 +8,23 @@
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 interface CompositionEvent : UIEvent
 {
   readonly attribute DOMString? data;
   readonly attribute DOMString  locale;
+
+ /**
+  * ranges is trying to expose TextRangeArray in Gecko so a
+  * js-plugin couble be able to know the clauses information
+  */
+  [ChromeOnly,Cached,Pure]
+  readonly attribute sequence<TextClause> ranges;
 };
 
 partial interface CompositionEvent
 {
   void initCompositionEvent(DOMString typeArg,
                             boolean canBubbleArg,
                             boolean cancelableArg,
                             Window? viewArg,
new file mode 100644
--- /dev/null
+++ b/dom/webidl/TextClause.webidl
@@ -0,0 +1,21 @@
+/* -*- Mode: IDL; tab-width: 2; 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/.
+ */
+
+[ChromeOnly]
+interface TextClause
+{
+  // The start offset of TextClause
+  readonly attribute long startOffset;
+
+  // The end offset of TextClause
+  readonly attribute long endOffset;
+
+  // If the TextClause is Caret or not
+  readonly attribute boolean isCaret;
+
+  // If the TextClause is TargetClause or not
+  readonly attribute boolean isTargetClause;
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -540,16 +540,17 @@ WEBIDL_FILES = [
     'TCPSocket.webidl',
     'TCPSocketErrorEvent.webidl',
     'TCPSocketEvent.webidl',
     'Telephony.webidl',
     'TelephonyCall.webidl',
     'TelephonyCallGroup.webidl',
     'TelephonyCallId.webidl',
     'Text.webidl',
+    'TextClause.webidl',
     'TextDecoder.webidl',
     'TextEncoder.webidl',
     'TextTrack.webidl',
     'TextTrackCue.webidl',
     'TextTrackCueList.webidl',
     'TextTrackList.webidl',
     'ThreadSafeChromeUtils.webidl',
     'TimeEvent.webidl',
--- a/widget/TextEvents.h
+++ b/widget/TextEvents.h
@@ -543,16 +543,17 @@ public:
 
   void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
                                   bool aCopyTargets)
   {
     AssignGUIEventData(aEvent, aCopyTargets);
 
     mData = aEvent.mData;
     mOriginalMessage = aEvent.mOriginalMessage;
+    mRanges = aEvent.mRanges;
 
     // Currently, we don't need to copy the other members because they are
     // for internal use only (not available from JS).
   }
 
   bool IsComposing() const
   {
     return mRanges && mRanges->IsComposing();