Bug 1643246 - Don't use attribute selectors for determining if a select is a drop...
[gecko.git] / widget / WidgetEventImpl.cpp
blobc00850842c0ab5d5fff857a7a5cd3f2335120e63
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/BasicEvents.h"
7 #include "mozilla/ContentEvents.h"
8 #include "mozilla/EventStateManager.h"
9 #include "mozilla/InternalMutationEvent.h"
10 #include "mozilla/MiscEvents.h"
11 #include "mozilla/MouseEvents.h"
12 #include "mozilla/Preferences.h"
13 #include "mozilla/StaticPrefs_mousewheel.h"
14 #include "mozilla/StaticPrefs_ui.h"
15 #include "mozilla/TextEvents.h"
16 #include "mozilla/TouchEvents.h"
17 #include "mozilla/dom/KeyboardEventBinding.h"
18 #include "nsCommandParams.h"
19 #include "nsContentUtils.h"
20 #include "nsIContent.h"
21 #include "nsIDragSession.h"
22 #include "nsPrintfCString.h"
24 #if defined(XP_WIN)
25 # include "npapi.h"
26 #endif
28 namespace mozilla {
30 /******************************************************************************
31 * Global helper methods
32 ******************************************************************************/
34 const char* ToChar(EventMessage aEventMessage) {
35 switch (aEventMessage) {
36 #define NS_EVENT_MESSAGE(aMessage) \
37 case aMessage: \
38 return #aMessage;
40 #include "mozilla/EventMessageList.h"
42 #undef NS_EVENT_MESSAGE
43 default:
44 return "illegal event message";
48 const char* ToChar(EventClassID aEventClassID) {
49 switch (aEventClassID) {
50 #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
51 case eBasic##aName##Class: \
52 return "eBasic" #aName "Class";
54 #define NS_EVENT_CLASS(aPrefix, aName) \
55 case e##aName##Class: \
56 return "e" #aName "Class";
58 #include "mozilla/EventClassList.h"
60 #undef NS_EVENT_CLASS
61 #undef NS_ROOT_EVENT_CLASS
62 default:
63 return "illegal event class ID";
67 const nsCString ToString(KeyNameIndex aKeyNameIndex) {
68 if (aKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
69 return "USE_STRING"_ns;
71 nsAutoString keyName;
72 WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex, keyName);
73 return NS_ConvertUTF16toUTF8(keyName);
76 const nsCString ToString(CodeNameIndex aCodeNameIndex) {
77 if (aCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
78 return "USE_STRING"_ns;
80 nsAutoString codeName;
81 WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex, codeName);
82 return NS_ConvertUTF16toUTF8(codeName);
85 const char* ToChar(Command aCommand) {
86 if (aCommand == Command::DoNothing) {
87 return "CommandDoNothing";
90 switch (aCommand) {
91 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
92 case Command::aName: \
93 return "Command::" #aName;
94 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) \
95 case Command::aName: \
96 return "Command::" #aName;
97 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) \
98 case Command::aName: \
99 return "Command::" #aName;
101 #include "mozilla/CommandList.h"
103 #undef NS_DEFINE_COMMAND
104 #undef NS_DEFINE_COMMAND_WITH_PARAM
105 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
107 default:
108 return "illegal command value";
112 const nsCString GetDOMKeyCodeName(uint32_t aKeyCode) {
113 switch (aKeyCode) {
114 #define NS_DISALLOW_SAME_KEYCODE
115 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
116 case aDOMKeyCode: \
117 return nsLiteralCString(#aDOMKeyName);
119 #include "mozilla/VirtualKeyCodeList.h"
121 #undef NS_DEFINE_VK
122 #undef NS_DISALLOW_SAME_KEYCODE
124 default:
125 return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode);
129 bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeType) {
130 switch (static_cast<TextRangeType>(aRawTextRangeType)) {
131 case TextRangeType::eUninitialized:
132 case TextRangeType::eCaret:
133 case TextRangeType::eRawClause:
134 case TextRangeType::eSelectedRawClause:
135 case TextRangeType::eConvertedClause:
136 case TextRangeType::eSelectedClause:
137 return true;
138 default:
139 return false;
143 RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType) {
144 return static_cast<RawTextRangeType>(aTextRangeType);
147 TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType) {
148 MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType));
149 return static_cast<TextRangeType>(aRawTextRangeType);
152 const char* ToChar(TextRangeType aTextRangeType) {
153 switch (aTextRangeType) {
154 case TextRangeType::eUninitialized:
155 return "TextRangeType::eUninitialized";
156 case TextRangeType::eCaret:
157 return "TextRangeType::eCaret";
158 case TextRangeType::eRawClause:
159 return "TextRangeType::eRawClause";
160 case TextRangeType::eSelectedRawClause:
161 return "TextRangeType::eSelectedRawClause";
162 case TextRangeType::eConvertedClause:
163 return "TextRangeType::eConvertedClause";
164 case TextRangeType::eSelectedClause:
165 return "TextRangeType::eSelectedClause";
166 default:
167 return "Invalid TextRangeType";
171 SelectionType ToSelectionType(TextRangeType aTextRangeType) {
172 switch (aTextRangeType) {
173 case TextRangeType::eRawClause:
174 return SelectionType::eIMERawClause;
175 case TextRangeType::eSelectedRawClause:
176 return SelectionType::eIMESelectedRawClause;
177 case TextRangeType::eConvertedClause:
178 return SelectionType::eIMEConvertedClause;
179 case TextRangeType::eSelectedClause:
180 return SelectionType::eIMESelectedClause;
181 default:
182 MOZ_CRASH("TextRangeType is invalid");
183 return SelectionType::eNormal;
187 /******************************************************************************
188 * non class method implementation
189 ******************************************************************************/
191 static nsDataHashtable<nsDepCharHashKey, Command>* sCommandHashtable = nullptr;
193 Command GetInternalCommand(const char* aCommandName,
194 const nsCommandParams* aCommandParams) {
195 if (!aCommandName) {
196 return Command::DoNothing;
199 // Special cases for "cmd_align". It's mapped to multiple internal commands
200 // with additional param. Therefore, we cannot handle it with the hashtable.
201 if (!strcmp(aCommandName, "cmd_align")) {
202 if (!aCommandParams) {
203 // Note that if this is called by EditorCommand::IsCommandEnabled(),
204 // it cannot set aCommandParams. So, don't warn in this case even though
205 // this is illegal case for DoCommandParams().
206 return Command::FormatJustify;
208 nsAutoCString cValue;
209 nsresult rv = aCommandParams->GetCString("state_attribute", cValue);
210 if (NS_FAILED(rv)) {
211 nsString value; // Avoid copying the string buffer with using nsString.
212 rv = aCommandParams->GetString("state_attribute", value);
213 if (NS_FAILED(rv)) {
214 return Command::FormatJustifyNone;
216 cValue = NS_ConvertUTF16toUTF8(value);
218 if (cValue.LowerCaseEqualsASCII("left")) {
219 return Command::FormatJustifyLeft;
221 if (cValue.LowerCaseEqualsASCII("right")) {
222 return Command::FormatJustifyRight;
224 if (cValue.LowerCaseEqualsASCII("center")) {
225 return Command::FormatJustifyCenter;
227 if (cValue.LowerCaseEqualsASCII("justify")) {
228 return Command::FormatJustifyFull;
230 if (cValue.IsEmpty()) {
231 return Command::FormatJustifyNone;
233 return Command::DoNothing;
236 if (!sCommandHashtable) {
237 sCommandHashtable = new nsDataHashtable<nsDepCharHashKey, Command>();
238 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
239 sCommandHashtable->Put(#aCommandStr, Command::aName);
241 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam)
243 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName)
245 #include "mozilla/CommandList.h"
247 #undef NS_DEFINE_COMMAND
248 #undef NS_DEFINE_COMMAND_WITH_PARAM
249 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
251 Command command = Command::DoNothing;
252 if (!sCommandHashtable->Get(aCommandName, &command)) {
253 return Command::DoNothing;
255 return command;
258 /******************************************************************************
259 * As*Event() implementation
260 ******************************************************************************/
262 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
263 #define NS_EVENT_CLASS(aPrefix, aName) \
264 aPrefix##aName* WidgetEvent::As##aName() { return nullptr; } \
266 const aPrefix##aName* WidgetEvent::As##aName() const { \
267 return const_cast<WidgetEvent*>(this)->As##aName(); \
270 #include "mozilla/EventClassList.h"
272 #undef NS_EVENT_CLASS
273 #undef NS_ROOT_EVENT_CLASS
275 /******************************************************************************
276 * mozilla::WidgetEvent
278 * Event struct type checking methods.
279 ******************************************************************************/
281 bool WidgetEvent::IsQueryContentEvent() const {
282 return mClass == eQueryContentEventClass;
285 bool WidgetEvent::IsSelectionEvent() const {
286 return mClass == eSelectionEventClass;
289 bool WidgetEvent::IsContentCommandEvent() const {
290 return mClass == eContentCommandEventClass;
293 bool WidgetEvent::IsNativeEventDelivererForPlugin() const {
294 return mClass == ePluginEventClass;
297 /******************************************************************************
298 * mozilla::WidgetEvent
300 * Event message checking methods.
301 ******************************************************************************/
303 bool WidgetEvent::HasMouseEventMessage() const {
304 switch (mMessage) {
305 case eMouseDown:
306 case eMouseUp:
307 case eMouseClick:
308 case eMouseDoubleClick:
309 case eMouseAuxClick:
310 case eMouseEnterIntoWidget:
311 case eMouseExitFromWidget:
312 case eMouseActivate:
313 case eMouseOver:
314 case eMouseOut:
315 case eMouseHitTest:
316 case eMouseMove:
317 return true;
318 default:
319 return false;
323 bool WidgetEvent::HasDragEventMessage() const {
324 switch (mMessage) {
325 case eDragEnter:
326 case eDragOver:
327 case eDragExit:
328 case eDrag:
329 case eDragEnd:
330 case eDragStart:
331 case eDrop:
332 case eDragLeave:
333 return true;
334 default:
335 return false;
339 /* static */
340 bool WidgetEvent::IsKeyEventMessage(EventMessage aMessage) {
341 switch (aMessage) {
342 case eKeyDown:
343 case eKeyPress:
344 case eKeyUp:
345 case eKeyDownOnPlugin:
346 case eKeyUpOnPlugin:
347 case eAccessKeyNotFound:
348 return true;
349 default:
350 return false;
354 bool WidgetEvent::HasIMEEventMessage() const {
355 switch (mMessage) {
356 case eCompositionStart:
357 case eCompositionEnd:
358 case eCompositionUpdate:
359 case eCompositionChange:
360 case eCompositionCommitAsIs:
361 case eCompositionCommit:
362 return true;
363 default:
364 return false;
368 bool WidgetEvent::HasPluginActivationEventMessage() const {
369 return mMessage == ePluginActivate || mMessage == ePluginFocus;
372 /******************************************************************************
373 * mozilla::WidgetEvent
375 * Specific event checking methods.
376 ******************************************************************************/
378 bool WidgetEvent::CanBeSentToRemoteProcess() const {
379 // If this event is explicitly marked as shouldn't be sent to remote process,
380 // just return false.
381 if (IsCrossProcessForwardingStopped()) {
382 return false;
385 if (mClass == eKeyboardEventClass || mClass == eWheelEventClass) {
386 return true;
389 switch (mMessage) {
390 case eMouseDown:
391 case eMouseUp:
392 case eMouseMove:
393 case eContextMenu:
394 case eMouseEnterIntoWidget:
395 case eMouseExitFromWidget:
396 case eMouseTouchDrag:
397 case eTouchStart:
398 case eTouchMove:
399 case eTouchEnd:
400 case eTouchCancel:
401 case eDragOver:
402 case eDragExit:
403 case eDrop:
404 return true;
405 #if defined(XP_WIN)
406 case ePluginInputEvent: {
407 auto evt = static_cast<const NPEvent*>(AsPluginEvent()->mPluginEvent);
408 return evt && evt->event == WM_SETTINGCHANGE &&
409 (evt->wParam == SPI_SETWHEELSCROLLLINES ||
410 evt->wParam == SPI_SETWHEELSCROLLCHARS);
412 #endif
413 default:
414 return false;
418 bool WidgetEvent::WillBeSentToRemoteProcess() const {
419 // This event won't be posted to remote process if it's already explicitly
420 // stopped.
421 if (IsCrossProcessForwardingStopped()) {
422 return false;
425 // When mOriginalTarget is nullptr, this method shouldn't be used.
426 if (NS_WARN_IF(!mOriginalTarget)) {
427 return false;
430 nsCOMPtr<nsIContent> originalTarget = do_QueryInterface(mOriginalTarget);
431 return EventStateManager::IsTopLevelRemoteTarget(originalTarget);
434 bool WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const {
435 const WidgetPluginEvent* pluginEvent = AsPluginEvent();
436 return pluginEvent && pluginEvent->mRetargetToFocusedDocument;
439 bool WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const {
440 const WidgetPluginEvent* pluginEvent = AsPluginEvent();
441 return pluginEvent && !pluginEvent->mRetargetToFocusedDocument;
444 bool WidgetEvent::IsIMERelatedEvent() const {
445 return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
448 bool WidgetEvent::IsUsingCoordinates() const {
449 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
450 if (mouseEvent) {
451 return !mouseEvent->IsContextMenuKeyEvent();
453 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
454 !HasPluginActivationEventMessage() &&
455 !IsNativeEventDelivererForPlugin() && !IsContentCommandEvent();
458 bool WidgetEvent::IsTargetedAtFocusedWindow() const {
459 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
460 if (mouseEvent) {
461 return mouseEvent->IsContextMenuKeyEvent();
463 return HasKeyEventMessage() || IsIMERelatedEvent() ||
464 IsContentCommandEvent() || IsRetargetedNativeEventDelivererForPlugin();
467 bool WidgetEvent::IsTargetedAtFocusedContent() const {
468 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
469 if (mouseEvent) {
470 return mouseEvent->IsContextMenuKeyEvent();
472 return HasKeyEventMessage() || IsIMERelatedEvent() ||
473 IsRetargetedNativeEventDelivererForPlugin();
476 bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
477 switch (mClass) {
478 case eMouseEventClass:
479 if (mMessage == eMouseTouchDrag) {
480 return false;
482 [[fallthrough]];
483 case ePointerEventClass:
484 // We want synthesized mouse moves to cause mouseover and mouseout
485 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
486 // DOM events.
487 // Synthesized button up events also do not cause DOM events because they
488 // do not have a reliable mRefPoint.
489 return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
491 case eWheelEventClass: {
492 // wheel event whose all delta values are zero by user pref applied, it
493 // shouldn't cause a DOM event.
494 const WidgetWheelEvent* wheelEvent = AsWheelEvent();
495 return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
496 wheelEvent->mDeltaZ != 0.0;
498 case eTouchEventClass:
499 return mMessage != eTouchPointerCancel;
500 // Following events are handled in EventStateManager, so, we don't need to
501 // dispatch DOM event for them into the DOM tree.
502 case eQueryContentEventClass:
503 case eSelectionEventClass:
504 case eContentCommandEventClass:
505 return false;
507 default:
508 return true;
512 bool WidgetEvent::IsAllowedToDispatchInSystemGroup() const {
513 // We don't expect to implement default behaviors with pointer events because
514 // if we do, prevent default on mouse events can't prevent default behaviors
515 // anymore.
516 return mClass != ePointerEventClass;
519 bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
520 if (!nsContentUtils::ShouldResistFingerprinting()) {
521 return false;
524 switch (mClass) {
525 case eKeyboardEventClass: {
526 const WidgetKeyboardEvent* keyboardEvent = AsKeyboardEvent();
528 return (keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Alt ||
529 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Shift ||
530 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Control ||
531 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_AltGraph);
533 case ePointerEventClass: {
534 const WidgetPointerEvent* pointerEvent = AsPointerEvent();
536 // We suppress the pointer events if it is not primary for fingerprinting
537 // resistance. It is because of that we want to spoof any pointer event
538 // into a mouse pointer event and the mouse pointer event only has
539 // isPrimary as true.
540 return !pointerEvent->mIsPrimary;
542 default:
543 return false;
547 /******************************************************************************
548 * mozilla::WidgetEvent
550 * Misc methods.
551 ******************************************************************************/
553 static dom::EventTarget* GetTargetForDOMEvent(dom::EventTarget* aTarget) {
554 return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
557 dom::EventTarget* WidgetEvent::GetDOMEventTarget() const {
558 return GetTargetForDOMEvent(mTarget);
561 dom::EventTarget* WidgetEvent::GetCurrentDOMEventTarget() const {
562 return GetTargetForDOMEvent(mCurrentTarget);
565 dom::EventTarget* WidgetEvent::GetOriginalDOMEventTarget() const {
566 if (mOriginalTarget) {
567 return GetTargetForDOMEvent(mOriginalTarget);
569 return GetDOMEventTarget();
572 void WidgetEvent::PreventDefault(bool aCalledByDefaultHandler,
573 nsIPrincipal* aPrincipal) {
574 if (mMessage == ePointerDown) {
575 if (aCalledByDefaultHandler) {
576 // Shouldn't prevent default on pointerdown by default handlers to stop
577 // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages
578 // in debug builds.
579 MOZ_ASSERT(false);
580 return;
582 if (aPrincipal) {
583 nsAutoString addonId;
584 Unused << NS_WARN_IF(NS_FAILED(aPrincipal->GetAddonId(addonId)));
585 if (!addonId.IsEmpty()) {
586 // Ignore the case that it's called by a web extension.
587 return;
591 mFlags.PreventDefault(aCalledByDefaultHandler);
594 bool WidgetEvent::IsUserAction() const {
595 if (!IsTrusted()) {
596 return false;
598 // FYI: eMouseScrollEventClass and ePointerEventClass represent
599 // user action but they are synthesized events.
600 switch (mClass) {
601 case eKeyboardEventClass:
602 case eCompositionEventClass:
603 case eMouseScrollEventClass:
604 case eWheelEventClass:
605 case eGestureNotifyEventClass:
606 case eSimpleGestureEventClass:
607 case eTouchEventClass:
608 case eCommandEventClass:
609 case eContentCommandEventClass:
610 case ePluginEventClass:
611 return true;
612 case eMouseEventClass:
613 case eDragEventClass:
614 case ePointerEventClass:
615 return AsMouseEvent()->IsReal();
616 default:
617 return false;
621 /******************************************************************************
622 * mozilla::WidgetInputEvent
623 ******************************************************************************/
625 /* static */
626 Modifier WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName) {
627 if (aDOMKeyName.EqualsLiteral("Accel")) {
628 return AccelModifier();
630 KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName);
631 return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex);
634 /* static */
635 Modifier WidgetInputEvent::AccelModifier() {
636 static Modifier sAccelModifier = MODIFIER_NONE;
637 if (sAccelModifier == MODIFIER_NONE) {
638 switch (Preferences::GetInt("ui.key.accelKey", 0)) {
639 case dom::KeyboardEvent_Binding::DOM_VK_META:
640 sAccelModifier = MODIFIER_META;
641 break;
642 case dom::KeyboardEvent_Binding::DOM_VK_WIN:
643 sAccelModifier = MODIFIER_OS;
644 break;
645 case dom::KeyboardEvent_Binding::DOM_VK_ALT:
646 sAccelModifier = MODIFIER_ALT;
647 break;
648 case dom::KeyboardEvent_Binding::DOM_VK_CONTROL:
649 sAccelModifier = MODIFIER_CONTROL;
650 break;
651 default:
652 #ifdef XP_MACOSX
653 sAccelModifier = MODIFIER_META;
654 #else
655 sAccelModifier = MODIFIER_CONTROL;
656 #endif
657 break;
660 return sAccelModifier;
663 /******************************************************************************
664 * mozilla::WidgetMouseEvent (MouseEvents.h)
665 ******************************************************************************/
667 /* static */
668 bool WidgetMouseEvent::IsMiddleClickPasteEnabled() {
669 return Preferences::GetBool("middlemouse.paste", false);
672 /******************************************************************************
673 * mozilla::WidgetDragEvent (MouseEvents.h)
674 ******************************************************************************/
676 void WidgetDragEvent::InitDropEffectForTests() {
677 MOZ_ASSERT(mFlags.mIsSynthesizedForTests);
679 nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
680 if (NS_WARN_IF(!session)) {
681 return;
684 uint32_t effectAllowed = session->GetEffectAllowedForTests();
685 uint32_t desiredDropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
686 #ifdef XP_MACOSX
687 if (IsAlt()) {
688 desiredDropEffect = IsMeta() ? nsIDragService::DRAGDROP_ACTION_LINK
689 : nsIDragService::DRAGDROP_ACTION_COPY;
691 #else
692 // On Linux, we know user's intention from API, but we should use
693 // same modifiers as Windows for tests because GNOME on Ubuntu use
694 // them and that makes each test simpler.
695 if (IsControl()) {
696 desiredDropEffect = IsShift() ? nsIDragService::DRAGDROP_ACTION_LINK
697 : nsIDragService::DRAGDROP_ACTION_COPY;
698 } else if (IsShift()) {
699 desiredDropEffect = nsIDragService::DRAGDROP_ACTION_MOVE;
701 #endif // #ifdef XP_MACOSX #else
702 // First, use modifier state for preferring action which is explicitly
703 // specified by the synthesizer.
704 if (!(desiredDropEffect &= effectAllowed)) {
705 // Otherwise, use an action which is allowed at starting the session.
706 desiredDropEffect = effectAllowed;
708 if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_MOVE) {
709 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE);
710 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_COPY) {
711 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY);
712 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_LINK) {
713 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK);
714 } else {
715 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_NONE);
719 /******************************************************************************
720 * mozilla::WidgetWheelEvent (MouseEvents.h)
721 ******************************************************************************/
723 /* static */
724 double WidgetWheelEvent::ComputeOverriddenDelta(double aDelta,
725 bool aIsForVertical) {
726 if (!StaticPrefs::
727 mousewheel_system_scroll_override_on_root_content_enabled()) {
728 return aDelta;
730 int32_t intFactor =
731 aIsForVertical
732 ? StaticPrefs::
733 mousewheel_system_scroll_override_on_root_content_vertical_factor()
734 : StaticPrefs::
735 mousewheel_system_scroll_override_on_root_content_horizontal_factor();
736 // Making the scroll speed slower doesn't make sense. So, ignore odd factor
737 // which is less than 1.0.
738 if (intFactor <= 100) {
739 return aDelta;
741 double factor = static_cast<double>(intFactor) / 100;
742 return aDelta * factor;
745 double WidgetWheelEvent::OverriddenDeltaX() const {
746 if (!mAllowToOverrideSystemScrollSpeed) {
747 return mDeltaX;
749 return ComputeOverriddenDelta(mDeltaX, false);
752 double WidgetWheelEvent::OverriddenDeltaY() const {
753 if (!mAllowToOverrideSystemScrollSpeed) {
754 return mDeltaY;
756 return ComputeOverriddenDelta(mDeltaY, true);
759 /******************************************************************************
760 * mozilla::WidgetKeyboardEvent (TextEvents.h)
761 ******************************************************************************/
763 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
764 const char16_t* const WidgetKeyboardEvent::kKeyNames[] = {
765 #include "mozilla/KeyNameList.h"
767 #undef NS_DEFINE_KEYNAME
769 #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
770 (u"" aDOMCodeName),
771 const char16_t* const WidgetKeyboardEvent::kCodeNames[] = {
772 #include "mozilla/PhysicalKeyCodeNameList.h"
774 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
776 WidgetKeyboardEvent::KeyNameIndexHashtable*
777 WidgetKeyboardEvent::sKeyNameIndexHashtable = nullptr;
778 WidgetKeyboardEvent::CodeNameIndexHashtable*
779 WidgetKeyboardEvent::sCodeNameIndexHashtable = nullptr;
781 void WidgetKeyboardEvent::InitAllEditCommands() {
782 // If the event was created without widget, e.g., created event in chrome
783 // script, this shouldn't execute native key bindings.
784 if (NS_WARN_IF(!mWidget)) {
785 return;
788 // This event should be trusted event here and we shouldn't expose native
789 // key binding information to web contents with untrusted events.
790 if (NS_WARN_IF(!IsTrusted())) {
791 return;
794 MOZ_ASSERT(
795 XRE_IsParentProcess(),
796 "It's too expensive to retrieve all edit commands from remote process");
797 MOZ_ASSERT(!AreAllEditCommandsInitialized(),
798 "Shouldn't be called two or more times");
800 DebugOnly<bool> okIgnored =
801 InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor);
802 NS_WARNING_ASSERTION(
803 okIgnored,
804 "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor) "
805 "failed, but ignored");
806 okIgnored =
807 InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor);
808 NS_WARNING_ASSERTION(
809 okIgnored,
810 "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor) "
811 "failed, but ignored");
812 okIgnored =
813 InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor);
814 NS_WARNING_ASSERTION(
815 okIgnored,
816 "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor) "
817 "failed, but ignored");
820 bool WidgetKeyboardEvent::InitEditCommandsFor(
821 nsIWidget::NativeKeyBindingsType aType) {
822 if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
823 return false;
826 bool& initialized = IsEditCommandsInitializedRef(aType);
827 if (initialized) {
828 return true;
830 nsTArray<CommandInt>& commands = EditCommandsRef(aType);
831 initialized = mWidget->GetEditCommands(aType, *this, commands);
832 return initialized;
835 bool WidgetKeyboardEvent::ExecuteEditCommands(
836 nsIWidget::NativeKeyBindingsType aType, DoCommandCallback aCallback,
837 void* aCallbackData) {
838 // If the event was created without widget, e.g., created event in chrome
839 // script, this shouldn't execute native key bindings.
840 if (NS_WARN_IF(!mWidget)) {
841 return false;
844 // This event should be trusted event here and we shouldn't expose native
845 // key binding information to web contents with untrusted events.
846 if (NS_WARN_IF(!IsTrusted())) {
847 return false;
850 if (NS_WARN_IF(!InitEditCommandsFor(aType))) {
851 return false;
854 const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
855 if (commands.IsEmpty()) {
856 return false;
859 for (CommandInt command : commands) {
860 aCallback(static_cast<Command>(command), aCallbackData);
862 return true;
865 bool WidgetKeyboardEvent::ShouldCauseKeypressEvents() const {
866 // Currently, we don't dispatch keypress events of modifier keys and
867 // dead keys.
868 switch (mKeyNameIndex) {
869 case KEY_NAME_INDEX_Alt:
870 case KEY_NAME_INDEX_AltGraph:
871 case KEY_NAME_INDEX_CapsLock:
872 case KEY_NAME_INDEX_Control:
873 case KEY_NAME_INDEX_Fn:
874 case KEY_NAME_INDEX_FnLock:
875 // case KEY_NAME_INDEX_Hyper:
876 case KEY_NAME_INDEX_Meta:
877 case KEY_NAME_INDEX_NumLock:
878 case KEY_NAME_INDEX_OS:
879 case KEY_NAME_INDEX_ScrollLock:
880 case KEY_NAME_INDEX_Shift:
881 // case KEY_NAME_INDEX_Super:
882 case KEY_NAME_INDEX_Symbol:
883 case KEY_NAME_INDEX_SymbolLock:
884 case KEY_NAME_INDEX_Dead:
885 return false;
886 default:
887 return true;
891 static bool HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates) {
892 for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
893 uint32_t ch = aCandidates[i].mCharCode;
894 if (ch >= '0' && ch <= '9') return true;
896 return false;
899 static bool CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2) {
900 return aChar1 == aChar2 || (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
901 ToLowerCase(static_cast<char16_t>(aChar1)) ==
902 ToLowerCase(static_cast<char16_t>(aChar2)));
905 static bool IsCaseChangeableChar(uint32_t aChar) {
906 return IS_IN_BMP(aChar) && ToLowerCase(static_cast<char16_t>(aChar)) !=
907 ToUpperCase(static_cast<char16_t>(aChar));
910 void WidgetKeyboardEvent::GetShortcutKeyCandidates(
911 ShortcutKeyCandidateArray& aCandidates) const {
912 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
914 // ShortcutKeyCandidate::mCharCode is a candidate charCode.
915 // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
916 // execute a command with/without shift key state. If this is TRUE, the
917 // shifted key state should be ignored. Otherwise, don't ignore the state.
918 // the priority of the charCodes are (shift key is not pressed):
919 // 0: PseudoCharCode()/false,
920 // 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
921 // the priority of the charCodes are (shift key is pressed):
922 // 0: PseudoCharCode()/false,
923 // 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
924 // 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
925 uint32_t pseudoCharCode = PseudoCharCode();
926 if (pseudoCharCode) {
927 ShortcutKeyCandidate key(pseudoCharCode, false);
928 aCandidates.AppendElement(key);
931 uint32_t len = mAlternativeCharCodes.Length();
932 if (!IsShift()) {
933 for (uint32_t i = 0; i < len; ++i) {
934 uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
935 if (!ch || ch == pseudoCharCode) {
936 continue;
938 ShortcutKeyCandidate key(ch, false);
939 aCandidates.AppendElement(key);
941 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
942 // this keyboard layout is AZERTY or similar layout, probably.
943 // In this case, Accel+[0-9] should be accessible without shift key.
944 // However, the priority should be lowest.
945 if (!HasASCIIDigit(aCandidates)) {
946 for (uint32_t i = 0; i < len; ++i) {
947 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
948 if (ch >= '0' && ch <= '9') {
949 ShortcutKeyCandidate key(ch, false);
950 aCandidates.AppendElement(key);
951 break;
955 } else {
956 for (uint32_t i = 0; i < len; ++i) {
957 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
958 if (!ch) {
959 continue;
962 if (ch != pseudoCharCode) {
963 ShortcutKeyCandidate key(ch, false);
964 aCandidates.AppendElement(key);
967 // If the char is an alphabet, the shift key state should not be
968 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
970 // And checking the charCode is same as unshiftedCharCode too.
971 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
972 uint32_t unshiftCh = mAlternativeCharCodes[i].mUnshiftedCharCode;
973 if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
974 continue;
977 // On the Hebrew keyboard layout on Windows, the unshifted char is a
978 // localized character but the shifted char is a Latin alphabet,
979 // then, we should not execute without the shift state. See bug 433192.
980 if (IsCaseChangeableChar(ch)) {
981 continue;
984 // Setting the alternative charCode candidates for retry without shift
985 // key state only when the shift key is pressed.
986 ShortcutKeyCandidate key(ch, true);
987 aCandidates.AppendElement(key);
991 // Special case for "Space" key. With some keyboard layouts, "Space" with
992 // or without Shift key causes non-ASCII space. For such keyboard layouts,
993 // we should guarantee that the key press works as an ASCII white space key
994 // press. However, if the space key is assigned to a function key, it
995 // shouldn't work as a space key.
996 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
997 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
998 ShortcutKeyCandidate spaceKey(' ', false);
999 aCandidates.AppendElement(spaceKey);
1003 void WidgetKeyboardEvent::GetAccessKeyCandidates(
1004 nsTArray<uint32_t>& aCandidates) const {
1005 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
1007 // return the lower cased charCode candidates for access keys.
1008 // the priority of the charCodes are:
1009 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
1010 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
1011 uint32_t pseudoCharCode = PseudoCharCode();
1012 if (pseudoCharCode) {
1013 uint32_t ch = pseudoCharCode;
1014 if (IS_IN_BMP(ch)) {
1015 ch = ToLowerCase(static_cast<char16_t>(ch));
1017 aCandidates.AppendElement(ch);
1019 for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
1020 uint32_t ch[2] = {mAlternativeCharCodes[i].mUnshiftedCharCode,
1021 mAlternativeCharCodes[i].mShiftedCharCode};
1022 for (uint32_t j = 0; j < 2; ++j) {
1023 if (!ch[j]) {
1024 continue;
1026 if (IS_IN_BMP(ch[j])) {
1027 ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
1029 // Don't append the charcode that was already appended.
1030 if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
1031 aCandidates.AppendElement(ch[j]);
1035 // Special case for "Space" key. With some keyboard layouts, "Space" with
1036 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1037 // we should guarantee that the key press works as an ASCII white space key
1038 // press. However, if the space key is assigned to a function key, it
1039 // shouldn't work as a space key.
1040 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1041 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1042 aCandidates.AppendElement(' ');
1046 // mask values for ui.key.chromeAccess and ui.key.contentAccess
1047 #define NS_MODIFIER_SHIFT 1
1048 #define NS_MODIFIER_CONTROL 2
1049 #define NS_MODIFIER_ALT 4
1050 #define NS_MODIFIER_META 8
1051 #define NS_MODIFIER_OS 16
1053 static Modifiers PrefFlagsToModifiers(int32_t aPrefFlags) {
1054 Modifiers result = 0;
1055 if (aPrefFlags & NS_MODIFIER_SHIFT) {
1056 result |= MODIFIER_SHIFT;
1058 if (aPrefFlags & NS_MODIFIER_CONTROL) {
1059 result |= MODIFIER_CONTROL;
1061 if (aPrefFlags & NS_MODIFIER_ALT) {
1062 result |= MODIFIER_ALT;
1064 if (aPrefFlags & NS_MODIFIER_META) {
1065 result |= MODIFIER_META;
1067 if (aPrefFlags & NS_MODIFIER_OS) {
1068 result |= MODIFIER_OS;
1070 return result;
1073 bool WidgetKeyboardEvent::ModifiersMatchWithAccessKey(
1074 AccessKeyType aType) const {
1075 if (!ModifiersForAccessKeyMatching()) {
1076 return false;
1078 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
1081 Modifiers WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const {
1082 static const Modifiers kModifierMask = MODIFIER_SHIFT | MODIFIER_CONTROL |
1083 MODIFIER_ALT | MODIFIER_META |
1084 MODIFIER_OS;
1085 return mModifiers & kModifierMask;
1088 /* static */
1089 Modifiers WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType) {
1090 switch (StaticPrefs::ui_key_generalAccessKey()) {
1091 case -1:
1092 break; // use the individual prefs
1093 case NS_VK_SHIFT:
1094 return MODIFIER_SHIFT;
1095 case NS_VK_CONTROL:
1096 return MODIFIER_CONTROL;
1097 case NS_VK_ALT:
1098 return MODIFIER_ALT;
1099 case NS_VK_META:
1100 return MODIFIER_META;
1101 case NS_VK_WIN:
1102 return MODIFIER_OS;
1103 default:
1104 return MODIFIER_NONE;
1107 switch (aType) {
1108 case AccessKeyType::eChrome:
1109 return PrefFlagsToModifiers(StaticPrefs::ui_key_chromeAccess());
1110 case AccessKeyType::eContent:
1111 return PrefFlagsToModifiers(StaticPrefs::ui_key_contentAccess());
1112 default:
1113 return MODIFIER_NONE;
1117 /* static */
1118 void WidgetKeyboardEvent::Shutdown() {
1119 delete sKeyNameIndexHashtable;
1120 sKeyNameIndexHashtable = nullptr;
1121 delete sCodeNameIndexHashtable;
1122 sCodeNameIndexHashtable = nullptr;
1123 // Although sCommandHashtable is not a member of WidgetKeyboardEvent, but
1124 // let's delete it here since we need to do it at same time.
1125 delete sCommandHashtable;
1126 sCommandHashtable = nullptr;
1129 /* static */
1130 void WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
1131 nsAString& aKeyName) {
1132 if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
1133 aKeyName.Truncate();
1134 return;
1137 MOZ_RELEASE_ASSERT(
1138 static_cast<size_t>(aKeyNameIndex) < ArrayLength(kKeyNames),
1139 "Illegal key enumeration value");
1140 aKeyName = kKeyNames[aKeyNameIndex];
1143 /* static */
1144 void WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
1145 nsAString& aCodeName) {
1146 if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
1147 aCodeName.Truncate();
1148 return;
1151 MOZ_RELEASE_ASSERT(
1152 static_cast<size_t>(aCodeNameIndex) < ArrayLength(kCodeNames),
1153 "Illegal physical code enumeration value");
1154 aCodeName = kCodeNames[aCodeNameIndex];
1157 /* static */
1158 KeyNameIndex WidgetKeyboardEvent::GetKeyNameIndex(const nsAString& aKeyValue) {
1159 if (!sKeyNameIndexHashtable) {
1160 sKeyNameIndexHashtable = new KeyNameIndexHashtable(ArrayLength(kKeyNames));
1161 for (size_t i = 0; i < ArrayLength(kKeyNames); i++) {
1162 sKeyNameIndexHashtable->Put(nsDependentString(kKeyNames[i]),
1163 static_cast<KeyNameIndex>(i));
1166 KeyNameIndex result = KEY_NAME_INDEX_USE_STRING;
1167 sKeyNameIndexHashtable->Get(aKeyValue, &result);
1168 return result;
1171 /* static */
1172 CodeNameIndex WidgetKeyboardEvent::GetCodeNameIndex(
1173 const nsAString& aCodeValue) {
1174 if (!sCodeNameIndexHashtable) {
1175 sCodeNameIndexHashtable =
1176 new CodeNameIndexHashtable(ArrayLength(kCodeNames));
1177 for (size_t i = 0; i < ArrayLength(kCodeNames); i++) {
1178 sCodeNameIndexHashtable->Put(nsDependentString(kCodeNames[i]),
1179 static_cast<CodeNameIndex>(i));
1182 CodeNameIndex result = CODE_NAME_INDEX_USE_STRING;
1183 sCodeNameIndexHashtable->Get(aCodeValue, &result);
1184 return result;
1187 /* static */
1188 uint32_t WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(
1189 CodeNameIndex aCodeNameIndex) {
1190 switch (aCodeNameIndex) {
1191 case CODE_NAME_INDEX_Semicolon: // VK_OEM_1 on Windows
1192 return dom::KeyboardEvent_Binding::DOM_VK_SEMICOLON;
1193 case CODE_NAME_INDEX_Equal: // VK_OEM_PLUS on Windows
1194 return dom::KeyboardEvent_Binding::DOM_VK_EQUALS;
1195 case CODE_NAME_INDEX_Comma: // VK_OEM_COMMA on Windows
1196 return dom::KeyboardEvent_Binding::DOM_VK_COMMA;
1197 case CODE_NAME_INDEX_Minus: // VK_OEM_MINUS on Windows
1198 return dom::KeyboardEvent_Binding::DOM_VK_HYPHEN_MINUS;
1199 case CODE_NAME_INDEX_Period: // VK_OEM_PERIOD on Windows
1200 return dom::KeyboardEvent_Binding::DOM_VK_PERIOD;
1201 case CODE_NAME_INDEX_Slash: // VK_OEM_2 on Windows
1202 return dom::KeyboardEvent_Binding::DOM_VK_SLASH;
1203 case CODE_NAME_INDEX_Backquote: // VK_OEM_3 on Windows
1204 return dom::KeyboardEvent_Binding::DOM_VK_BACK_QUOTE;
1205 case CODE_NAME_INDEX_BracketLeft: // VK_OEM_4 on Windows
1206 return dom::KeyboardEvent_Binding::DOM_VK_OPEN_BRACKET;
1207 case CODE_NAME_INDEX_Backslash: // VK_OEM_5 on Windows
1208 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1209 case CODE_NAME_INDEX_BracketRight: // VK_OEM_6 on Windows
1210 return dom::KeyboardEvent_Binding::DOM_VK_CLOSE_BRACKET;
1211 case CODE_NAME_INDEX_Quote: // VK_OEM_7 on Windows
1212 return dom::KeyboardEvent_Binding::DOM_VK_QUOTE;
1213 case CODE_NAME_INDEX_IntlBackslash: // VK_OEM_5 on Windows (ABNT, etc)
1214 case CODE_NAME_INDEX_IntlYen: // VK_OEM_5 on Windows (JIS)
1215 case CODE_NAME_INDEX_IntlRo: // VK_OEM_102 on Windows
1216 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1217 default:
1218 return 0;
1222 /* static */ const char* WidgetKeyboardEvent::GetCommandStr(Command aCommand) {
1223 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1224 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) , #aCommandStr
1225 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName)
1226 static const char* const kCommands[] = {
1227 "" // DoNothing
1228 #include "mozilla/CommandList.h"
1230 #undef NS_DEFINE_COMMAND
1231 #undef NS_DEFINE_COMMAND_WITH_PARAM
1232 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
1234 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand) < ArrayLength(kCommands),
1235 "Illegal command enumeration value");
1236 return kCommands[static_cast<CommandInt>(aCommand)];
1239 /* static */
1240 uint32_t WidgetKeyboardEvent::ComputeLocationFromCodeValue(
1241 CodeNameIndex aCodeNameIndex) {
1242 // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1243 // but are defined by D3E spec. So, they should be uncommented when the
1244 // code values are defined in the header.
1245 switch (aCodeNameIndex) {
1246 case CODE_NAME_INDEX_AltLeft:
1247 case CODE_NAME_INDEX_ControlLeft:
1248 case CODE_NAME_INDEX_OSLeft:
1249 case CODE_NAME_INDEX_ShiftLeft:
1250 return eKeyLocationLeft;
1251 case CODE_NAME_INDEX_AltRight:
1252 case CODE_NAME_INDEX_ControlRight:
1253 case CODE_NAME_INDEX_OSRight:
1254 case CODE_NAME_INDEX_ShiftRight:
1255 return eKeyLocationRight;
1256 case CODE_NAME_INDEX_Numpad0:
1257 case CODE_NAME_INDEX_Numpad1:
1258 case CODE_NAME_INDEX_Numpad2:
1259 case CODE_NAME_INDEX_Numpad3:
1260 case CODE_NAME_INDEX_Numpad4:
1261 case CODE_NAME_INDEX_Numpad5:
1262 case CODE_NAME_INDEX_Numpad6:
1263 case CODE_NAME_INDEX_Numpad7:
1264 case CODE_NAME_INDEX_Numpad8:
1265 case CODE_NAME_INDEX_Numpad9:
1266 case CODE_NAME_INDEX_NumpadAdd:
1267 case CODE_NAME_INDEX_NumpadBackspace:
1268 case CODE_NAME_INDEX_NumpadClear:
1269 case CODE_NAME_INDEX_NumpadClearEntry:
1270 case CODE_NAME_INDEX_NumpadComma:
1271 case CODE_NAME_INDEX_NumpadDecimal:
1272 case CODE_NAME_INDEX_NumpadDivide:
1273 case CODE_NAME_INDEX_NumpadEnter:
1274 case CODE_NAME_INDEX_NumpadEqual:
1275 case CODE_NAME_INDEX_NumpadMemoryAdd:
1276 case CODE_NAME_INDEX_NumpadMemoryClear:
1277 case CODE_NAME_INDEX_NumpadMemoryRecall:
1278 case CODE_NAME_INDEX_NumpadMemoryStore:
1279 case CODE_NAME_INDEX_NumpadMemorySubtract:
1280 case CODE_NAME_INDEX_NumpadMultiply:
1281 case CODE_NAME_INDEX_NumpadParenLeft:
1282 case CODE_NAME_INDEX_NumpadParenRight:
1283 case CODE_NAME_INDEX_NumpadSubtract:
1284 return eKeyLocationNumpad;
1285 default:
1286 return eKeyLocationStandard;
1290 /* static */
1291 uint32_t WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(
1292 KeyNameIndex aKeyNameIndex) {
1293 switch (aKeyNameIndex) {
1294 case KEY_NAME_INDEX_Cancel:
1295 return dom::KeyboardEvent_Binding::DOM_VK_CANCEL;
1296 case KEY_NAME_INDEX_Help:
1297 return dom::KeyboardEvent_Binding::DOM_VK_HELP;
1298 case KEY_NAME_INDEX_Backspace:
1299 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SPACE;
1300 case KEY_NAME_INDEX_Tab:
1301 return dom::KeyboardEvent_Binding::DOM_VK_TAB;
1302 case KEY_NAME_INDEX_Clear:
1303 return dom::KeyboardEvent_Binding::DOM_VK_CLEAR;
1304 case KEY_NAME_INDEX_Enter:
1305 return dom::KeyboardEvent_Binding::DOM_VK_RETURN;
1306 case KEY_NAME_INDEX_Shift:
1307 return dom::KeyboardEvent_Binding::DOM_VK_SHIFT;
1308 case KEY_NAME_INDEX_Control:
1309 return dom::KeyboardEvent_Binding::DOM_VK_CONTROL;
1310 case KEY_NAME_INDEX_Alt:
1311 return dom::KeyboardEvent_Binding::DOM_VK_ALT;
1312 case KEY_NAME_INDEX_Pause:
1313 return dom::KeyboardEvent_Binding::DOM_VK_PAUSE;
1314 case KEY_NAME_INDEX_CapsLock:
1315 return dom::KeyboardEvent_Binding::DOM_VK_CAPS_LOCK;
1316 case KEY_NAME_INDEX_Hiragana:
1317 case KEY_NAME_INDEX_Katakana:
1318 case KEY_NAME_INDEX_HiraganaKatakana:
1319 case KEY_NAME_INDEX_KanaMode:
1320 return dom::KeyboardEvent_Binding::DOM_VK_KANA;
1321 case KEY_NAME_INDEX_HangulMode:
1322 return dom::KeyboardEvent_Binding::DOM_VK_HANGUL;
1323 case KEY_NAME_INDEX_Eisu:
1324 return dom::KeyboardEvent_Binding::DOM_VK_EISU;
1325 case KEY_NAME_INDEX_JunjaMode:
1326 return dom::KeyboardEvent_Binding::DOM_VK_JUNJA;
1327 case KEY_NAME_INDEX_FinalMode:
1328 return dom::KeyboardEvent_Binding::DOM_VK_FINAL;
1329 case KEY_NAME_INDEX_HanjaMode:
1330 return dom::KeyboardEvent_Binding::DOM_VK_HANJA;
1331 case KEY_NAME_INDEX_KanjiMode:
1332 return dom::KeyboardEvent_Binding::DOM_VK_KANJI;
1333 case KEY_NAME_INDEX_Escape:
1334 return dom::KeyboardEvent_Binding::DOM_VK_ESCAPE;
1335 case KEY_NAME_INDEX_Convert:
1336 return dom::KeyboardEvent_Binding::DOM_VK_CONVERT;
1337 case KEY_NAME_INDEX_NonConvert:
1338 return dom::KeyboardEvent_Binding::DOM_VK_NONCONVERT;
1339 case KEY_NAME_INDEX_Accept:
1340 return dom::KeyboardEvent_Binding::DOM_VK_ACCEPT;
1341 case KEY_NAME_INDEX_ModeChange:
1342 return dom::KeyboardEvent_Binding::DOM_VK_MODECHANGE;
1343 case KEY_NAME_INDEX_PageUp:
1344 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_UP;
1345 case KEY_NAME_INDEX_PageDown:
1346 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_DOWN;
1347 case KEY_NAME_INDEX_End:
1348 return dom::KeyboardEvent_Binding::DOM_VK_END;
1349 case KEY_NAME_INDEX_Home:
1350 return dom::KeyboardEvent_Binding::DOM_VK_HOME;
1351 case KEY_NAME_INDEX_ArrowLeft:
1352 return dom::KeyboardEvent_Binding::DOM_VK_LEFT;
1353 case KEY_NAME_INDEX_ArrowUp:
1354 return dom::KeyboardEvent_Binding::DOM_VK_UP;
1355 case KEY_NAME_INDEX_ArrowRight:
1356 return dom::KeyboardEvent_Binding::DOM_VK_RIGHT;
1357 case KEY_NAME_INDEX_ArrowDown:
1358 return dom::KeyboardEvent_Binding::DOM_VK_DOWN;
1359 case KEY_NAME_INDEX_Select:
1360 return dom::KeyboardEvent_Binding::DOM_VK_SELECT;
1361 case KEY_NAME_INDEX_Print:
1362 return dom::KeyboardEvent_Binding::DOM_VK_PRINT;
1363 case KEY_NAME_INDEX_Execute:
1364 return dom::KeyboardEvent_Binding::DOM_VK_EXECUTE;
1365 case KEY_NAME_INDEX_PrintScreen:
1366 return dom::KeyboardEvent_Binding::DOM_VK_PRINTSCREEN;
1367 case KEY_NAME_INDEX_Insert:
1368 return dom::KeyboardEvent_Binding::DOM_VK_INSERT;
1369 case KEY_NAME_INDEX_Delete:
1370 return dom::KeyboardEvent_Binding::DOM_VK_DELETE;
1371 case KEY_NAME_INDEX_OS:
1372 // case KEY_NAME_INDEX_Super:
1373 // case KEY_NAME_INDEX_Hyper:
1374 return dom::KeyboardEvent_Binding::DOM_VK_WIN;
1375 case KEY_NAME_INDEX_ContextMenu:
1376 return dom::KeyboardEvent_Binding::DOM_VK_CONTEXT_MENU;
1377 case KEY_NAME_INDEX_Standby:
1378 return dom::KeyboardEvent_Binding::DOM_VK_SLEEP;
1379 case KEY_NAME_INDEX_F1:
1380 return dom::KeyboardEvent_Binding::DOM_VK_F1;
1381 case KEY_NAME_INDEX_F2:
1382 return dom::KeyboardEvent_Binding::DOM_VK_F2;
1383 case KEY_NAME_INDEX_F3:
1384 return dom::KeyboardEvent_Binding::DOM_VK_F3;
1385 case KEY_NAME_INDEX_F4:
1386 return dom::KeyboardEvent_Binding::DOM_VK_F4;
1387 case KEY_NAME_INDEX_F5:
1388 return dom::KeyboardEvent_Binding::DOM_VK_F5;
1389 case KEY_NAME_INDEX_F6:
1390 return dom::KeyboardEvent_Binding::DOM_VK_F6;
1391 case KEY_NAME_INDEX_F7:
1392 return dom::KeyboardEvent_Binding::DOM_VK_F7;
1393 case KEY_NAME_INDEX_F8:
1394 return dom::KeyboardEvent_Binding::DOM_VK_F8;
1395 case KEY_NAME_INDEX_F9:
1396 return dom::KeyboardEvent_Binding::DOM_VK_F9;
1397 case KEY_NAME_INDEX_F10:
1398 return dom::KeyboardEvent_Binding::DOM_VK_F10;
1399 case KEY_NAME_INDEX_F11:
1400 return dom::KeyboardEvent_Binding::DOM_VK_F11;
1401 case KEY_NAME_INDEX_F12:
1402 return dom::KeyboardEvent_Binding::DOM_VK_F12;
1403 case KEY_NAME_INDEX_F13:
1404 return dom::KeyboardEvent_Binding::DOM_VK_F13;
1405 case KEY_NAME_INDEX_F14:
1406 return dom::KeyboardEvent_Binding::DOM_VK_F14;
1407 case KEY_NAME_INDEX_F15:
1408 return dom::KeyboardEvent_Binding::DOM_VK_F15;
1409 case KEY_NAME_INDEX_F16:
1410 return dom::KeyboardEvent_Binding::DOM_VK_F16;
1411 case KEY_NAME_INDEX_F17:
1412 return dom::KeyboardEvent_Binding::DOM_VK_F17;
1413 case KEY_NAME_INDEX_F18:
1414 return dom::KeyboardEvent_Binding::DOM_VK_F18;
1415 case KEY_NAME_INDEX_F19:
1416 return dom::KeyboardEvent_Binding::DOM_VK_F19;
1417 case KEY_NAME_INDEX_F20:
1418 return dom::KeyboardEvent_Binding::DOM_VK_F20;
1419 case KEY_NAME_INDEX_F21:
1420 return dom::KeyboardEvent_Binding::DOM_VK_F21;
1421 case KEY_NAME_INDEX_F22:
1422 return dom::KeyboardEvent_Binding::DOM_VK_F22;
1423 case KEY_NAME_INDEX_F23:
1424 return dom::KeyboardEvent_Binding::DOM_VK_F23;
1425 case KEY_NAME_INDEX_F24:
1426 return dom::KeyboardEvent_Binding::DOM_VK_F24;
1427 case KEY_NAME_INDEX_NumLock:
1428 return dom::KeyboardEvent_Binding::DOM_VK_NUM_LOCK;
1429 case KEY_NAME_INDEX_ScrollLock:
1430 return dom::KeyboardEvent_Binding::DOM_VK_SCROLL_LOCK;
1431 case KEY_NAME_INDEX_AudioVolumeMute:
1432 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_MUTE;
1433 case KEY_NAME_INDEX_AudioVolumeDown:
1434 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_DOWN;
1435 case KEY_NAME_INDEX_AudioVolumeUp:
1436 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_UP;
1437 case KEY_NAME_INDEX_Meta:
1438 return dom::KeyboardEvent_Binding::DOM_VK_META;
1439 case KEY_NAME_INDEX_AltGraph:
1440 return dom::KeyboardEvent_Binding::DOM_VK_ALTGR;
1441 case KEY_NAME_INDEX_Process:
1442 return dom::KeyboardEvent_Binding::DOM_VK_PROCESSKEY;
1443 case KEY_NAME_INDEX_Attn:
1444 return dom::KeyboardEvent_Binding::DOM_VK_ATTN;
1445 case KEY_NAME_INDEX_CrSel:
1446 return dom::KeyboardEvent_Binding::DOM_VK_CRSEL;
1447 case KEY_NAME_INDEX_ExSel:
1448 return dom::KeyboardEvent_Binding::DOM_VK_EXSEL;
1449 case KEY_NAME_INDEX_EraseEof:
1450 return dom::KeyboardEvent_Binding::DOM_VK_EREOF;
1451 case KEY_NAME_INDEX_Play:
1452 return dom::KeyboardEvent_Binding::DOM_VK_PLAY;
1453 case KEY_NAME_INDEX_ZoomToggle:
1454 case KEY_NAME_INDEX_ZoomIn:
1455 case KEY_NAME_INDEX_ZoomOut:
1456 return dom::KeyboardEvent_Binding::DOM_VK_ZOOM;
1457 default:
1458 return 0;
1462 /* static */
1463 CodeNameIndex WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex(
1464 KeyNameIndex aKeyNameIndex, const Maybe<uint32_t>& aLocation) {
1465 if (aLocation.isSome() &&
1466 aLocation.value() ==
1467 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_NUMPAD) {
1468 // On macOS, NumLock is not supported. Therefore, this handles
1469 // control key values except "Enter" only on non-macOS platforms.
1470 switch (aKeyNameIndex) {
1471 #ifndef XP_MACOSX
1472 case KEY_NAME_INDEX_Insert:
1473 return CODE_NAME_INDEX_Numpad0;
1474 case KEY_NAME_INDEX_End:
1475 return CODE_NAME_INDEX_Numpad1;
1476 case KEY_NAME_INDEX_ArrowDown:
1477 return CODE_NAME_INDEX_Numpad2;
1478 case KEY_NAME_INDEX_PageDown:
1479 return CODE_NAME_INDEX_Numpad3;
1480 case KEY_NAME_INDEX_ArrowLeft:
1481 return CODE_NAME_INDEX_Numpad4;
1482 case KEY_NAME_INDEX_Clear:
1483 // FYI: "Clear" on macOS should be DOM_KEY_LOCATION_STANDARD.
1484 return CODE_NAME_INDEX_Numpad5;
1485 case KEY_NAME_INDEX_ArrowRight:
1486 return CODE_NAME_INDEX_Numpad6;
1487 case KEY_NAME_INDEX_Home:
1488 return CODE_NAME_INDEX_Numpad7;
1489 case KEY_NAME_INDEX_ArrowUp:
1490 return CODE_NAME_INDEX_Numpad8;
1491 case KEY_NAME_INDEX_PageUp:
1492 return CODE_NAME_INDEX_Numpad9;
1493 case KEY_NAME_INDEX_Delete:
1494 return CODE_NAME_INDEX_NumpadDecimal;
1495 #endif // #ifndef XP_MACOSX
1496 case KEY_NAME_INDEX_Enter:
1497 return CODE_NAME_INDEX_NumpadEnter;
1498 default:
1499 return CODE_NAME_INDEX_UNKNOWN;
1503 if (WidgetKeyboardEvent::IsLeftOrRightModiferKeyNameIndex(aKeyNameIndex)) {
1504 if (aLocation.isSome() &&
1505 (aLocation.value() !=
1506 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_LEFT &&
1507 aLocation.value() !=
1508 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT)) {
1509 return CODE_NAME_INDEX_UNKNOWN;
1511 bool isRight =
1512 aLocation.isSome() &&
1513 aLocation.value() == dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT;
1514 switch (aKeyNameIndex) {
1515 case KEY_NAME_INDEX_Alt:
1516 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1517 case KEY_NAME_INDEX_Control:
1518 return isRight ? CODE_NAME_INDEX_ControlRight
1519 : CODE_NAME_INDEX_ControlLeft;
1520 case KEY_NAME_INDEX_Shift:
1521 return isRight ? CODE_NAME_INDEX_ShiftRight : CODE_NAME_INDEX_ShiftLeft;
1522 #if defined(XP_WIN)
1523 case KEY_NAME_INDEX_Meta:
1524 return CODE_NAME_INDEX_UNKNOWN;
1525 case KEY_NAME_INDEX_OS: // win key.
1526 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1527 #elif defined(XP_MACOSX) || defined(ANDROID)
1528 case KEY_NAME_INDEX_Meta: // command key.
1529 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1530 case KEY_NAME_INDEX_OS:
1531 return CODE_NAME_INDEX_UNKNOWN;
1532 #else
1533 case KEY_NAME_INDEX_Meta: // Alt + Shift.
1534 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1535 case KEY_NAME_INDEX_OS: // Super/Hyper key.
1536 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1537 #endif
1538 default:
1539 return CODE_NAME_INDEX_UNKNOWN;
1543 if (aLocation.isSome() &&
1544 aLocation.value() !=
1545 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_STANDARD) {
1546 return CODE_NAME_INDEX_UNKNOWN;
1549 switch (aKeyNameIndex) {
1550 // Standard section:
1551 case KEY_NAME_INDEX_Escape:
1552 return CODE_NAME_INDEX_Escape;
1553 case KEY_NAME_INDEX_Tab:
1554 return CODE_NAME_INDEX_Tab;
1555 case KEY_NAME_INDEX_CapsLock:
1556 return CODE_NAME_INDEX_CapsLock;
1557 case KEY_NAME_INDEX_ContextMenu:
1558 return CODE_NAME_INDEX_ContextMenu;
1559 case KEY_NAME_INDEX_Backspace:
1560 return CODE_NAME_INDEX_Backspace;
1561 case KEY_NAME_INDEX_Enter:
1562 return CODE_NAME_INDEX_Enter;
1563 #ifdef XP_MACOSX
1564 // Although, macOS does not fire native key event of "Fn" key, we support
1565 // Fn key event if it's sent by other apps directly.
1566 case KEY_NAME_INDEX_Fn:
1567 return CODE_NAME_INDEX_Fn;
1568 #endif // #ifdef
1570 // Arrow Pad section:
1571 case KEY_NAME_INDEX_ArrowLeft:
1572 return CODE_NAME_INDEX_ArrowLeft;
1573 case KEY_NAME_INDEX_ArrowUp:
1574 return CODE_NAME_INDEX_ArrowUp;
1575 case KEY_NAME_INDEX_ArrowDown:
1576 return CODE_NAME_INDEX_ArrowDown;
1577 case KEY_NAME_INDEX_ArrowRight:
1578 return CODE_NAME_INDEX_ArrowRight;
1580 // Control Pad section:
1581 #ifndef XP_MACOSX
1582 case KEY_NAME_INDEX_Insert:
1583 return CODE_NAME_INDEX_Insert;
1584 #else
1585 case KEY_NAME_INDEX_Help:
1586 return CODE_NAME_INDEX_Help;
1587 #endif // #ifndef XP_MACOSX #else
1588 case KEY_NAME_INDEX_Delete:
1589 return CODE_NAME_INDEX_Delete;
1590 case KEY_NAME_INDEX_Home:
1591 return CODE_NAME_INDEX_Home;
1592 case KEY_NAME_INDEX_End:
1593 return CODE_NAME_INDEX_End;
1594 case KEY_NAME_INDEX_PageUp:
1595 return CODE_NAME_INDEX_PageUp;
1596 case KEY_NAME_INDEX_PageDown:
1597 return CODE_NAME_INDEX_PageDown;
1599 // Function keys:
1600 case KEY_NAME_INDEX_F1:
1601 return CODE_NAME_INDEX_F1;
1602 case KEY_NAME_INDEX_F2:
1603 return CODE_NAME_INDEX_F2;
1604 case KEY_NAME_INDEX_F3:
1605 return CODE_NAME_INDEX_F3;
1606 case KEY_NAME_INDEX_F4:
1607 return CODE_NAME_INDEX_F4;
1608 case KEY_NAME_INDEX_F5:
1609 return CODE_NAME_INDEX_F5;
1610 case KEY_NAME_INDEX_F6:
1611 return CODE_NAME_INDEX_F6;
1612 case KEY_NAME_INDEX_F7:
1613 return CODE_NAME_INDEX_F7;
1614 case KEY_NAME_INDEX_F8:
1615 return CODE_NAME_INDEX_F8;
1616 case KEY_NAME_INDEX_F9:
1617 return CODE_NAME_INDEX_F9;
1618 case KEY_NAME_INDEX_F10:
1619 return CODE_NAME_INDEX_F10;
1620 case KEY_NAME_INDEX_F11:
1621 return CODE_NAME_INDEX_F11;
1622 case KEY_NAME_INDEX_F12:
1623 return CODE_NAME_INDEX_F12;
1624 case KEY_NAME_INDEX_F13:
1625 return CODE_NAME_INDEX_F13;
1626 case KEY_NAME_INDEX_F14:
1627 return CODE_NAME_INDEX_F14;
1628 case KEY_NAME_INDEX_F15:
1629 return CODE_NAME_INDEX_F15;
1630 case KEY_NAME_INDEX_F16:
1631 return CODE_NAME_INDEX_F16;
1632 case KEY_NAME_INDEX_F17:
1633 return CODE_NAME_INDEX_F17;
1634 case KEY_NAME_INDEX_F18:
1635 return CODE_NAME_INDEX_F18;
1636 case KEY_NAME_INDEX_F19:
1637 return CODE_NAME_INDEX_F19;
1638 case KEY_NAME_INDEX_F20:
1639 return CODE_NAME_INDEX_F20;
1640 #ifndef XP_MACOSX
1641 case KEY_NAME_INDEX_F21:
1642 return CODE_NAME_INDEX_F21;
1643 case KEY_NAME_INDEX_F22:
1644 return CODE_NAME_INDEX_F22;
1645 case KEY_NAME_INDEX_F23:
1646 return CODE_NAME_INDEX_F23;
1647 case KEY_NAME_INDEX_F24:
1648 return CODE_NAME_INDEX_F24;
1649 case KEY_NAME_INDEX_Pause:
1650 return CODE_NAME_INDEX_Pause;
1651 case KEY_NAME_INDEX_PrintScreen:
1652 return CODE_NAME_INDEX_PrintScreen;
1653 case KEY_NAME_INDEX_ScrollLock:
1654 return CODE_NAME_INDEX_ScrollLock;
1655 #endif // #ifndef XP_MACOSX
1657 // NumLock key:
1658 #ifndef XP_MACOSX
1659 case KEY_NAME_INDEX_NumLock:
1660 return CODE_NAME_INDEX_NumLock;
1661 #else
1662 case KEY_NAME_INDEX_Clear:
1663 return CODE_NAME_INDEX_NumLock;
1664 #endif // #ifndef XP_MACOSX #else
1666 // Media keys:
1667 case KEY_NAME_INDEX_AudioVolumeDown:
1668 return CODE_NAME_INDEX_VolumeDown;
1669 case KEY_NAME_INDEX_AudioVolumeMute:
1670 return CODE_NAME_INDEX_VolumeMute;
1671 case KEY_NAME_INDEX_AudioVolumeUp:
1672 return CODE_NAME_INDEX_VolumeUp;
1673 #ifndef XP_MACOSX
1674 case KEY_NAME_INDEX_BrowserBack:
1675 return CODE_NAME_INDEX_BrowserBack;
1676 case KEY_NAME_INDEX_BrowserFavorites:
1677 return CODE_NAME_INDEX_BrowserFavorites;
1678 case KEY_NAME_INDEX_BrowserForward:
1679 return CODE_NAME_INDEX_BrowserForward;
1680 case KEY_NAME_INDEX_BrowserRefresh:
1681 return CODE_NAME_INDEX_BrowserRefresh;
1682 case KEY_NAME_INDEX_BrowserSearch:
1683 return CODE_NAME_INDEX_BrowserSearch;
1684 case KEY_NAME_INDEX_BrowserStop:
1685 return CODE_NAME_INDEX_BrowserStop;
1686 case KEY_NAME_INDEX_MediaPlayPause:
1687 return CODE_NAME_INDEX_MediaPlayPause;
1688 case KEY_NAME_INDEX_MediaStop:
1689 return CODE_NAME_INDEX_MediaStop;
1690 case KEY_NAME_INDEX_MediaTrackNext:
1691 return CODE_NAME_INDEX_MediaTrackNext;
1692 case KEY_NAME_INDEX_MediaTrackPrevious:
1693 return CODE_NAME_INDEX_MediaTrackPrevious;
1694 case KEY_NAME_INDEX_LaunchApplication1:
1695 return CODE_NAME_INDEX_LaunchApp1;
1696 #endif // #ifndef XP_MACOSX
1698 // Only Windows and GTK supports the following multimedia keys.
1699 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1700 case KEY_NAME_INDEX_BrowserHome:
1701 return CODE_NAME_INDEX_BrowserHome;
1702 case KEY_NAME_INDEX_LaunchApplication2:
1703 return CODE_NAME_INDEX_LaunchApp2;
1704 #endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1706 // Only GTK and Android supports the following multimedia keys.
1707 #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1708 case KEY_NAME_INDEX_Eject:
1709 return CODE_NAME_INDEX_Eject;
1710 case KEY_NAME_INDEX_WakeUp:
1711 return CODE_NAME_INDEX_WakeUp;
1712 #endif // #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1714 // Only Windows does not support Help key (and macOS handled above).
1715 #if !defined(XP_WIN) && !defined(XP_MACOSX)
1716 case KEY_NAME_INDEX_Help:
1717 return CODE_NAME_INDEX_Help;
1718 #endif // #if !defined(XP_WIN) && !defined(XP_MACOSX)
1720 // IME specific keys:
1721 #ifdef XP_WIN
1722 case KEY_NAME_INDEX_Convert:
1723 return CODE_NAME_INDEX_Convert;
1724 case KEY_NAME_INDEX_NonConvert:
1725 return CODE_NAME_INDEX_NonConvert;
1726 case KEY_NAME_INDEX_Alphanumeric:
1727 return CODE_NAME_INDEX_CapsLock;
1728 case KEY_NAME_INDEX_KanaMode:
1729 case KEY_NAME_INDEX_Romaji:
1730 case KEY_NAME_INDEX_Katakana:
1731 case KEY_NAME_INDEX_Hiragana:
1732 return CODE_NAME_INDEX_KanaMode;
1733 case KEY_NAME_INDEX_Hankaku:
1734 case KEY_NAME_INDEX_Zenkaku:
1735 case KEY_NAME_INDEX_KanjiMode:
1736 return CODE_NAME_INDEX_Backquote;
1737 case KEY_NAME_INDEX_HanjaMode:
1738 return CODE_NAME_INDEX_Lang2;
1739 case KEY_NAME_INDEX_HangulMode:
1740 return CODE_NAME_INDEX_Lang1;
1741 #endif // #ifdef XP_WIN
1743 #ifdef MOZ_WIDGET_GTK
1744 case KEY_NAME_INDEX_Convert:
1745 return CODE_NAME_INDEX_Convert;
1746 case KEY_NAME_INDEX_NonConvert:
1747 return CODE_NAME_INDEX_NonConvert;
1748 case KEY_NAME_INDEX_Alphanumeric:
1749 return CODE_NAME_INDEX_CapsLock;
1750 case KEY_NAME_INDEX_HiraganaKatakana:
1751 return CODE_NAME_INDEX_KanaMode;
1752 case KEY_NAME_INDEX_ZenkakuHankaku:
1753 return CODE_NAME_INDEX_Backquote;
1754 #endif // #ifdef MOZ_WIDGET_GTK
1756 #ifdef ANDROID
1757 case KEY_NAME_INDEX_Convert:
1758 return CODE_NAME_INDEX_Convert;
1759 case KEY_NAME_INDEX_NonConvert:
1760 return CODE_NAME_INDEX_NonConvert;
1761 case KEY_NAME_INDEX_HiraganaKatakana:
1762 return CODE_NAME_INDEX_KanaMode;
1763 case KEY_NAME_INDEX_ZenkakuHankaku:
1764 return CODE_NAME_INDEX_Backquote;
1765 case KEY_NAME_INDEX_Eisu:
1766 return CODE_NAME_INDEX_Lang2;
1767 case KEY_NAME_INDEX_KanjiMode:
1768 return CODE_NAME_INDEX_Lang1;
1769 #endif // #ifdef ANDROID
1771 #ifdef XP_MACOSX
1772 case KEY_NAME_INDEX_Eisu:
1773 return CODE_NAME_INDEX_Lang2;
1774 case KEY_NAME_INDEX_KanjiMode:
1775 return CODE_NAME_INDEX_Lang1;
1776 #endif // #ifdef XP_MACOSX
1778 default:
1779 return CODE_NAME_INDEX_UNKNOWN;
1783 /* static */
1784 Modifier WidgetKeyboardEvent::GetModifierForKeyName(
1785 KeyNameIndex aKeyNameIndex) {
1786 switch (aKeyNameIndex) {
1787 case KEY_NAME_INDEX_Alt:
1788 return MODIFIER_ALT;
1789 case KEY_NAME_INDEX_AltGraph:
1790 return MODIFIER_ALTGRAPH;
1791 case KEY_NAME_INDEX_CapsLock:
1792 return MODIFIER_CAPSLOCK;
1793 case KEY_NAME_INDEX_Control:
1794 return MODIFIER_CONTROL;
1795 case KEY_NAME_INDEX_Fn:
1796 return MODIFIER_FN;
1797 case KEY_NAME_INDEX_FnLock:
1798 return MODIFIER_FNLOCK;
1799 // case KEY_NAME_INDEX_Hyper:
1800 case KEY_NAME_INDEX_Meta:
1801 return MODIFIER_META;
1802 case KEY_NAME_INDEX_NumLock:
1803 return MODIFIER_NUMLOCK;
1804 case KEY_NAME_INDEX_OS:
1805 return MODIFIER_OS;
1806 case KEY_NAME_INDEX_ScrollLock:
1807 return MODIFIER_SCROLLLOCK;
1808 case KEY_NAME_INDEX_Shift:
1809 return MODIFIER_SHIFT;
1810 // case KEY_NAME_INDEX_Super:
1811 case KEY_NAME_INDEX_Symbol:
1812 return MODIFIER_SYMBOL;
1813 case KEY_NAME_INDEX_SymbolLock:
1814 return MODIFIER_SYMBOLLOCK;
1815 default:
1816 return MODIFIER_NONE;
1820 /* static */
1821 bool WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex) {
1822 switch (aKeyNameIndex) {
1823 case KEY_NAME_INDEX_CapsLock:
1824 case KEY_NAME_INDEX_FnLock:
1825 case KEY_NAME_INDEX_NumLock:
1826 case KEY_NAME_INDEX_ScrollLock:
1827 case KEY_NAME_INDEX_SymbolLock:
1828 return true;
1829 default:
1830 return false;
1834 /******************************************************************************
1835 * mozilla::InternalEditorInputEvent (TextEvents.h)
1836 ******************************************************************************/
1838 #define NS_DEFINE_INPUTTYPE(aCPPName, aDOMName) (u"" aDOMName),
1839 const char16_t* const InternalEditorInputEvent::kInputTypeNames[] = {
1840 #include "mozilla/InputTypeList.h"
1842 #undef NS_DEFINE_INPUTTYPE
1844 InternalEditorInputEvent::InputTypeHashtable*
1845 InternalEditorInputEvent::sInputTypeHashtable = nullptr;
1847 /* static */
1848 void InternalEditorInputEvent::Shutdown() {
1849 delete sInputTypeHashtable;
1850 sInputTypeHashtable = nullptr;
1853 /* static */
1854 void InternalEditorInputEvent::GetDOMInputTypeName(EditorInputType aInputType,
1855 nsAString& aInputTypeName) {
1856 if (static_cast<size_t>(aInputType) >=
1857 static_cast<size_t>(EditorInputType::eUnknown)) {
1858 aInputTypeName.Truncate();
1859 return;
1862 MOZ_RELEASE_ASSERT(
1863 static_cast<size_t>(aInputType) < ArrayLength(kInputTypeNames),
1864 "Illegal input type enumeration value");
1865 aInputTypeName.Assign(kInputTypeNames[static_cast<size_t>(aInputType)]);
1868 /* static */
1869 EditorInputType InternalEditorInputEvent::GetEditorInputType(
1870 const nsAString& aInputType) {
1871 if (aInputType.IsEmpty()) {
1872 return EditorInputType::eUnknown;
1875 if (!sInputTypeHashtable) {
1876 sInputTypeHashtable = new InputTypeHashtable(ArrayLength(kInputTypeNames));
1877 for (size_t i = 0; i < ArrayLength(kInputTypeNames); i++) {
1878 sInputTypeHashtable->Put(nsDependentString(kInputTypeNames[i]),
1879 static_cast<EditorInputType>(i));
1882 EditorInputType result = EditorInputType::eUnknown;
1883 sInputTypeHashtable->Get(aInputType, &result);
1884 return result;
1887 } // namespace mozilla