dom/events/UIEvent.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "base/basictypes.h"
     7 #include "ipc/IPCMessageUtils.h"
     8 #include "mozilla/dom/UIEvent.h"
     9 #include "mozilla/ArrayUtils.h"
    10 #include "mozilla/Assertions.h"
    11 #include "mozilla/ContentEvents.h"
    12 #include "mozilla/EventStateManager.h"
    13 #include "mozilla/TextEvents.h"
    14 #include "nsCOMPtr.h"
    15 #include "nsContentUtils.h"
    16 #include "nsIContent.h"
    17 #include "nsIInterfaceRequestorUtils.h"
    18 #include "nsIDOMWindow.h"
    19 #include "nsIDOMNode.h"
    20 #include "nsIFrame.h"
    21 #include "prtime.h"
    23 namespace mozilla {
    24 namespace dom {
    26 UIEvent::UIEvent(EventTarget* aOwner,
    27                  nsPresContext* aPresContext,
    28                  WidgetGUIEvent* aEvent)
    29   : Event(aOwner, aPresContext,
    30           aEvent ? aEvent : new InternalUIEvent(false, 0))
    31   , mClientPoint(0, 0)
    32   , mLayerPoint(0, 0)
    33   , mPagePoint(0, 0)
    34   , mMovementPoint(0, 0)
    35   , mIsPointerLocked(EventStateManager::sIsPointerLocked)
    36   , mLastClientPoint(EventStateManager::sLastClientPoint)
    37 {
    38   if (aEvent) {
    39     mEventIsInternal = false;
    40   }
    41   else {
    42     mEventIsInternal = true;
    43     mEvent->time = PR_Now();
    44   }
    46   // Fill mDetail and mView according to the mEvent (widget-generated
    47   // event) we've got
    48   switch(mEvent->eventStructType)
    49   {
    50     case NS_UI_EVENT:
    51     {
    52       mDetail = mEvent->AsUIEvent()->detail;
    53       break;
    54     }
    56     case NS_SCROLLPORT_EVENT:
    57     {
    58       InternalScrollPortEvent* scrollEvent = mEvent->AsScrollPortEvent();
    59       mDetail = (int32_t)scrollEvent->orient;
    60       break;
    61     }
    63     default:
    64       mDetail = 0;
    65       break;
    66   }
    68   mView = nullptr;
    69   if (mPresContext)
    70   {
    71     nsISupports* container = mPresContext->GetContainerWeak();
    72     if (container)
    73     {
    74        nsCOMPtr<nsIDOMWindow> window = do_GetInterface(container);
    75        if (window)
    76           mView = do_QueryInterface(window);
    77     }
    78   }
    79 }
    81 // static
    82 already_AddRefed<UIEvent>
    83 UIEvent::Constructor(const GlobalObject& aGlobal,
    84                      const nsAString& aType,
    85                      const UIEventInit& aParam,
    86                      ErrorResult& aRv)
    87 {
    88   nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
    89   nsRefPtr<UIEvent> e = new UIEvent(t, nullptr, nullptr);
    90   bool trusted = e->Init(t);
    91   aRv = e->InitUIEvent(aType, aParam.mBubbles, aParam.mCancelable, aParam.mView,
    92                        aParam.mDetail);
    93   e->SetTrusted(trusted);
    94   return e.forget();
    95 }
    97 NS_IMPL_CYCLE_COLLECTION_INHERITED(UIEvent, Event,
    98                                    mView)
   100 NS_IMPL_ADDREF_INHERITED(UIEvent, Event)
   101 NS_IMPL_RELEASE_INHERITED(UIEvent, Event)
   103 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(UIEvent)
   104   NS_INTERFACE_MAP_ENTRY(nsIDOMUIEvent)
   105 NS_INTERFACE_MAP_END_INHERITING(Event)
   107 static nsIntPoint
   108 DevPixelsToCSSPixels(const LayoutDeviceIntPoint& aPoint,
   109                      nsPresContext* aContext)
   110 {
   111   return nsIntPoint(aContext->DevPixelsToIntCSSPixels(aPoint.x),
   112                     aContext->DevPixelsToIntCSSPixels(aPoint.y));
   113 }
   115 nsIntPoint
   116 UIEvent::GetMovementPoint()
   117 {
   118   if (mPrivateDataDuplicated) {
   119     return mMovementPoint;
   120   }
   122   if (!mEvent ||
   123       (mEvent->eventStructType != NS_MOUSE_EVENT &&
   124        mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
   125        mEvent->eventStructType != NS_WHEEL_EVENT &&
   126        mEvent->eventStructType != NS_DRAG_EVENT &&
   127        mEvent->eventStructType != NS_POINTER_EVENT &&
   128        mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
   129        !mEvent->AsGUIEvent()->widget) {
   130     return nsIntPoint(0, 0);
   131   }
   133   // Calculate the delta between the last screen point and the current one.
   134   nsIntPoint current = DevPixelsToCSSPixels(mEvent->refPoint, mPresContext);
   135   nsIntPoint last = DevPixelsToCSSPixels(mEvent->lastRefPoint, mPresContext);
   136   return current - last;
   137 }
   139 NS_IMETHODIMP
   140 UIEvent::GetView(nsIDOMWindow** aView)
   141 {
   142   *aView = mView;
   143   NS_IF_ADDREF(*aView);
   144   return NS_OK;
   145 }
   147 NS_IMETHODIMP
   148 UIEvent::GetDetail(int32_t* aDetail)
   149 {
   150   *aDetail = mDetail;
   151   return NS_OK;
   152 }
   154 NS_IMETHODIMP
   155 UIEvent::InitUIEvent(const nsAString& typeArg,
   156                      bool canBubbleArg,
   157                      bool cancelableArg,
   158                      nsIDOMWindow* viewArg,
   159                      int32_t detailArg)
   160 {
   161   if (viewArg) {
   162     nsCOMPtr<nsPIDOMWindow> view = do_QueryInterface(viewArg);
   163     NS_ENSURE_TRUE(view, NS_ERROR_INVALID_ARG);
   164   }
   165   nsresult rv = Event::InitEvent(typeArg, canBubbleArg, cancelableArg);
   166   NS_ENSURE_SUCCESS(rv, rv);
   168   mDetail = detailArg;
   169   mView = viewArg;
   171   return NS_OK;
   172 }
   174 NS_IMETHODIMP
   175 UIEvent::GetPageX(int32_t* aPageX)
   176 {
   177   NS_ENSURE_ARG_POINTER(aPageX);
   178   *aPageX = PageX();
   179   return NS_OK;
   180 }
   182 int32_t
   183 UIEvent::PageX() const
   184 {
   185   if (mPrivateDataDuplicated) {
   186     return mPagePoint.x;
   187   }
   189   return Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint,
   190                               mClientPoint).x;
   191 }
   193 NS_IMETHODIMP
   194 UIEvent::GetPageY(int32_t* aPageY)
   195 {
   196   NS_ENSURE_ARG_POINTER(aPageY);
   197   *aPageY = PageY();
   198   return NS_OK;
   199 }
   201 int32_t
   202 UIEvent::PageY() const
   203 {
   204   if (mPrivateDataDuplicated) {
   205     return mPagePoint.y;
   206   }
   208   return Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint,
   209                               mClientPoint).y;
   210 }
   212 NS_IMETHODIMP
   213 UIEvent::GetWhich(uint32_t* aWhich)
   214 {
   215   NS_ENSURE_ARG_POINTER(aWhich);
   216   *aWhich = Which();
   217   return NS_OK;
   218 }
   220 already_AddRefed<nsINode>
   221 UIEvent::GetRangeParent()
   222 {
   223   nsIFrame* targetFrame = nullptr;
   225   if (mPresContext) {
   226     targetFrame = mPresContext->EventStateManager()->GetEventTarget();
   227   }
   229   if (targetFrame) {
   230     nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent,
   231                                                               targetFrame);
   232     nsCOMPtr<nsIContent> parent = targetFrame->GetContentOffsetsFromPoint(pt).content;
   233     if (parent) {
   234       if (parent->ChromeOnlyAccess() &&
   235           !nsContentUtils::CanAccessNativeAnon()) {
   236         return nullptr;
   237       }
   238       return parent.forget();
   239     }
   240   }
   242   return nullptr;
   243 }
   245 NS_IMETHODIMP
   246 UIEvent::GetRangeParent(nsIDOMNode** aRangeParent)
   247 {
   248   NS_ENSURE_ARG_POINTER(aRangeParent);
   249   *aRangeParent = nullptr;
   250   nsCOMPtr<nsINode> n = GetRangeParent();
   251   if (n) {
   252     CallQueryInterface(n, aRangeParent);
   253   }
   254   return NS_OK;
   255 }
   257 NS_IMETHODIMP
   258 UIEvent::GetRangeOffset(int32_t* aRangeOffset)
   259 {
   260   NS_ENSURE_ARG_POINTER(aRangeOffset);
   261   *aRangeOffset = RangeOffset();
   262   return NS_OK;
   263 }
   265 int32_t
   266 UIEvent::RangeOffset() const
   267 {
   268   if (!mPresContext) {
   269     return 0;
   270   }
   272   nsIFrame* targetFrame = mPresContext->EventStateManager()->GetEventTarget();
   273   if (!targetFrame) {
   274     return 0;
   275   }
   277   nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent,
   278                                                             targetFrame);
   279   return targetFrame->GetContentOffsetsFromPoint(pt).offset;
   280 }
   282 NS_IMETHODIMP
   283 UIEvent::GetCancelBubble(bool* aCancelBubble)
   284 {
   285   NS_ENSURE_ARG_POINTER(aCancelBubble);
   286   *aCancelBubble = CancelBubble();
   287   return NS_OK;
   288 }
   290 NS_IMETHODIMP
   291 UIEvent::SetCancelBubble(bool aCancelBubble)
   292 {
   293   mEvent->mFlags.mPropagationStopped = aCancelBubble;
   294   return NS_OK;
   295 }
   297 nsIntPoint
   298 UIEvent::GetLayerPoint() const
   299 {
   300   if (!mEvent ||
   301       (mEvent->eventStructType != NS_MOUSE_EVENT &&
   302        mEvent->eventStructType != NS_MOUSE_SCROLL_EVENT &&
   303        mEvent->eventStructType != NS_WHEEL_EVENT &&
   304        mEvent->eventStructType != NS_POINTER_EVENT &&
   305        mEvent->eventStructType != NS_TOUCH_EVENT &&
   306        mEvent->eventStructType != NS_DRAG_EVENT &&
   307        mEvent->eventStructType != NS_SIMPLE_GESTURE_EVENT) ||
   308       !mPresContext ||
   309       mEventIsInternal) {
   310     return mLayerPoint;
   311   }
   312   // XXX I'm not really sure this is correct; it's my best shot, though
   313   nsIFrame* targetFrame = mPresContext->EventStateManager()->GetEventTarget();
   314   if (!targetFrame)
   315     return mLayerPoint;
   316   nsIFrame* layer = nsLayoutUtils::GetClosestLayer(targetFrame);
   317   nsPoint pt(nsLayoutUtils::GetEventCoordinatesRelativeTo(mEvent, layer));
   318   return nsIntPoint(nsPresContext::AppUnitsToIntCSSPixels(pt.x),
   319                     nsPresContext::AppUnitsToIntCSSPixels(pt.y));
   320 }
   322 NS_IMETHODIMP
   323 UIEvent::GetLayerX(int32_t* aLayerX)
   324 {
   325   NS_ENSURE_ARG_POINTER(aLayerX);
   326   *aLayerX = GetLayerPoint().x;
   327   return NS_OK;
   328 }
   330 NS_IMETHODIMP
   331 UIEvent::GetLayerY(int32_t* aLayerY)
   332 {
   333   NS_ENSURE_ARG_POINTER(aLayerY);
   334   *aLayerY = GetLayerPoint().y;
   335   return NS_OK;
   336 }
   338 NS_IMETHODIMP
   339 UIEvent::GetIsChar(bool* aIsChar)
   340 {
   341   *aIsChar = IsChar();
   342   return NS_OK;
   343 }
   345 bool
   346 UIEvent::IsChar() const
   347 {
   348   WidgetKeyboardEvent* keyEvent = mEvent->AsKeyboardEvent();
   349   if (keyEvent) {
   350     return keyEvent->isChar;
   351   }
   352   WidgetTextEvent* textEvent = mEvent->AsTextEvent();
   353   return textEvent ? textEvent->isChar : false;
   354 }
   356 NS_IMETHODIMP
   357 UIEvent::DuplicatePrivateData()
   358 {
   359   mClientPoint =
   360     Event::GetClientCoords(mPresContext, mEvent, mEvent->refPoint,
   361                            mClientPoint);
   362   mMovementPoint = GetMovementPoint();
   363   mLayerPoint = GetLayerPoint();
   364   mPagePoint =
   365     Event::GetPageCoords(mPresContext, mEvent, mEvent->refPoint, mClientPoint);
   366   // GetScreenPoint converts mEvent->refPoint to right coordinates.
   367   nsIntPoint screenPoint =
   368     Event::GetScreenCoords(mPresContext, mEvent, mEvent->refPoint);
   369   nsresult rv = Event::DuplicatePrivateData();
   370   if (NS_SUCCEEDED(rv)) {
   371     mEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(screenPoint);
   372   }
   373   return rv;
   374 }
   376 NS_IMETHODIMP_(void)
   377 UIEvent::Serialize(IPC::Message* aMsg, bool aSerializeInterfaceType)
   378 {
   379   if (aSerializeInterfaceType) {
   380     IPC::WriteParam(aMsg, NS_LITERAL_STRING("uievent"));
   381   }
   383   Event::Serialize(aMsg, false);
   385   int32_t detail = 0;
   386   GetDetail(&detail);
   387   IPC::WriteParam(aMsg, detail);
   388 }
   390 NS_IMETHODIMP_(bool)
   391 UIEvent::Deserialize(const IPC::Message* aMsg, void** aIter)
   392 {
   393   NS_ENSURE_TRUE(Event::Deserialize(aMsg, aIter), false);
   394   NS_ENSURE_TRUE(IPC::ReadParam(aMsg, aIter, &mDetail), false);
   395   return true;
   396 }
   398 // XXX Following struct and array are used only in
   399 //     UIEvent::ComputeModifierState(), but if we define them in it,
   400 //     we fail to build on Mac at calling mozilla::ArrayLength().
   401 struct ModifierPair
   402 {
   403   Modifier modifier;
   404   const char* name;
   405 };
   406 static const ModifierPair kPairs[] = {
   407   { MODIFIER_ALT,        NS_DOM_KEYNAME_ALT },
   408   { MODIFIER_ALTGRAPH,   NS_DOM_KEYNAME_ALTGRAPH },
   409   { MODIFIER_CAPSLOCK,   NS_DOM_KEYNAME_CAPSLOCK },
   410   { MODIFIER_CONTROL,    NS_DOM_KEYNAME_CONTROL },
   411   { MODIFIER_FN,         NS_DOM_KEYNAME_FN },
   412   { MODIFIER_META,       NS_DOM_KEYNAME_META },
   413   { MODIFIER_NUMLOCK,    NS_DOM_KEYNAME_NUMLOCK },
   414   { MODIFIER_SCROLLLOCK, NS_DOM_KEYNAME_SCROLLLOCK },
   415   { MODIFIER_SHIFT,      NS_DOM_KEYNAME_SHIFT },
   416   { MODIFIER_SYMBOLLOCK, NS_DOM_KEYNAME_SYMBOLLOCK },
   417   { MODIFIER_OS,         NS_DOM_KEYNAME_OS }
   418 };
   420 // static
   421 Modifiers
   422 UIEvent::ComputeModifierState(const nsAString& aModifiersList)
   423 {
   424   if (aModifiersList.IsEmpty()) {
   425     return 0;
   426   }
   428   // Be careful about the performance.  If aModifiersList is too long,
   429   // parsing it needs too long time.
   430   // XXX Should we abort if aModifiersList is too long?
   432   Modifiers modifiers = 0;
   434   nsAString::const_iterator listStart, listEnd;
   435   aModifiersList.BeginReading(listStart);
   436   aModifiersList.EndReading(listEnd);
   438   for (uint32_t i = 0; i < ArrayLength(kPairs); i++) {
   439     nsAString::const_iterator start(listStart), end(listEnd);
   440     if (!FindInReadable(NS_ConvertASCIItoUTF16(kPairs[i].name), start, end)) {
   441       continue;
   442     }
   444     if ((start != listStart && !NS_IsAsciiWhitespace(*(--start))) ||
   445         (end != listEnd && !NS_IsAsciiWhitespace(*(end)))) {
   446       continue;
   447     }
   448     modifiers |= kPairs[i].modifier;
   449   }
   451   return modifiers;
   452 }
   454 bool
   455 UIEvent::GetModifierStateInternal(const nsAString& aKey)
   456 {
   457   WidgetInputEvent* inputEvent = mEvent->AsInputEvent();
   458   MOZ_ASSERT(inputEvent, "mEvent must be WidgetInputEvent or derived class");
   459   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SHIFT)) {
   460     return inputEvent->IsShift();
   461   }
   462   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_CONTROL)) {
   463     return inputEvent->IsControl();
   464   }
   465   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_META)) {
   466     return inputEvent->IsMeta();
   467   }
   468   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_ALT)) {
   469     return inputEvent->IsAlt();
   470   }
   472   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_ALTGRAPH)) {
   473     return inputEvent->IsAltGraph();
   474   }
   475   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_OS)) {
   476     return inputEvent->IsOS();
   477   }
   479   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_CAPSLOCK)) {
   480     return inputEvent->IsCapsLocked();
   481   }
   482   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_NUMLOCK)) {
   483     return inputEvent->IsNumLocked();
   484   }
   486   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_FN)) {
   487     return inputEvent->IsFn();
   488   }
   489   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SCROLLLOCK)) {
   490     return inputEvent->IsScrollLocked();
   491   }
   492   if (aKey.EqualsLiteral(NS_DOM_KEYNAME_SYMBOLLOCK)) {
   493     return inputEvent->IsSymbolLocked();
   494   }
   495   return false;
   496 }
   498 } // namespace dom
   499 } // namespace mozilla
   501 using namespace mozilla;
   502 using namespace mozilla::dom;
   504 nsresult
   505 NS_NewDOMUIEvent(nsIDOMEvent** aInstancePtrResult,
   506                  EventTarget* aOwner,
   507                  nsPresContext* aPresContext,
   508                  WidgetGUIEvent* aEvent) 
   509 {
   510   UIEvent* it = new UIEvent(aOwner, aPresContext, aEvent);
   511   NS_ADDREF(it);
   512   *aInstancePtrResult = static_cast<Event*>(it);
   513   return NS_OK;
   514 }

mercurial