Bug 1697672 [wpt PR 28012] - Disable SVG composited animation if effective zoom is...
[gecko.git] / widget / WidgetEventImpl.cpp
blob8242c24a53817fb2e38e63c9c61408a52e6d3ff2
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/Maybe.h"
11 #include "mozilla/MiscEvents.h"
12 #include "mozilla/MouseEvents.h"
13 #include "mozilla/Preferences.h"
14 #include "mozilla/StaticPrefs_mousewheel.h"
15 #include "mozilla/StaticPrefs_ui.h"
16 #include "mozilla/TextEventDispatcher.h"
17 #include "mozilla/TextEvents.h"
18 #include "mozilla/TouchEvents.h"
19 #include "mozilla/WritingModes.h"
20 #include "mozilla/dom/KeyboardEventBinding.h"
21 #include "nsCommandParams.h"
22 #include "nsContentUtils.h"
23 #include "nsIContent.h"
24 #include "nsIDragSession.h"
25 #include "nsPrintfCString.h"
27 #if defined(XP_WIN)
28 # include "npapi.h"
29 # include "WinUtils.h"
30 #endif // #if defined (XP_WIN)
32 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
33 # include "NativeKeyBindings.h"
34 #endif // #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
36 namespace mozilla {
38 /******************************************************************************
39 * Global helper methods
40 ******************************************************************************/
42 const char* ToChar(EventMessage aEventMessage) {
43 switch (aEventMessage) {
44 #define NS_EVENT_MESSAGE(aMessage) \
45 case aMessage: \
46 return #aMessage;
48 #include "mozilla/EventMessageList.h"
50 #undef NS_EVENT_MESSAGE
51 default:
52 return "illegal event message";
56 const char* ToChar(EventClassID aEventClassID) {
57 switch (aEventClassID) {
58 #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
59 case eBasic##aName##Class: \
60 return "eBasic" #aName "Class";
62 #define NS_EVENT_CLASS(aPrefix, aName) \
63 case e##aName##Class: \
64 return "e" #aName "Class";
66 #include "mozilla/EventClassList.h"
68 #undef NS_EVENT_CLASS
69 #undef NS_ROOT_EVENT_CLASS
70 default:
71 return "illegal event class ID";
75 const nsCString ToString(KeyNameIndex aKeyNameIndex) {
76 if (aKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
77 return "USE_STRING"_ns;
79 nsAutoString keyName;
80 WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex, keyName);
81 return NS_ConvertUTF16toUTF8(keyName);
84 const nsCString ToString(CodeNameIndex aCodeNameIndex) {
85 if (aCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
86 return "USE_STRING"_ns;
88 nsAutoString codeName;
89 WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex, codeName);
90 return NS_ConvertUTF16toUTF8(codeName);
93 const char* ToChar(Command aCommand) {
94 if (aCommand == Command::DoNothing) {
95 return "CommandDoNothing";
98 switch (aCommand) {
99 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
100 case Command::aName: \
101 return "Command::" #aName;
102 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) \
103 case Command::aName: \
104 return "Command::" #aName;
105 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) \
106 case Command::aName: \
107 return "Command::" #aName;
109 #include "mozilla/CommandList.h"
111 #undef NS_DEFINE_COMMAND
112 #undef NS_DEFINE_COMMAND_WITH_PARAM
113 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
115 default:
116 return "illegal command value";
120 const nsCString GetDOMKeyCodeName(uint32_t aKeyCode) {
121 switch (aKeyCode) {
122 #define NS_DISALLOW_SAME_KEYCODE
123 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
124 case aDOMKeyCode: \
125 return nsLiteralCString(#aDOMKeyName);
127 #include "mozilla/VirtualKeyCodeList.h"
129 #undef NS_DEFINE_VK
130 #undef NS_DISALLOW_SAME_KEYCODE
132 default:
133 return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode);
137 bool IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeType) {
138 switch (static_cast<TextRangeType>(aRawTextRangeType)) {
139 case TextRangeType::eUninitialized:
140 case TextRangeType::eCaret:
141 case TextRangeType::eRawClause:
142 case TextRangeType::eSelectedRawClause:
143 case TextRangeType::eConvertedClause:
144 case TextRangeType::eSelectedClause:
145 return true;
146 default:
147 return false;
151 RawTextRangeType ToRawTextRangeType(TextRangeType aTextRangeType) {
152 return static_cast<RawTextRangeType>(aTextRangeType);
155 TextRangeType ToTextRangeType(RawTextRangeType aRawTextRangeType) {
156 MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType));
157 return static_cast<TextRangeType>(aRawTextRangeType);
160 const char* ToChar(TextRangeType aTextRangeType) {
161 switch (aTextRangeType) {
162 case TextRangeType::eUninitialized:
163 return "TextRangeType::eUninitialized";
164 case TextRangeType::eCaret:
165 return "TextRangeType::eCaret";
166 case TextRangeType::eRawClause:
167 return "TextRangeType::eRawClause";
168 case TextRangeType::eSelectedRawClause:
169 return "TextRangeType::eSelectedRawClause";
170 case TextRangeType::eConvertedClause:
171 return "TextRangeType::eConvertedClause";
172 case TextRangeType::eSelectedClause:
173 return "TextRangeType::eSelectedClause";
174 default:
175 return "Invalid TextRangeType";
179 SelectionType ToSelectionType(TextRangeType aTextRangeType) {
180 switch (aTextRangeType) {
181 case TextRangeType::eRawClause:
182 return SelectionType::eIMERawClause;
183 case TextRangeType::eSelectedRawClause:
184 return SelectionType::eIMESelectedRawClause;
185 case TextRangeType::eConvertedClause:
186 return SelectionType::eIMEConvertedClause;
187 case TextRangeType::eSelectedClause:
188 return SelectionType::eIMESelectedClause;
189 default:
190 MOZ_CRASH("TextRangeType is invalid");
191 return SelectionType::eNormal;
195 /******************************************************************************
196 * non class method implementation
197 ******************************************************************************/
199 static nsTHashMap<nsDepCharHashKey, Command>* sCommandHashtable = nullptr;
201 Command GetInternalCommand(const char* aCommandName,
202 const nsCommandParams* aCommandParams) {
203 if (!aCommandName) {
204 return Command::DoNothing;
207 // Special cases for "cmd_align". It's mapped to multiple internal commands
208 // with additional param. Therefore, we cannot handle it with the hashtable.
209 if (!strcmp(aCommandName, "cmd_align")) {
210 if (!aCommandParams) {
211 // Note that if this is called by EditorCommand::IsCommandEnabled(),
212 // it cannot set aCommandParams. So, don't warn in this case even though
213 // this is illegal case for DoCommandParams().
214 return Command::FormatJustify;
216 nsAutoCString cValue;
217 nsresult rv = aCommandParams->GetCString("state_attribute", cValue);
218 if (NS_FAILED(rv)) {
219 nsString value; // Avoid copying the string buffer with using nsString.
220 rv = aCommandParams->GetString("state_attribute", value);
221 if (NS_FAILED(rv)) {
222 return Command::FormatJustifyNone;
224 CopyUTF16toUTF8(value, cValue);
226 if (cValue.LowerCaseEqualsASCII("left")) {
227 return Command::FormatJustifyLeft;
229 if (cValue.LowerCaseEqualsASCII("right")) {
230 return Command::FormatJustifyRight;
232 if (cValue.LowerCaseEqualsASCII("center")) {
233 return Command::FormatJustifyCenter;
235 if (cValue.LowerCaseEqualsASCII("justify")) {
236 return Command::FormatJustifyFull;
238 if (cValue.IsEmpty()) {
239 return Command::FormatJustifyNone;
241 return Command::DoNothing;
244 if (!sCommandHashtable) {
245 sCommandHashtable = new nsTHashMap<nsDepCharHashKey, Command>();
246 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
247 sCommandHashtable->InsertOrUpdate(#aCommandStr, Command::aName);
249 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam)
251 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName)
253 #include "mozilla/CommandList.h"
255 #undef NS_DEFINE_COMMAND
256 #undef NS_DEFINE_COMMAND_WITH_PARAM
257 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
259 Command command = Command::DoNothing;
260 if (!sCommandHashtable->Get(aCommandName, &command)) {
261 return Command::DoNothing;
263 return command;
266 /******************************************************************************
267 * As*Event() implementation
268 ******************************************************************************/
270 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
271 #define NS_EVENT_CLASS(aPrefix, aName) \
272 aPrefix##aName* WidgetEvent::As##aName() { return nullptr; } \
274 const aPrefix##aName* WidgetEvent::As##aName() const { \
275 return const_cast<WidgetEvent*>(this)->As##aName(); \
278 #include "mozilla/EventClassList.h"
280 #undef NS_EVENT_CLASS
281 #undef NS_ROOT_EVENT_CLASS
283 /******************************************************************************
284 * mozilla::WidgetEvent
286 * Event struct type checking methods.
287 ******************************************************************************/
289 bool WidgetEvent::IsQueryContentEvent() const {
290 return mClass == eQueryContentEventClass;
293 bool WidgetEvent::IsSelectionEvent() const {
294 return mClass == eSelectionEventClass;
297 bool WidgetEvent::IsContentCommandEvent() const {
298 return mClass == eContentCommandEventClass;
301 /******************************************************************************
302 * mozilla::WidgetEvent
304 * Event message checking methods.
305 ******************************************************************************/
307 bool WidgetEvent::HasMouseEventMessage() const {
308 switch (mMessage) {
309 case eMouseDown:
310 case eMouseUp:
311 case eMouseClick:
312 case eMouseDoubleClick:
313 case eMouseAuxClick:
314 case eMouseEnterIntoWidget:
315 case eMouseExitFromWidget:
316 case eMouseActivate:
317 case eMouseOver:
318 case eMouseOut:
319 case eMouseHitTest:
320 case eMouseMove:
321 return true;
322 default:
323 return false;
327 bool WidgetEvent::HasDragEventMessage() const {
328 switch (mMessage) {
329 case eDragEnter:
330 case eDragOver:
331 case eDragExit:
332 case eDrag:
333 case eDragEnd:
334 case eDragStart:
335 case eDrop:
336 case eDragLeave:
337 return true;
338 default:
339 return false;
343 /* static */
344 bool WidgetEvent::IsKeyEventMessage(EventMessage aMessage) {
345 switch (aMessage) {
346 case eKeyDown:
347 case eKeyPress:
348 case eKeyUp:
349 case eKeyDownOnPlugin:
350 case eKeyUpOnPlugin:
351 case eAccessKeyNotFound:
352 return true;
353 default:
354 return false;
358 bool WidgetEvent::HasIMEEventMessage() const {
359 switch (mMessage) {
360 case eCompositionStart:
361 case eCompositionEnd:
362 case eCompositionUpdate:
363 case eCompositionChange:
364 case eCompositionCommitAsIs:
365 case eCompositionCommit:
366 return true;
367 default:
368 return false;
372 bool WidgetEvent::HasPluginActivationEventMessage() const {
373 return mMessage == ePluginActivate || mMessage == ePluginFocus;
376 /******************************************************************************
377 * mozilla::WidgetEvent
379 * Specific event checking methods.
380 ******************************************************************************/
382 bool WidgetEvent::CanBeSentToRemoteProcess() const {
383 // If this event is explicitly marked as shouldn't be sent to remote process,
384 // just return false.
385 if (IsCrossProcessForwardingStopped()) {
386 return false;
389 if (mClass == eKeyboardEventClass || mClass == eWheelEventClass) {
390 return true;
393 switch (mMessage) {
394 case eMouseDown:
395 case eMouseUp:
396 case eMouseMove:
397 case eContextMenu:
398 case eMouseEnterIntoWidget:
399 case eMouseExitFromWidget:
400 case eMouseTouchDrag:
401 case eTouchStart:
402 case eTouchMove:
403 case eTouchEnd:
404 case eTouchCancel:
405 case eDragOver:
406 case eDragExit:
407 case eDrop:
408 return true;
409 default:
410 return false;
414 bool WidgetEvent::WillBeSentToRemoteProcess() const {
415 // This event won't be posted to remote process if it's already explicitly
416 // stopped.
417 if (IsCrossProcessForwardingStopped()) {
418 return false;
421 // When mOriginalTarget is nullptr, this method shouldn't be used.
422 if (NS_WARN_IF(!mOriginalTarget)) {
423 return false;
426 nsCOMPtr<nsIContent> originalTarget = do_QueryInterface(mOriginalTarget);
427 return EventStateManager::IsTopLevelRemoteTarget(originalTarget);
430 bool WidgetEvent::IsIMERelatedEvent() const {
431 return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
434 bool WidgetEvent::IsUsingCoordinates() const {
435 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
436 if (mouseEvent) {
437 return !mouseEvent->IsContextMenuKeyEvent();
439 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
440 !HasPluginActivationEventMessage() && !IsContentCommandEvent();
443 bool WidgetEvent::IsTargetedAtFocusedWindow() const {
444 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
445 if (mouseEvent) {
446 return mouseEvent->IsContextMenuKeyEvent();
448 return HasKeyEventMessage() || IsIMERelatedEvent() || IsContentCommandEvent();
451 bool WidgetEvent::IsTargetedAtFocusedContent() const {
452 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
453 if (mouseEvent) {
454 return mouseEvent->IsContextMenuKeyEvent();
456 return HasKeyEventMessage() || IsIMERelatedEvent();
459 bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
460 switch (mClass) {
461 case eMouseEventClass:
462 if (mMessage == eMouseTouchDrag) {
463 return false;
465 [[fallthrough]];
466 case ePointerEventClass:
467 // We want synthesized mouse moves to cause mouseover and mouseout
468 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
469 // DOM events.
470 // Synthesized button up events also do not cause DOM events because they
471 // do not have a reliable mRefPoint.
472 return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
474 case eWheelEventClass: {
475 // wheel event whose all delta values are zero by user pref applied, it
476 // shouldn't cause a DOM event.
477 const WidgetWheelEvent* wheelEvent = AsWheelEvent();
478 return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
479 wheelEvent->mDeltaZ != 0.0;
481 case eTouchEventClass:
482 return mMessage != eTouchPointerCancel;
483 // Following events are handled in EventStateManager, so, we don't need to
484 // dispatch DOM event for them into the DOM tree.
485 case eQueryContentEventClass:
486 case eSelectionEventClass:
487 case eContentCommandEventClass:
488 return false;
490 default:
491 return true;
495 bool WidgetEvent::IsAllowedToDispatchInSystemGroup() const {
496 // We don't expect to implement default behaviors with pointer events because
497 // if we do, prevent default on mouse events can't prevent default behaviors
498 // anymore.
499 return mClass != ePointerEventClass;
502 bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
503 if (!nsContentUtils::ShouldResistFingerprinting()) {
504 return false;
507 switch (mClass) {
508 case eKeyboardEventClass: {
509 const WidgetKeyboardEvent* keyboardEvent = AsKeyboardEvent();
511 return (keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Alt ||
512 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Shift ||
513 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Control ||
514 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_AltGraph);
516 case ePointerEventClass: {
517 const WidgetPointerEvent* pointerEvent = AsPointerEvent();
519 // We suppress the pointer events if it is not primary for fingerprinting
520 // resistance. It is because of that we want to spoof any pointer event
521 // into a mouse pointer event and the mouse pointer event only has
522 // isPrimary as true.
523 return !pointerEvent->mIsPrimary;
525 default:
526 return false;
530 /******************************************************************************
531 * mozilla::WidgetEvent
533 * Misc methods.
534 ******************************************************************************/
536 static dom::EventTarget* GetTargetForDOMEvent(dom::EventTarget* aTarget) {
537 return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
540 dom::EventTarget* WidgetEvent::GetDOMEventTarget() const {
541 return GetTargetForDOMEvent(mTarget);
544 dom::EventTarget* WidgetEvent::GetCurrentDOMEventTarget() const {
545 return GetTargetForDOMEvent(mCurrentTarget);
548 dom::EventTarget* WidgetEvent::GetOriginalDOMEventTarget() const {
549 if (mOriginalTarget) {
550 return GetTargetForDOMEvent(mOriginalTarget);
552 return GetDOMEventTarget();
555 void WidgetEvent::PreventDefault(bool aCalledByDefaultHandler,
556 nsIPrincipal* aPrincipal) {
557 if (mMessage == ePointerDown) {
558 if (aCalledByDefaultHandler) {
559 // Shouldn't prevent default on pointerdown by default handlers to stop
560 // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages
561 // in debug builds.
562 MOZ_ASSERT(false);
563 return;
565 if (aPrincipal) {
566 nsAutoString addonId;
567 Unused << NS_WARN_IF(NS_FAILED(aPrincipal->GetAddonId(addonId)));
568 if (!addonId.IsEmpty()) {
569 // Ignore the case that it's called by a web extension.
570 return;
574 mFlags.PreventDefault(aCalledByDefaultHandler);
577 bool WidgetEvent::IsUserAction() const {
578 if (!IsTrusted()) {
579 return false;
581 // FYI: eMouseScrollEventClass and ePointerEventClass represent
582 // user action but they are synthesized events.
583 switch (mClass) {
584 case eKeyboardEventClass:
585 case eCompositionEventClass:
586 case eMouseScrollEventClass:
587 case eWheelEventClass:
588 case eGestureNotifyEventClass:
589 case eSimpleGestureEventClass:
590 case eTouchEventClass:
591 case eCommandEventClass:
592 case eContentCommandEventClass:
593 return true;
594 case eMouseEventClass:
595 case eDragEventClass:
596 case ePointerEventClass:
597 return AsMouseEvent()->IsReal();
598 default:
599 return false;
603 /******************************************************************************
604 * mozilla::WidgetInputEvent
605 ******************************************************************************/
607 /* static */
608 Modifier WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName) {
609 if (aDOMKeyName.EqualsLiteral("Accel")) {
610 return AccelModifier();
612 KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName);
613 return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex);
616 /* static */
617 Modifier WidgetInputEvent::AccelModifier() {
618 static Modifier sAccelModifier = MODIFIER_NONE;
619 if (sAccelModifier == MODIFIER_NONE) {
620 switch (Preferences::GetInt("ui.key.accelKey", 0)) {
621 case dom::KeyboardEvent_Binding::DOM_VK_META:
622 sAccelModifier = MODIFIER_META;
623 break;
624 case dom::KeyboardEvent_Binding::DOM_VK_WIN:
625 sAccelModifier = MODIFIER_OS;
626 break;
627 case dom::KeyboardEvent_Binding::DOM_VK_ALT:
628 sAccelModifier = MODIFIER_ALT;
629 break;
630 case dom::KeyboardEvent_Binding::DOM_VK_CONTROL:
631 sAccelModifier = MODIFIER_CONTROL;
632 break;
633 default:
634 #ifdef XP_MACOSX
635 sAccelModifier = MODIFIER_META;
636 #else
637 sAccelModifier = MODIFIER_CONTROL;
638 #endif
639 break;
642 return sAccelModifier;
645 /******************************************************************************
646 * mozilla::WidgetMouseEvent (MouseEvents.h)
647 ******************************************************************************/
649 /* static */
650 bool WidgetMouseEvent::IsMiddleClickPasteEnabled() {
651 return Preferences::GetBool("middlemouse.paste", false);
654 /******************************************************************************
655 * mozilla::WidgetDragEvent (MouseEvents.h)
656 ******************************************************************************/
658 void WidgetDragEvent::InitDropEffectForTests() {
659 MOZ_ASSERT(mFlags.mIsSynthesizedForTests);
661 nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
662 if (NS_WARN_IF(!session)) {
663 return;
666 uint32_t effectAllowed = session->GetEffectAllowedForTests();
667 uint32_t desiredDropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
668 #ifdef XP_MACOSX
669 if (IsAlt()) {
670 desiredDropEffect = IsMeta() ? nsIDragService::DRAGDROP_ACTION_LINK
671 : nsIDragService::DRAGDROP_ACTION_COPY;
673 #else
674 // On Linux, we know user's intention from API, but we should use
675 // same modifiers as Windows for tests because GNOME on Ubuntu use
676 // them and that makes each test simpler.
677 if (IsControl()) {
678 desiredDropEffect = IsShift() ? nsIDragService::DRAGDROP_ACTION_LINK
679 : nsIDragService::DRAGDROP_ACTION_COPY;
680 } else if (IsShift()) {
681 desiredDropEffect = nsIDragService::DRAGDROP_ACTION_MOVE;
683 #endif // #ifdef XP_MACOSX #else
684 // First, use modifier state for preferring action which is explicitly
685 // specified by the synthesizer.
686 if (!(desiredDropEffect &= effectAllowed)) {
687 // Otherwise, use an action which is allowed at starting the session.
688 desiredDropEffect = effectAllowed;
690 if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_MOVE) {
691 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE);
692 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_COPY) {
693 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY);
694 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_LINK) {
695 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK);
696 } else {
697 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_NONE);
701 /******************************************************************************
702 * mozilla::WidgetWheelEvent (MouseEvents.h)
703 ******************************************************************************/
705 /* static */
706 double WidgetWheelEvent::ComputeOverriddenDelta(double aDelta,
707 bool aIsForVertical) {
708 if (!StaticPrefs::
709 mousewheel_system_scroll_override_on_root_content_enabled()) {
710 return aDelta;
712 int32_t intFactor =
713 aIsForVertical
714 ? StaticPrefs::
715 mousewheel_system_scroll_override_on_root_content_vertical_factor()
716 : StaticPrefs::
717 mousewheel_system_scroll_override_on_root_content_horizontal_factor();
718 // Making the scroll speed slower doesn't make sense. So, ignore odd factor
719 // which is less than 1.0.
720 if (intFactor <= 100) {
721 return aDelta;
723 double factor = static_cast<double>(intFactor) / 100;
724 return aDelta * factor;
727 double WidgetWheelEvent::OverriddenDeltaX() const {
728 if (!mAllowToOverrideSystemScrollSpeed) {
729 return mDeltaX;
731 return ComputeOverriddenDelta(mDeltaX, false);
734 double WidgetWheelEvent::OverriddenDeltaY() const {
735 if (!mAllowToOverrideSystemScrollSpeed) {
736 return mDeltaY;
738 return ComputeOverriddenDelta(mDeltaY, true);
741 /******************************************************************************
742 * mozilla::WidgetKeyboardEvent (TextEvents.h)
743 ******************************************************************************/
745 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
746 const char16_t* const WidgetKeyboardEvent::kKeyNames[] = {
747 #include "mozilla/KeyNameList.h"
749 #undef NS_DEFINE_KEYNAME
751 #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
752 (u"" aDOMCodeName),
753 const char16_t* const WidgetKeyboardEvent::kCodeNames[] = {
754 #include "mozilla/PhysicalKeyCodeNameList.h"
756 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
758 WidgetKeyboardEvent::KeyNameIndexHashtable*
759 WidgetKeyboardEvent::sKeyNameIndexHashtable = nullptr;
760 WidgetKeyboardEvent::CodeNameIndexHashtable*
761 WidgetKeyboardEvent::sCodeNameIndexHashtable = nullptr;
763 void WidgetKeyboardEvent::InitAllEditCommands(
764 const Maybe<WritingMode>& aWritingMode) {
765 // If this event is synthesized for tests, we don't need to retrieve the
766 // command via the main process. So, we don't need widget and can trust
767 // the event.
768 if (!mFlags.mIsSynthesizedForTests) {
769 // If the event was created without widget, e.g., created event in chrome
770 // script, this shouldn't execute native key bindings.
771 if (NS_WARN_IF(!mWidget)) {
772 return;
775 // This event should be trusted event here and we shouldn't expose native
776 // key binding information to web contents with untrusted events.
777 if (NS_WARN_IF(!IsTrusted())) {
778 return;
781 MOZ_ASSERT(
782 XRE_IsParentProcess(),
783 "It's too expensive to retrieve all edit commands from remote process");
784 MOZ_ASSERT(!AreAllEditCommandsInitialized(),
785 "Shouldn't be called two or more times");
788 DebugOnly<bool> okIgnored = InitEditCommandsFor(
789 nsIWidget::NativeKeyBindingsForSingleLineEditor, aWritingMode);
790 NS_WARNING_ASSERTION(
791 okIgnored,
792 "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor) "
793 "failed, but ignored");
794 okIgnored = InitEditCommandsFor(
795 nsIWidget::NativeKeyBindingsForMultiLineEditor, aWritingMode);
796 NS_WARNING_ASSERTION(
797 okIgnored,
798 "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor) "
799 "failed, but ignored");
800 okIgnored = InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor,
801 aWritingMode);
802 NS_WARNING_ASSERTION(
803 okIgnored,
804 "InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor) "
805 "failed, but ignored");
808 bool WidgetKeyboardEvent::InitEditCommandsFor(
809 nsIWidget::NativeKeyBindingsType aType,
810 const Maybe<WritingMode>& aWritingMode) {
811 bool& initialized = IsEditCommandsInitializedRef(aType);
812 if (initialized) {
813 return true;
815 nsTArray<CommandInt>& commands = EditCommandsRef(aType);
817 // If this event is synthesized for tests, we shouldn't access customized
818 // shortcut settings of the environment. Therefore, we don't need to check
819 // whether `widget` is set or not. And we can treat synthesized events are
820 // always trusted.
821 if (mFlags.mIsSynthesizedForTests) {
822 MOZ_DIAGNOSTIC_ASSERT(IsTrusted());
823 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
824 // TODO: We should implement `NativeKeyBindings` for Windows and Android
825 // too in bug 1301497 for getting rid of the #if.
826 widget::NativeKeyBindings::GetEditCommandsForTests(aType, *this,
827 aWritingMode, commands);
828 #endif
829 initialized = true;
830 return true;
833 if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
834 return false;
836 // `nsIWidget::GetEditCommands()` will retrieve `WritingMode` at selection
837 // again, but it should be almost zero-cost since `TextEventDispatcher`
838 // caches the value.
839 nsCOMPtr<nsIWidget> widget = mWidget;
840 initialized = widget->GetEditCommands(aType, *this, commands);
841 return initialized;
844 bool WidgetKeyboardEvent::ExecuteEditCommands(
845 nsIWidget::NativeKeyBindingsType aType, DoCommandCallback aCallback,
846 void* aCallbackData) {
847 // If the event was created without widget, e.g., created event in chrome
848 // script, this shouldn't execute native key bindings.
849 if (NS_WARN_IF(!mWidget)) {
850 return false;
853 // This event should be trusted event here and we shouldn't expose native
854 // key binding information to web contents with untrusted events.
855 if (NS_WARN_IF(!IsTrusted())) {
856 return false;
859 if (!IsEditCommandsInitializedRef(aType)) {
860 Maybe<WritingMode> writingMode;
861 if (RefPtr<widget::TextEventDispatcher> textEventDispatcher =
862 mWidget->GetTextEventDispatcher()) {
863 writingMode = textEventDispatcher->MaybeWritingModeAtSelection();
865 if (NS_WARN_IF(!InitEditCommandsFor(aType, writingMode))) {
866 return false;
870 const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
871 if (commands.IsEmpty()) {
872 return false;
875 for (CommandInt command : commands) {
876 aCallback(static_cast<Command>(command), aCallbackData);
878 return true;
881 bool WidgetKeyboardEvent::ShouldCauseKeypressEvents() const {
882 // Currently, we don't dispatch keypress events of modifier keys and
883 // dead keys.
884 switch (mKeyNameIndex) {
885 case KEY_NAME_INDEX_Alt:
886 case KEY_NAME_INDEX_AltGraph:
887 case KEY_NAME_INDEX_CapsLock:
888 case KEY_NAME_INDEX_Control:
889 case KEY_NAME_INDEX_Fn:
890 case KEY_NAME_INDEX_FnLock:
891 // case KEY_NAME_INDEX_Hyper:
892 case KEY_NAME_INDEX_Meta:
893 case KEY_NAME_INDEX_NumLock:
894 case KEY_NAME_INDEX_OS:
895 case KEY_NAME_INDEX_ScrollLock:
896 case KEY_NAME_INDEX_Shift:
897 // case KEY_NAME_INDEX_Super:
898 case KEY_NAME_INDEX_Symbol:
899 case KEY_NAME_INDEX_SymbolLock:
900 case KEY_NAME_INDEX_Dead:
901 return false;
902 default:
903 return true;
907 static bool HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates) {
908 for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
909 uint32_t ch = aCandidates[i].mCharCode;
910 if (ch >= '0' && ch <= '9') return true;
912 return false;
915 static bool CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2) {
916 return aChar1 == aChar2 || (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
917 ToLowerCase(static_cast<char16_t>(aChar1)) ==
918 ToLowerCase(static_cast<char16_t>(aChar2)));
921 static bool IsCaseChangeableChar(uint32_t aChar) {
922 return IS_IN_BMP(aChar) && ToLowerCase(static_cast<char16_t>(aChar)) !=
923 ToUpperCase(static_cast<char16_t>(aChar));
926 void WidgetKeyboardEvent::GetShortcutKeyCandidates(
927 ShortcutKeyCandidateArray& aCandidates) const {
928 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
930 // ShortcutKeyCandidate::mCharCode is a candidate charCode.
931 // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
932 // execute a command with/without shift key state. If this is TRUE, the
933 // shifted key state should be ignored. Otherwise, don't ignore the state.
934 // the priority of the charCodes are (shift key is not pressed):
935 // 0: PseudoCharCode()/false,
936 // 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
937 // the priority of the charCodes are (shift key is pressed):
938 // 0: PseudoCharCode()/false,
939 // 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
940 // 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
941 uint32_t pseudoCharCode = PseudoCharCode();
942 if (pseudoCharCode) {
943 ShortcutKeyCandidate key(pseudoCharCode, false);
944 aCandidates.AppendElement(key);
947 uint32_t len = mAlternativeCharCodes.Length();
948 if (!IsShift()) {
949 for (uint32_t i = 0; i < len; ++i) {
950 uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
951 if (!ch || ch == pseudoCharCode) {
952 continue;
954 ShortcutKeyCandidate key(ch, false);
955 aCandidates.AppendElement(key);
957 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
958 // this keyboard layout is AZERTY or similar layout, probably.
959 // In this case, Accel+[0-9] should be accessible without shift key.
960 // However, the priority should be lowest.
961 if (!HasASCIIDigit(aCandidates)) {
962 for (uint32_t i = 0; i < len; ++i) {
963 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
964 if (ch >= '0' && ch <= '9') {
965 ShortcutKeyCandidate key(ch, false);
966 aCandidates.AppendElement(key);
967 break;
971 } else {
972 for (uint32_t i = 0; i < len; ++i) {
973 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
974 if (!ch) {
975 continue;
978 if (ch != pseudoCharCode) {
979 ShortcutKeyCandidate key(ch, false);
980 aCandidates.AppendElement(key);
983 // If the char is an alphabet, the shift key state should not be
984 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
986 // And checking the charCode is same as unshiftedCharCode too.
987 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
988 uint32_t unshiftCh = mAlternativeCharCodes[i].mUnshiftedCharCode;
989 if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
990 continue;
993 // On the Hebrew keyboard layout on Windows, the unshifted char is a
994 // localized character but the shifted char is a Latin alphabet,
995 // then, we should not execute without the shift state. See bug 433192.
996 if (IsCaseChangeableChar(ch)) {
997 continue;
1000 // Setting the alternative charCode candidates for retry without shift
1001 // key state only when the shift key is pressed.
1002 ShortcutKeyCandidate key(ch, true);
1003 aCandidates.AppendElement(key);
1007 // Special case for "Space" key. With some keyboard layouts, "Space" with
1008 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1009 // we should guarantee that the key press works as an ASCII white space key
1010 // press. However, if the space key is assigned to a function key, it
1011 // shouldn't work as a space key.
1012 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1013 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1014 ShortcutKeyCandidate spaceKey(' ', false);
1015 aCandidates.AppendElement(spaceKey);
1019 void WidgetKeyboardEvent::GetAccessKeyCandidates(
1020 nsTArray<uint32_t>& aCandidates) const {
1021 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
1023 // return the lower cased charCode candidates for access keys.
1024 // the priority of the charCodes are:
1025 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
1026 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
1027 uint32_t pseudoCharCode = PseudoCharCode();
1028 if (pseudoCharCode) {
1029 uint32_t ch = pseudoCharCode;
1030 if (IS_IN_BMP(ch)) {
1031 ch = ToLowerCase(static_cast<char16_t>(ch));
1033 aCandidates.AppendElement(ch);
1035 for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
1036 uint32_t ch[2] = {mAlternativeCharCodes[i].mUnshiftedCharCode,
1037 mAlternativeCharCodes[i].mShiftedCharCode};
1038 for (uint32_t j = 0; j < 2; ++j) {
1039 if (!ch[j]) {
1040 continue;
1042 if (IS_IN_BMP(ch[j])) {
1043 ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
1045 // Don't append the charcode that was already appended.
1046 if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
1047 aCandidates.AppendElement(ch[j]);
1051 // Special case for "Space" key. With some keyboard layouts, "Space" with
1052 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1053 // we should guarantee that the key press works as an ASCII white space key
1054 // press. However, if the space key is assigned to a function key, it
1055 // shouldn't work as a space key.
1056 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1057 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1058 aCandidates.AppendElement(' ');
1062 // mask values for ui.key.chromeAccess and ui.key.contentAccess
1063 #define NS_MODIFIER_SHIFT 1
1064 #define NS_MODIFIER_CONTROL 2
1065 #define NS_MODIFIER_ALT 4
1066 #define NS_MODIFIER_META 8
1067 #define NS_MODIFIER_OS 16
1069 static Modifiers PrefFlagsToModifiers(int32_t aPrefFlags) {
1070 Modifiers result = 0;
1071 if (aPrefFlags & NS_MODIFIER_SHIFT) {
1072 result |= MODIFIER_SHIFT;
1074 if (aPrefFlags & NS_MODIFIER_CONTROL) {
1075 result |= MODIFIER_CONTROL;
1077 if (aPrefFlags & NS_MODIFIER_ALT) {
1078 result |= MODIFIER_ALT;
1080 if (aPrefFlags & NS_MODIFIER_META) {
1081 result |= MODIFIER_META;
1083 if (aPrefFlags & NS_MODIFIER_OS) {
1084 result |= MODIFIER_OS;
1086 return result;
1089 bool WidgetKeyboardEvent::ModifiersMatchWithAccessKey(
1090 AccessKeyType aType) const {
1091 if (!ModifiersForAccessKeyMatching()) {
1092 return false;
1094 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
1097 Modifiers WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const {
1098 static const Modifiers kModifierMask = MODIFIER_SHIFT | MODIFIER_CONTROL |
1099 MODIFIER_ALT | MODIFIER_META |
1100 MODIFIER_OS;
1101 return mModifiers & kModifierMask;
1104 /* static */
1105 Modifiers WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType) {
1106 switch (StaticPrefs::ui_key_generalAccessKey()) {
1107 case -1:
1108 break; // use the individual prefs
1109 case NS_VK_SHIFT:
1110 return MODIFIER_SHIFT;
1111 case NS_VK_CONTROL:
1112 return MODIFIER_CONTROL;
1113 case NS_VK_ALT:
1114 return MODIFIER_ALT;
1115 case NS_VK_META:
1116 return MODIFIER_META;
1117 case NS_VK_WIN:
1118 return MODIFIER_OS;
1119 default:
1120 return MODIFIER_NONE;
1123 switch (aType) {
1124 case AccessKeyType::eChrome:
1125 return PrefFlagsToModifiers(StaticPrefs::ui_key_chromeAccess());
1126 case AccessKeyType::eContent:
1127 return PrefFlagsToModifiers(StaticPrefs::ui_key_contentAccess());
1128 default:
1129 return MODIFIER_NONE;
1133 /* static */
1134 void WidgetKeyboardEvent::Shutdown() {
1135 delete sKeyNameIndexHashtable;
1136 sKeyNameIndexHashtable = nullptr;
1137 delete sCodeNameIndexHashtable;
1138 sCodeNameIndexHashtable = nullptr;
1139 // Although sCommandHashtable is not a member of WidgetKeyboardEvent, but
1140 // let's delete it here since we need to do it at same time.
1141 delete sCommandHashtable;
1142 sCommandHashtable = nullptr;
1145 /* static */
1146 void WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
1147 nsAString& aKeyName) {
1148 if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
1149 aKeyName.Truncate();
1150 return;
1153 MOZ_RELEASE_ASSERT(
1154 static_cast<size_t>(aKeyNameIndex) < ArrayLength(kKeyNames),
1155 "Illegal key enumeration value");
1156 aKeyName = kKeyNames[aKeyNameIndex];
1159 /* static */
1160 void WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
1161 nsAString& aCodeName) {
1162 if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
1163 aCodeName.Truncate();
1164 return;
1167 MOZ_RELEASE_ASSERT(
1168 static_cast<size_t>(aCodeNameIndex) < ArrayLength(kCodeNames),
1169 "Illegal physical code enumeration value");
1170 aCodeName = kCodeNames[aCodeNameIndex];
1173 /* static */
1174 KeyNameIndex WidgetKeyboardEvent::GetKeyNameIndex(const nsAString& aKeyValue) {
1175 if (!sKeyNameIndexHashtable) {
1176 sKeyNameIndexHashtable = new KeyNameIndexHashtable(ArrayLength(kKeyNames));
1177 for (size_t i = 0; i < ArrayLength(kKeyNames); i++) {
1178 sKeyNameIndexHashtable->InsertOrUpdate(nsDependentString(kKeyNames[i]),
1179 static_cast<KeyNameIndex>(i));
1182 return sKeyNameIndexHashtable->MaybeGet(aKeyValue).valueOr(
1183 KEY_NAME_INDEX_USE_STRING);
1186 /* static */
1187 CodeNameIndex WidgetKeyboardEvent::GetCodeNameIndex(
1188 const nsAString& aCodeValue) {
1189 if (!sCodeNameIndexHashtable) {
1190 sCodeNameIndexHashtable =
1191 new CodeNameIndexHashtable(ArrayLength(kCodeNames));
1192 for (size_t i = 0; i < ArrayLength(kCodeNames); i++) {
1193 sCodeNameIndexHashtable->InsertOrUpdate(nsDependentString(kCodeNames[i]),
1194 static_cast<CodeNameIndex>(i));
1197 return sCodeNameIndexHashtable->MaybeGet(aCodeValue)
1198 .valueOr(CODE_NAME_INDEX_USE_STRING);
1201 /* static */
1202 uint32_t WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(
1203 CodeNameIndex aCodeNameIndex) {
1204 switch (aCodeNameIndex) {
1205 case CODE_NAME_INDEX_Semicolon: // VK_OEM_1 on Windows
1206 return dom::KeyboardEvent_Binding::DOM_VK_SEMICOLON;
1207 case CODE_NAME_INDEX_Equal: // VK_OEM_PLUS on Windows
1208 return dom::KeyboardEvent_Binding::DOM_VK_EQUALS;
1209 case CODE_NAME_INDEX_Comma: // VK_OEM_COMMA on Windows
1210 return dom::KeyboardEvent_Binding::DOM_VK_COMMA;
1211 case CODE_NAME_INDEX_Minus: // VK_OEM_MINUS on Windows
1212 return dom::KeyboardEvent_Binding::DOM_VK_HYPHEN_MINUS;
1213 case CODE_NAME_INDEX_Period: // VK_OEM_PERIOD on Windows
1214 return dom::KeyboardEvent_Binding::DOM_VK_PERIOD;
1215 case CODE_NAME_INDEX_Slash: // VK_OEM_2 on Windows
1216 return dom::KeyboardEvent_Binding::DOM_VK_SLASH;
1217 case CODE_NAME_INDEX_Backquote: // VK_OEM_3 on Windows
1218 return dom::KeyboardEvent_Binding::DOM_VK_BACK_QUOTE;
1219 case CODE_NAME_INDEX_BracketLeft: // VK_OEM_4 on Windows
1220 return dom::KeyboardEvent_Binding::DOM_VK_OPEN_BRACKET;
1221 case CODE_NAME_INDEX_Backslash: // VK_OEM_5 on Windows
1222 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1223 case CODE_NAME_INDEX_BracketRight: // VK_OEM_6 on Windows
1224 return dom::KeyboardEvent_Binding::DOM_VK_CLOSE_BRACKET;
1225 case CODE_NAME_INDEX_Quote: // VK_OEM_7 on Windows
1226 return dom::KeyboardEvent_Binding::DOM_VK_QUOTE;
1227 case CODE_NAME_INDEX_IntlBackslash: // VK_OEM_5 on Windows (ABNT, etc)
1228 case CODE_NAME_INDEX_IntlYen: // VK_OEM_5 on Windows (JIS)
1229 case CODE_NAME_INDEX_IntlRo: // VK_OEM_102 on Windows
1230 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1231 default:
1232 return 0;
1236 /* static */ const char* WidgetKeyboardEvent::GetCommandStr(Command aCommand) {
1237 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1238 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) , #aCommandStr
1239 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) , ""
1240 static const char* const kCommands[] = {
1241 "" // DoNothing
1242 #include "mozilla/CommandList.h"
1244 #undef NS_DEFINE_COMMAND
1245 #undef NS_DEFINE_COMMAND_WITH_PARAM
1246 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
1248 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand) < ArrayLength(kCommands),
1249 "Illegal command enumeration value");
1250 return kCommands[static_cast<CommandInt>(aCommand)];
1253 /* static */
1254 uint32_t WidgetKeyboardEvent::ComputeLocationFromCodeValue(
1255 CodeNameIndex aCodeNameIndex) {
1256 // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1257 // but are defined by D3E spec. So, they should be uncommented when the
1258 // code values are defined in the header.
1259 switch (aCodeNameIndex) {
1260 case CODE_NAME_INDEX_AltLeft:
1261 case CODE_NAME_INDEX_ControlLeft:
1262 case CODE_NAME_INDEX_OSLeft:
1263 case CODE_NAME_INDEX_ShiftLeft:
1264 return eKeyLocationLeft;
1265 case CODE_NAME_INDEX_AltRight:
1266 case CODE_NAME_INDEX_ControlRight:
1267 case CODE_NAME_INDEX_OSRight:
1268 case CODE_NAME_INDEX_ShiftRight:
1269 return eKeyLocationRight;
1270 case CODE_NAME_INDEX_Numpad0:
1271 case CODE_NAME_INDEX_Numpad1:
1272 case CODE_NAME_INDEX_Numpad2:
1273 case CODE_NAME_INDEX_Numpad3:
1274 case CODE_NAME_INDEX_Numpad4:
1275 case CODE_NAME_INDEX_Numpad5:
1276 case CODE_NAME_INDEX_Numpad6:
1277 case CODE_NAME_INDEX_Numpad7:
1278 case CODE_NAME_INDEX_Numpad8:
1279 case CODE_NAME_INDEX_Numpad9:
1280 case CODE_NAME_INDEX_NumpadAdd:
1281 case CODE_NAME_INDEX_NumpadBackspace:
1282 case CODE_NAME_INDEX_NumpadClear:
1283 case CODE_NAME_INDEX_NumpadClearEntry:
1284 case CODE_NAME_INDEX_NumpadComma:
1285 case CODE_NAME_INDEX_NumpadDecimal:
1286 case CODE_NAME_INDEX_NumpadDivide:
1287 case CODE_NAME_INDEX_NumpadEnter:
1288 case CODE_NAME_INDEX_NumpadEqual:
1289 case CODE_NAME_INDEX_NumpadMemoryAdd:
1290 case CODE_NAME_INDEX_NumpadMemoryClear:
1291 case CODE_NAME_INDEX_NumpadMemoryRecall:
1292 case CODE_NAME_INDEX_NumpadMemoryStore:
1293 case CODE_NAME_INDEX_NumpadMemorySubtract:
1294 case CODE_NAME_INDEX_NumpadMultiply:
1295 case CODE_NAME_INDEX_NumpadParenLeft:
1296 case CODE_NAME_INDEX_NumpadParenRight:
1297 case CODE_NAME_INDEX_NumpadSubtract:
1298 return eKeyLocationNumpad;
1299 default:
1300 return eKeyLocationStandard;
1304 /* static */
1305 uint32_t WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(
1306 KeyNameIndex aKeyNameIndex) {
1307 switch (aKeyNameIndex) {
1308 case KEY_NAME_INDEX_Cancel:
1309 return dom::KeyboardEvent_Binding::DOM_VK_CANCEL;
1310 case KEY_NAME_INDEX_Help:
1311 return dom::KeyboardEvent_Binding::DOM_VK_HELP;
1312 case KEY_NAME_INDEX_Backspace:
1313 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SPACE;
1314 case KEY_NAME_INDEX_Tab:
1315 return dom::KeyboardEvent_Binding::DOM_VK_TAB;
1316 case KEY_NAME_INDEX_Clear:
1317 return dom::KeyboardEvent_Binding::DOM_VK_CLEAR;
1318 case KEY_NAME_INDEX_Enter:
1319 return dom::KeyboardEvent_Binding::DOM_VK_RETURN;
1320 case KEY_NAME_INDEX_Shift:
1321 return dom::KeyboardEvent_Binding::DOM_VK_SHIFT;
1322 case KEY_NAME_INDEX_Control:
1323 return dom::KeyboardEvent_Binding::DOM_VK_CONTROL;
1324 case KEY_NAME_INDEX_Alt:
1325 return dom::KeyboardEvent_Binding::DOM_VK_ALT;
1326 case KEY_NAME_INDEX_Pause:
1327 return dom::KeyboardEvent_Binding::DOM_VK_PAUSE;
1328 case KEY_NAME_INDEX_CapsLock:
1329 return dom::KeyboardEvent_Binding::DOM_VK_CAPS_LOCK;
1330 case KEY_NAME_INDEX_Hiragana:
1331 case KEY_NAME_INDEX_Katakana:
1332 case KEY_NAME_INDEX_HiraganaKatakana:
1333 case KEY_NAME_INDEX_KanaMode:
1334 return dom::KeyboardEvent_Binding::DOM_VK_KANA;
1335 case KEY_NAME_INDEX_HangulMode:
1336 return dom::KeyboardEvent_Binding::DOM_VK_HANGUL;
1337 case KEY_NAME_INDEX_Eisu:
1338 return dom::KeyboardEvent_Binding::DOM_VK_EISU;
1339 case KEY_NAME_INDEX_JunjaMode:
1340 return dom::KeyboardEvent_Binding::DOM_VK_JUNJA;
1341 case KEY_NAME_INDEX_FinalMode:
1342 return dom::KeyboardEvent_Binding::DOM_VK_FINAL;
1343 case KEY_NAME_INDEX_HanjaMode:
1344 return dom::KeyboardEvent_Binding::DOM_VK_HANJA;
1345 case KEY_NAME_INDEX_KanjiMode:
1346 return dom::KeyboardEvent_Binding::DOM_VK_KANJI;
1347 case KEY_NAME_INDEX_Escape:
1348 return dom::KeyboardEvent_Binding::DOM_VK_ESCAPE;
1349 case KEY_NAME_INDEX_Convert:
1350 return dom::KeyboardEvent_Binding::DOM_VK_CONVERT;
1351 case KEY_NAME_INDEX_NonConvert:
1352 return dom::KeyboardEvent_Binding::DOM_VK_NONCONVERT;
1353 case KEY_NAME_INDEX_Accept:
1354 return dom::KeyboardEvent_Binding::DOM_VK_ACCEPT;
1355 case KEY_NAME_INDEX_ModeChange:
1356 return dom::KeyboardEvent_Binding::DOM_VK_MODECHANGE;
1357 case KEY_NAME_INDEX_PageUp:
1358 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_UP;
1359 case KEY_NAME_INDEX_PageDown:
1360 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_DOWN;
1361 case KEY_NAME_INDEX_End:
1362 return dom::KeyboardEvent_Binding::DOM_VK_END;
1363 case KEY_NAME_INDEX_Home:
1364 return dom::KeyboardEvent_Binding::DOM_VK_HOME;
1365 case KEY_NAME_INDEX_ArrowLeft:
1366 return dom::KeyboardEvent_Binding::DOM_VK_LEFT;
1367 case KEY_NAME_INDEX_ArrowUp:
1368 return dom::KeyboardEvent_Binding::DOM_VK_UP;
1369 case KEY_NAME_INDEX_ArrowRight:
1370 return dom::KeyboardEvent_Binding::DOM_VK_RIGHT;
1371 case KEY_NAME_INDEX_ArrowDown:
1372 return dom::KeyboardEvent_Binding::DOM_VK_DOWN;
1373 case KEY_NAME_INDEX_Select:
1374 return dom::KeyboardEvent_Binding::DOM_VK_SELECT;
1375 case KEY_NAME_INDEX_Print:
1376 return dom::KeyboardEvent_Binding::DOM_VK_PRINT;
1377 case KEY_NAME_INDEX_Execute:
1378 return dom::KeyboardEvent_Binding::DOM_VK_EXECUTE;
1379 case KEY_NAME_INDEX_PrintScreen:
1380 return dom::KeyboardEvent_Binding::DOM_VK_PRINTSCREEN;
1381 case KEY_NAME_INDEX_Insert:
1382 return dom::KeyboardEvent_Binding::DOM_VK_INSERT;
1383 case KEY_NAME_INDEX_Delete:
1384 return dom::KeyboardEvent_Binding::DOM_VK_DELETE;
1385 case KEY_NAME_INDEX_OS:
1386 // case KEY_NAME_INDEX_Super:
1387 // case KEY_NAME_INDEX_Hyper:
1388 return dom::KeyboardEvent_Binding::DOM_VK_WIN;
1389 case KEY_NAME_INDEX_ContextMenu:
1390 return dom::KeyboardEvent_Binding::DOM_VK_CONTEXT_MENU;
1391 case KEY_NAME_INDEX_Standby:
1392 return dom::KeyboardEvent_Binding::DOM_VK_SLEEP;
1393 case KEY_NAME_INDEX_F1:
1394 return dom::KeyboardEvent_Binding::DOM_VK_F1;
1395 case KEY_NAME_INDEX_F2:
1396 return dom::KeyboardEvent_Binding::DOM_VK_F2;
1397 case KEY_NAME_INDEX_F3:
1398 return dom::KeyboardEvent_Binding::DOM_VK_F3;
1399 case KEY_NAME_INDEX_F4:
1400 return dom::KeyboardEvent_Binding::DOM_VK_F4;
1401 case KEY_NAME_INDEX_F5:
1402 return dom::KeyboardEvent_Binding::DOM_VK_F5;
1403 case KEY_NAME_INDEX_F6:
1404 return dom::KeyboardEvent_Binding::DOM_VK_F6;
1405 case KEY_NAME_INDEX_F7:
1406 return dom::KeyboardEvent_Binding::DOM_VK_F7;
1407 case KEY_NAME_INDEX_F8:
1408 return dom::KeyboardEvent_Binding::DOM_VK_F8;
1409 case KEY_NAME_INDEX_F9:
1410 return dom::KeyboardEvent_Binding::DOM_VK_F9;
1411 case KEY_NAME_INDEX_F10:
1412 return dom::KeyboardEvent_Binding::DOM_VK_F10;
1413 case KEY_NAME_INDEX_F11:
1414 return dom::KeyboardEvent_Binding::DOM_VK_F11;
1415 case KEY_NAME_INDEX_F12:
1416 return dom::KeyboardEvent_Binding::DOM_VK_F12;
1417 case KEY_NAME_INDEX_F13:
1418 return dom::KeyboardEvent_Binding::DOM_VK_F13;
1419 case KEY_NAME_INDEX_F14:
1420 return dom::KeyboardEvent_Binding::DOM_VK_F14;
1421 case KEY_NAME_INDEX_F15:
1422 return dom::KeyboardEvent_Binding::DOM_VK_F15;
1423 case KEY_NAME_INDEX_F16:
1424 return dom::KeyboardEvent_Binding::DOM_VK_F16;
1425 case KEY_NAME_INDEX_F17:
1426 return dom::KeyboardEvent_Binding::DOM_VK_F17;
1427 case KEY_NAME_INDEX_F18:
1428 return dom::KeyboardEvent_Binding::DOM_VK_F18;
1429 case KEY_NAME_INDEX_F19:
1430 return dom::KeyboardEvent_Binding::DOM_VK_F19;
1431 case KEY_NAME_INDEX_F20:
1432 return dom::KeyboardEvent_Binding::DOM_VK_F20;
1433 case KEY_NAME_INDEX_F21:
1434 return dom::KeyboardEvent_Binding::DOM_VK_F21;
1435 case KEY_NAME_INDEX_F22:
1436 return dom::KeyboardEvent_Binding::DOM_VK_F22;
1437 case KEY_NAME_INDEX_F23:
1438 return dom::KeyboardEvent_Binding::DOM_VK_F23;
1439 case KEY_NAME_INDEX_F24:
1440 return dom::KeyboardEvent_Binding::DOM_VK_F24;
1441 case KEY_NAME_INDEX_NumLock:
1442 return dom::KeyboardEvent_Binding::DOM_VK_NUM_LOCK;
1443 case KEY_NAME_INDEX_ScrollLock:
1444 return dom::KeyboardEvent_Binding::DOM_VK_SCROLL_LOCK;
1445 case KEY_NAME_INDEX_AudioVolumeMute:
1446 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_MUTE;
1447 case KEY_NAME_INDEX_AudioVolumeDown:
1448 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_DOWN;
1449 case KEY_NAME_INDEX_AudioVolumeUp:
1450 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_UP;
1451 case KEY_NAME_INDEX_Meta:
1452 return dom::KeyboardEvent_Binding::DOM_VK_META;
1453 case KEY_NAME_INDEX_AltGraph:
1454 return dom::KeyboardEvent_Binding::DOM_VK_ALTGR;
1455 case KEY_NAME_INDEX_Process:
1456 return dom::KeyboardEvent_Binding::DOM_VK_PROCESSKEY;
1457 case KEY_NAME_INDEX_Attn:
1458 return dom::KeyboardEvent_Binding::DOM_VK_ATTN;
1459 case KEY_NAME_INDEX_CrSel:
1460 return dom::KeyboardEvent_Binding::DOM_VK_CRSEL;
1461 case KEY_NAME_INDEX_ExSel:
1462 return dom::KeyboardEvent_Binding::DOM_VK_EXSEL;
1463 case KEY_NAME_INDEX_EraseEof:
1464 return dom::KeyboardEvent_Binding::DOM_VK_EREOF;
1465 case KEY_NAME_INDEX_Play:
1466 return dom::KeyboardEvent_Binding::DOM_VK_PLAY;
1467 case KEY_NAME_INDEX_ZoomToggle:
1468 case KEY_NAME_INDEX_ZoomIn:
1469 case KEY_NAME_INDEX_ZoomOut:
1470 return dom::KeyboardEvent_Binding::DOM_VK_ZOOM;
1471 default:
1472 return 0;
1476 /* static */
1477 CodeNameIndex WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex(
1478 KeyNameIndex aKeyNameIndex, const Maybe<uint32_t>& aLocation) {
1479 if (aLocation.isSome() &&
1480 aLocation.value() ==
1481 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_NUMPAD) {
1482 // On macOS, NumLock is not supported. Therefore, this handles
1483 // control key values except "Enter" only on non-macOS platforms.
1484 switch (aKeyNameIndex) {
1485 #ifndef XP_MACOSX
1486 case KEY_NAME_INDEX_Insert:
1487 return CODE_NAME_INDEX_Numpad0;
1488 case KEY_NAME_INDEX_End:
1489 return CODE_NAME_INDEX_Numpad1;
1490 case KEY_NAME_INDEX_ArrowDown:
1491 return CODE_NAME_INDEX_Numpad2;
1492 case KEY_NAME_INDEX_PageDown:
1493 return CODE_NAME_INDEX_Numpad3;
1494 case KEY_NAME_INDEX_ArrowLeft:
1495 return CODE_NAME_INDEX_Numpad4;
1496 case KEY_NAME_INDEX_Clear:
1497 // FYI: "Clear" on macOS should be DOM_KEY_LOCATION_STANDARD.
1498 return CODE_NAME_INDEX_Numpad5;
1499 case KEY_NAME_INDEX_ArrowRight:
1500 return CODE_NAME_INDEX_Numpad6;
1501 case KEY_NAME_INDEX_Home:
1502 return CODE_NAME_INDEX_Numpad7;
1503 case KEY_NAME_INDEX_ArrowUp:
1504 return CODE_NAME_INDEX_Numpad8;
1505 case KEY_NAME_INDEX_PageUp:
1506 return CODE_NAME_INDEX_Numpad9;
1507 case KEY_NAME_INDEX_Delete:
1508 return CODE_NAME_INDEX_NumpadDecimal;
1509 #endif // #ifndef XP_MACOSX
1510 case KEY_NAME_INDEX_Enter:
1511 return CODE_NAME_INDEX_NumpadEnter;
1512 default:
1513 return CODE_NAME_INDEX_UNKNOWN;
1517 if (WidgetKeyboardEvent::IsLeftOrRightModiferKeyNameIndex(aKeyNameIndex)) {
1518 if (aLocation.isSome() &&
1519 (aLocation.value() !=
1520 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_LEFT &&
1521 aLocation.value() !=
1522 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT)) {
1523 return CODE_NAME_INDEX_UNKNOWN;
1525 bool isRight =
1526 aLocation.isSome() &&
1527 aLocation.value() == dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT;
1528 switch (aKeyNameIndex) {
1529 case KEY_NAME_INDEX_Alt:
1530 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1531 case KEY_NAME_INDEX_Control:
1532 return isRight ? CODE_NAME_INDEX_ControlRight
1533 : CODE_NAME_INDEX_ControlLeft;
1534 case KEY_NAME_INDEX_Shift:
1535 return isRight ? CODE_NAME_INDEX_ShiftRight : CODE_NAME_INDEX_ShiftLeft;
1536 #if defined(XP_WIN)
1537 case KEY_NAME_INDEX_Meta:
1538 return CODE_NAME_INDEX_UNKNOWN;
1539 case KEY_NAME_INDEX_OS: // win key.
1540 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1541 #elif defined(XP_MACOSX) || defined(ANDROID)
1542 case KEY_NAME_INDEX_Meta: // command key.
1543 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1544 case KEY_NAME_INDEX_OS:
1545 return CODE_NAME_INDEX_UNKNOWN;
1546 #else
1547 case KEY_NAME_INDEX_Meta: // Alt + Shift.
1548 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1549 case KEY_NAME_INDEX_OS: // Super/Hyper key.
1550 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1551 #endif
1552 default:
1553 return CODE_NAME_INDEX_UNKNOWN;
1557 if (aLocation.isSome() &&
1558 aLocation.value() !=
1559 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_STANDARD) {
1560 return CODE_NAME_INDEX_UNKNOWN;
1563 switch (aKeyNameIndex) {
1564 // Standard section:
1565 case KEY_NAME_INDEX_Escape:
1566 return CODE_NAME_INDEX_Escape;
1567 case KEY_NAME_INDEX_Tab:
1568 return CODE_NAME_INDEX_Tab;
1569 case KEY_NAME_INDEX_CapsLock:
1570 return CODE_NAME_INDEX_CapsLock;
1571 case KEY_NAME_INDEX_ContextMenu:
1572 return CODE_NAME_INDEX_ContextMenu;
1573 case KEY_NAME_INDEX_Backspace:
1574 return CODE_NAME_INDEX_Backspace;
1575 case KEY_NAME_INDEX_Enter:
1576 return CODE_NAME_INDEX_Enter;
1577 #ifdef XP_MACOSX
1578 // Although, macOS does not fire native key event of "Fn" key, we support
1579 // Fn key event if it's sent by other apps directly.
1580 case KEY_NAME_INDEX_Fn:
1581 return CODE_NAME_INDEX_Fn;
1582 #endif // #ifdef
1584 // Arrow Pad section:
1585 case KEY_NAME_INDEX_ArrowLeft:
1586 return CODE_NAME_INDEX_ArrowLeft;
1587 case KEY_NAME_INDEX_ArrowUp:
1588 return CODE_NAME_INDEX_ArrowUp;
1589 case KEY_NAME_INDEX_ArrowDown:
1590 return CODE_NAME_INDEX_ArrowDown;
1591 case KEY_NAME_INDEX_ArrowRight:
1592 return CODE_NAME_INDEX_ArrowRight;
1594 // Control Pad section:
1595 #ifndef XP_MACOSX
1596 case KEY_NAME_INDEX_Insert:
1597 return CODE_NAME_INDEX_Insert;
1598 #else
1599 case KEY_NAME_INDEX_Help:
1600 return CODE_NAME_INDEX_Help;
1601 #endif // #ifndef XP_MACOSX #else
1602 case KEY_NAME_INDEX_Delete:
1603 return CODE_NAME_INDEX_Delete;
1604 case KEY_NAME_INDEX_Home:
1605 return CODE_NAME_INDEX_Home;
1606 case KEY_NAME_INDEX_End:
1607 return CODE_NAME_INDEX_End;
1608 case KEY_NAME_INDEX_PageUp:
1609 return CODE_NAME_INDEX_PageUp;
1610 case KEY_NAME_INDEX_PageDown:
1611 return CODE_NAME_INDEX_PageDown;
1613 // Function keys:
1614 case KEY_NAME_INDEX_F1:
1615 return CODE_NAME_INDEX_F1;
1616 case KEY_NAME_INDEX_F2:
1617 return CODE_NAME_INDEX_F2;
1618 case KEY_NAME_INDEX_F3:
1619 return CODE_NAME_INDEX_F3;
1620 case KEY_NAME_INDEX_F4:
1621 return CODE_NAME_INDEX_F4;
1622 case KEY_NAME_INDEX_F5:
1623 return CODE_NAME_INDEX_F5;
1624 case KEY_NAME_INDEX_F6:
1625 return CODE_NAME_INDEX_F6;
1626 case KEY_NAME_INDEX_F7:
1627 return CODE_NAME_INDEX_F7;
1628 case KEY_NAME_INDEX_F8:
1629 return CODE_NAME_INDEX_F8;
1630 case KEY_NAME_INDEX_F9:
1631 return CODE_NAME_INDEX_F9;
1632 case KEY_NAME_INDEX_F10:
1633 return CODE_NAME_INDEX_F10;
1634 case KEY_NAME_INDEX_F11:
1635 return CODE_NAME_INDEX_F11;
1636 case KEY_NAME_INDEX_F12:
1637 return CODE_NAME_INDEX_F12;
1638 case KEY_NAME_INDEX_F13:
1639 return CODE_NAME_INDEX_F13;
1640 case KEY_NAME_INDEX_F14:
1641 return CODE_NAME_INDEX_F14;
1642 case KEY_NAME_INDEX_F15:
1643 return CODE_NAME_INDEX_F15;
1644 case KEY_NAME_INDEX_F16:
1645 return CODE_NAME_INDEX_F16;
1646 case KEY_NAME_INDEX_F17:
1647 return CODE_NAME_INDEX_F17;
1648 case KEY_NAME_INDEX_F18:
1649 return CODE_NAME_INDEX_F18;
1650 case KEY_NAME_INDEX_F19:
1651 return CODE_NAME_INDEX_F19;
1652 case KEY_NAME_INDEX_F20:
1653 return CODE_NAME_INDEX_F20;
1654 #ifndef XP_MACOSX
1655 case KEY_NAME_INDEX_F21:
1656 return CODE_NAME_INDEX_F21;
1657 case KEY_NAME_INDEX_F22:
1658 return CODE_NAME_INDEX_F22;
1659 case KEY_NAME_INDEX_F23:
1660 return CODE_NAME_INDEX_F23;
1661 case KEY_NAME_INDEX_F24:
1662 return CODE_NAME_INDEX_F24;
1663 case KEY_NAME_INDEX_Pause:
1664 return CODE_NAME_INDEX_Pause;
1665 case KEY_NAME_INDEX_PrintScreen:
1666 return CODE_NAME_INDEX_PrintScreen;
1667 case KEY_NAME_INDEX_ScrollLock:
1668 return CODE_NAME_INDEX_ScrollLock;
1669 #endif // #ifndef XP_MACOSX
1671 // NumLock key:
1672 #ifndef XP_MACOSX
1673 case KEY_NAME_INDEX_NumLock:
1674 return CODE_NAME_INDEX_NumLock;
1675 #else
1676 case KEY_NAME_INDEX_Clear:
1677 return CODE_NAME_INDEX_NumLock;
1678 #endif // #ifndef XP_MACOSX #else
1680 // Media keys:
1681 case KEY_NAME_INDEX_AudioVolumeDown:
1682 return CODE_NAME_INDEX_VolumeDown;
1683 case KEY_NAME_INDEX_AudioVolumeMute:
1684 return CODE_NAME_INDEX_VolumeMute;
1685 case KEY_NAME_INDEX_AudioVolumeUp:
1686 return CODE_NAME_INDEX_VolumeUp;
1687 #ifndef XP_MACOSX
1688 case KEY_NAME_INDEX_BrowserBack:
1689 return CODE_NAME_INDEX_BrowserBack;
1690 case KEY_NAME_INDEX_BrowserFavorites:
1691 return CODE_NAME_INDEX_BrowserFavorites;
1692 case KEY_NAME_INDEX_BrowserForward:
1693 return CODE_NAME_INDEX_BrowserForward;
1694 case KEY_NAME_INDEX_BrowserRefresh:
1695 return CODE_NAME_INDEX_BrowserRefresh;
1696 case KEY_NAME_INDEX_BrowserSearch:
1697 return CODE_NAME_INDEX_BrowserSearch;
1698 case KEY_NAME_INDEX_BrowserStop:
1699 return CODE_NAME_INDEX_BrowserStop;
1700 case KEY_NAME_INDEX_MediaPlayPause:
1701 return CODE_NAME_INDEX_MediaPlayPause;
1702 case KEY_NAME_INDEX_MediaStop:
1703 return CODE_NAME_INDEX_MediaStop;
1704 case KEY_NAME_INDEX_MediaTrackNext:
1705 return CODE_NAME_INDEX_MediaTrackNext;
1706 case KEY_NAME_INDEX_MediaTrackPrevious:
1707 return CODE_NAME_INDEX_MediaTrackPrevious;
1708 case KEY_NAME_INDEX_LaunchApplication1:
1709 return CODE_NAME_INDEX_LaunchApp1;
1710 #endif // #ifndef XP_MACOSX
1712 // Only Windows and GTK supports the following multimedia keys.
1713 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1714 case KEY_NAME_INDEX_BrowserHome:
1715 return CODE_NAME_INDEX_BrowserHome;
1716 case KEY_NAME_INDEX_LaunchApplication2:
1717 return CODE_NAME_INDEX_LaunchApp2;
1718 #endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1720 // Only GTK and Android supports the following multimedia keys.
1721 #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1722 case KEY_NAME_INDEX_Eject:
1723 return CODE_NAME_INDEX_Eject;
1724 case KEY_NAME_INDEX_WakeUp:
1725 return CODE_NAME_INDEX_WakeUp;
1726 #endif // #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1728 // Only Windows does not support Help key (and macOS handled above).
1729 #if !defined(XP_WIN) && !defined(XP_MACOSX)
1730 case KEY_NAME_INDEX_Help:
1731 return CODE_NAME_INDEX_Help;
1732 #endif // #if !defined(XP_WIN) && !defined(XP_MACOSX)
1734 // IME specific keys:
1735 #ifdef XP_WIN
1736 case KEY_NAME_INDEX_Convert:
1737 return CODE_NAME_INDEX_Convert;
1738 case KEY_NAME_INDEX_NonConvert:
1739 return CODE_NAME_INDEX_NonConvert;
1740 case KEY_NAME_INDEX_Alphanumeric:
1741 return CODE_NAME_INDEX_CapsLock;
1742 case KEY_NAME_INDEX_KanaMode:
1743 case KEY_NAME_INDEX_Romaji:
1744 case KEY_NAME_INDEX_Katakana:
1745 case KEY_NAME_INDEX_Hiragana:
1746 return CODE_NAME_INDEX_KanaMode;
1747 case KEY_NAME_INDEX_Hankaku:
1748 case KEY_NAME_INDEX_Zenkaku:
1749 case KEY_NAME_INDEX_KanjiMode:
1750 return CODE_NAME_INDEX_Backquote;
1751 case KEY_NAME_INDEX_HanjaMode:
1752 return CODE_NAME_INDEX_Lang2;
1753 case KEY_NAME_INDEX_HangulMode:
1754 return CODE_NAME_INDEX_Lang1;
1755 #endif // #ifdef XP_WIN
1757 #ifdef MOZ_WIDGET_GTK
1758 case KEY_NAME_INDEX_Convert:
1759 return CODE_NAME_INDEX_Convert;
1760 case KEY_NAME_INDEX_NonConvert:
1761 return CODE_NAME_INDEX_NonConvert;
1762 case KEY_NAME_INDEX_Alphanumeric:
1763 return CODE_NAME_INDEX_CapsLock;
1764 case KEY_NAME_INDEX_HiraganaKatakana:
1765 return CODE_NAME_INDEX_KanaMode;
1766 case KEY_NAME_INDEX_ZenkakuHankaku:
1767 return CODE_NAME_INDEX_Backquote;
1768 #endif // #ifdef MOZ_WIDGET_GTK
1770 #ifdef ANDROID
1771 case KEY_NAME_INDEX_Convert:
1772 return CODE_NAME_INDEX_Convert;
1773 case KEY_NAME_INDEX_NonConvert:
1774 return CODE_NAME_INDEX_NonConvert;
1775 case KEY_NAME_INDEX_HiraganaKatakana:
1776 return CODE_NAME_INDEX_KanaMode;
1777 case KEY_NAME_INDEX_ZenkakuHankaku:
1778 return CODE_NAME_INDEX_Backquote;
1779 case KEY_NAME_INDEX_Eisu:
1780 return CODE_NAME_INDEX_Lang2;
1781 case KEY_NAME_INDEX_KanjiMode:
1782 return CODE_NAME_INDEX_Lang1;
1783 #endif // #ifdef ANDROID
1785 #ifdef XP_MACOSX
1786 case KEY_NAME_INDEX_Eisu:
1787 return CODE_NAME_INDEX_Lang2;
1788 case KEY_NAME_INDEX_KanjiMode:
1789 return CODE_NAME_INDEX_Lang1;
1790 #endif // #ifdef XP_MACOSX
1792 default:
1793 return CODE_NAME_INDEX_UNKNOWN;
1797 /* static */
1798 Modifier WidgetKeyboardEvent::GetModifierForKeyName(
1799 KeyNameIndex aKeyNameIndex) {
1800 switch (aKeyNameIndex) {
1801 case KEY_NAME_INDEX_Alt:
1802 return MODIFIER_ALT;
1803 case KEY_NAME_INDEX_AltGraph:
1804 return MODIFIER_ALTGRAPH;
1805 case KEY_NAME_INDEX_CapsLock:
1806 return MODIFIER_CAPSLOCK;
1807 case KEY_NAME_INDEX_Control:
1808 return MODIFIER_CONTROL;
1809 case KEY_NAME_INDEX_Fn:
1810 return MODIFIER_FN;
1811 case KEY_NAME_INDEX_FnLock:
1812 return MODIFIER_FNLOCK;
1813 // case KEY_NAME_INDEX_Hyper:
1814 case KEY_NAME_INDEX_Meta:
1815 return MODIFIER_META;
1816 case KEY_NAME_INDEX_NumLock:
1817 return MODIFIER_NUMLOCK;
1818 case KEY_NAME_INDEX_OS:
1819 return MODIFIER_OS;
1820 case KEY_NAME_INDEX_ScrollLock:
1821 return MODIFIER_SCROLLLOCK;
1822 case KEY_NAME_INDEX_Shift:
1823 return MODIFIER_SHIFT;
1824 // case KEY_NAME_INDEX_Super:
1825 case KEY_NAME_INDEX_Symbol:
1826 return MODIFIER_SYMBOL;
1827 case KEY_NAME_INDEX_SymbolLock:
1828 return MODIFIER_SYMBOLLOCK;
1829 default:
1830 return MODIFIER_NONE;
1834 /* static */
1835 bool WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex) {
1836 switch (aKeyNameIndex) {
1837 case KEY_NAME_INDEX_CapsLock:
1838 case KEY_NAME_INDEX_FnLock:
1839 case KEY_NAME_INDEX_NumLock:
1840 case KEY_NAME_INDEX_ScrollLock:
1841 case KEY_NAME_INDEX_SymbolLock:
1842 return true;
1843 default:
1844 return false;
1848 /******************************************************************************
1849 * mozilla::InternalEditorInputEvent (TextEvents.h)
1850 ******************************************************************************/
1852 #define NS_DEFINE_INPUTTYPE(aCPPName, aDOMName) (u"" aDOMName),
1853 const char16_t* const InternalEditorInputEvent::kInputTypeNames[] = {
1854 #include "mozilla/InputTypeList.h"
1856 #undef NS_DEFINE_INPUTTYPE
1858 InternalEditorInputEvent::InputTypeHashtable*
1859 InternalEditorInputEvent::sInputTypeHashtable = nullptr;
1861 /* static */
1862 void InternalEditorInputEvent::Shutdown() {
1863 delete sInputTypeHashtable;
1864 sInputTypeHashtable = nullptr;
1867 /* static */
1868 void InternalEditorInputEvent::GetDOMInputTypeName(EditorInputType aInputType,
1869 nsAString& aInputTypeName) {
1870 if (static_cast<size_t>(aInputType) >=
1871 static_cast<size_t>(EditorInputType::eUnknown)) {
1872 aInputTypeName.Truncate();
1873 return;
1876 MOZ_RELEASE_ASSERT(
1877 static_cast<size_t>(aInputType) < ArrayLength(kInputTypeNames),
1878 "Illegal input type enumeration value");
1879 aInputTypeName.Assign(kInputTypeNames[static_cast<size_t>(aInputType)]);
1882 /* static */
1883 EditorInputType InternalEditorInputEvent::GetEditorInputType(
1884 const nsAString& aInputType) {
1885 if (aInputType.IsEmpty()) {
1886 return EditorInputType::eUnknown;
1889 if (!sInputTypeHashtable) {
1890 sInputTypeHashtable = new InputTypeHashtable(ArrayLength(kInputTypeNames));
1891 for (size_t i = 0; i < ArrayLength(kInputTypeNames); i++) {
1892 sInputTypeHashtable->InsertOrUpdate(nsDependentString(kInputTypeNames[i]),
1893 static_cast<EditorInputType>(i));
1896 return sInputTypeHashtable->MaybeGet(aInputType)
1897 .valueOr(EditorInputType::eUnknown);
1900 } // namespace mozilla