Bug 1756130 [wpt PR 32898] - [CSP] Enhance unsafe-eval test to check both realms...
[gecko.git] / widget / WidgetEventImpl.cpp
blobce64c899ae076bc0a3d5305f01db0e1456066ca6
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 "BasicEvents.h"
7 #include "ContentEvents.h"
8 #include "MiscEvents.h"
9 #include "MouseEvents.h"
10 #include "NativeKeyBindingsType.h"
11 #include "TextEventDispatcher.h"
12 #include "TextEvents.h"
13 #include "TouchEvents.h"
15 #include "mozilla/EventStateManager.h"
16 #include "mozilla/InternalMutationEvent.h"
17 #include "mozilla/Maybe.h"
18 #include "mozilla/Preferences.h"
19 #include "mozilla/StaticPrefs_mousewheel.h"
20 #include "mozilla/StaticPrefs_ui.h"
21 #include "mozilla/WritingModes.h"
22 #include "mozilla/dom/KeyboardEventBinding.h"
23 #include "mozilla/dom/WheelEventBinding.h"
24 #include "nsCommandParams.h"
25 #include "nsContentUtils.h"
26 #include "nsIContent.h"
27 #include "nsIDragSession.h"
28 #include "nsPrintfCString.h"
30 #if defined(XP_WIN)
31 # include "npapi.h"
32 # include "WinUtils.h"
33 #endif // #if defined (XP_WIN)
35 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
36 # include "NativeKeyBindings.h"
37 #endif // #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
39 namespace mozilla {
41 /******************************************************************************
42 * Global helper methods
43 ******************************************************************************/
45 const char* ToChar(EventMessage aEventMessage) {
46 switch (aEventMessage) {
47 #define NS_EVENT_MESSAGE(aMessage) \
48 case aMessage: \
49 return #aMessage;
51 #include "mozilla/EventMessageList.h"
53 #undef NS_EVENT_MESSAGE
54 default:
55 return "illegal event message";
59 const char* ToChar(EventClassID aEventClassID) {
60 switch (aEventClassID) {
61 #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
62 case eBasic##aName##Class: \
63 return "eBasic" #aName "Class";
65 #define NS_EVENT_CLASS(aPrefix, aName) \
66 case e##aName##Class: \
67 return "e" #aName "Class";
69 #include "mozilla/EventClassList.h"
71 #undef NS_EVENT_CLASS
72 #undef NS_ROOT_EVENT_CLASS
73 default:
74 return "illegal event class ID";
78 const nsCString ToString(KeyNameIndex aKeyNameIndex) {
79 if (aKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
80 return "USE_STRING"_ns;
82 nsAutoString keyName;
83 WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex, keyName);
84 return NS_ConvertUTF16toUTF8(keyName);
87 const nsCString ToString(CodeNameIndex aCodeNameIndex) {
88 if (aCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
89 return "USE_STRING"_ns;
91 nsAutoString codeName;
92 WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex, codeName);
93 return NS_ConvertUTF16toUTF8(codeName);
96 const char* ToChar(Command aCommand) {
97 if (aCommand == Command::DoNothing) {
98 return "CommandDoNothing";
101 switch (aCommand) {
102 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
103 case Command::aName: \
104 return "Command::" #aName;
105 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) \
106 case Command::aName: \
107 return "Command::" #aName;
108 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) \
109 case Command::aName: \
110 return "Command::" #aName;
112 #include "mozilla/CommandList.h"
114 #undef NS_DEFINE_COMMAND
115 #undef NS_DEFINE_COMMAND_WITH_PARAM
116 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
118 default:
119 return "illegal command value";
123 const nsCString GetDOMKeyCodeName(uint32_t aKeyCode) {
124 switch (aKeyCode) {
125 #define NS_DISALLOW_SAME_KEYCODE
126 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
127 case aDOMKeyCode: \
128 return nsLiteralCString(#aDOMKeyName);
130 #include "mozilla/VirtualKeyCodeList.h"
132 #undef NS_DEFINE_VK
133 #undef NS_DISALLOW_SAME_KEYCODE
135 default:
136 return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode);
140 bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeType) {
141 switch (static_cast<TextRangeType>(aRawTextRangeType)) {
142 case TextRangeType::eUninitialized:
143 case TextRangeType::eCaret:
144 case TextRangeType::eRawClause:
145 case TextRangeType::eSelectedRawClause:
146 case TextRangeType::eConvertedClause:
147 case TextRangeType::eSelectedClause:
148 return true;
149 default:
150 return false;
154 RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType) {
155 return static_cast<RawTextRangeType>(aTextRangeType);
158 TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType) {
159 MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType));
160 return static_cast<TextRangeType>(aRawTextRangeType);
163 const char* ToChar(TextRangeType aTextRangeType) {
164 switch (aTextRangeType) {
165 case TextRangeType::eUninitialized:
166 return "TextRangeType::eUninitialized";
167 case TextRangeType::eCaret:
168 return "TextRangeType::eCaret";
169 case TextRangeType::eRawClause:
170 return "TextRangeType::eRawClause";
171 case TextRangeType::eSelectedRawClause:
172 return "TextRangeType::eSelectedRawClause";
173 case TextRangeType::eConvertedClause:
174 return "TextRangeType::eConvertedClause";
175 case TextRangeType::eSelectedClause:
176 return "TextRangeType::eSelectedClause";
177 default:
178 return "Invalid TextRangeType";
182 SelectionType ToSelectionType(TextRangeType aTextRangeType) {
183 switch (aTextRangeType) {
184 case TextRangeType::eRawClause:
185 return SelectionType::eIMERawClause;
186 case TextRangeType::eSelectedRawClause:
187 return SelectionType::eIMESelectedRawClause;
188 case TextRangeType::eConvertedClause:
189 return SelectionType::eIMEConvertedClause;
190 case TextRangeType::eSelectedClause:
191 return SelectionType::eIMESelectedClause;
192 default:
193 MOZ_CRASH("TextRangeType is invalid");
194 return SelectionType::eNormal;
198 /******************************************************************************
199 * non class method implementation
200 ******************************************************************************/
202 static nsTHashMap<nsDepCharHashKey, Command>* sCommandHashtable = nullptr;
204 Command GetInternalCommand(const char* aCommandName,
205 const nsCommandParams* aCommandParams) {
206 if (!aCommandName) {
207 return Command::DoNothing;
210 // Special cases for "cmd_align". It's mapped to multiple internal commands
211 // with additional param. Therefore, we cannot handle it with the hashtable.
212 if (!strcmp(aCommandName, "cmd_align")) {
213 if (!aCommandParams) {
214 // Note that if this is called by EditorCommand::IsCommandEnabled(),
215 // it cannot set aCommandParams. So, don't warn in this case even though
216 // this is illegal case for DoCommandParams().
217 return Command::FormatJustify;
219 nsAutoCString cValue;
220 nsresult rv = aCommandParams->GetCString("state_attribute", cValue);
221 if (NS_FAILED(rv)) {
222 nsString value; // Avoid copying the string buffer with using nsString.
223 rv = aCommandParams->GetString("state_attribute", value);
224 if (NS_FAILED(rv)) {
225 return Command::FormatJustifyNone;
227 CopyUTF16toUTF8(value, cValue);
229 if (cValue.LowerCaseEqualsASCII("left")) {
230 return Command::FormatJustifyLeft;
232 if (cValue.LowerCaseEqualsASCII("right")) {
233 return Command::FormatJustifyRight;
235 if (cValue.LowerCaseEqualsASCII("center")) {
236 return Command::FormatJustifyCenter;
238 if (cValue.LowerCaseEqualsASCII("justify")) {
239 return Command::FormatJustifyFull;
241 if (cValue.IsEmpty()) {
242 return Command::FormatJustifyNone;
244 return Command::DoNothing;
247 if (!sCommandHashtable) {
248 sCommandHashtable = new nsTHashMap<nsDepCharHashKey, Command>();
249 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
250 sCommandHashtable->InsertOrUpdate(#aCommandStr, Command::aName);
252 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam)
254 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName)
256 #include "mozilla/CommandList.h"
258 #undef NS_DEFINE_COMMAND
259 #undef NS_DEFINE_COMMAND_WITH_PARAM
260 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
262 Command command = Command::DoNothing;
263 if (!sCommandHashtable->Get(aCommandName, &command)) {
264 return Command::DoNothing;
266 return command;
269 /******************************************************************************
270 * As*Event() implementation
271 ******************************************************************************/
273 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
274 #define NS_EVENT_CLASS(aPrefix, aName) \
275 aPrefix##aName* WidgetEvent::As##aName() { return nullptr; } \
277 const aPrefix##aName* WidgetEvent::As##aName() const { \
278 return const_cast<WidgetEvent*>(this)->As##aName(); \
281 #include "mozilla/EventClassList.h"
283 #undef NS_EVENT_CLASS
284 #undef NS_ROOT_EVENT_CLASS
286 /******************************************************************************
287 * mozilla::WidgetEvent
289 * Event struct type checking methods.
290 ******************************************************************************/
292 bool WidgetEvent::IsQueryContentEvent() const {
293 return mClass == eQueryContentEventClass;
296 bool WidgetEvent::IsSelectionEvent() const {
297 return mClass == eSelectionEventClass;
300 bool WidgetEvent::IsContentCommandEvent() const {
301 return mClass == eContentCommandEventClass;
304 /******************************************************************************
305 * mozilla::WidgetEvent
307 * Event message checking methods.
308 ******************************************************************************/
310 bool WidgetEvent::HasMouseEventMessage() const {
311 switch (mMessage) {
312 case eMouseDown:
313 case eMouseUp:
314 case eMouseClick:
315 case eMouseDoubleClick:
316 case eMouseAuxClick:
317 case eMouseEnterIntoWidget:
318 case eMouseExitFromWidget:
319 case eMouseActivate:
320 case eMouseOver:
321 case eMouseOut:
322 case eMouseHitTest:
323 case eMouseMove:
324 return true;
325 default:
326 return false;
330 bool WidgetEvent::HasDragEventMessage() const {
331 switch (mMessage) {
332 case eDragEnter:
333 case eDragOver:
334 case eDragExit:
335 case eDrag:
336 case eDragEnd:
337 case eDragStart:
338 case eDrop:
339 case eDragLeave:
340 return true;
341 default:
342 return false;
346 /* static */
347 bool WidgetEvent::IsKeyEventMessage(EventMessage aMessage) {
348 switch (aMessage) {
349 case eKeyDown:
350 case eKeyPress:
351 case eKeyUp:
352 case eKeyDownOnPlugin:
353 case eKeyUpOnPlugin:
354 case eAccessKeyNotFound:
355 return true;
356 default:
357 return false;
361 bool WidgetEvent::HasIMEEventMessage() const {
362 switch (mMessage) {
363 case eCompositionStart:
364 case eCompositionEnd:
365 case eCompositionUpdate:
366 case eCompositionChange:
367 case eCompositionCommitAsIs:
368 case eCompositionCommit:
369 return true;
370 default:
371 return false;
375 bool WidgetEvent::HasPluginActivationEventMessage() const {
376 return mMessage == ePluginActivate || mMessage == ePluginFocus;
379 /******************************************************************************
380 * mozilla::WidgetEvent
382 * Specific event checking methods.
383 ******************************************************************************/
385 bool WidgetEvent::CanBeSentToRemoteProcess() const {
386 // If this event is explicitly marked as shouldn't be sent to remote process,
387 // just return false.
388 if (IsCrossProcessForwardingStopped()) {
389 return false;
392 if (mClass == eKeyboardEventClass || mClass == eWheelEventClass) {
393 return true;
396 switch (mMessage) {
397 case eMouseDown:
398 case eMouseUp:
399 case eMouseMove:
400 case eMouseExploreByTouch:
401 case eContextMenu:
402 case eMouseEnterIntoWidget:
403 case eMouseExitFromWidget:
404 case eMouseTouchDrag:
405 case eTouchStart:
406 case eTouchMove:
407 case eTouchEnd:
408 case eTouchCancel:
409 case eDragOver:
410 case eDragExit:
411 case eDrop:
412 return true;
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 return EventStateManager::IsTopLevelRemoteTarget(
431 nsIContent::FromEventTarget(mOriginalTarget));
434 bool WidgetEvent::IsIMERelatedEvent() const {
435 return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
438 bool WidgetEvent::IsUsingCoordinates() const {
439 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
440 if (mouseEvent) {
441 return !mouseEvent->IsContextMenuKeyEvent();
443 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
444 !HasPluginActivationEventMessage() && !IsContentCommandEvent();
447 bool WidgetEvent::IsTargetedAtFocusedWindow() const {
448 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
449 if (mouseEvent) {
450 return mouseEvent->IsContextMenuKeyEvent();
452 return HasKeyEventMessage() || IsIMERelatedEvent() || IsContentCommandEvent();
455 bool WidgetEvent::IsTargetedAtFocusedContent() const {
456 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
457 if (mouseEvent) {
458 return mouseEvent->IsContextMenuKeyEvent();
460 return HasKeyEventMessage() || IsIMERelatedEvent();
463 bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
464 switch (mClass) {
465 case eMouseEventClass:
466 if (mMessage == eMouseTouchDrag) {
467 return false;
469 [[fallthrough]];
470 case ePointerEventClass:
471 // We want synthesized mouse moves to cause mouseover and mouseout
472 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
473 // DOM events.
474 // Synthesized button up events also do not cause DOM events because they
475 // do not have a reliable mRefPoint.
476 return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
478 case eWheelEventClass: {
479 // wheel event whose all delta values are zero by user pref applied, it
480 // shouldn't cause a DOM event.
481 const WidgetWheelEvent* wheelEvent = AsWheelEvent();
482 return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
483 wheelEvent->mDeltaZ != 0.0;
485 case eTouchEventClass:
486 return mMessage != eTouchPointerCancel;
487 // Following events are handled in EventStateManager, so, we don't need to
488 // dispatch DOM event for them into the DOM tree.
489 case eQueryContentEventClass:
490 case eSelectionEventClass:
491 case eContentCommandEventClass:
492 return false;
494 default:
495 return true;
499 bool WidgetEvent::IsAllowedToDispatchInSystemGroup() const {
500 // We don't expect to implement default behaviors with pointer events because
501 // if we do, prevent default on mouse events can't prevent default behaviors
502 // anymore.
503 return mClass != ePointerEventClass;
506 bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
507 if (!nsContentUtils::ShouldResistFingerprinting()) {
508 return false;
511 switch (mClass) {
512 case eKeyboardEventClass: {
513 const WidgetKeyboardEvent* keyboardEvent = AsKeyboardEvent();
515 return (keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Alt ||
516 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Shift ||
517 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Control ||
518 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_AltGraph);
520 case ePointerEventClass: {
521 const WidgetPointerEvent* pointerEvent = AsPointerEvent();
523 // We suppress the pointer events if it is not primary for fingerprinting
524 // resistance. It is because of that we want to spoof any pointer event
525 // into a mouse pointer event and the mouse pointer event only has
526 // isPrimary as true.
527 return !pointerEvent->mIsPrimary;
529 default:
530 return false;
534 /******************************************************************************
535 * mozilla::WidgetEvent
537 * Misc methods.
538 ******************************************************************************/
540 static dom::EventTarget* GetTargetForDOMEvent(dom::EventTarget* aTarget) {
541 return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
544 dom::EventTarget* WidgetEvent::GetDOMEventTarget() const {
545 return GetTargetForDOMEvent(mTarget);
548 dom::EventTarget* WidgetEvent::GetCurrentDOMEventTarget() const {
549 return GetTargetForDOMEvent(mCurrentTarget);
552 dom::EventTarget* WidgetEvent::GetOriginalDOMEventTarget() const {
553 if (mOriginalTarget) {
554 return GetTargetForDOMEvent(mOriginalTarget);
556 return GetDOMEventTarget();
559 void WidgetEvent::PreventDefault(bool aCalledByDefaultHandler,
560 nsIPrincipal* aPrincipal) {
561 if (mMessage == ePointerDown) {
562 if (aCalledByDefaultHandler) {
563 // Shouldn't prevent default on pointerdown by default handlers to stop
564 // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages
565 // in debug builds.
566 MOZ_ASSERT(false);
567 return;
569 if (aPrincipal) {
570 nsAutoString addonId;
571 Unused << NS_WARN_IF(NS_FAILED(aPrincipal->GetAddonId(addonId)));
572 if (!addonId.IsEmpty()) {
573 // Ignore the case that it's called by a web extension.
574 return;
578 mFlags.PreventDefault(aCalledByDefaultHandler);
581 bool WidgetEvent::IsUserAction() const {
582 if (!IsTrusted()) {
583 return false;
585 // FYI: eMouseScrollEventClass and ePointerEventClass represent
586 // user action but they are synthesized events.
587 switch (mClass) {
588 case eKeyboardEventClass:
589 case eCompositionEventClass:
590 case eMouseScrollEventClass:
591 case eWheelEventClass:
592 case eGestureNotifyEventClass:
593 case eSimpleGestureEventClass:
594 case eTouchEventClass:
595 case eCommandEventClass:
596 case eContentCommandEventClass:
597 return true;
598 case eMouseEventClass:
599 case eDragEventClass:
600 case ePointerEventClass:
601 return AsMouseEvent()->IsReal();
602 default:
603 return false;
607 /******************************************************************************
608 * mozilla::WidgetInputEvent
609 ******************************************************************************/
611 /* static */
612 Modifier WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName) {
613 if (aDOMKeyName.EqualsLiteral("Accel")) {
614 return AccelModifier();
616 KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName);
617 return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex);
620 /* static */
621 Modifier WidgetInputEvent::AccelModifier() {
622 static Modifier sAccelModifier = MODIFIER_NONE;
623 if (sAccelModifier == MODIFIER_NONE) {
624 switch (Preferences::GetInt("ui.key.accelKey", 0)) {
625 case dom::KeyboardEvent_Binding::DOM_VK_META:
626 sAccelModifier = MODIFIER_META;
627 break;
628 case dom::KeyboardEvent_Binding::DOM_VK_WIN:
629 sAccelModifier = MODIFIER_OS;
630 break;
631 case dom::KeyboardEvent_Binding::DOM_VK_ALT:
632 sAccelModifier = MODIFIER_ALT;
633 break;
634 case dom::KeyboardEvent_Binding::DOM_VK_CONTROL:
635 sAccelModifier = MODIFIER_CONTROL;
636 break;
637 default:
638 #ifdef XP_MACOSX
639 sAccelModifier = MODIFIER_META;
640 #else
641 sAccelModifier = MODIFIER_CONTROL;
642 #endif
643 break;
646 return sAccelModifier;
649 /******************************************************************************
650 * mozilla::WidgetMouseEvent (MouseEvents.h)
651 ******************************************************************************/
653 /* static */
654 bool WidgetMouseEvent::IsMiddleClickPasteEnabled() {
655 return Preferences::GetBool("middlemouse.paste", false);
658 #ifdef DEBUG
659 void WidgetMouseEvent::AssertContextMenuEventButtonConsistency() const {
660 if (mMessage != eContextMenu) {
661 return;
664 if (mContextMenuTrigger == eNormal) {
665 NS_WARNING_ASSERTION(mButton == MouseButton::eSecondary,
666 "eContextMenu events with eNormal trigger should use "
667 "secondary mouse button");
668 } else {
669 NS_WARNING_ASSERTION(mButton == MouseButton::ePrimary,
670 "eContextMenu events with non-eNormal trigger should "
671 "use primary mouse button");
674 if (mContextMenuTrigger == eControlClick) {
675 NS_WARNING_ASSERTION(IsControl(),
676 "eContextMenu events with eControlClick trigger "
677 "should return true from IsControl()");
680 #endif
682 /******************************************************************************
683 * mozilla::WidgetDragEvent (MouseEvents.h)
684 ******************************************************************************/
686 void WidgetDragEvent::InitDropEffectForTests() {
687 MOZ_ASSERT(mFlags.mIsSynthesizedForTests);
689 nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
690 if (NS_WARN_IF(!session)) {
691 return;
694 uint32_t effectAllowed = session->GetEffectAllowedForTests();
695 uint32_t desiredDropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
696 #ifdef XP_MACOSX
697 if (IsAlt()) {
698 desiredDropEffect = IsMeta() ? nsIDragService::DRAGDROP_ACTION_LINK
699 : nsIDragService::DRAGDROP_ACTION_COPY;
701 #else
702 // On Linux, we know user's intention from API, but we should use
703 // same modifiers as Windows for tests because GNOME on Ubuntu use
704 // them and that makes each test simpler.
705 if (IsControl()) {
706 desiredDropEffect = IsShift() ? nsIDragService::DRAGDROP_ACTION_LINK
707 : nsIDragService::DRAGDROP_ACTION_COPY;
708 } else if (IsShift()) {
709 desiredDropEffect = nsIDragService::DRAGDROP_ACTION_MOVE;
711 #endif // #ifdef XP_MACOSX #else
712 // First, use modifier state for preferring action which is explicitly
713 // specified by the synthesizer.
714 if (!(desiredDropEffect &= effectAllowed)) {
715 // Otherwise, use an action which is allowed at starting the session.
716 desiredDropEffect = effectAllowed;
718 if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_MOVE) {
719 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE);
720 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_COPY) {
721 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY);
722 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_LINK) {
723 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK);
724 } else {
725 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_NONE);
729 /******************************************************************************
730 * mozilla::WidgetWheelEvent (MouseEvents.h)
731 ******************************************************************************/
733 /* static */
734 double WidgetWheelEvent::ComputeOverriddenDelta(double aDelta,
735 bool aIsForVertical) {
736 if (!StaticPrefs::mousewheel_system_scroll_override_enabled()) {
737 return aDelta;
739 int32_t intFactor =
740 aIsForVertical
741 ? StaticPrefs::mousewheel_system_scroll_override_vertical_factor()
742 : StaticPrefs::mousewheel_system_scroll_override_horizontal_factor();
743 // Making the scroll speed slower doesn't make sense. So, ignore odd factor
744 // which is less than 1.0.
745 if (intFactor <= 100) {
746 return aDelta;
748 double factor = static_cast<double>(intFactor) / 100;
749 return aDelta * factor;
752 double WidgetWheelEvent::OverriddenDeltaX() const {
753 if (!mAllowToOverrideSystemScrollSpeed ||
754 mDeltaMode != dom::WheelEvent_Binding::DOM_DELTA_LINE ||
755 mCustomizedByUserPrefs) {
756 return mDeltaX;
758 return ComputeOverriddenDelta(mDeltaX, false);
761 double WidgetWheelEvent::OverriddenDeltaY() const {
762 if (!mAllowToOverrideSystemScrollSpeed ||
763 mDeltaMode != dom::WheelEvent_Binding::DOM_DELTA_LINE ||
764 mCustomizedByUserPrefs) {
765 return mDeltaY;
767 return ComputeOverriddenDelta(mDeltaY, true);
770 /******************************************************************************
771 * mozilla::WidgetKeyboardEvent (TextEvents.h)
772 ******************************************************************************/
774 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
775 const char16_t* const WidgetKeyboardEvent::kKeyNames[] = {
776 #include "mozilla/KeyNameList.h"
778 #undef NS_DEFINE_KEYNAME
780 #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
781 (u"" aDOMCodeName),
782 const char16_t* const WidgetKeyboardEvent::kCodeNames[] = {
783 #include "mozilla/PhysicalKeyCodeNameList.h"
785 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
787 WidgetKeyboardEvent::KeyNameIndexHashtable*
788 WidgetKeyboardEvent::sKeyNameIndexHashtable = nullptr;
789 WidgetKeyboardEvent::CodeNameIndexHashtable*
790 WidgetKeyboardEvent::sCodeNameIndexHashtable = nullptr;
792 void WidgetKeyboardEvent::InitAllEditCommands(
793 const Maybe<WritingMode>& aWritingMode) {
794 // If this event is synthesized for tests, we don't need to retrieve the
795 // command via the main process. So, we don't need widget and can trust
796 // the event.
797 if (!mFlags.mIsSynthesizedForTests) {
798 // If the event was created without widget, e.g., created event in chrome
799 // script, this shouldn't execute native key bindings.
800 if (NS_WARN_IF(!mWidget)) {
801 return;
804 // This event should be trusted event here and we shouldn't expose native
805 // key binding information to web contents with untrusted events.
806 if (NS_WARN_IF(!IsTrusted())) {
807 return;
810 MOZ_ASSERT(
811 XRE_IsParentProcess(),
812 "It's too expensive to retrieve all edit commands from remote process");
813 MOZ_ASSERT(!AreAllEditCommandsInitialized(),
814 "Shouldn't be called two or more times");
817 DebugOnly<bool> okIgnored = InitEditCommandsFor(
818 NativeKeyBindingsType::SingleLineEditor, aWritingMode);
819 NS_WARNING_ASSERTION(okIgnored,
820 "InitEditCommandsFor(NativeKeyBindingsType::"
821 "SingleLineEditor) failed, but ignored");
822 okIgnored =
823 InitEditCommandsFor(NativeKeyBindingsType::MultiLineEditor, aWritingMode);
824 NS_WARNING_ASSERTION(okIgnored,
825 "InitEditCommandsFor(NativeKeyBindingsType::"
826 "MultiLineEditor) failed, but ignored");
827 okIgnored =
828 InitEditCommandsFor(NativeKeyBindingsType::RichTextEditor, aWritingMode);
829 NS_WARNING_ASSERTION(okIgnored,
830 "InitEditCommandsFor(NativeKeyBindingsType::"
831 "RichTextEditor) failed, but ignored");
834 bool WidgetKeyboardEvent::InitEditCommandsFor(
835 NativeKeyBindingsType aType, const Maybe<WritingMode>& aWritingMode) {
836 bool& initialized = IsEditCommandsInitializedRef(aType);
837 if (initialized) {
838 return true;
840 nsTArray<CommandInt>& commands = EditCommandsRef(aType);
842 // If this event is synthesized for tests, we shouldn't access customized
843 // shortcut settings of the environment. Therefore, we don't need to check
844 // whether `widget` is set or not. And we can treat synthesized events are
845 // always trusted.
846 if (mFlags.mIsSynthesizedForTests) {
847 MOZ_DIAGNOSTIC_ASSERT(IsTrusted());
848 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
849 // TODO: We should implement `NativeKeyBindings` for Windows and Android
850 // too in bug 1301497 for getting rid of the #if.
851 widget::NativeKeyBindings::GetEditCommandsForTests(aType, *this,
852 aWritingMode, commands);
853 #endif
854 initialized = true;
855 return true;
858 if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
859 return false;
861 // `nsIWidget::GetEditCommands()` will retrieve `WritingMode` at selection
862 // again, but it should be almost zero-cost since `TextEventDispatcher`
863 // caches the value.
864 nsCOMPtr<nsIWidget> widget = mWidget;
865 initialized = widget->GetEditCommands(aType, *this, commands);
866 return initialized;
869 bool WidgetKeyboardEvent::ExecuteEditCommands(NativeKeyBindingsType aType,
870 DoCommandCallback aCallback,
871 void* aCallbackData) {
872 // If the event was created without widget, e.g., created event in chrome
873 // script, this shouldn't execute native key bindings.
874 if (NS_WARN_IF(!mWidget)) {
875 return false;
878 // This event should be trusted event here and we shouldn't expose native
879 // key binding information to web contents with untrusted events.
880 if (NS_WARN_IF(!IsTrusted())) {
881 return false;
884 if (!IsEditCommandsInitializedRef(aType)) {
885 Maybe<WritingMode> writingMode;
886 if (RefPtr<widget::TextEventDispatcher> textEventDispatcher =
887 mWidget->GetTextEventDispatcher()) {
888 writingMode = textEventDispatcher->MaybeQueryWritingModeAtSelection();
890 if (NS_WARN_IF(!InitEditCommandsFor(aType, writingMode))) {
891 return false;
895 const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
896 if (commands.IsEmpty()) {
897 return false;
900 for (CommandInt command : commands) {
901 aCallback(static_cast<Command>(command), aCallbackData);
903 return true;
906 bool WidgetKeyboardEvent::ShouldCauseKeypressEvents() const {
907 // Currently, we don't dispatch keypress events of modifier keys and
908 // dead keys.
909 switch (mKeyNameIndex) {
910 case KEY_NAME_INDEX_Alt:
911 case KEY_NAME_INDEX_AltGraph:
912 case KEY_NAME_INDEX_CapsLock:
913 case KEY_NAME_INDEX_Control:
914 case KEY_NAME_INDEX_Fn:
915 case KEY_NAME_INDEX_FnLock:
916 // case KEY_NAME_INDEX_Hyper:
917 case KEY_NAME_INDEX_Meta:
918 case KEY_NAME_INDEX_NumLock:
919 case KEY_NAME_INDEX_OS:
920 case KEY_NAME_INDEX_ScrollLock:
921 case KEY_NAME_INDEX_Shift:
922 // case KEY_NAME_INDEX_Super:
923 case KEY_NAME_INDEX_Symbol:
924 case KEY_NAME_INDEX_SymbolLock:
925 case KEY_NAME_INDEX_Dead:
926 return false;
927 default:
928 return true;
932 static bool HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates) {
933 for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
934 uint32_t ch = aCandidates[i].mCharCode;
935 if (ch >= '0' && ch <= '9') return true;
937 return false;
940 static bool CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2) {
941 return aChar1 == aChar2 || (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
942 ToLowerCase(static_cast<char16_t>(aChar1)) ==
943 ToLowerCase(static_cast<char16_t>(aChar2)));
946 static bool IsCaseChangeableChar(uint32_t aChar) {
947 return IS_IN_BMP(aChar) && ToLowerCase(static_cast<char16_t>(aChar)) !=
948 ToUpperCase(static_cast<char16_t>(aChar));
951 void WidgetKeyboardEvent::GetShortcutKeyCandidates(
952 ShortcutKeyCandidateArray& aCandidates) const {
953 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
955 // ShortcutKeyCandidate::mCharCode is a candidate charCode.
956 // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
957 // execute a command with/without shift key state. If this is TRUE, the
958 // shifted key state should be ignored. Otherwise, don't ignore the state.
959 // the priority of the charCodes are (shift key is not pressed):
960 // 0: PseudoCharCode()/false,
961 // 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
962 // the priority of the charCodes are (shift key is pressed):
963 // 0: PseudoCharCode()/false,
964 // 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
965 // 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
966 uint32_t pseudoCharCode = PseudoCharCode();
967 if (pseudoCharCode) {
968 ShortcutKeyCandidate key(pseudoCharCode, false);
969 aCandidates.AppendElement(key);
972 uint32_t len = mAlternativeCharCodes.Length();
973 if (!IsShift()) {
974 for (uint32_t i = 0; i < len; ++i) {
975 uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
976 if (!ch || ch == pseudoCharCode) {
977 continue;
979 ShortcutKeyCandidate key(ch, false);
980 aCandidates.AppendElement(key);
982 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
983 // this keyboard layout is AZERTY or similar layout, probably.
984 // In this case, Accel+[0-9] should be accessible without shift key.
985 // However, the priority should be lowest.
986 if (!HasASCIIDigit(aCandidates)) {
987 for (uint32_t i = 0; i < len; ++i) {
988 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
989 if (ch >= '0' && ch <= '9') {
990 ShortcutKeyCandidate key(ch, false);
991 aCandidates.AppendElement(key);
992 break;
996 } else {
997 for (uint32_t i = 0; i < len; ++i) {
998 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
999 if (!ch) {
1000 continue;
1003 if (ch != pseudoCharCode) {
1004 ShortcutKeyCandidate key(ch, false);
1005 aCandidates.AppendElement(key);
1008 // If the char is an alphabet, the shift key state should not be
1009 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
1011 // And checking the charCode is same as unshiftedCharCode too.
1012 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
1013 uint32_t unshiftCh = mAlternativeCharCodes[i].mUnshiftedCharCode;
1014 if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
1015 continue;
1018 // On the Hebrew keyboard layout on Windows, the unshifted char is a
1019 // localized character but the shifted char is a Latin alphabet,
1020 // then, we should not execute without the shift state. See bug 433192.
1021 if (IsCaseChangeableChar(ch)) {
1022 continue;
1025 // Setting the alternative charCode candidates for retry without shift
1026 // key state only when the shift key is pressed.
1027 ShortcutKeyCandidate key(ch, true);
1028 aCandidates.AppendElement(key);
1032 // Special case for "Space" key. With some keyboard layouts, "Space" with
1033 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1034 // we should guarantee that the key press works as an ASCII white space key
1035 // press. However, if the space key is assigned to a function key, it
1036 // shouldn't work as a space key.
1037 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1038 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1039 ShortcutKeyCandidate spaceKey(' ', false);
1040 aCandidates.AppendElement(spaceKey);
1044 void WidgetKeyboardEvent::GetAccessKeyCandidates(
1045 nsTArray<uint32_t>& aCandidates) const {
1046 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
1048 // return the lower cased charCode candidates for access keys.
1049 // the priority of the charCodes are:
1050 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
1051 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
1052 uint32_t pseudoCharCode = PseudoCharCode();
1053 if (pseudoCharCode) {
1054 uint32_t ch = pseudoCharCode;
1055 if (IS_IN_BMP(ch)) {
1056 ch = ToLowerCase(static_cast<char16_t>(ch));
1058 aCandidates.AppendElement(ch);
1060 for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
1061 uint32_t ch[2] = {mAlternativeCharCodes[i].mUnshiftedCharCode,
1062 mAlternativeCharCodes[i].mShiftedCharCode};
1063 for (uint32_t j = 0; j < 2; ++j) {
1064 if (!ch[j]) {
1065 continue;
1067 if (IS_IN_BMP(ch[j])) {
1068 ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
1070 // Don't append the charcode that was already appended.
1071 if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
1072 aCandidates.AppendElement(ch[j]);
1076 // Special case for "Space" key. With some keyboard layouts, "Space" with
1077 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1078 // we should guarantee that the key press works as an ASCII white space key
1079 // press. However, if the space key is assigned to a function key, it
1080 // shouldn't work as a space key.
1081 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1082 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1083 aCandidates.AppendElement(' ');
1087 // mask values for ui.key.chromeAccess and ui.key.contentAccess
1088 #define NS_MODIFIER_SHIFT 1
1089 #define NS_MODIFIER_CONTROL 2
1090 #define NS_MODIFIER_ALT 4
1091 #define NS_MODIFIER_META 8
1092 #define NS_MODIFIER_OS 16
1094 static Modifiers PrefFlagsToModifiers(int32_t aPrefFlags) {
1095 Modifiers result = 0;
1096 if (aPrefFlags & NS_MODIFIER_SHIFT) {
1097 result |= MODIFIER_SHIFT;
1099 if (aPrefFlags & NS_MODIFIER_CONTROL) {
1100 result |= MODIFIER_CONTROL;
1102 if (aPrefFlags & NS_MODIFIER_ALT) {
1103 result |= MODIFIER_ALT;
1105 if (aPrefFlags & NS_MODIFIER_META) {
1106 result |= MODIFIER_META;
1108 if (aPrefFlags & NS_MODIFIER_OS) {
1109 result |= MODIFIER_OS;
1111 return result;
1114 bool WidgetKeyboardEvent::ModifiersMatchWithAccessKey(
1115 AccessKeyType aType) const {
1116 if (!ModifiersForAccessKeyMatching()) {
1117 return false;
1119 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
1122 Modifiers WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const {
1123 static const Modifiers kModifierMask = MODIFIER_SHIFT | MODIFIER_CONTROL |
1124 MODIFIER_ALT | MODIFIER_META |
1125 MODIFIER_OS;
1126 return mModifiers & kModifierMask;
1129 /* static */
1130 Modifiers WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType) {
1131 switch (StaticPrefs::ui_key_generalAccessKey()) {
1132 case -1:
1133 break; // use the individual prefs
1134 case NS_VK_SHIFT:
1135 return MODIFIER_SHIFT;
1136 case NS_VK_CONTROL:
1137 return MODIFIER_CONTROL;
1138 case NS_VK_ALT:
1139 return MODIFIER_ALT;
1140 case NS_VK_META:
1141 return MODIFIER_META;
1142 case NS_VK_WIN:
1143 return MODIFIER_OS;
1144 default:
1145 return MODIFIER_NONE;
1148 switch (aType) {
1149 case AccessKeyType::eChrome:
1150 return PrefFlagsToModifiers(StaticPrefs::ui_key_chromeAccess());
1151 case AccessKeyType::eContent:
1152 return PrefFlagsToModifiers(StaticPrefs::ui_key_contentAccess());
1153 default:
1154 return MODIFIER_NONE;
1158 /* static */
1159 void WidgetKeyboardEvent::Shutdown() {
1160 delete sKeyNameIndexHashtable;
1161 sKeyNameIndexHashtable = nullptr;
1162 delete sCodeNameIndexHashtable;
1163 sCodeNameIndexHashtable = nullptr;
1164 // Although sCommandHashtable is not a member of WidgetKeyboardEvent, but
1165 // let's delete it here since we need to do it at same time.
1166 delete sCommandHashtable;
1167 sCommandHashtable = nullptr;
1170 /* static */
1171 void WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
1172 nsAString& aKeyName) {
1173 if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
1174 aKeyName.Truncate();
1175 return;
1178 MOZ_RELEASE_ASSERT(
1179 static_cast<size_t>(aKeyNameIndex) < ArrayLength(kKeyNames),
1180 "Illegal key enumeration value");
1181 aKeyName = kKeyNames[aKeyNameIndex];
1184 /* static */
1185 void WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
1186 nsAString& aCodeName) {
1187 if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
1188 aCodeName.Truncate();
1189 return;
1192 MOZ_RELEASE_ASSERT(
1193 static_cast<size_t>(aCodeNameIndex) < ArrayLength(kCodeNames),
1194 "Illegal physical code enumeration value");
1195 aCodeName = kCodeNames[aCodeNameIndex];
1198 /* static */
1199 KeyNameIndex WidgetKeyboardEvent::GetKeyNameIndex(const nsAString& aKeyValue) {
1200 if (!sKeyNameIndexHashtable) {
1201 sKeyNameIndexHashtable = new KeyNameIndexHashtable(ArrayLength(kKeyNames));
1202 for (size_t i = 0; i < ArrayLength(kKeyNames); i++) {
1203 sKeyNameIndexHashtable->InsertOrUpdate(nsDependentString(kKeyNames[i]),
1204 static_cast<KeyNameIndex>(i));
1207 return sKeyNameIndexHashtable->MaybeGet(aKeyValue).valueOr(
1208 KEY_NAME_INDEX_USE_STRING);
1211 /* static */
1212 CodeNameIndex WidgetKeyboardEvent::GetCodeNameIndex(
1213 const nsAString& aCodeValue) {
1214 if (!sCodeNameIndexHashtable) {
1215 sCodeNameIndexHashtable =
1216 new CodeNameIndexHashtable(ArrayLength(kCodeNames));
1217 for (size_t i = 0; i < ArrayLength(kCodeNames); i++) {
1218 sCodeNameIndexHashtable->InsertOrUpdate(nsDependentString(kCodeNames[i]),
1219 static_cast<CodeNameIndex>(i));
1222 return sCodeNameIndexHashtable->MaybeGet(aCodeValue)
1223 .valueOr(CODE_NAME_INDEX_USE_STRING);
1226 /* static */
1227 uint32_t WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(
1228 CodeNameIndex aCodeNameIndex) {
1229 switch (aCodeNameIndex) {
1230 case CODE_NAME_INDEX_Semicolon: // VK_OEM_1 on Windows
1231 return dom::KeyboardEvent_Binding::DOM_VK_SEMICOLON;
1232 case CODE_NAME_INDEX_Equal: // VK_OEM_PLUS on Windows
1233 return dom::KeyboardEvent_Binding::DOM_VK_EQUALS;
1234 case CODE_NAME_INDEX_Comma: // VK_OEM_COMMA on Windows
1235 return dom::KeyboardEvent_Binding::DOM_VK_COMMA;
1236 case CODE_NAME_INDEX_Minus: // VK_OEM_MINUS on Windows
1237 return dom::KeyboardEvent_Binding::DOM_VK_HYPHEN_MINUS;
1238 case CODE_NAME_INDEX_Period: // VK_OEM_PERIOD on Windows
1239 return dom::KeyboardEvent_Binding::DOM_VK_PERIOD;
1240 case CODE_NAME_INDEX_Slash: // VK_OEM_2 on Windows
1241 return dom::KeyboardEvent_Binding::DOM_VK_SLASH;
1242 case CODE_NAME_INDEX_Backquote: // VK_OEM_3 on Windows
1243 return dom::KeyboardEvent_Binding::DOM_VK_BACK_QUOTE;
1244 case CODE_NAME_INDEX_BracketLeft: // VK_OEM_4 on Windows
1245 return dom::KeyboardEvent_Binding::DOM_VK_OPEN_BRACKET;
1246 case CODE_NAME_INDEX_Backslash: // VK_OEM_5 on Windows
1247 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1248 case CODE_NAME_INDEX_BracketRight: // VK_OEM_6 on Windows
1249 return dom::KeyboardEvent_Binding::DOM_VK_CLOSE_BRACKET;
1250 case CODE_NAME_INDEX_Quote: // VK_OEM_7 on Windows
1251 return dom::KeyboardEvent_Binding::DOM_VK_QUOTE;
1252 case CODE_NAME_INDEX_IntlBackslash: // VK_OEM_5 on Windows (ABNT, etc)
1253 case CODE_NAME_INDEX_IntlYen: // VK_OEM_5 on Windows (JIS)
1254 case CODE_NAME_INDEX_IntlRo: // VK_OEM_102 on Windows
1255 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1256 default:
1257 return 0;
1261 /* static */ const char* WidgetKeyboardEvent::GetCommandStr(Command aCommand) {
1262 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1263 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) , #aCommandStr
1264 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) , ""
1265 static const char* const kCommands[] = {
1266 "" // DoNothing
1267 #include "mozilla/CommandList.h"
1269 #undef NS_DEFINE_COMMAND
1270 #undef NS_DEFINE_COMMAND_WITH_PARAM
1271 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
1273 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand) < ArrayLength(kCommands),
1274 "Illegal command enumeration value");
1275 return kCommands[static_cast<CommandInt>(aCommand)];
1278 /* static */
1279 uint32_t WidgetKeyboardEvent::ComputeLocationFromCodeValue(
1280 CodeNameIndex aCodeNameIndex) {
1281 // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1282 // but are defined by D3E spec. So, they should be uncommented when the
1283 // code values are defined in the header.
1284 switch (aCodeNameIndex) {
1285 case CODE_NAME_INDEX_AltLeft:
1286 case CODE_NAME_INDEX_ControlLeft:
1287 case CODE_NAME_INDEX_OSLeft:
1288 case CODE_NAME_INDEX_ShiftLeft:
1289 return eKeyLocationLeft;
1290 case CODE_NAME_INDEX_AltRight:
1291 case CODE_NAME_INDEX_ControlRight:
1292 case CODE_NAME_INDEX_OSRight:
1293 case CODE_NAME_INDEX_ShiftRight:
1294 return eKeyLocationRight;
1295 case CODE_NAME_INDEX_Numpad0:
1296 case CODE_NAME_INDEX_Numpad1:
1297 case CODE_NAME_INDEX_Numpad2:
1298 case CODE_NAME_INDEX_Numpad3:
1299 case CODE_NAME_INDEX_Numpad4:
1300 case CODE_NAME_INDEX_Numpad5:
1301 case CODE_NAME_INDEX_Numpad6:
1302 case CODE_NAME_INDEX_Numpad7:
1303 case CODE_NAME_INDEX_Numpad8:
1304 case CODE_NAME_INDEX_Numpad9:
1305 case CODE_NAME_INDEX_NumpadAdd:
1306 case CODE_NAME_INDEX_NumpadBackspace:
1307 case CODE_NAME_INDEX_NumpadClear:
1308 case CODE_NAME_INDEX_NumpadClearEntry:
1309 case CODE_NAME_INDEX_NumpadComma:
1310 case CODE_NAME_INDEX_NumpadDecimal:
1311 case CODE_NAME_INDEX_NumpadDivide:
1312 case CODE_NAME_INDEX_NumpadEnter:
1313 case CODE_NAME_INDEX_NumpadEqual:
1314 case CODE_NAME_INDEX_NumpadMemoryAdd:
1315 case CODE_NAME_INDEX_NumpadMemoryClear:
1316 case CODE_NAME_INDEX_NumpadMemoryRecall:
1317 case CODE_NAME_INDEX_NumpadMemoryStore:
1318 case CODE_NAME_INDEX_NumpadMemorySubtract:
1319 case CODE_NAME_INDEX_NumpadMultiply:
1320 case CODE_NAME_INDEX_NumpadParenLeft:
1321 case CODE_NAME_INDEX_NumpadParenRight:
1322 case CODE_NAME_INDEX_NumpadSubtract:
1323 return eKeyLocationNumpad;
1324 default:
1325 return eKeyLocationStandard;
1329 /* static */
1330 uint32_t WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(
1331 KeyNameIndex aKeyNameIndex) {
1332 switch (aKeyNameIndex) {
1333 case KEY_NAME_INDEX_Cancel:
1334 return dom::KeyboardEvent_Binding::DOM_VK_CANCEL;
1335 case KEY_NAME_INDEX_Help:
1336 return dom::KeyboardEvent_Binding::DOM_VK_HELP;
1337 case KEY_NAME_INDEX_Backspace:
1338 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SPACE;
1339 case KEY_NAME_INDEX_Tab:
1340 return dom::KeyboardEvent_Binding::DOM_VK_TAB;
1341 case KEY_NAME_INDEX_Clear:
1342 return dom::KeyboardEvent_Binding::DOM_VK_CLEAR;
1343 case KEY_NAME_INDEX_Enter:
1344 return dom::KeyboardEvent_Binding::DOM_VK_RETURN;
1345 case KEY_NAME_INDEX_Shift:
1346 return dom::KeyboardEvent_Binding::DOM_VK_SHIFT;
1347 case KEY_NAME_INDEX_Control:
1348 return dom::KeyboardEvent_Binding::DOM_VK_CONTROL;
1349 case KEY_NAME_INDEX_Alt:
1350 return dom::KeyboardEvent_Binding::DOM_VK_ALT;
1351 case KEY_NAME_INDEX_Pause:
1352 return dom::KeyboardEvent_Binding::DOM_VK_PAUSE;
1353 case KEY_NAME_INDEX_CapsLock:
1354 return dom::KeyboardEvent_Binding::DOM_VK_CAPS_LOCK;
1355 case KEY_NAME_INDEX_Hiragana:
1356 case KEY_NAME_INDEX_Katakana:
1357 case KEY_NAME_INDEX_HiraganaKatakana:
1358 case KEY_NAME_INDEX_KanaMode:
1359 return dom::KeyboardEvent_Binding::DOM_VK_KANA;
1360 case KEY_NAME_INDEX_HangulMode:
1361 return dom::KeyboardEvent_Binding::DOM_VK_HANGUL;
1362 case KEY_NAME_INDEX_Eisu:
1363 return dom::KeyboardEvent_Binding::DOM_VK_EISU;
1364 case KEY_NAME_INDEX_JunjaMode:
1365 return dom::KeyboardEvent_Binding::DOM_VK_JUNJA;
1366 case KEY_NAME_INDEX_FinalMode:
1367 return dom::KeyboardEvent_Binding::DOM_VK_FINAL;
1368 case KEY_NAME_INDEX_HanjaMode:
1369 return dom::KeyboardEvent_Binding::DOM_VK_HANJA;
1370 case KEY_NAME_INDEX_KanjiMode:
1371 return dom::KeyboardEvent_Binding::DOM_VK_KANJI;
1372 case KEY_NAME_INDEX_Escape:
1373 return dom::KeyboardEvent_Binding::DOM_VK_ESCAPE;
1374 case KEY_NAME_INDEX_Convert:
1375 return dom::KeyboardEvent_Binding::DOM_VK_CONVERT;
1376 case KEY_NAME_INDEX_NonConvert:
1377 return dom::KeyboardEvent_Binding::DOM_VK_NONCONVERT;
1378 case KEY_NAME_INDEX_Accept:
1379 return dom::KeyboardEvent_Binding::DOM_VK_ACCEPT;
1380 case KEY_NAME_INDEX_ModeChange:
1381 return dom::KeyboardEvent_Binding::DOM_VK_MODECHANGE;
1382 case KEY_NAME_INDEX_PageUp:
1383 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_UP;
1384 case KEY_NAME_INDEX_PageDown:
1385 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_DOWN;
1386 case KEY_NAME_INDEX_End:
1387 return dom::KeyboardEvent_Binding::DOM_VK_END;
1388 case KEY_NAME_INDEX_Home:
1389 return dom::KeyboardEvent_Binding::DOM_VK_HOME;
1390 case KEY_NAME_INDEX_ArrowLeft:
1391 return dom::KeyboardEvent_Binding::DOM_VK_LEFT;
1392 case KEY_NAME_INDEX_ArrowUp:
1393 return dom::KeyboardEvent_Binding::DOM_VK_UP;
1394 case KEY_NAME_INDEX_ArrowRight:
1395 return dom::KeyboardEvent_Binding::DOM_VK_RIGHT;
1396 case KEY_NAME_INDEX_ArrowDown:
1397 return dom::KeyboardEvent_Binding::DOM_VK_DOWN;
1398 case KEY_NAME_INDEX_Select:
1399 return dom::KeyboardEvent_Binding::DOM_VK_SELECT;
1400 case KEY_NAME_INDEX_Print:
1401 return dom::KeyboardEvent_Binding::DOM_VK_PRINT;
1402 case KEY_NAME_INDEX_Execute:
1403 return dom::KeyboardEvent_Binding::DOM_VK_EXECUTE;
1404 case KEY_NAME_INDEX_PrintScreen:
1405 return dom::KeyboardEvent_Binding::DOM_VK_PRINTSCREEN;
1406 case KEY_NAME_INDEX_Insert:
1407 return dom::KeyboardEvent_Binding::DOM_VK_INSERT;
1408 case KEY_NAME_INDEX_Delete:
1409 return dom::KeyboardEvent_Binding::DOM_VK_DELETE;
1410 case KEY_NAME_INDEX_OS:
1411 // case KEY_NAME_INDEX_Super:
1412 // case KEY_NAME_INDEX_Hyper:
1413 return dom::KeyboardEvent_Binding::DOM_VK_WIN;
1414 case KEY_NAME_INDEX_ContextMenu:
1415 return dom::KeyboardEvent_Binding::DOM_VK_CONTEXT_MENU;
1416 case KEY_NAME_INDEX_Standby:
1417 return dom::KeyboardEvent_Binding::DOM_VK_SLEEP;
1418 case KEY_NAME_INDEX_F1:
1419 return dom::KeyboardEvent_Binding::DOM_VK_F1;
1420 case KEY_NAME_INDEX_F2:
1421 return dom::KeyboardEvent_Binding::DOM_VK_F2;
1422 case KEY_NAME_INDEX_F3:
1423 return dom::KeyboardEvent_Binding::DOM_VK_F3;
1424 case KEY_NAME_INDEX_F4:
1425 return dom::KeyboardEvent_Binding::DOM_VK_F4;
1426 case KEY_NAME_INDEX_F5:
1427 return dom::KeyboardEvent_Binding::DOM_VK_F5;
1428 case KEY_NAME_INDEX_F6:
1429 return dom::KeyboardEvent_Binding::DOM_VK_F6;
1430 case KEY_NAME_INDEX_F7:
1431 return dom::KeyboardEvent_Binding::DOM_VK_F7;
1432 case KEY_NAME_INDEX_F8:
1433 return dom::KeyboardEvent_Binding::DOM_VK_F8;
1434 case KEY_NAME_INDEX_F9:
1435 return dom::KeyboardEvent_Binding::DOM_VK_F9;
1436 case KEY_NAME_INDEX_F10:
1437 return dom::KeyboardEvent_Binding::DOM_VK_F10;
1438 case KEY_NAME_INDEX_F11:
1439 return dom::KeyboardEvent_Binding::DOM_VK_F11;
1440 case KEY_NAME_INDEX_F12:
1441 return dom::KeyboardEvent_Binding::DOM_VK_F12;
1442 case KEY_NAME_INDEX_F13:
1443 return dom::KeyboardEvent_Binding::DOM_VK_F13;
1444 case KEY_NAME_INDEX_F14:
1445 return dom::KeyboardEvent_Binding::DOM_VK_F14;
1446 case KEY_NAME_INDEX_F15:
1447 return dom::KeyboardEvent_Binding::DOM_VK_F15;
1448 case KEY_NAME_INDEX_F16:
1449 return dom::KeyboardEvent_Binding::DOM_VK_F16;
1450 case KEY_NAME_INDEX_F17:
1451 return dom::KeyboardEvent_Binding::DOM_VK_F17;
1452 case KEY_NAME_INDEX_F18:
1453 return dom::KeyboardEvent_Binding::DOM_VK_F18;
1454 case KEY_NAME_INDEX_F19:
1455 return dom::KeyboardEvent_Binding::DOM_VK_F19;
1456 case KEY_NAME_INDEX_F20:
1457 return dom::KeyboardEvent_Binding::DOM_VK_F20;
1458 case KEY_NAME_INDEX_F21:
1459 return dom::KeyboardEvent_Binding::DOM_VK_F21;
1460 case KEY_NAME_INDEX_F22:
1461 return dom::KeyboardEvent_Binding::DOM_VK_F22;
1462 case KEY_NAME_INDEX_F23:
1463 return dom::KeyboardEvent_Binding::DOM_VK_F23;
1464 case KEY_NAME_INDEX_F24:
1465 return dom::KeyboardEvent_Binding::DOM_VK_F24;
1466 case KEY_NAME_INDEX_NumLock:
1467 return dom::KeyboardEvent_Binding::DOM_VK_NUM_LOCK;
1468 case KEY_NAME_INDEX_ScrollLock:
1469 return dom::KeyboardEvent_Binding::DOM_VK_SCROLL_LOCK;
1470 case KEY_NAME_INDEX_AudioVolumeMute:
1471 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_MUTE;
1472 case KEY_NAME_INDEX_AudioVolumeDown:
1473 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_DOWN;
1474 case KEY_NAME_INDEX_AudioVolumeUp:
1475 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_UP;
1476 case KEY_NAME_INDEX_Meta:
1477 return dom::KeyboardEvent_Binding::DOM_VK_META;
1478 case KEY_NAME_INDEX_AltGraph:
1479 return dom::KeyboardEvent_Binding::DOM_VK_ALTGR;
1480 case KEY_NAME_INDEX_Process:
1481 return dom::KeyboardEvent_Binding::DOM_VK_PROCESSKEY;
1482 case KEY_NAME_INDEX_Attn:
1483 return dom::KeyboardEvent_Binding::DOM_VK_ATTN;
1484 case KEY_NAME_INDEX_CrSel:
1485 return dom::KeyboardEvent_Binding::DOM_VK_CRSEL;
1486 case KEY_NAME_INDEX_ExSel:
1487 return dom::KeyboardEvent_Binding::DOM_VK_EXSEL;
1488 case KEY_NAME_INDEX_EraseEof:
1489 return dom::KeyboardEvent_Binding::DOM_VK_EREOF;
1490 case KEY_NAME_INDEX_Play:
1491 return dom::KeyboardEvent_Binding::DOM_VK_PLAY;
1492 case KEY_NAME_INDEX_ZoomToggle:
1493 case KEY_NAME_INDEX_ZoomIn:
1494 case KEY_NAME_INDEX_ZoomOut:
1495 return dom::KeyboardEvent_Binding::DOM_VK_ZOOM;
1496 default:
1497 return 0;
1501 /* static */
1502 CodeNameIndex WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex(
1503 KeyNameIndex aKeyNameIndex, const Maybe<uint32_t>& aLocation) {
1504 if (aLocation.isSome() &&
1505 aLocation.value() ==
1506 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_NUMPAD) {
1507 // On macOS, NumLock is not supported. Therefore, this handles
1508 // control key values except "Enter" only on non-macOS platforms.
1509 switch (aKeyNameIndex) {
1510 #ifndef XP_MACOSX
1511 case KEY_NAME_INDEX_Insert:
1512 return CODE_NAME_INDEX_Numpad0;
1513 case KEY_NAME_INDEX_End:
1514 return CODE_NAME_INDEX_Numpad1;
1515 case KEY_NAME_INDEX_ArrowDown:
1516 return CODE_NAME_INDEX_Numpad2;
1517 case KEY_NAME_INDEX_PageDown:
1518 return CODE_NAME_INDEX_Numpad3;
1519 case KEY_NAME_INDEX_ArrowLeft:
1520 return CODE_NAME_INDEX_Numpad4;
1521 case KEY_NAME_INDEX_Clear:
1522 // FYI: "Clear" on macOS should be DOM_KEY_LOCATION_STANDARD.
1523 return CODE_NAME_INDEX_Numpad5;
1524 case KEY_NAME_INDEX_ArrowRight:
1525 return CODE_NAME_INDEX_Numpad6;
1526 case KEY_NAME_INDEX_Home:
1527 return CODE_NAME_INDEX_Numpad7;
1528 case KEY_NAME_INDEX_ArrowUp:
1529 return CODE_NAME_INDEX_Numpad8;
1530 case KEY_NAME_INDEX_PageUp:
1531 return CODE_NAME_INDEX_Numpad9;
1532 case KEY_NAME_INDEX_Delete:
1533 return CODE_NAME_INDEX_NumpadDecimal;
1534 #endif // #ifndef XP_MACOSX
1535 case KEY_NAME_INDEX_Enter:
1536 return CODE_NAME_INDEX_NumpadEnter;
1537 default:
1538 return CODE_NAME_INDEX_UNKNOWN;
1542 if (WidgetKeyboardEvent::IsLeftOrRightModiferKeyNameIndex(aKeyNameIndex)) {
1543 if (aLocation.isSome() &&
1544 (aLocation.value() !=
1545 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_LEFT &&
1546 aLocation.value() !=
1547 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT)) {
1548 return CODE_NAME_INDEX_UNKNOWN;
1550 bool isRight =
1551 aLocation.isSome() &&
1552 aLocation.value() == dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT;
1553 switch (aKeyNameIndex) {
1554 case KEY_NAME_INDEX_Alt:
1555 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1556 case KEY_NAME_INDEX_Control:
1557 return isRight ? CODE_NAME_INDEX_ControlRight
1558 : CODE_NAME_INDEX_ControlLeft;
1559 case KEY_NAME_INDEX_Shift:
1560 return isRight ? CODE_NAME_INDEX_ShiftRight : CODE_NAME_INDEX_ShiftLeft;
1561 #if defined(XP_WIN)
1562 case KEY_NAME_INDEX_Meta:
1563 return CODE_NAME_INDEX_UNKNOWN;
1564 case KEY_NAME_INDEX_OS: // win key.
1565 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1566 #elif defined(XP_MACOSX) || defined(ANDROID)
1567 case KEY_NAME_INDEX_Meta: // command key.
1568 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1569 case KEY_NAME_INDEX_OS:
1570 return CODE_NAME_INDEX_UNKNOWN;
1571 #else
1572 case KEY_NAME_INDEX_Meta: // Alt + Shift.
1573 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1574 case KEY_NAME_INDEX_OS: // Super/Hyper key.
1575 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1576 #endif
1577 default:
1578 return CODE_NAME_INDEX_UNKNOWN;
1582 if (aLocation.isSome() &&
1583 aLocation.value() !=
1584 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_STANDARD) {
1585 return CODE_NAME_INDEX_UNKNOWN;
1588 switch (aKeyNameIndex) {
1589 // Standard section:
1590 case KEY_NAME_INDEX_Escape:
1591 return CODE_NAME_INDEX_Escape;
1592 case KEY_NAME_INDEX_Tab:
1593 return CODE_NAME_INDEX_Tab;
1594 case KEY_NAME_INDEX_CapsLock:
1595 return CODE_NAME_INDEX_CapsLock;
1596 case KEY_NAME_INDEX_ContextMenu:
1597 return CODE_NAME_INDEX_ContextMenu;
1598 case KEY_NAME_INDEX_Backspace:
1599 return CODE_NAME_INDEX_Backspace;
1600 case KEY_NAME_INDEX_Enter:
1601 return CODE_NAME_INDEX_Enter;
1602 #ifdef XP_MACOSX
1603 // Although, macOS does not fire native key event of "Fn" key, we support
1604 // Fn key event if it's sent by other apps directly.
1605 case KEY_NAME_INDEX_Fn:
1606 return CODE_NAME_INDEX_Fn;
1607 #endif // #ifdef
1609 // Arrow Pad section:
1610 case KEY_NAME_INDEX_ArrowLeft:
1611 return CODE_NAME_INDEX_ArrowLeft;
1612 case KEY_NAME_INDEX_ArrowUp:
1613 return CODE_NAME_INDEX_ArrowUp;
1614 case KEY_NAME_INDEX_ArrowDown:
1615 return CODE_NAME_INDEX_ArrowDown;
1616 case KEY_NAME_INDEX_ArrowRight:
1617 return CODE_NAME_INDEX_ArrowRight;
1619 // Control Pad section:
1620 #ifndef XP_MACOSX
1621 case KEY_NAME_INDEX_Insert:
1622 return CODE_NAME_INDEX_Insert;
1623 #else
1624 case KEY_NAME_INDEX_Help:
1625 return CODE_NAME_INDEX_Help;
1626 #endif // #ifndef XP_MACOSX #else
1627 case KEY_NAME_INDEX_Delete:
1628 return CODE_NAME_INDEX_Delete;
1629 case KEY_NAME_INDEX_Home:
1630 return CODE_NAME_INDEX_Home;
1631 case KEY_NAME_INDEX_End:
1632 return CODE_NAME_INDEX_End;
1633 case KEY_NAME_INDEX_PageUp:
1634 return CODE_NAME_INDEX_PageUp;
1635 case KEY_NAME_INDEX_PageDown:
1636 return CODE_NAME_INDEX_PageDown;
1638 // Function keys:
1639 case KEY_NAME_INDEX_F1:
1640 return CODE_NAME_INDEX_F1;
1641 case KEY_NAME_INDEX_F2:
1642 return CODE_NAME_INDEX_F2;
1643 case KEY_NAME_INDEX_F3:
1644 return CODE_NAME_INDEX_F3;
1645 case KEY_NAME_INDEX_F4:
1646 return CODE_NAME_INDEX_F4;
1647 case KEY_NAME_INDEX_F5:
1648 return CODE_NAME_INDEX_F5;
1649 case KEY_NAME_INDEX_F6:
1650 return CODE_NAME_INDEX_F6;
1651 case KEY_NAME_INDEX_F7:
1652 return CODE_NAME_INDEX_F7;
1653 case KEY_NAME_INDEX_F8:
1654 return CODE_NAME_INDEX_F8;
1655 case KEY_NAME_INDEX_F9:
1656 return CODE_NAME_INDEX_F9;
1657 case KEY_NAME_INDEX_F10:
1658 return CODE_NAME_INDEX_F10;
1659 case KEY_NAME_INDEX_F11:
1660 return CODE_NAME_INDEX_F11;
1661 case KEY_NAME_INDEX_F12:
1662 return CODE_NAME_INDEX_F12;
1663 case KEY_NAME_INDEX_F13:
1664 return CODE_NAME_INDEX_F13;
1665 case KEY_NAME_INDEX_F14:
1666 return CODE_NAME_INDEX_F14;
1667 case KEY_NAME_INDEX_F15:
1668 return CODE_NAME_INDEX_F15;
1669 case KEY_NAME_INDEX_F16:
1670 return CODE_NAME_INDEX_F16;
1671 case KEY_NAME_INDEX_F17:
1672 return CODE_NAME_INDEX_F17;
1673 case KEY_NAME_INDEX_F18:
1674 return CODE_NAME_INDEX_F18;
1675 case KEY_NAME_INDEX_F19:
1676 return CODE_NAME_INDEX_F19;
1677 case KEY_NAME_INDEX_F20:
1678 return CODE_NAME_INDEX_F20;
1679 #ifndef XP_MACOSX
1680 case KEY_NAME_INDEX_F21:
1681 return CODE_NAME_INDEX_F21;
1682 case KEY_NAME_INDEX_F22:
1683 return CODE_NAME_INDEX_F22;
1684 case KEY_NAME_INDEX_F23:
1685 return CODE_NAME_INDEX_F23;
1686 case KEY_NAME_INDEX_F24:
1687 return CODE_NAME_INDEX_F24;
1688 case KEY_NAME_INDEX_Pause:
1689 return CODE_NAME_INDEX_Pause;
1690 case KEY_NAME_INDEX_PrintScreen:
1691 return CODE_NAME_INDEX_PrintScreen;
1692 case KEY_NAME_INDEX_ScrollLock:
1693 return CODE_NAME_INDEX_ScrollLock;
1694 #endif // #ifndef XP_MACOSX
1696 // NumLock key:
1697 #ifndef XP_MACOSX
1698 case KEY_NAME_INDEX_NumLock:
1699 return CODE_NAME_INDEX_NumLock;
1700 #else
1701 case KEY_NAME_INDEX_Clear:
1702 return CODE_NAME_INDEX_NumLock;
1703 #endif // #ifndef XP_MACOSX #else
1705 // Media keys:
1706 case KEY_NAME_INDEX_AudioVolumeDown:
1707 return CODE_NAME_INDEX_VolumeDown;
1708 case KEY_NAME_INDEX_AudioVolumeMute:
1709 return CODE_NAME_INDEX_VolumeMute;
1710 case KEY_NAME_INDEX_AudioVolumeUp:
1711 return CODE_NAME_INDEX_VolumeUp;
1712 #ifndef XP_MACOSX
1713 case KEY_NAME_INDEX_BrowserBack:
1714 return CODE_NAME_INDEX_BrowserBack;
1715 case KEY_NAME_INDEX_BrowserFavorites:
1716 return CODE_NAME_INDEX_BrowserFavorites;
1717 case KEY_NAME_INDEX_BrowserForward:
1718 return CODE_NAME_INDEX_BrowserForward;
1719 case KEY_NAME_INDEX_BrowserRefresh:
1720 return CODE_NAME_INDEX_BrowserRefresh;
1721 case KEY_NAME_INDEX_BrowserSearch:
1722 return CODE_NAME_INDEX_BrowserSearch;
1723 case KEY_NAME_INDEX_BrowserStop:
1724 return CODE_NAME_INDEX_BrowserStop;
1725 case KEY_NAME_INDEX_MediaPlayPause:
1726 return CODE_NAME_INDEX_MediaPlayPause;
1727 case KEY_NAME_INDEX_MediaStop:
1728 return CODE_NAME_INDEX_MediaStop;
1729 case KEY_NAME_INDEX_MediaTrackNext:
1730 return CODE_NAME_INDEX_MediaTrackNext;
1731 case KEY_NAME_INDEX_MediaTrackPrevious:
1732 return CODE_NAME_INDEX_MediaTrackPrevious;
1733 case KEY_NAME_INDEX_LaunchApplication1:
1734 return CODE_NAME_INDEX_LaunchApp1;
1735 #endif // #ifndef XP_MACOSX
1737 // Only Windows and GTK supports the following multimedia keys.
1738 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1739 case KEY_NAME_INDEX_BrowserHome:
1740 return CODE_NAME_INDEX_BrowserHome;
1741 case KEY_NAME_INDEX_LaunchApplication2:
1742 return CODE_NAME_INDEX_LaunchApp2;
1743 #endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1745 // Only GTK and Android supports the following multimedia keys.
1746 #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1747 case KEY_NAME_INDEX_Eject:
1748 return CODE_NAME_INDEX_Eject;
1749 case KEY_NAME_INDEX_WakeUp:
1750 return CODE_NAME_INDEX_WakeUp;
1751 #endif // #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1753 // Only Windows does not support Help key (and macOS handled above).
1754 #if !defined(XP_WIN) && !defined(XP_MACOSX)
1755 case KEY_NAME_INDEX_Help:
1756 return CODE_NAME_INDEX_Help;
1757 #endif // #if !defined(XP_WIN) && !defined(XP_MACOSX)
1759 // IME specific keys:
1760 #ifdef XP_WIN
1761 case KEY_NAME_INDEX_Convert:
1762 return CODE_NAME_INDEX_Convert;
1763 case KEY_NAME_INDEX_NonConvert:
1764 return CODE_NAME_INDEX_NonConvert;
1765 case KEY_NAME_INDEX_Alphanumeric:
1766 return CODE_NAME_INDEX_CapsLock;
1767 case KEY_NAME_INDEX_KanaMode:
1768 case KEY_NAME_INDEX_Romaji:
1769 case KEY_NAME_INDEX_Katakana:
1770 case KEY_NAME_INDEX_Hiragana:
1771 return CODE_NAME_INDEX_KanaMode;
1772 case KEY_NAME_INDEX_Hankaku:
1773 case KEY_NAME_INDEX_Zenkaku:
1774 case KEY_NAME_INDEX_KanjiMode:
1775 return CODE_NAME_INDEX_Backquote;
1776 case KEY_NAME_INDEX_HanjaMode:
1777 return CODE_NAME_INDEX_Lang2;
1778 case KEY_NAME_INDEX_HangulMode:
1779 return CODE_NAME_INDEX_Lang1;
1780 #endif // #ifdef XP_WIN
1782 #ifdef MOZ_WIDGET_GTK
1783 case KEY_NAME_INDEX_Convert:
1784 return CODE_NAME_INDEX_Convert;
1785 case KEY_NAME_INDEX_NonConvert:
1786 return CODE_NAME_INDEX_NonConvert;
1787 case KEY_NAME_INDEX_Alphanumeric:
1788 return CODE_NAME_INDEX_CapsLock;
1789 case KEY_NAME_INDEX_HiraganaKatakana:
1790 return CODE_NAME_INDEX_KanaMode;
1791 case KEY_NAME_INDEX_ZenkakuHankaku:
1792 return CODE_NAME_INDEX_Backquote;
1793 #endif // #ifdef MOZ_WIDGET_GTK
1795 #ifdef ANDROID
1796 case KEY_NAME_INDEX_Convert:
1797 return CODE_NAME_INDEX_Convert;
1798 case KEY_NAME_INDEX_NonConvert:
1799 return CODE_NAME_INDEX_NonConvert;
1800 case KEY_NAME_INDEX_HiraganaKatakana:
1801 return CODE_NAME_INDEX_KanaMode;
1802 case KEY_NAME_INDEX_ZenkakuHankaku:
1803 return CODE_NAME_INDEX_Backquote;
1804 case KEY_NAME_INDEX_Eisu:
1805 return CODE_NAME_INDEX_Lang2;
1806 case KEY_NAME_INDEX_KanjiMode:
1807 return CODE_NAME_INDEX_Lang1;
1808 #endif // #ifdef ANDROID
1810 #ifdef XP_MACOSX
1811 case KEY_NAME_INDEX_Eisu:
1812 return CODE_NAME_INDEX_Lang2;
1813 case KEY_NAME_INDEX_KanjiMode:
1814 return CODE_NAME_INDEX_Lang1;
1815 #endif // #ifdef XP_MACOSX
1817 default:
1818 return CODE_NAME_INDEX_UNKNOWN;
1822 /* static */
1823 Modifier WidgetKeyboardEvent::GetModifierForKeyName(
1824 KeyNameIndex aKeyNameIndex) {
1825 switch (aKeyNameIndex) {
1826 case KEY_NAME_INDEX_Alt:
1827 return MODIFIER_ALT;
1828 case KEY_NAME_INDEX_AltGraph:
1829 return MODIFIER_ALTGRAPH;
1830 case KEY_NAME_INDEX_CapsLock:
1831 return MODIFIER_CAPSLOCK;
1832 case KEY_NAME_INDEX_Control:
1833 return MODIFIER_CONTROL;
1834 case KEY_NAME_INDEX_Fn:
1835 return MODIFIER_FN;
1836 case KEY_NAME_INDEX_FnLock:
1837 return MODIFIER_FNLOCK;
1838 // case KEY_NAME_INDEX_Hyper:
1839 case KEY_NAME_INDEX_Meta:
1840 return MODIFIER_META;
1841 case KEY_NAME_INDEX_NumLock:
1842 return MODIFIER_NUMLOCK;
1843 case KEY_NAME_INDEX_OS:
1844 return MODIFIER_OS;
1845 case KEY_NAME_INDEX_ScrollLock:
1846 return MODIFIER_SCROLLLOCK;
1847 case KEY_NAME_INDEX_Shift:
1848 return MODIFIER_SHIFT;
1849 // case KEY_NAME_INDEX_Super:
1850 case KEY_NAME_INDEX_Symbol:
1851 return MODIFIER_SYMBOL;
1852 case KEY_NAME_INDEX_SymbolLock:
1853 return MODIFIER_SYMBOLLOCK;
1854 default:
1855 return MODIFIER_NONE;
1859 /* static */
1860 bool WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex) {
1861 switch (aKeyNameIndex) {
1862 case KEY_NAME_INDEX_CapsLock:
1863 case KEY_NAME_INDEX_FnLock:
1864 case KEY_NAME_INDEX_NumLock:
1865 case KEY_NAME_INDEX_ScrollLock:
1866 case KEY_NAME_INDEX_SymbolLock:
1867 return true;
1868 default:
1869 return false;
1873 /******************************************************************************
1874 * mozilla::InternalEditorInputEvent (TextEvents.h)
1875 ******************************************************************************/
1877 #define NS_DEFINE_INPUTTYPE(aCPPName, aDOMName) (u"" aDOMName),
1878 const char16_t* const InternalEditorInputEvent::kInputTypeNames[] = {
1879 #include "mozilla/InputTypeList.h"
1881 #undef NS_DEFINE_INPUTTYPE
1883 InternalEditorInputEvent::InputTypeHashtable*
1884 InternalEditorInputEvent::sInputTypeHashtable = nullptr;
1886 /* static */
1887 void InternalEditorInputEvent::Shutdown() {
1888 delete sInputTypeHashtable;
1889 sInputTypeHashtable = nullptr;
1892 /* static */
1893 void InternalEditorInputEvent::GetDOMInputTypeName(EditorInputType aInputType,
1894 nsAString& aInputTypeName) {
1895 if (static_cast<size_t>(aInputType) >=
1896 static_cast<size_t>(EditorInputType::eUnknown)) {
1897 aInputTypeName.Truncate();
1898 return;
1901 MOZ_RELEASE_ASSERT(
1902 static_cast<size_t>(aInputType) < ArrayLength(kInputTypeNames),
1903 "Illegal input type enumeration value");
1904 aInputTypeName.Assign(kInputTypeNames[static_cast<size_t>(aInputType)]);
1907 /* static */
1908 EditorInputType InternalEditorInputEvent::GetEditorInputType(
1909 const nsAString& aInputType) {
1910 if (aInputType.IsEmpty()) {
1911 return EditorInputType::eUnknown;
1914 if (!sInputTypeHashtable) {
1915 sInputTypeHashtable = new InputTypeHashtable(ArrayLength(kInputTypeNames));
1916 for (size_t i = 0; i < ArrayLength(kInputTypeNames); i++) {
1917 sInputTypeHashtable->InsertOrUpdate(nsDependentString(kInputTypeNames[i]),
1918 static_cast<EditorInputType>(i));
1921 return sInputTypeHashtable->MaybeGet(aInputType)
1922 .valueOr(EditorInputType::eUnknown);
1925 } // namespace mozilla