LCOV - code coverage report
Current view: top level - dom/events - TouchEvent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 26 134 19.4 %
Date: 2017-07-14 16:53:18 Functions: 2 28 7.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/Navigator.h"
       8             : #include "mozilla/dom/TouchEvent.h"
       9             : #include "mozilla/dom/Touch.h"
      10             : #include "mozilla/dom/TouchListBinding.h"
      11             : #include "mozilla/Preferences.h"
      12             : #include "mozilla/TouchEvents.h"
      13             : #include "nsContentUtils.h"
      14             : #include "nsIDocShell.h"
      15             : #include "mozilla/WidgetUtils.h"
      16             : 
      17             : namespace mozilla {
      18             : 
      19             : namespace dom {
      20             : 
      21             : /******************************************************************************
      22             :  * TouchList
      23             :  *****************************************************************************/
      24             : 
      25           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TouchList)
      26           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      27           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      28           0 : NS_INTERFACE_MAP_END
      29             : 
      30           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TouchList, mParent, mPoints)
      31             : 
      32           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(TouchList)
      33           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(TouchList)
      34             : 
      35             : JSObject*
      36           0 : TouchList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      37             : {
      38           0 :   return TouchListBinding::Wrap(aCx, this, aGivenProto);
      39             : }
      40             : 
      41             : // static
      42             : bool
      43           0 : TouchList::PrefEnabled(JSContext* aCx, JSObject* aGlobal)
      44             : {
      45           0 :   return TouchEvent::PrefEnabled(aCx, aGlobal);
      46             : }
      47             : 
      48             : /******************************************************************************
      49             :  * TouchEvent
      50             :  *****************************************************************************/
      51             : 
      52           0 : TouchEvent::TouchEvent(EventTarget* aOwner,
      53             :                        nsPresContext* aPresContext,
      54           0 :                        WidgetTouchEvent* aEvent)
      55             :   : UIEvent(aOwner, aPresContext,
      56             :             aEvent ? aEvent :
      57           0 :                      new WidgetTouchEvent(false, eVoidEvent, nullptr))
      58             : {
      59           0 :   if (aEvent) {
      60           0 :     mEventIsInternal = false;
      61             : 
      62           0 :     for (uint32_t i = 0; i < aEvent->mTouches.Length(); ++i) {
      63           0 :       Touch* touch = aEvent->mTouches[i];
      64           0 :       touch->InitializePoints(mPresContext, aEvent);
      65             :     }
      66             :   } else {
      67           0 :     mEventIsInternal = true;
      68           0 :     mEvent->mTime = PR_Now();
      69             :   }
      70           0 : }
      71             : 
      72           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(TouchEvent, UIEvent,
      73             :                                    mTouches,
      74             :                                    mTargetTouches,
      75             :                                    mChangedTouches)
      76             : 
      77           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TouchEvent)
      78           0 : NS_INTERFACE_MAP_END_INHERITING(UIEvent)
      79             : 
      80           0 : NS_IMPL_ADDREF_INHERITED(TouchEvent, UIEvent)
      81           0 : NS_IMPL_RELEASE_INHERITED(TouchEvent, UIEvent)
      82             : 
      83             : void
      84           0 : TouchEvent::InitTouchEvent(const nsAString& aType,
      85             :                            bool aCanBubble,
      86             :                            bool aCancelable,
      87             :                            nsGlobalWindow* aView,
      88             :                            int32_t aDetail,
      89             :                            bool aCtrlKey,
      90             :                            bool aAltKey,
      91             :                            bool aShiftKey,
      92             :                            bool aMetaKey,
      93             :                            TouchList* aTouches,
      94             :                            TouchList* aTargetTouches,
      95             :                            TouchList* aChangedTouches)
      96             : {
      97           0 :   NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
      98             : 
      99           0 :   UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
     100           0 :   mEvent->AsInputEvent()->InitBasicModifiers(aCtrlKey, aAltKey,
     101           0 :                                              aShiftKey, aMetaKey);
     102           0 :   mTouches = aTouches;
     103           0 :   mTargetTouches = aTargetTouches;
     104           0 :   mChangedTouches = aChangedTouches;
     105             : }
     106             : 
     107             : TouchList*
     108           0 : TouchEvent::Touches()
     109             : {
     110           0 :   if (!mTouches) {
     111           0 :     WidgetTouchEvent* touchEvent = mEvent->AsTouchEvent();
     112           0 :     if (mEvent->mMessage == eTouchEnd || mEvent->mMessage == eTouchCancel) {
     113             :       // for touchend events, remove any changed touches from mTouches
     114           0 :       WidgetTouchEvent::AutoTouchArray unchangedTouches;
     115           0 :       const WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
     116           0 :       for (uint32_t i = 0; i < touches.Length(); ++i) {
     117           0 :         if (!touches[i]->mChanged) {
     118           0 :           unchangedTouches.AppendElement(touches[i]);
     119             :         }
     120             :       }
     121           0 :       mTouches = new TouchList(ToSupports(this), unchangedTouches);
     122             :     } else {
     123           0 :       mTouches = new TouchList(ToSupports(this), touchEvent->mTouches);
     124             :     }
     125             :   }
     126           0 :   return mTouches;
     127             : }
     128             : 
     129             : TouchList*
     130           0 : TouchEvent::TargetTouches()
     131             : {
     132           0 :   if (!mTargetTouches) {
     133           0 :     WidgetTouchEvent::AutoTouchArray targetTouches;
     134           0 :     WidgetTouchEvent* touchEvent = mEvent->AsTouchEvent();
     135           0 :     const WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
     136           0 :     for (uint32_t i = 0; i < touches.Length(); ++i) {
     137             :       // for touchend/cancel events, don't append to the target list if this is a
     138             :       // touch that is ending
     139           0 :       if ((mEvent->mMessage != eTouchEnd && mEvent->mMessage != eTouchCancel) ||
     140           0 :           !touches[i]->mChanged) {
     141           0 :         if (touches[i]->mTarget == mEvent->mOriginalTarget) {
     142           0 :           targetTouches.AppendElement(touches[i]);
     143             :         }
     144             :       }
     145             :     }
     146           0 :     mTargetTouches = new TouchList(ToSupports(this), targetTouches);
     147             :   }
     148           0 :   return mTargetTouches;
     149             : }
     150             : 
     151             : TouchList*
     152           0 : TouchEvent::ChangedTouches()
     153             : {
     154           0 :   if (!mChangedTouches) {
     155           0 :     WidgetTouchEvent::AutoTouchArray changedTouches;
     156           0 :     WidgetTouchEvent* touchEvent = mEvent->AsTouchEvent();
     157           0 :     const WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
     158           0 :     for (uint32_t i = 0; i < touches.Length(); ++i) {
     159           0 :       if (touches[i]->mChanged) {
     160           0 :         changedTouches.AppendElement(touches[i]);
     161             :       }
     162             :     }
     163           0 :     mChangedTouches = new TouchList(ToSupports(this), changedTouches);
     164             :   }
     165           0 :   return mChangedTouches;
     166             : }
     167             : 
     168             : // static
     169             : bool
     170          24 : TouchEvent::PrefEnabled(JSContext* aCx, JSObject* aGlobal)
     171             : {
     172          24 :   nsIDocShell* docShell = nullptr;
     173          24 :   if (aGlobal) {
     174          24 :     nsGlobalWindow* win = xpc::WindowOrNull(aGlobal);
     175          24 :     if (win) {
     176          24 :       docShell = win->GetDocShell();
     177             :     }
     178             :   }
     179          24 :   return PrefEnabled(docShell);
     180             : }
     181             : 
     182             : // static
     183             : bool
     184          68 : TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
     185             : {
     186             :   static bool sPrefCached = false;
     187             :   static int32_t sPrefCacheValue = 0;
     188             : 
     189          68 :   uint32_t touchEventsOverride = nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE;
     190          68 :   if (aDocShell) {
     191          47 :     aDocShell->GetTouchEventsOverride(&touchEventsOverride);
     192             :   }
     193             : 
     194          68 :   if (!sPrefCached) {
     195           2 :     sPrefCached = true;
     196           2 :     Preferences::AddIntVarCache(&sPrefCacheValue, "dom.w3c_touch_events.enabled");
     197             :   }
     198             : 
     199          68 :   bool enabled = false;
     200          68 :   if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED) {
     201           0 :     enabled = true;
     202          68 :   } else if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED) {
     203           0 :     enabled = false;
     204             :   } else {
     205          68 :     if (sPrefCacheValue == 2) {
     206             : #if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
     207             :       // Touch support is always enabled on B2G and android.
     208             :       enabled = true;
     209             : #elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3
     210             :       static bool sDidCheckTouchDeviceSupport = false;
     211             :       static bool sIsTouchDeviceSupportPresent = false;
     212             :       // On Windows and GTK3 we auto-detect based on device support.
     213          68 :       if (!sDidCheckTouchDeviceSupport) {
     214           2 :         sDidCheckTouchDeviceSupport = true;
     215           2 :         sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
     216             :         // But touch events are only actually supported if APZ is enabled. If
     217             :         // APZ is disabled globally, we can check that once and incorporate that
     218             :         // into the cached state. If APZ is enabled, we need to further check
     219             :         // based on the widget, which we do below (and don't cache that result).
     220           2 :         sIsTouchDeviceSupportPresent &= gfxPlatform::AsyncPanZoomEnabled();
     221             :       }
     222          68 :       enabled = sIsTouchDeviceSupportPresent;
     223          68 :       if (enabled && aDocShell) {
     224             :         // APZ might be disabled on this particular widget, in which case
     225             :         // TouchEvent support will also be disabled. Try to detect that.
     226           0 :         RefPtr<nsPresContext> pc;
     227           0 :         aDocShell->GetPresContext(getter_AddRefs(pc));
     228           0 :         if (pc && pc->GetRootWidget()) {
     229           0 :           enabled &= pc->GetRootWidget()->AsyncPanZoomEnabled();
     230             :         }
     231             :       }
     232             : #else
     233             :       enabled = false;
     234             : #endif
     235             :     } else {
     236           0 :       enabled = !!sPrefCacheValue;
     237             :     }
     238             :   }
     239             : 
     240          68 :   if (enabled) {
     241           0 :     nsContentUtils::InitializeTouchEventTable();
     242             :   }
     243          68 :   return enabled;
     244             : }
     245             : 
     246             : // static
     247             : already_AddRefed<Event>
     248           0 : TouchEvent::Constructor(const GlobalObject& aGlobal,
     249             :                         const nsAString& aType,
     250             :                         const TouchEventInit& aParam,
     251             :                         ErrorResult& aRv)
     252             : {
     253           0 :   nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
     254           0 :   RefPtr<TouchEvent> e = new TouchEvent(t, nullptr, nullptr);
     255           0 :   bool trusted = e->Init(t);
     256           0 :   RefPtr<TouchList> touches = e->CopyTouches(aParam.mTouches);
     257           0 :   RefPtr<TouchList> targetTouches = e->CopyTouches(aParam.mTargetTouches);
     258           0 :   RefPtr<TouchList> changedTouches = e->CopyTouches(aParam.mChangedTouches);
     259           0 :   e->InitTouchEvent(aType, aParam.mBubbles, aParam.mCancelable, aParam.mView,
     260           0 :                     aParam.mDetail, aParam.mCtrlKey, aParam.mAltKey,
     261           0 :                     aParam.mShiftKey, aParam.mMetaKey, touches, targetTouches,
     262           0 :                     changedTouches);
     263           0 :   e->SetTrusted(trusted);
     264           0 :   e->SetComposed(aParam.mComposed);
     265           0 :   return e.forget();
     266             : }
     267             : 
     268             : 
     269             : already_AddRefed<TouchList>
     270           0 : TouchEvent::CopyTouches(const Sequence<OwningNonNull<Touch>>& aTouches)
     271             : {
     272           0 :   RefPtr<TouchList> list = new TouchList(GetParentObject());
     273           0 :   size_t len = aTouches.Length();
     274           0 :   for (size_t i = 0; i < len; ++i) {
     275           0 :     list->Append(aTouches[i]);
     276             :   }
     277           0 :   return list.forget();
     278             : }
     279             : 
     280             : bool
     281           0 : TouchEvent::AltKey()
     282             : {
     283           0 :   return mEvent->AsTouchEvent()->IsAlt();
     284             : }
     285             : 
     286             : bool
     287           0 : TouchEvent::MetaKey()
     288             : {
     289           0 :   return mEvent->AsTouchEvent()->IsMeta();
     290             : }
     291             : 
     292             : bool
     293           0 : TouchEvent::CtrlKey()
     294             : {
     295           0 :   return mEvent->AsTouchEvent()->IsControl();
     296             : }
     297             : 
     298             : bool
     299           0 : TouchEvent::ShiftKey()
     300             : {
     301           0 :   return mEvent->AsTouchEvent()->IsShift();
     302             : }
     303             : 
     304             : } // namespace dom
     305             : } // namespace mozilla
     306             : 
     307             : using namespace mozilla;
     308             : using namespace mozilla::dom;
     309             : 
     310             : already_AddRefed<TouchEvent>
     311           0 : NS_NewDOMTouchEvent(EventTarget* aOwner,
     312             :                     nsPresContext* aPresContext,
     313             :                     WidgetTouchEvent* aEvent)
     314             : {
     315           0 :   RefPtr<TouchEvent> it = new TouchEvent(aOwner, aPresContext, aEvent);
     316           0 :   return it.forget();
     317             : }

Generated by: LCOV version 1.13