gecko-dev/dom/events/TouchEvent.cpp

304 lines
9.0 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 11:12:37 +00:00
/* 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/Navigator.h"
#include "mozilla/dom/TouchEvent.h"
#include "mozilla/dom/Touch.h"
#include "mozilla/dom/TouchListBinding.h"
#include "mozilla/Preferences.h"
#include "mozilla/TouchEvents.h"
#include "nsContentUtils.h"
#include "nsIDocShell.h"
#include "mozilla/WidgetUtils.h"
namespace mozilla {
namespace dom {
/******************************************************************************
* TouchList
*****************************************************************************/
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TouchList)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(TouchList, mParent, mPoints)
NS_IMPL_CYCLE_COLLECTING_ADDREF(TouchList)
NS_IMPL_CYCLE_COLLECTING_RELEASE(TouchList)
JSObject*
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv The only manual changes here are to BindingUtils.h, BindingUtils.cpp, Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp, dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp, Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp, Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The rest of this diff was generated by running the following commands: find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 14:13:33 +00:00
TouchList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv The only manual changes here are to BindingUtils.h, BindingUtils.cpp, Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp, dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp, Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp, Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The rest of this diff was generated by running the following commands: find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g' find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 14:13:33 +00:00
return TouchListBinding::Wrap(aCx, this, aGivenProto);
}
// static
bool
TouchList::PrefEnabled(JSContext* aCx, JSObject* aGlobal)
{
return TouchEvent::PrefEnabled(aCx, aGlobal);
}
/******************************************************************************
* TouchEvent
*****************************************************************************/
TouchEvent::TouchEvent(EventTarget* aOwner,
nsPresContext* aPresContext,
WidgetTouchEvent* aEvent)
: UIEvent(aOwner, aPresContext,
aEvent ? aEvent :
new WidgetTouchEvent(false, eVoidEvent, nullptr))
{
if (aEvent) {
mEventIsInternal = false;
for (uint32_t i = 0; i < aEvent->mTouches.Length(); ++i) {
Touch* touch = aEvent->mTouches[i];
touch->InitializePoints(mPresContext, aEvent);
}
} else {
mEventIsInternal = true;
mEvent->mTime = PR_Now();
}
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(TouchEvent, UIEvent,
mTouches,
mTargetTouches,
mChangedTouches)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TouchEvent)
NS_INTERFACE_MAP_END_INHERITING(UIEvent)
NS_IMPL_ADDREF_INHERITED(TouchEvent, UIEvent)
NS_IMPL_RELEASE_INHERITED(TouchEvent, UIEvent)
void
TouchEvent::InitTouchEvent(const nsAString& aType,
bool aCanBubble,
bool aCancelable,
nsGlobalWindow* aView,
int32_t aDetail,
bool aCtrlKey,
bool aAltKey,
bool aShiftKey,
bool aMetaKey,
TouchList* aTouches,
TouchList* aTargetTouches,
TouchList* aChangedTouches)
{
NS_ENSURE_TRUE_VOID(!mEvent->mFlags.mIsBeingDispatched);
UIEvent::InitUIEvent(aType, aCanBubble, aCancelable, aView, aDetail);
mEvent->AsInputEvent()->InitBasicModifiers(aCtrlKey, aAltKey,
aShiftKey, aMetaKey);
mTouches = aTouches;
mTargetTouches = aTargetTouches;
mChangedTouches = aChangedTouches;
}
TouchList*
TouchEvent::Touches()
{
if (!mTouches) {
WidgetTouchEvent* touchEvent = mEvent->AsTouchEvent();
if (mEvent->mMessage == eTouchEnd || mEvent->mMessage == eTouchCancel) {
// for touchend events, remove any changed touches from mTouches
WidgetTouchEvent::AutoTouchArray unchangedTouches;
const WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
for (uint32_t i = 0; i < touches.Length(); ++i) {
if (!touches[i]->mChanged) {
unchangedTouches.AppendElement(touches[i]);
}
}
mTouches = new TouchList(ToSupports(this), unchangedTouches);
} else {
mTouches = new TouchList(ToSupports(this), touchEvent->mTouches);
}
}
return mTouches;
}
TouchList*
TouchEvent::TargetTouches()
{
if (!mTargetTouches) {
WidgetTouchEvent::AutoTouchArray targetTouches;
WidgetTouchEvent* touchEvent = mEvent->AsTouchEvent();
const WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
for (uint32_t i = 0; i < touches.Length(); ++i) {
// for touchend/cancel events, don't append to the target list if this is a
// touch that is ending
if ((mEvent->mMessage != eTouchEnd && mEvent->mMessage != eTouchCancel) ||
!touches[i]->mChanged) {
if (touches[i]->mTarget == mEvent->mOriginalTarget) {
targetTouches.AppendElement(touches[i]);
}
}
}
mTargetTouches = new TouchList(ToSupports(this), targetTouches);
}
return mTargetTouches;
}
TouchList*
TouchEvent::ChangedTouches()
{
if (!mChangedTouches) {
WidgetTouchEvent::AutoTouchArray changedTouches;
WidgetTouchEvent* touchEvent = mEvent->AsTouchEvent();
const WidgetTouchEvent::TouchArray& touches = touchEvent->mTouches;
for (uint32_t i = 0; i < touches.Length(); ++i) {
if (touches[i]->mChanged) {
changedTouches.AppendElement(touches[i]);
}
}
mChangedTouches = new TouchList(ToSupports(this), changedTouches);
}
return mChangedTouches;
}
// static
bool
TouchEvent::PrefEnabled(JSContext* aCx, JSObject* aGlobal)
{
nsIDocShell* docShell = nullptr;
if (aGlobal) {
nsGlobalWindow* win = xpc::WindowOrNull(aGlobal);
if (win) {
docShell = win->GetDocShell();
}
}
return PrefEnabled(docShell);
}
// static
bool
TouchEvent::PrefEnabled(nsIDocShell* aDocShell)
{
static bool sPrefCached = false;
static int32_t sPrefCacheValue = 0;
uint32_t touchEventsOverride = nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE;
if (aDocShell) {
aDocShell->GetTouchEventsOverride(&touchEventsOverride);
}
if (!sPrefCached) {
sPrefCached = true;
Preferences::AddIntVarCache(&sPrefCacheValue, "dom.w3c_touch_events.enabled");
}
bool enabled = false;
if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_ENABLED) {
enabled = true;
} else if (touchEventsOverride == nsIDocShell::TOUCHEVENTS_OVERRIDE_DISABLED) {
enabled = false;
} else {
if (sPrefCacheValue == 2) {
#if defined(MOZ_B2G) || defined(MOZ_WIDGET_ANDROID)
// Touch support is always enabled on B2G and android.
enabled = true;
#elif defined(XP_WIN) || MOZ_WIDGET_GTK == 3
static bool sDidCheckTouchDeviceSupport = false;
static bool sIsTouchDeviceSupportPresent = false;
// On Windows and GTK3 we auto-detect based on device support.
if (!sDidCheckTouchDeviceSupport) {
sDidCheckTouchDeviceSupport = true;
sIsTouchDeviceSupportPresent = WidgetUtils::IsTouchDeviceSupportPresent();
}
enabled = sIsTouchDeviceSupportPresent;
#else
enabled = false;
#endif
} else {
enabled = !!sPrefCacheValue;
}
}
if (enabled) {
nsContentUtils::InitializeTouchEventTable();
}
return enabled;
}
// static
already_AddRefed<Event>
TouchEvent::Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
const TouchEventInit& aParam,
ErrorResult& aRv)
{
nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
RefPtr<TouchEvent> e = new TouchEvent(t, nullptr, nullptr);
bool trusted = e->Init(t);
RefPtr<TouchList> touches = e->CopyTouches(aParam.mTouches);
RefPtr<TouchList> targetTouches = e->CopyTouches(aParam.mTargetTouches);
RefPtr<TouchList> changedTouches = e->CopyTouches(aParam.mChangedTouches);
e->InitTouchEvent(aType, aParam.mBubbles, aParam.mCancelable, aParam.mView,
aParam.mDetail, aParam.mCtrlKey, aParam.mAltKey,
aParam.mShiftKey, aParam.mMetaKey, touches, targetTouches,
changedTouches);
e->SetTrusted(trusted);
e->SetComposed(aParam.mComposed);
return e.forget();
}
already_AddRefed<TouchList>
TouchEvent::CopyTouches(const Sequence<OwningNonNull<Touch>>& aTouches)
{
RefPtr<TouchList> list = new TouchList(GetParentObject());
size_t len = aTouches.Length();
for (size_t i = 0; i < len; ++i) {
list->Append(aTouches[i]);
}
return list.forget();
}
bool
TouchEvent::AltKey()
{
return mEvent->AsTouchEvent()->IsAlt();
}
bool
TouchEvent::MetaKey()
{
return mEvent->AsTouchEvent()->IsMeta();
}
bool
TouchEvent::CtrlKey()
{
return mEvent->AsTouchEvent()->IsControl();
}
bool
TouchEvent::ShiftKey()
{
return mEvent->AsTouchEvent()->IsShift();
}
} // namespace dom
} // namespace mozilla
using namespace mozilla;
using namespace mozilla::dom;
already_AddRefed<TouchEvent>
NS_NewDOMTouchEvent(EventTarget* aOwner,
nsPresContext* aPresContext,
WidgetTouchEvent* aEvent)
{
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<TouchEvent> it = new TouchEvent(aOwner, aPresContext, aEvent);
return it.forget();
}