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_EventStates_h_ michael@0: #define mozilla_EventStates_h_ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "nsDebug.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: /** michael@0: * EventStates is the class used to represent the event states of nsIContent michael@0: * instances. These states are calculated by IntrinsicState() and michael@0: * ContentStatesChanged() has to be called when one of them changes thus michael@0: * informing the layout/style engine of the change. michael@0: * Event states are associated with pseudo-classes. michael@0: */ michael@0: class EventStates michael@0: { michael@0: public: michael@0: typedef uint64_t InternalType; michael@0: michael@0: MOZ_CONSTEXPR EventStates() michael@0: : mStates(0) michael@0: { michael@0: } michael@0: michael@0: // NOTE: the ideal scenario would be to have the default constructor public michael@0: // setting mStates to 0 and this constructor (without = 0) private. michael@0: // In that case, we could be sure that only macros at the end were creating michael@0: // EventStates instances with mStates set to something else than 0. michael@0: // Unfortunately, this constructor is needed at at least two places now. michael@0: explicit MOZ_CONSTEXPR EventStates(InternalType aStates) michael@0: : mStates(aStates) michael@0: { michael@0: } michael@0: michael@0: MOZ_CONSTEXPR EventStates(const EventStates& aEventStates) michael@0: : mStates(aEventStates.mStates) michael@0: { michael@0: } michael@0: michael@0: EventStates& operator=(const EventStates& aEventStates) michael@0: { michael@0: mStates = aEventStates.mStates; michael@0: return *this; michael@0: } michael@0: michael@0: EventStates MOZ_CONSTEXPR operator|(const EventStates& aEventStates) const michael@0: { michael@0: return EventStates(mStates | aEventStates.mStates); michael@0: } michael@0: michael@0: EventStates& operator|=(const EventStates& aEventStates) michael@0: { michael@0: mStates |= aEventStates.mStates; michael@0: return *this; michael@0: } michael@0: michael@0: // NOTE: calling if (eventStates1 & eventStates2) will not build. michael@0: // This might work correctly if operator bool() is defined michael@0: // but using HasState, HasAllStates or HasAtLeastOneOfStates is recommended. michael@0: EventStates MOZ_CONSTEXPR operator&(const EventStates& aEventStates) const michael@0: { michael@0: return EventStates(mStates & aEventStates.mStates); michael@0: } michael@0: michael@0: EventStates& operator&=(const EventStates& aEventStates) michael@0: { michael@0: mStates &= aEventStates.mStates; michael@0: return *this; michael@0: } michael@0: michael@0: bool operator==(const EventStates& aEventStates) const michael@0: { michael@0: return mStates == aEventStates.mStates; michael@0: } michael@0: michael@0: bool operator!=(const EventStates& aEventStates) const michael@0: { michael@0: return mStates != aEventStates.mStates; michael@0: } michael@0: michael@0: EventStates operator~() const michael@0: { michael@0: return EventStates(~mStates); michael@0: } michael@0: michael@0: EventStates operator^(const EventStates& aEventStates) const michael@0: { michael@0: return EventStates(mStates ^ aEventStates.mStates); michael@0: } michael@0: michael@0: EventStates& operator^=(const EventStates& aEventStates) michael@0: { michael@0: mStates ^= aEventStates.mStates; michael@0: return *this; michael@0: } michael@0: michael@0: /** michael@0: * Returns true if the EventStates instance is empty. michael@0: * A EventStates instance is empty if it contains no state. michael@0: * michael@0: * @return Whether if the object is empty. michael@0: */ michael@0: bool IsEmpty() const michael@0: { michael@0: return mStates == 0; michael@0: } michael@0: michael@0: /** michael@0: * Returns true if the EventStates instance contains the state michael@0: * contained in aEventStates. michael@0: * @note aEventStates should contain only one state. michael@0: * michael@0: * @param aEventStates The state to check. michael@0: * michael@0: * @return Whether the object has the state from aEventStates michael@0: */ michael@0: bool HasState(EventStates aEventStates) const michael@0: { michael@0: #ifdef DEBUG michael@0: // If aEventStates.mStates is a power of two, it contains only one state michael@0: // (or none, but we don't really care). michael@0: if ((aEventStates.mStates & (aEventStates.mStates - 1))) { michael@0: NS_ERROR("When calling HasState, " michael@0: "EventStates object has to contain only one state!"); michael@0: } michael@0: #endif // DEBUG michael@0: return mStates & aEventStates.mStates; michael@0: } michael@0: michael@0: /** michael@0: * Returns true if the EventStates instance contains one of the states michael@0: * contained in aEventStates. michael@0: * michael@0: * @param aEventStates The states to check. michael@0: * michael@0: * @return Whether the object has at least one state from aEventStates michael@0: */ michael@0: bool HasAtLeastOneOfStates(EventStates aEventStates) const michael@0: { michael@0: return mStates & aEventStates.mStates; michael@0: } michael@0: michael@0: /** michael@0: * Returns true if the EventStates instance contains all states michael@0: * contained in aEventStates. michael@0: * michael@0: * @param aEventStates The states to check. michael@0: * michael@0: * @return Whether the object has all states from aEventStates michael@0: */ michael@0: bool HasAllStates(EventStates aEventStates) const michael@0: { michael@0: return (mStates & aEventStates.mStates) == aEventStates.mStates; michael@0: } michael@0: michael@0: // We only need that method for inDOMUtils::GetContentState. michael@0: // If inDOMUtils::GetContentState is removed, this method should be removed. michael@0: InternalType GetInternalValue() const { michael@0: return mStates; michael@0: } michael@0: michael@0: private: michael@0: InternalType mStates; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: /** michael@0: * The following macros are creating EventStates instance with different michael@0: * values depending of their meaning. michael@0: * Ideally, EventStates instance with values different than 0 should only be michael@0: * created that way. michael@0: */ michael@0: michael@0: // Helper to define a new EventStates macro. michael@0: #define NS_DEFINE_EVENT_STATE_MACRO(_val) \ michael@0: (mozilla::EventStates(mozilla::EventStates::InternalType(1) << _val)) michael@0: michael@0: // Mouse is down on content. michael@0: #define NS_EVENT_STATE_ACTIVE NS_DEFINE_EVENT_STATE_MACRO(0) michael@0: // Content has focus. michael@0: #define NS_EVENT_STATE_FOCUS NS_DEFINE_EVENT_STATE_MACRO(1) michael@0: // Mouse is hovering over content. michael@0: #define NS_EVENT_STATE_HOVER NS_DEFINE_EVENT_STATE_MACRO(2) michael@0: // Drag is hovering over content. michael@0: #define NS_EVENT_STATE_DRAGOVER NS_DEFINE_EVENT_STATE_MACRO(3) michael@0: // Content is URL's target (ref). michael@0: #define NS_EVENT_STATE_URLTARGET NS_DEFINE_EVENT_STATE_MACRO(4) michael@0: // Content is checked. michael@0: #define NS_EVENT_STATE_CHECKED NS_DEFINE_EVENT_STATE_MACRO(5) michael@0: // Content is enabled (and can be disabled). michael@0: #define NS_EVENT_STATE_ENABLED NS_DEFINE_EVENT_STATE_MACRO(6) michael@0: // Content is disabled. michael@0: #define NS_EVENT_STATE_DISABLED NS_DEFINE_EVENT_STATE_MACRO(7) michael@0: // Content is required. michael@0: #define NS_EVENT_STATE_REQUIRED NS_DEFINE_EVENT_STATE_MACRO(8) michael@0: // Content is optional (and can be required). michael@0: #define NS_EVENT_STATE_OPTIONAL NS_DEFINE_EVENT_STATE_MACRO(9) michael@0: // Link has been visited. michael@0: #define NS_EVENT_STATE_VISITED NS_DEFINE_EVENT_STATE_MACRO(10) michael@0: // Link hasn't been visited. michael@0: #define NS_EVENT_STATE_UNVISITED NS_DEFINE_EVENT_STATE_MACRO(11) michael@0: // Content is valid (and can be invalid). michael@0: #define NS_EVENT_STATE_VALID NS_DEFINE_EVENT_STATE_MACRO(12) michael@0: // Content is invalid. michael@0: #define NS_EVENT_STATE_INVALID NS_DEFINE_EVENT_STATE_MACRO(13) michael@0: // Content value is in-range (and can be out-of-range). michael@0: #define NS_EVENT_STATE_INRANGE NS_DEFINE_EVENT_STATE_MACRO(14) michael@0: // Content value is out-of-range. michael@0: #define NS_EVENT_STATE_OUTOFRANGE NS_DEFINE_EVENT_STATE_MACRO(15) michael@0: // These two are temporary (see bug 302188) michael@0: // Content is read-only. michael@0: #define NS_EVENT_STATE_MOZ_READONLY NS_DEFINE_EVENT_STATE_MACRO(16) michael@0: // Content is editable. michael@0: #define NS_EVENT_STATE_MOZ_READWRITE NS_DEFINE_EVENT_STATE_MACRO(17) michael@0: // Content is the default one (meaning depends of the context). michael@0: #define NS_EVENT_STATE_DEFAULT NS_DEFINE_EVENT_STATE_MACRO(18) michael@0: // Content could not be rendered (image/object/etc). michael@0: #define NS_EVENT_STATE_BROKEN NS_DEFINE_EVENT_STATE_MACRO(19) michael@0: // Content disabled by the user (images turned off, say). michael@0: #define NS_EVENT_STATE_USERDISABLED NS_DEFINE_EVENT_STATE_MACRO(20) michael@0: // Content suppressed by the user (ad blocking, etc). michael@0: #define NS_EVENT_STATE_SUPPRESSED NS_DEFINE_EVENT_STATE_MACRO(21) michael@0: // Content is still loading such that there is nothing to show the michael@0: // user (eg an image which hasn't started coming in yet). michael@0: #define NS_EVENT_STATE_LOADING NS_DEFINE_EVENT_STATE_MACRO(22) michael@0: // Content is of a type that gecko can't handle. michael@0: #define NS_EVENT_STATE_TYPE_UNSUPPORTED NS_DEFINE_EVENT_STATE_MACRO(23) michael@0: #define NS_EVENT_STATE_INCREMENT_SCRIPT_LEVEL NS_DEFINE_EVENT_STATE_MACRO(24) michael@0: // Handler for the content has been blocked. michael@0: #define NS_EVENT_STATE_HANDLER_BLOCKED NS_DEFINE_EVENT_STATE_MACRO(25) michael@0: // Handler for the content has been disabled. michael@0: #define NS_EVENT_STATE_HANDLER_DISABLED NS_DEFINE_EVENT_STATE_MACRO(26) michael@0: // Content is in the indeterminate state. michael@0: #define NS_EVENT_STATE_INDETERMINATE NS_DEFINE_EVENT_STATE_MACRO(27) michael@0: // Handler for the content has crashed michael@0: #define NS_EVENT_STATE_HANDLER_CRASHED NS_DEFINE_EVENT_STATE_MACRO(28) michael@0: // Content has focus and should show a ring. michael@0: #define NS_EVENT_STATE_FOCUSRING NS_DEFINE_EVENT_STATE_MACRO(29) michael@0: // Content is a submit control and the form isn't valid. michael@0: #define NS_EVENT_STATE_MOZ_SUBMITINVALID NS_DEFINE_EVENT_STATE_MACRO(30) michael@0: // UI friendly version of :invalid pseudo-class. michael@0: #define NS_EVENT_STATE_MOZ_UI_INVALID NS_DEFINE_EVENT_STATE_MACRO(31) michael@0: // UI friendly version of :valid pseudo-class. michael@0: #define NS_EVENT_STATE_MOZ_UI_VALID NS_DEFINE_EVENT_STATE_MACRO(32) michael@0: // Content is the full screen element, or a frame containing the michael@0: // current full-screen element. michael@0: #define NS_EVENT_STATE_FULL_SCREEN NS_DEFINE_EVENT_STATE_MACRO(33) michael@0: // Content is an ancestor of the DOM full-screen element. michael@0: #define NS_EVENT_STATE_FULL_SCREEN_ANCESTOR NS_DEFINE_EVENT_STATE_MACRO(34) michael@0: // Handler for click to play plugin michael@0: #define NS_EVENT_STATE_TYPE_CLICK_TO_PLAY NS_DEFINE_EVENT_STATE_MACRO(35) michael@0: // Content is in the optimum region. michael@0: #define NS_EVENT_STATE_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(36) michael@0: // Content is in the suboptimal region. michael@0: #define NS_EVENT_STATE_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(37) michael@0: // Content is in the sub-suboptimal region. michael@0: #define NS_EVENT_STATE_SUB_SUB_OPTIMUM NS_DEFINE_EVENT_STATE_MACRO(38) michael@0: // Handler for click to play plugin (vulnerable w/update) michael@0: #define NS_EVENT_STATE_VULNERABLE_UPDATABLE NS_DEFINE_EVENT_STATE_MACRO(39) michael@0: // Handler for click to play plugin (vulnerable w/no update) michael@0: #define NS_EVENT_STATE_VULNERABLE_NO_UPDATE NS_DEFINE_EVENT_STATE_MACRO(40) michael@0: // Platform does not support plugin content (some mobile platforms) michael@0: #define NS_EVENT_STATE_TYPE_UNSUPPORTED_PLATFORM NS_DEFINE_EVENT_STATE_MACRO(41) michael@0: // Element is ltr (for :dir pseudo-class) michael@0: #define NS_EVENT_STATE_LTR NS_DEFINE_EVENT_STATE_MACRO(42) michael@0: // Element is rtl (for :dir pseudo-class) michael@0: #define NS_EVENT_STATE_RTL NS_DEFINE_EVENT_STATE_MACRO(43) michael@0: // Handler for play preview plugin michael@0: #define NS_EVENT_STATE_TYPE_PLAY_PREVIEW NS_DEFINE_EVENT_STATE_MACRO(44) michael@0: // Element is highlighted (devtools inspector) michael@0: #define NS_EVENT_STATE_DEVTOOLS_HIGHLIGHTED NS_DEFINE_EVENT_STATE_MACRO(45) michael@0: michael@0: // Event state that is used for values that need to be parsed but do nothing. michael@0: #define NS_EVENT_STATE_IGNORE NS_DEFINE_EVENT_STATE_MACRO(63) michael@0: michael@0: /** michael@0: * NOTE: do not go over 63 without updating EventStates::InternalType! michael@0: */ michael@0: michael@0: #define DIRECTION_STATES (NS_EVENT_STATE_LTR | NS_EVENT_STATE_RTL) michael@0: michael@0: #define ESM_MANAGED_STATES (NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS | \ michael@0: NS_EVENT_STATE_HOVER | NS_EVENT_STATE_DRAGOVER | \ michael@0: NS_EVENT_STATE_URLTARGET | NS_EVENT_STATE_FOCUSRING | \ michael@0: NS_EVENT_STATE_FULL_SCREEN | NS_EVENT_STATE_FULL_SCREEN_ANCESTOR) michael@0: michael@0: #define INTRINSIC_STATES (~ESM_MANAGED_STATES) michael@0: michael@0: #endif // mozilla_EventStates_h_ michael@0: