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 nsXBLPrototypeHandler_h__ michael@0: #define nsXBLPrototypeHandler_h__ michael@0: michael@0: #include "nsIAtom.h" michael@0: #include "nsString.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsIController.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsXBLEventHandler.h" michael@0: #include "nsIWeakReference.h" michael@0: #include "nsIScriptGlobalObject.h" michael@0: #include "nsCycleCollectionParticipant.h" michael@0: #include "js/TypeDecls.h" michael@0: michael@0: class nsIDOMEvent; michael@0: class nsIContent; michael@0: class nsIDOMUIEvent; michael@0: class nsIDOMKeyEvent; michael@0: class nsIDOMMouseEvent; michael@0: class nsIObjectInputStream; michael@0: class nsIObjectOutputStream; michael@0: class nsXBLPrototypeBinding; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: class EventTarget; michael@0: } michael@0: } michael@0: michael@0: #define NS_HANDLER_TYPE_XBL_JS (1 << 0) michael@0: #define NS_HANDLER_TYPE_XBL_COMMAND (1 << 1) michael@0: #define NS_HANDLER_TYPE_XUL (1 << 2) michael@0: #define NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR (1 << 4) michael@0: #define NS_HANDLER_ALLOW_UNTRUSTED (1 << 5) michael@0: #define NS_HANDLER_TYPE_SYSTEM (1 << 6) michael@0: #define NS_HANDLER_TYPE_PREVENTDEFAULT (1 << 7) michael@0: michael@0: // XXX Use nsIDOMEvent:: codes? michael@0: #define NS_PHASE_CAPTURING 1 michael@0: #define NS_PHASE_TARGET 2 michael@0: #define NS_PHASE_BUBBLING 3 michael@0: michael@0: class nsXBLPrototypeHandler michael@0: { michael@0: public: michael@0: // This constructor is used by XBL handlers (both the JS and command shorthand variety) michael@0: nsXBLPrototypeHandler(const char16_t* aEvent, const char16_t* aPhase, michael@0: const char16_t* aAction, const char16_t* aCommand, michael@0: const char16_t* aKeyCode, const char16_t* aCharCode, michael@0: const char16_t* aModifiers, const char16_t* aButton, michael@0: const char16_t* aClickCount, const char16_t* aGroup, michael@0: const char16_t* aPreventDefault, michael@0: const char16_t* aAllowUntrusted, michael@0: nsXBLPrototypeBinding* aBinding, michael@0: uint32_t aLineNumber); michael@0: michael@0: // This constructor is used only by XUL key handlers (e.g., ) michael@0: nsXBLPrototypeHandler(nsIContent* aKeyElement); michael@0: michael@0: // This constructor is used for handlers loaded from the cache michael@0: nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding); michael@0: michael@0: ~nsXBLPrototypeHandler(); michael@0: michael@0: // if aCharCode is not zero, it is used instead of the charCode of aKeyEvent. michael@0: bool KeyEventMatched(nsIDOMKeyEvent* aKeyEvent, michael@0: uint32_t aCharCode = 0, michael@0: bool aIgnoreShiftKey = false); michael@0: inline bool KeyEventMatched(nsIAtom* aEventType, michael@0: nsIDOMKeyEvent* aEvent, michael@0: uint32_t aCharCode = 0, michael@0: bool aIgnoreShiftKey = false) michael@0: { michael@0: if (aEventType != mEventName) michael@0: return false; michael@0: michael@0: return KeyEventMatched(aEvent, aCharCode, aIgnoreShiftKey); michael@0: } michael@0: michael@0: bool MouseEventMatched(nsIDOMMouseEvent* aMouseEvent); michael@0: inline bool MouseEventMatched(nsIAtom* aEventType, michael@0: nsIDOMMouseEvent* aEvent) michael@0: { michael@0: if (aEventType != mEventName) michael@0: return false; michael@0: michael@0: return MouseEventMatched(aEvent); michael@0: } michael@0: michael@0: already_AddRefed GetHandlerElement(); michael@0: michael@0: void AppendHandlerText(const nsAString& aText); michael@0: michael@0: uint8_t GetPhase() { return mPhase; } michael@0: uint8_t GetType() { return mType; } michael@0: michael@0: nsXBLPrototypeHandler* GetNextHandler() { return mNextHandler; } michael@0: void SetNextHandler(nsXBLPrototypeHandler* aHandler) { mNextHandler = aHandler; } michael@0: michael@0: nsresult ExecuteHandler(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent); michael@0: michael@0: already_AddRefed GetEventName(); michael@0: void SetEventName(nsIAtom* aName) { mEventName = aName; } michael@0: michael@0: nsXBLEventHandler* GetEventHandler() michael@0: { michael@0: if (!mHandler) { michael@0: NS_NewXBLEventHandler(this, mEventName, getter_AddRefs(mHandler)); michael@0: // XXX Need to signal out of memory? michael@0: } michael@0: michael@0: return mHandler; michael@0: } michael@0: michael@0: nsXBLEventHandler* GetCachedEventHandler() michael@0: { michael@0: return mHandler; michael@0: } michael@0: michael@0: bool HasAllowUntrustedAttr() michael@0: { michael@0: return (mType & NS_HANDLER_HAS_ALLOW_UNTRUSTED_ATTR) != 0; michael@0: } michael@0: michael@0: // This returns a valid value only if HasAllowUntrustedEventsAttr returns michael@0: // true. michael@0: bool AllowUntrustedEvents() michael@0: { michael@0: return (mType & NS_HANDLER_ALLOW_UNTRUSTED) != 0; michael@0: } michael@0: michael@0: nsresult Read(nsIObjectInputStream* aStream); michael@0: nsresult Write(nsIObjectOutputStream* aStream); michael@0: michael@0: public: michael@0: static uint32_t gRefCnt; michael@0: michael@0: protected: michael@0: void Init() { michael@0: ++gRefCnt; michael@0: if (gRefCnt == 1) michael@0: // Get the primary accelerator key. michael@0: InitAccessKeys(); michael@0: } michael@0: michael@0: already_AddRefed GetController(mozilla::dom::EventTarget* aTarget); michael@0: michael@0: inline int32_t GetMatchingKeyCode(const nsAString& aKeyName); michael@0: void ConstructPrototype(nsIContent* aKeyElement, michael@0: const char16_t* aEvent=nullptr, const char16_t* aPhase=nullptr, michael@0: const char16_t* aAction=nullptr, const char16_t* aCommand=nullptr, michael@0: const char16_t* aKeyCode=nullptr, const char16_t* aCharCode=nullptr, michael@0: const char16_t* aModifiers=nullptr, const char16_t* aButton=nullptr, michael@0: const char16_t* aClickCount=nullptr, const char16_t* aGroup=nullptr, michael@0: const char16_t* aPreventDefault=nullptr, michael@0: const char16_t* aAllowUntrusted=nullptr); michael@0: michael@0: void ReportKeyConflict(const char16_t* aKey, const char16_t* aModifiers, nsIContent* aElement, const char *aMessageName); michael@0: void GetEventType(nsAString& type); michael@0: bool ModifiersMatchMask(nsIDOMUIEvent* aEvent, michael@0: bool aIgnoreShiftKey = false); michael@0: nsresult DispatchXBLCommand(mozilla::dom::EventTarget* aTarget, nsIDOMEvent* aEvent); michael@0: nsresult DispatchXULKeyCommand(nsIDOMEvent* aEvent); michael@0: nsresult EnsureEventHandler(nsIScriptGlobalObject* aGlobal, michael@0: nsIScriptContext *aBoundContext, nsIAtom *aName, michael@0: JS::MutableHandle aHandler); michael@0: static int32_t KeyToMask(int32_t key); michael@0: michael@0: static int32_t kAccelKey; michael@0: static int32_t kMenuAccessKey; michael@0: static void InitAccessKeys(); michael@0: michael@0: static const int32_t cShift; michael@0: static const int32_t cAlt; michael@0: static const int32_t cControl; michael@0: static const int32_t cMeta; michael@0: static const int32_t cOS; michael@0: michael@0: static const int32_t cShiftMask; michael@0: static const int32_t cAltMask; michael@0: static const int32_t cControlMask; michael@0: static const int32_t cMetaMask; michael@0: static const int32_t cOSMask; michael@0: michael@0: static const int32_t cAllModifiers; michael@0: michael@0: protected: michael@0: union { michael@0: nsIWeakReference* mHandlerElement; // For XUL element handlers. [STRONG] michael@0: char16_t* mHandlerText; // For XBL handlers (we don't build an michael@0: // element for the , and instead michael@0: // we cache the JS text or command name michael@0: // that we should use. michael@0: }; michael@0: michael@0: uint32_t mLineNumber; // The line number we started at in the XBL file michael@0: michael@0: // The following four values make up 32 bits. michael@0: uint8_t mPhase; // The phase (capturing, bubbling) michael@0: uint8_t mType; // The type of the handler. The handler is either a XUL key michael@0: // handler, an XBL "command" event, or a normal XBL event with michael@0: // accompanying JavaScript. The high bit is used to indicate michael@0: // whether this handler should prevent the default action. michael@0: uint8_t mMisc; // Miscellaneous extra information. For key events, michael@0: // stores whether or not we're a key code or char code. michael@0: // For mouse events, stores the clickCount. michael@0: michael@0: int32_t mKeyMask; // Which modifier keys this event handler expects to have down michael@0: // in order to be matched. michael@0: michael@0: // The primary filter information for mouse/key events. michael@0: int32_t mDetail; // For key events, contains a charcode or keycode. For michael@0: // mouse events, stores the button info. michael@0: michael@0: // Prototype handlers are chained. We own the next handler in the chain. michael@0: nsXBLPrototypeHandler* mNextHandler; michael@0: nsCOMPtr mEventName; // The type of the event, e.g., "keypress" michael@0: nsRefPtr mHandler; michael@0: nsXBLPrototypeBinding* mPrototypeBinding; // the binding owns us michael@0: }; michael@0: michael@0: #endif