michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_dom_Event_h_ michael@0: #define mozilla_dom_Event_h_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/BasicEvents.h" michael@0: #include "nsIDOMEvent.h" michael@0: #include "nsISupports.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsPIDOMWindow.h" michael@0: #include "nsPoint.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "mozilla/dom/EventBinding.h" michael@0: #include "nsIScriptGlobalObject.h" michael@0: #include "Units.h" michael@0: #include "js/TypeDecls.h" michael@0: michael@0: class nsIContent; michael@0: class nsIDOMEventTarget; michael@0: class nsPresContext; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: class EventTarget; michael@0: class ErrorEvent; michael@0: michael@0: // Dummy class so we can cast through it to get from nsISupports to michael@0: // Event subclasses with only two non-ambiguous static casts. michael@0: class EventBase : public nsIDOMEvent michael@0: { michael@0: }; michael@0: michael@0: class Event : public EventBase, michael@0: public nsWrapperCache michael@0: { michael@0: public: michael@0: Event(EventTarget* aOwner, michael@0: nsPresContext* aPresContext, michael@0: WidgetEvent* aEvent); michael@0: Event(nsPIDOMWindow* aWindow); michael@0: virtual ~Event(); michael@0: michael@0: private: michael@0: void ConstructorInit(EventTarget* aOwner, michael@0: nsPresContext* aPresContext, michael@0: WidgetEvent* aEvent); michael@0: michael@0: public: michael@0: void GetParentObject(nsIScriptGlobalObject** aParentObject) michael@0: { michael@0: if (mOwner) { michael@0: CallQueryInterface(mOwner, aParentObject); michael@0: } else { michael@0: *aParentObject = nullptr; michael@0: } michael@0: } michael@0: michael@0: static Event* FromSupports(nsISupports* aSupports) michael@0: { michael@0: nsIDOMEvent* event = michael@0: static_cast(aSupports); michael@0: #ifdef DEBUG michael@0: { michael@0: nsCOMPtr target_qi = michael@0: do_QueryInterface(aSupports); michael@0: michael@0: // If this assertion fires the QI implementation for the object in michael@0: // question doesn't use the nsIDOMEvent pointer as the michael@0: // nsISupports pointer. That must be fixed, or we'll crash... michael@0: MOZ_ASSERT(target_qi == event, "Uh, fix QI!"); michael@0: } michael@0: #endif michael@0: return static_cast(event); michael@0: } michael@0: michael@0: NS_DECL_CYCLE_COLLECTING_ISUPPORTS michael@0: NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Event) michael@0: michael@0: nsISupports* GetParentObject() michael@0: { michael@0: return mOwner; michael@0: } michael@0: michael@0: virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE michael@0: { michael@0: return EventBinding::Wrap(aCx, this); michael@0: } michael@0: michael@0: virtual ErrorEvent* AsErrorEvent() michael@0: { michael@0: return nullptr; michael@0: } michael@0: michael@0: // nsIDOMEvent Interface michael@0: NS_DECL_NSIDOMEVENT michael@0: michael@0: void InitPresContextData(nsPresContext* aPresContext); michael@0: michael@0: // Returns true if the event should be trusted. michael@0: bool Init(EventTarget* aGlobal); michael@0: michael@0: static PopupControlState GetEventPopupControlState(WidgetEvent* aEvent); michael@0: michael@0: static void PopupAllowedEventsChanged(); michael@0: michael@0: static void Shutdown(); michael@0: michael@0: static const char* GetEventName(uint32_t aEventType); michael@0: static CSSIntPoint GetClientCoords(nsPresContext* aPresContext, michael@0: WidgetEvent* aEvent, michael@0: LayoutDeviceIntPoint aPoint, michael@0: CSSIntPoint aDefaultPoint); michael@0: static CSSIntPoint GetPageCoords(nsPresContext* aPresContext, michael@0: WidgetEvent* aEvent, michael@0: LayoutDeviceIntPoint aPoint, michael@0: CSSIntPoint aDefaultPoint); michael@0: static nsIntPoint GetScreenCoords(nsPresContext* aPresContext, michael@0: WidgetEvent* aEvent, michael@0: LayoutDeviceIntPoint aPoint); michael@0: michael@0: static already_AddRefed Constructor(const GlobalObject& aGlobal, michael@0: const nsAString& aType, michael@0: const EventInit& aParam, michael@0: ErrorResult& aRv); michael@0: michael@0: // Implemented as xpidl method michael@0: // void GetType(nsString& aRetval) {} michael@0: michael@0: EventTarget* GetTarget() const; michael@0: EventTarget* GetCurrentTarget() const; michael@0: michael@0: uint16_t EventPhase() const; michael@0: michael@0: // xpidl implementation michael@0: // void StopPropagation(); michael@0: michael@0: // xpidl implementation michael@0: // void StopImmediatePropagation(); michael@0: michael@0: bool Bubbles() const michael@0: { michael@0: return mEvent->mFlags.mBubbles; michael@0: } michael@0: michael@0: bool Cancelable() const michael@0: { michael@0: return mEvent->mFlags.mCancelable; michael@0: } michael@0: michael@0: // xpidl implementation michael@0: // void PreventDefault(); michael@0: michael@0: // You MUST NOT call PreventDefaultJ(JSContext*) from C++ code. A call of michael@0: // this method always sets Event.defaultPrevented true for web contents. michael@0: // If default action handler calls this, web applications meet wrong michael@0: // defaultPrevented value. michael@0: void PreventDefault(JSContext* aCx); michael@0: michael@0: // You MUST NOT call DefaultPrevented(JSContext*) from C++ code. This may michael@0: // return false even if PreventDefault() has been called. michael@0: // See comments in its implementation for the detail. michael@0: bool DefaultPrevented(JSContext* aCx) const; michael@0: michael@0: bool DefaultPrevented() const michael@0: { michael@0: return mEvent->mFlags.mDefaultPrevented; michael@0: } michael@0: michael@0: bool MultipleActionsPrevented() const michael@0: { michael@0: return mEvent->mFlags.mMultipleActionsPrevented; michael@0: } michael@0: michael@0: bool IsTrusted() const michael@0: { michael@0: return mEvent->mFlags.mIsTrusted; michael@0: } michael@0: michael@0: bool IsSynthesized() const michael@0: { michael@0: return mEvent->mFlags.mIsSynthesizedForTests; michael@0: } michael@0: michael@0: uint64_t TimeStamp() const michael@0: { michael@0: return mEvent->time; michael@0: } michael@0: michael@0: void InitEvent(const nsAString& aType, bool aBubbles, bool aCancelable, michael@0: ErrorResult& aRv) michael@0: { michael@0: aRv = InitEvent(aType, aBubbles, aCancelable); michael@0: } michael@0: michael@0: EventTarget* GetOriginalTarget() const; michael@0: EventTarget* GetExplicitOriginalTarget() const; michael@0: michael@0: bool GetPreventDefault() const; michael@0: michael@0: /** michael@0: * @param aCalledByDefaultHandler Should be true when this is called by michael@0: * C++ or Chrome. Otherwise, e.g., called michael@0: * by a call of Event.preventDefault() in michael@0: * content script, false. michael@0: */ michael@0: void PreventDefaultInternal(bool aCalledByDefaultHandler); michael@0: michael@0: bool IsMainThreadEvent() michael@0: { michael@0: return mIsMainThreadEvent; michael@0: } michael@0: michael@0: protected: michael@0: michael@0: // Internal helper functions michael@0: void SetEventType(const nsAString& aEventTypeArg); michael@0: already_AddRefed GetTargetFromFrame(); michael@0: michael@0: /** michael@0: * IsChrome() returns true if aCx is chrome context or the event is created michael@0: * in chrome's thread. Otherwise, false. michael@0: */ michael@0: bool IsChrome(JSContext* aCx) const; michael@0: michael@0: mozilla::WidgetEvent* mEvent; michael@0: nsRefPtr mPresContext; michael@0: nsCOMPtr mExplicitOriginalTarget; michael@0: nsCOMPtr mOwner; // nsPIDOMWindow for now. michael@0: bool mEventIsInternal; michael@0: bool mPrivateDataDuplicated; michael@0: bool mIsMainThreadEvent; michael@0: }; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #define NS_FORWARD_TO_EVENT \ michael@0: NS_FORWARD_NSIDOMEVENT(Event::) michael@0: michael@0: #define NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(_to) \ michael@0: NS_IMETHOD GetType(nsAString& aType){ return _to GetType(aType); } \ michael@0: NS_IMETHOD GetTarget(nsIDOMEventTarget * *aTarget) { return _to GetTarget(aTarget); } \ michael@0: NS_IMETHOD GetCurrentTarget(nsIDOMEventTarget * *aCurrentTarget) { return _to GetCurrentTarget(aCurrentTarget); } \ michael@0: NS_IMETHOD GetEventPhase(uint16_t *aEventPhase) { return _to GetEventPhase(aEventPhase); } \ michael@0: NS_IMETHOD GetBubbles(bool *aBubbles) { return _to GetBubbles(aBubbles); } \ michael@0: NS_IMETHOD GetCancelable(bool *aCancelable) { return _to GetCancelable(aCancelable); } \ michael@0: NS_IMETHOD GetTimeStamp(DOMTimeStamp *aTimeStamp) { return _to GetTimeStamp(aTimeStamp); } \ michael@0: NS_IMETHOD StopPropagation(void) { return _to StopPropagation(); } \ michael@0: NS_IMETHOD PreventDefault(void) { return _to PreventDefault(); } \ michael@0: NS_IMETHOD InitEvent(const nsAString & eventTypeArg, bool canBubbleArg, bool cancelableArg) { return _to InitEvent(eventTypeArg, canBubbleArg, cancelableArg); } \ michael@0: NS_IMETHOD GetDefaultPrevented(bool *aDefaultPrevented) { return _to GetDefaultPrevented(aDefaultPrevented); } \ michael@0: NS_IMETHOD StopImmediatePropagation(void) { return _to StopImmediatePropagation(); } \ michael@0: NS_IMETHOD GetOriginalTarget(nsIDOMEventTarget** aOriginalTarget) { return _to GetOriginalTarget(aOriginalTarget); } \ michael@0: NS_IMETHOD GetExplicitOriginalTarget(nsIDOMEventTarget** aExplicitOriginalTarget) { return _to GetExplicitOriginalTarget(aExplicitOriginalTarget); } \ michael@0: NS_IMETHOD GetPreventDefault(bool* aRetval) { return _to GetPreventDefault(aRetval); } \ michael@0: NS_IMETHOD GetIsTrusted(bool* aIsTrusted) { return _to GetIsTrusted(aIsTrusted); } \ michael@0: NS_IMETHOD SetTarget(nsIDOMEventTarget *aTarget) { return _to SetTarget(aTarget); } \ michael@0: NS_IMETHOD_(bool) IsDispatchStopped(void) { return _to IsDispatchStopped(); } \ michael@0: NS_IMETHOD_(WidgetEvent*) GetInternalNSEvent(void) { return _to GetInternalNSEvent(); } \ michael@0: NS_IMETHOD_(void) SetTrusted(bool aTrusted) { _to SetTrusted(aTrusted); } \ michael@0: NS_IMETHOD_(void) SetOwner(EventTarget* aOwner) { _to SetOwner(aOwner); } \ michael@0: NS_IMETHOD_(Event*) InternalDOMEvent() { return _to InternalDOMEvent(); } michael@0: michael@0: #define NS_FORWARD_TO_EVENT_NO_SERIALIZATION_NO_DUPLICATION \ michael@0: NS_FORWARD_NSIDOMEVENT_NO_SERIALIZATION_NO_DUPLICATION(Event::) michael@0: michael@0: inline nsISupports* michael@0: ToSupports(mozilla::dom::Event* e) michael@0: { michael@0: return static_cast(e); michael@0: } michael@0: michael@0: inline nsISupports* michael@0: ToCanonicalSupports(mozilla::dom::Event* e) michael@0: { michael@0: return static_cast(e); michael@0: } michael@0: michael@0: #endif // mozilla_dom_Event_h_