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: #include "mozilla/BasicEvents.h" michael@0: #include "mozilla/ContentEvents.h" michael@0: #include "mozilla/InternalMutationEvent.h" michael@0: #include "mozilla/MiscEvents.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: #include "mozilla/TextEvents.h" michael@0: #include "mozilla/TouchEvents.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: /****************************************************************************** michael@0: * As*Event() implementation michael@0: ******************************************************************************/ michael@0: michael@0: #define NS_ROOT_EVENT_CLASS(aPrefix, aName) michael@0: #define NS_EVENT_CLASS(aPrefix, aName) \ michael@0: aPrefix##aName* \ michael@0: WidgetEvent::As##aName() \ michael@0: { \ michael@0: return nullptr; \ michael@0: } \ michael@0: \ michael@0: const aPrefix##aName* \ michael@0: WidgetEvent::As##aName() const \ michael@0: { \ michael@0: return const_cast(this)->As##aName(); \ michael@0: } michael@0: michael@0: #include "mozilla/EventClassList.h" michael@0: michael@0: #undef NS_EVENT_CLASS michael@0: #undef NS_ROOT_EVENT_CLASS michael@0: michael@0: /****************************************************************************** michael@0: * mozilla::WidgetEvent michael@0: * michael@0: * Event struct type checking methods. michael@0: ******************************************************************************/ michael@0: michael@0: bool michael@0: WidgetEvent::IsQueryContentEvent() const michael@0: { michael@0: return eventStructType == NS_QUERY_CONTENT_EVENT; michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsSelectionEvent() const michael@0: { michael@0: return eventStructType == NS_SELECTION_EVENT; michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsContentCommandEvent() const michael@0: { michael@0: return eventStructType == NS_CONTENT_COMMAND_EVENT; michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsNativeEventDelivererForPlugin() const michael@0: { michael@0: return eventStructType == NS_PLUGIN_EVENT; michael@0: } michael@0: michael@0: michael@0: /****************************************************************************** michael@0: * mozilla::WidgetEvent michael@0: * michael@0: * Event message checking methods. michael@0: ******************************************************************************/ michael@0: michael@0: bool michael@0: WidgetEvent::HasMouseEventMessage() const michael@0: { michael@0: switch (message) { michael@0: case NS_MOUSE_BUTTON_DOWN: michael@0: case NS_MOUSE_BUTTON_UP: michael@0: case NS_MOUSE_CLICK: michael@0: case NS_MOUSE_DOUBLECLICK: michael@0: case NS_MOUSE_ENTER: michael@0: case NS_MOUSE_EXIT: michael@0: case NS_MOUSE_ACTIVATE: michael@0: case NS_MOUSE_ENTER_SYNTH: michael@0: case NS_MOUSE_EXIT_SYNTH: michael@0: case NS_MOUSE_MOZHITTEST: michael@0: case NS_MOUSE_MOVE: michael@0: return true; michael@0: default: michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::HasDragEventMessage() const michael@0: { michael@0: switch (message) { michael@0: case NS_DRAGDROP_ENTER: michael@0: case NS_DRAGDROP_OVER: michael@0: case NS_DRAGDROP_EXIT: michael@0: case NS_DRAGDROP_DRAGDROP: michael@0: case NS_DRAGDROP_GESTURE: michael@0: case NS_DRAGDROP_DRAG: michael@0: case NS_DRAGDROP_END: michael@0: case NS_DRAGDROP_START: michael@0: case NS_DRAGDROP_DROP: michael@0: case NS_DRAGDROP_LEAVE_SYNTH: michael@0: return true; michael@0: default: michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::HasKeyEventMessage() const michael@0: { michael@0: switch (message) { michael@0: case NS_KEY_DOWN: michael@0: case NS_KEY_PRESS: michael@0: case NS_KEY_UP: michael@0: return true; michael@0: default: michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::HasIMEEventMessage() const michael@0: { michael@0: switch (message) { michael@0: case NS_TEXT_TEXT: michael@0: case NS_COMPOSITION_START: michael@0: case NS_COMPOSITION_END: michael@0: case NS_COMPOSITION_UPDATE: michael@0: return true; michael@0: default: michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::HasPluginActivationEventMessage() const michael@0: { michael@0: return message == NS_PLUGIN_ACTIVATE || michael@0: message == NS_PLUGIN_FOCUS; michael@0: } michael@0: michael@0: /****************************************************************************** michael@0: * mozilla::WidgetEvent michael@0: * michael@0: * Specific event checking methods. michael@0: ******************************************************************************/ michael@0: michael@0: bool michael@0: WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const michael@0: { michael@0: const WidgetPluginEvent* pluginEvent = AsPluginEvent(); michael@0: return pluginEvent && pluginEvent->retargetToFocusedDocument; michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const michael@0: { michael@0: const WidgetPluginEvent* pluginEvent = AsPluginEvent(); michael@0: return pluginEvent && !pluginEvent->retargetToFocusedDocument; michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsIMERelatedEvent() const michael@0: { michael@0: return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent(); michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsUsingCoordinates() const michael@0: { michael@0: const WidgetMouseEvent* mouseEvent = AsMouseEvent(); michael@0: if (mouseEvent) { michael@0: return !mouseEvent->IsContextMenuKeyEvent(); michael@0: } michael@0: return !HasKeyEventMessage() && !IsIMERelatedEvent() && michael@0: !HasPluginActivationEventMessage() && michael@0: !IsNativeEventDelivererForPlugin() && michael@0: !IsContentCommandEvent() && michael@0: message != NS_PLUGIN_RESOLUTION_CHANGED; michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsTargetedAtFocusedWindow() const michael@0: { michael@0: const WidgetMouseEvent* mouseEvent = AsMouseEvent(); michael@0: if (mouseEvent) { michael@0: return mouseEvent->IsContextMenuKeyEvent(); michael@0: } michael@0: return HasKeyEventMessage() || IsIMERelatedEvent() || michael@0: IsContentCommandEvent() || michael@0: IsRetargetedNativeEventDelivererForPlugin(); michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsTargetedAtFocusedContent() const michael@0: { michael@0: const WidgetMouseEvent* mouseEvent = AsMouseEvent(); michael@0: if (mouseEvent) { michael@0: return mouseEvent->IsContextMenuKeyEvent(); michael@0: } michael@0: return HasKeyEventMessage() || IsIMERelatedEvent() || michael@0: IsRetargetedNativeEventDelivererForPlugin(); michael@0: } michael@0: michael@0: bool michael@0: WidgetEvent::IsAllowedToDispatchDOMEvent() const michael@0: { michael@0: switch (eventStructType) { michael@0: case NS_MOUSE_EVENT: michael@0: case NS_POINTER_EVENT: michael@0: // We want synthesized mouse moves to cause mouseover and mouseout michael@0: // DOM events (EventStateManager::PreHandleEvent), but not mousemove michael@0: // DOM events. michael@0: // Synthesized button up events also do not cause DOM events because they michael@0: // do not have a reliable refPoint. michael@0: return AsMouseEvent()->reason == WidgetMouseEvent::eReal; michael@0: michael@0: case NS_WHEEL_EVENT: { michael@0: // wheel event whose all delta values are zero by user pref applied, it michael@0: // shouldn't cause a DOM event. michael@0: const WidgetWheelEvent* wheelEvent = AsWheelEvent(); michael@0: return wheelEvent->deltaX != 0.0 || wheelEvent->deltaY != 0.0 || michael@0: wheelEvent->deltaZ != 0.0; michael@0: } michael@0: michael@0: // Following events are handled in EventStateManager, so, we don't need to michael@0: // dispatch DOM event for them into the DOM tree. michael@0: case NS_QUERY_CONTENT_EVENT: michael@0: case NS_SELECTION_EVENT: michael@0: case NS_CONTENT_COMMAND_EVENT: michael@0: return false; michael@0: michael@0: default: michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: /****************************************************************************** michael@0: * mozilla::WidgetKeyboardEvent (TextEvents.h) michael@0: ******************************************************************************/ michael@0: michael@0: /*static*/ void michael@0: WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex, michael@0: nsAString& aKeyName) michael@0: { michael@0: // The expected way to implement this function would be to use a michael@0: // switch statement. By using a table-based implementation, below, we michael@0: // ensure that this function executes in constant time in cases where michael@0: // compilers wouldn't be able to convert the switch statement to a michael@0: // jump table. This table-based implementation also minimizes the michael@0: // space required by the code and data. michael@0: #define KEY_STR_NUM_INTERNAL(line) key##line michael@0: #define KEY_STR_NUM(line) KEY_STR_NUM_INTERNAL(line) michael@0: michael@0: // Catch non-ASCII DOM key names in our key name list. michael@0: #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) \ michael@0: static_assert(sizeof(aDOMKeyName) == MOZ_ARRAY_LENGTH(aDOMKeyName), \ michael@0: "Invalid DOM key name"); michael@0: #include "mozilla/KeyNameList.h" michael@0: #undef NS_DEFINE_KEYNAME michael@0: michael@0: struct KeyNameTable michael@0: { michael@0: #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) \ michael@0: char16_t KEY_STR_NUM(__LINE__)[sizeof(aDOMKeyName)]; michael@0: #include "mozilla/KeyNameList.h" michael@0: #undef NS_DEFINE_KEYNAME michael@0: }; michael@0: michael@0: static const KeyNameTable kKeyNameTable = { michael@0: #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) MOZ_UTF16(aDOMKeyName), michael@0: #include "mozilla/KeyNameList.h" michael@0: #undef NS_DEFINE_KEYNAME michael@0: }; michael@0: michael@0: static const uint16_t kKeyNameOffsets[] = { michael@0: #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) \ michael@0: offsetof(struct KeyNameTable, KEY_STR_NUM(__LINE__)) / sizeof(char16_t), michael@0: #include "mozilla/KeyNameList.h" michael@0: #undef NS_DEFINE_KEYNAME michael@0: // Include this entry so we can compute lengths easily. michael@0: sizeof(kKeyNameTable) michael@0: }; michael@0: michael@0: // Use the sizeof trick rather than MOZ_ARRAY_LENGTH to avoid problems michael@0: // with constexpr functions called inside static_assert with some michael@0: // compilers. michael@0: static_assert(KEY_NAME_INDEX_USE_STRING == michael@0: (sizeof(kKeyNameOffsets)/sizeof(kKeyNameOffsets[0])) - 1, michael@0: "Invalid enumeration values!"); michael@0: michael@0: if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) { michael@0: aKeyName.Truncate(); michael@0: return; michael@0: } michael@0: michael@0: uint16_t offset = kKeyNameOffsets[aKeyNameIndex]; michael@0: uint16_t nextOffset = kKeyNameOffsets[aKeyNameIndex + 1]; michael@0: const char16_t* table = reinterpret_cast(&kKeyNameTable); michael@0: michael@0: // Subtract off 1 for the null terminator. michael@0: aKeyName.Assign(table + offset, nextOffset - offset - 1); michael@0: michael@0: #undef KEY_STR_NUM michael@0: #undef KEY_STR_NUM_INTERNAL michael@0: } michael@0: michael@0: /* static */ const char* michael@0: WidgetKeyboardEvent::GetCommandStr(Command aCommand) michael@0: { michael@0: #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr michael@0: static const char* kCommands[] = { michael@0: "" // CommandDoNothing michael@0: #include "mozilla/CommandList.h" michael@0: }; michael@0: #undef NS_DEFINE_COMMAND michael@0: michael@0: MOZ_RELEASE_ASSERT(static_cast(aCommand) < ArrayLength(kCommands), michael@0: "Illegal command enumeration value"); michael@0: return kCommands[aCommand]; michael@0: } michael@0: michael@0: } // namespace mozilla