Bug 1770047 [wpt PR 34117] - Update wpt metadata, a=testonly
[gecko.git] / widget / WidgetEventImpl.cpp
blob254b176a43655e84893958fdd9e2700188edbdba
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 eAccessKeyNotFound:
353 return true;
354 default:
355 return false;
359 bool WidgetEvent::HasIMEEventMessage() const {
360 switch (mMessage) {
361 case eCompositionStart:
362 case eCompositionEnd:
363 case eCompositionUpdate:
364 case eCompositionChange:
365 case eCompositionCommitAsIs:
366 case eCompositionCommit:
367 return true;
368 default:
369 return false;
373 /******************************************************************************
374 * mozilla::WidgetEvent
376 * Specific event checking methods.
377 ******************************************************************************/
379 bool WidgetEvent::CanBeSentToRemoteProcess() const {
380 // If this event is explicitly marked as shouldn't be sent to remote process,
381 // just return false.
382 if (IsCrossProcessForwardingStopped()) {
383 return false;
386 if (mClass == eKeyboardEventClass || mClass == eWheelEventClass) {
387 return true;
390 switch (mMessage) {
391 case eMouseDown:
392 case eMouseUp:
393 case eMouseMove:
394 case eMouseExploreByTouch:
395 case eContextMenu:
396 case eMouseEnterIntoWidget:
397 case eMouseExitFromWidget:
398 case eMouseTouchDrag:
399 case eTouchStart:
400 case eTouchMove:
401 case eTouchEnd:
402 case eTouchCancel:
403 case eDragOver:
404 case eDragExit:
405 case eDrop:
406 return true;
407 default:
408 return false;
412 bool WidgetEvent::WillBeSentToRemoteProcess() const {
413 // This event won't be posted to remote process if it's already explicitly
414 // stopped.
415 if (IsCrossProcessForwardingStopped()) {
416 return false;
419 // When mOriginalTarget is nullptr, this method shouldn't be used.
420 if (NS_WARN_IF(!mOriginalTarget)) {
421 return false;
424 return EventStateManager::IsTopLevelRemoteTarget(
425 nsIContent::FromEventTarget(mOriginalTarget));
428 bool WidgetEvent::IsIMERelatedEvent() const {
429 return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
432 bool WidgetEvent::IsUsingCoordinates() const {
433 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
434 if (mouseEvent) {
435 return !mouseEvent->IsContextMenuKeyEvent();
437 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
438 !IsContentCommandEvent();
441 bool WidgetEvent::IsTargetedAtFocusedWindow() const {
442 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
443 if (mouseEvent) {
444 return mouseEvent->IsContextMenuKeyEvent();
446 return HasKeyEventMessage() || IsIMERelatedEvent() || IsContentCommandEvent();
449 bool WidgetEvent::IsTargetedAtFocusedContent() const {
450 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
451 if (mouseEvent) {
452 return mouseEvent->IsContextMenuKeyEvent();
454 return HasKeyEventMessage() || IsIMERelatedEvent();
457 bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
458 switch (mClass) {
459 case eMouseEventClass:
460 if (mMessage == eMouseTouchDrag) {
461 return false;
463 [[fallthrough]];
464 case ePointerEventClass:
465 // We want synthesized mouse moves to cause mouseover and mouseout
466 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
467 // DOM events.
468 // Synthesized button up events also do not cause DOM events because they
469 // do not have a reliable mRefPoint.
470 return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
472 case eWheelEventClass: {
473 // wheel event whose all delta values are zero by user pref applied, it
474 // shouldn't cause a DOM event.
475 const WidgetWheelEvent* wheelEvent = AsWheelEvent();
476 return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
477 wheelEvent->mDeltaZ != 0.0;
479 case eTouchEventClass:
480 return mMessage != eTouchPointerCancel;
481 // Following events are handled in EventStateManager, so, we don't need to
482 // dispatch DOM event for them into the DOM tree.
483 case eQueryContentEventClass:
484 case eSelectionEventClass:
485 case eContentCommandEventClass:
486 return false;
488 default:
489 return true;
493 bool WidgetEvent::IsAllowedToDispatchInSystemGroup() const {
494 // We don't expect to implement default behaviors with pointer events because
495 // if we do, prevent default on mouse events can't prevent default behaviors
496 // anymore.
497 return mClass != ePointerEventClass;
500 bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
501 if (!nsContentUtils::ShouldResistFingerprinting()) {
502 return false;
505 switch (mClass) {
506 case eKeyboardEventClass: {
507 const WidgetKeyboardEvent* keyboardEvent = AsKeyboardEvent();
509 return (keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Alt ||
510 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Shift ||
511 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Control ||
512 keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_AltGraph);
514 case ePointerEventClass: {
515 const WidgetPointerEvent* pointerEvent = AsPointerEvent();
517 // We suppress the pointer events if it is not primary for fingerprinting
518 // resistance. It is because of that we want to spoof any pointer event
519 // into a mouse pointer event and the mouse pointer event only has
520 // isPrimary as true.
521 return !pointerEvent->mIsPrimary;
523 default:
524 return false;
528 /******************************************************************************
529 * mozilla::WidgetEvent
531 * Misc methods.
532 ******************************************************************************/
534 static dom::EventTarget* GetTargetForDOMEvent(dom::EventTarget* aTarget) {
535 return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
538 dom::EventTarget* WidgetEvent::GetDOMEventTarget() const {
539 return GetTargetForDOMEvent(mTarget);
542 dom::EventTarget* WidgetEvent::GetCurrentDOMEventTarget() const {
543 return GetTargetForDOMEvent(mCurrentTarget);
546 dom::EventTarget* WidgetEvent::GetOriginalDOMEventTarget() const {
547 if (mOriginalTarget) {
548 return GetTargetForDOMEvent(mOriginalTarget);
550 return GetDOMEventTarget();
553 void WidgetEvent::PreventDefault(bool aCalledByDefaultHandler,
554 nsIPrincipal* aPrincipal) {
555 if (mMessage == ePointerDown) {
556 if (aCalledByDefaultHandler) {
557 // Shouldn't prevent default on pointerdown by default handlers to stop
558 // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages
559 // in debug builds.
560 MOZ_ASSERT(false);
561 return;
563 if (aPrincipal) {
564 nsAutoString addonId;
565 Unused << NS_WARN_IF(NS_FAILED(aPrincipal->GetAddonId(addonId)));
566 if (!addonId.IsEmpty()) {
567 // Ignore the case that it's called by a web extension.
568 return;
572 mFlags.PreventDefault(aCalledByDefaultHandler);
575 bool WidgetEvent::IsUserAction() const {
576 if (!IsTrusted()) {
577 return false;
579 // FYI: eMouseScrollEventClass and ePointerEventClass represent
580 // user action but they are synthesized events.
581 switch (mClass) {
582 case eKeyboardEventClass:
583 case eCompositionEventClass:
584 case eMouseScrollEventClass:
585 case eWheelEventClass:
586 case eGestureNotifyEventClass:
587 case eSimpleGestureEventClass:
588 case eTouchEventClass:
589 case eCommandEventClass:
590 case eContentCommandEventClass:
591 return true;
592 case eMouseEventClass:
593 case eDragEventClass:
594 case ePointerEventClass:
595 return AsMouseEvent()->IsReal();
596 default:
597 return false;
601 /******************************************************************************
602 * mozilla::WidgetInputEvent
603 ******************************************************************************/
605 /* static */
606 Modifier WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName) {
607 if (aDOMKeyName.EqualsLiteral("Accel")) {
608 return AccelModifier();
610 KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName);
611 return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex);
614 /* static */
615 Modifier WidgetInputEvent::AccelModifier() {
616 static Modifier sAccelModifier = MODIFIER_NONE;
617 if (sAccelModifier == MODIFIER_NONE) {
618 switch (Preferences::GetInt("ui.key.accelKey", 0)) {
619 case dom::KeyboardEvent_Binding::DOM_VK_META:
620 sAccelModifier = MODIFIER_META;
621 break;
622 case dom::KeyboardEvent_Binding::DOM_VK_WIN:
623 sAccelModifier = MODIFIER_OS;
624 break;
625 case dom::KeyboardEvent_Binding::DOM_VK_ALT:
626 sAccelModifier = MODIFIER_ALT;
627 break;
628 case dom::KeyboardEvent_Binding::DOM_VK_CONTROL:
629 sAccelModifier = MODIFIER_CONTROL;
630 break;
631 default:
632 #ifdef XP_MACOSX
633 sAccelModifier = MODIFIER_META;
634 #else
635 sAccelModifier = MODIFIER_CONTROL;
636 #endif
637 break;
640 return sAccelModifier;
643 /******************************************************************************
644 * mozilla::WidgetMouseEvent (MouseEvents.h)
645 ******************************************************************************/
647 /* static */
648 bool WidgetMouseEvent::IsMiddleClickPasteEnabled() {
649 return Preferences::GetBool("middlemouse.paste", false);
652 #ifdef DEBUG
653 void WidgetMouseEvent::AssertContextMenuEventButtonConsistency() const {
654 if (mMessage != eContextMenu) {
655 return;
658 if (mContextMenuTrigger == eNormal) {
659 NS_WARNING_ASSERTION(mButton == MouseButton::eSecondary,
660 "eContextMenu events with eNormal trigger should use "
661 "secondary mouse button");
662 } else {
663 NS_WARNING_ASSERTION(mButton == MouseButton::ePrimary,
664 "eContextMenu events with non-eNormal trigger should "
665 "use primary mouse button");
668 if (mContextMenuTrigger == eControlClick) {
669 NS_WARNING_ASSERTION(IsControl(),
670 "eContextMenu events with eControlClick trigger "
671 "should return true from IsControl()");
674 #endif
676 /******************************************************************************
677 * mozilla::WidgetDragEvent (MouseEvents.h)
678 ******************************************************************************/
680 void WidgetDragEvent::InitDropEffectForTests() {
681 MOZ_ASSERT(mFlags.mIsSynthesizedForTests);
683 nsCOMPtr<nsIDragSession> session = nsContentUtils::GetDragSession();
684 if (NS_WARN_IF(!session)) {
685 return;
688 uint32_t effectAllowed = session->GetEffectAllowedForTests();
689 uint32_t desiredDropEffect = nsIDragService::DRAGDROP_ACTION_NONE;
690 #ifdef XP_MACOSX
691 if (IsAlt()) {
692 desiredDropEffect = IsMeta() ? nsIDragService::DRAGDROP_ACTION_LINK
693 : nsIDragService::DRAGDROP_ACTION_COPY;
695 #else
696 // On Linux, we know user's intention from API, but we should use
697 // same modifiers as Windows for tests because GNOME on Ubuntu use
698 // them and that makes each test simpler.
699 if (IsControl()) {
700 desiredDropEffect = IsShift() ? nsIDragService::DRAGDROP_ACTION_LINK
701 : nsIDragService::DRAGDROP_ACTION_COPY;
702 } else if (IsShift()) {
703 desiredDropEffect = nsIDragService::DRAGDROP_ACTION_MOVE;
705 #endif // #ifdef XP_MACOSX #else
706 // First, use modifier state for preferring action which is explicitly
707 // specified by the synthesizer.
708 if (!(desiredDropEffect &= effectAllowed)) {
709 // Otherwise, use an action which is allowed at starting the session.
710 desiredDropEffect = effectAllowed;
712 if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_MOVE) {
713 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE);
714 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_COPY) {
715 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY);
716 } else if (desiredDropEffect & nsIDragService::DRAGDROP_ACTION_LINK) {
717 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK);
718 } else {
719 session->SetDragAction(nsIDragService::DRAGDROP_ACTION_NONE);
723 /******************************************************************************
724 * mozilla::WidgetWheelEvent (MouseEvents.h)
725 ******************************************************************************/
727 /* static */
728 double WidgetWheelEvent::ComputeOverriddenDelta(double aDelta,
729 bool aIsForVertical) {
730 if (!StaticPrefs::mousewheel_system_scroll_override_enabled()) {
731 return aDelta;
733 int32_t intFactor =
734 aIsForVertical
735 ? StaticPrefs::mousewheel_system_scroll_override_vertical_factor()
736 : StaticPrefs::mousewheel_system_scroll_override_horizontal_factor();
737 // Making the scroll speed slower doesn't make sense. So, ignore odd factor
738 // which is less than 1.0.
739 if (intFactor <= 100) {
740 return aDelta;
742 double factor = static_cast<double>(intFactor) / 100;
743 return aDelta * factor;
746 double WidgetWheelEvent::OverriddenDeltaX() const {
747 if (!mAllowToOverrideSystemScrollSpeed ||
748 mDeltaMode != dom::WheelEvent_Binding::DOM_DELTA_LINE ||
749 mCustomizedByUserPrefs) {
750 return mDeltaX;
752 return ComputeOverriddenDelta(mDeltaX, false);
755 double WidgetWheelEvent::OverriddenDeltaY() const {
756 if (!mAllowToOverrideSystemScrollSpeed ||
757 mDeltaMode != dom::WheelEvent_Binding::DOM_DELTA_LINE ||
758 mCustomizedByUserPrefs) {
759 return mDeltaY;
761 return ComputeOverriddenDelta(mDeltaY, true);
764 /******************************************************************************
765 * mozilla::WidgetKeyboardEvent (TextEvents.h)
766 ******************************************************************************/
768 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
769 const char16_t* const WidgetKeyboardEvent::kKeyNames[] = {
770 #include "mozilla/KeyNameList.h"
772 #undef NS_DEFINE_KEYNAME
774 #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
775 (u"" aDOMCodeName),
776 const char16_t* const WidgetKeyboardEvent::kCodeNames[] = {
777 #include "mozilla/PhysicalKeyCodeNameList.h"
779 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
781 WidgetKeyboardEvent::KeyNameIndexHashtable*
782 WidgetKeyboardEvent::sKeyNameIndexHashtable = nullptr;
783 WidgetKeyboardEvent::CodeNameIndexHashtable*
784 WidgetKeyboardEvent::sCodeNameIndexHashtable = nullptr;
786 void WidgetKeyboardEvent::InitAllEditCommands(
787 const Maybe<WritingMode>& aWritingMode) {
788 // If this event is synthesized for tests, we don't need to retrieve the
789 // command via the main process. So, we don't need widget and can trust
790 // the event.
791 if (!mFlags.mIsSynthesizedForTests) {
792 // If the event was created without widget, e.g., created event in chrome
793 // script, this shouldn't execute native key bindings.
794 if (NS_WARN_IF(!mWidget)) {
795 return;
798 // This event should be trusted event here and we shouldn't expose native
799 // key binding information to web contents with untrusted events.
800 if (NS_WARN_IF(!IsTrusted())) {
801 return;
804 MOZ_ASSERT(
805 XRE_IsParentProcess(),
806 "It's too expensive to retrieve all edit commands from remote process");
807 MOZ_ASSERT(!AreAllEditCommandsInitialized(),
808 "Shouldn't be called two or more times");
811 DebugOnly<bool> okIgnored = InitEditCommandsFor(
812 NativeKeyBindingsType::SingleLineEditor, aWritingMode);
813 NS_WARNING_ASSERTION(okIgnored,
814 "InitEditCommandsFor(NativeKeyBindingsType::"
815 "SingleLineEditor) failed, but ignored");
816 okIgnored =
817 InitEditCommandsFor(NativeKeyBindingsType::MultiLineEditor, aWritingMode);
818 NS_WARNING_ASSERTION(okIgnored,
819 "InitEditCommandsFor(NativeKeyBindingsType::"
820 "MultiLineEditor) failed, but ignored");
821 okIgnored =
822 InitEditCommandsFor(NativeKeyBindingsType::RichTextEditor, aWritingMode);
823 NS_WARNING_ASSERTION(okIgnored,
824 "InitEditCommandsFor(NativeKeyBindingsType::"
825 "RichTextEditor) failed, but ignored");
828 bool WidgetKeyboardEvent::InitEditCommandsFor(
829 NativeKeyBindingsType aType, const Maybe<WritingMode>& aWritingMode) {
830 bool& initialized = IsEditCommandsInitializedRef(aType);
831 if (initialized) {
832 return true;
834 nsTArray<CommandInt>& commands = EditCommandsRef(aType);
836 // If this event is synthesized for tests, we shouldn't access customized
837 // shortcut settings of the environment. Therefore, we don't need to check
838 // whether `widget` is set or not. And we can treat synthesized events are
839 // always trusted.
840 if (mFlags.mIsSynthesizedForTests) {
841 MOZ_DIAGNOSTIC_ASSERT(IsTrusted());
842 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
843 // TODO: We should implement `NativeKeyBindings` for Windows and Android
844 // too in bug 1301497 for getting rid of the #if.
845 widget::NativeKeyBindings::GetEditCommandsForTests(aType, *this,
846 aWritingMode, commands);
847 #endif
848 initialized = true;
849 return true;
852 if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
853 return false;
855 // `nsIWidget::GetEditCommands()` will retrieve `WritingMode` at selection
856 // again, but it should be almost zero-cost since `TextEventDispatcher`
857 // caches the value.
858 nsCOMPtr<nsIWidget> widget = mWidget;
859 initialized = widget->GetEditCommands(aType, *this, commands);
860 return initialized;
863 bool WidgetKeyboardEvent::ExecuteEditCommands(NativeKeyBindingsType aType,
864 DoCommandCallback aCallback,
865 void* aCallbackData) {
866 // If the event was created without widget, e.g., created event in chrome
867 // script, this shouldn't execute native key bindings.
868 if (NS_WARN_IF(!mWidget)) {
869 return false;
872 // This event should be trusted event here and we shouldn't expose native
873 // key binding information to web contents with untrusted events.
874 if (NS_WARN_IF(!IsTrusted())) {
875 return false;
878 if (!IsEditCommandsInitializedRef(aType)) {
879 Maybe<WritingMode> writingMode;
880 if (RefPtr<widget::TextEventDispatcher> textEventDispatcher =
881 mWidget->GetTextEventDispatcher()) {
882 writingMode = textEventDispatcher->MaybeQueryWritingModeAtSelection();
884 if (NS_WARN_IF(!InitEditCommandsFor(aType, writingMode))) {
885 return false;
889 const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
890 if (commands.IsEmpty()) {
891 return false;
894 for (CommandInt command : commands) {
895 aCallback(static_cast<Command>(command), aCallbackData);
897 return true;
900 bool WidgetKeyboardEvent::ShouldCauseKeypressEvents() const {
901 // Currently, we don't dispatch keypress events of modifier keys and
902 // dead keys.
903 switch (mKeyNameIndex) {
904 case KEY_NAME_INDEX_Alt:
905 case KEY_NAME_INDEX_AltGraph:
906 case KEY_NAME_INDEX_CapsLock:
907 case KEY_NAME_INDEX_Control:
908 case KEY_NAME_INDEX_Fn:
909 case KEY_NAME_INDEX_FnLock:
910 // case KEY_NAME_INDEX_Hyper:
911 case KEY_NAME_INDEX_Meta:
912 case KEY_NAME_INDEX_NumLock:
913 case KEY_NAME_INDEX_OS:
914 case KEY_NAME_INDEX_ScrollLock:
915 case KEY_NAME_INDEX_Shift:
916 // case KEY_NAME_INDEX_Super:
917 case KEY_NAME_INDEX_Symbol:
918 case KEY_NAME_INDEX_SymbolLock:
919 case KEY_NAME_INDEX_Dead:
920 return false;
921 default:
922 return true;
926 static bool HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates) {
927 for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
928 uint32_t ch = aCandidates[i].mCharCode;
929 if (ch >= '0' && ch <= '9') return true;
931 return false;
934 static bool CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2) {
935 return aChar1 == aChar2 || (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
936 ToLowerCase(static_cast<char16_t>(aChar1)) ==
937 ToLowerCase(static_cast<char16_t>(aChar2)));
940 static bool IsCaseChangeableChar(uint32_t aChar) {
941 return IS_IN_BMP(aChar) && ToLowerCase(static_cast<char16_t>(aChar)) !=
942 ToUpperCase(static_cast<char16_t>(aChar));
945 void WidgetKeyboardEvent::GetShortcutKeyCandidates(
946 ShortcutKeyCandidateArray& aCandidates) const {
947 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
949 // ShortcutKeyCandidate::mCharCode is a candidate charCode.
950 // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
951 // execute a command with/without shift key state. If this is TRUE, the
952 // shifted key state should be ignored. Otherwise, don't ignore the state.
953 // the priority of the charCodes are (shift key is not pressed):
954 // 0: PseudoCharCode()/false,
955 // 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
956 // the priority of the charCodes are (shift key is pressed):
957 // 0: PseudoCharCode()/false,
958 // 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
959 // 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
960 uint32_t pseudoCharCode = PseudoCharCode();
961 if (pseudoCharCode) {
962 ShortcutKeyCandidate key(pseudoCharCode, false);
963 aCandidates.AppendElement(key);
966 uint32_t len = mAlternativeCharCodes.Length();
967 if (!IsShift()) {
968 for (uint32_t i = 0; i < len; ++i) {
969 uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
970 if (!ch || ch == pseudoCharCode) {
971 continue;
973 ShortcutKeyCandidate key(ch, false);
974 aCandidates.AppendElement(key);
976 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
977 // this keyboard layout is AZERTY or similar layout, probably.
978 // In this case, Accel+[0-9] should be accessible without shift key.
979 // However, the priority should be lowest.
980 if (!HasASCIIDigit(aCandidates)) {
981 for (uint32_t i = 0; i < len; ++i) {
982 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
983 if (ch >= '0' && ch <= '9') {
984 ShortcutKeyCandidate key(ch, false);
985 aCandidates.AppendElement(key);
986 break;
990 } else {
991 for (uint32_t i = 0; i < len; ++i) {
992 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
993 if (!ch) {
994 continue;
997 if (ch != pseudoCharCode) {
998 ShortcutKeyCandidate key(ch, false);
999 aCandidates.AppendElement(key);
1002 // If the char is an alphabet, the shift key state should not be
1003 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
1005 // And checking the charCode is same as unshiftedCharCode too.
1006 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
1007 uint32_t unshiftCh = mAlternativeCharCodes[i].mUnshiftedCharCode;
1008 if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
1009 continue;
1012 // On the Hebrew keyboard layout on Windows, the unshifted char is a
1013 // localized character but the shifted char is a Latin alphabet,
1014 // then, we should not execute without the shift state. See bug 433192.
1015 if (IsCaseChangeableChar(ch)) {
1016 continue;
1019 // Setting the alternative charCode candidates for retry without shift
1020 // key state only when the shift key is pressed.
1021 ShortcutKeyCandidate key(ch, true);
1022 aCandidates.AppendElement(key);
1026 // Special case for "Space" key. With some keyboard layouts, "Space" with
1027 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1028 // we should guarantee that the key press works as an ASCII white space key
1029 // press. However, if the space key is assigned to a function key, it
1030 // shouldn't work as a space key.
1031 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1032 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1033 ShortcutKeyCandidate spaceKey(' ', false);
1034 aCandidates.AppendElement(spaceKey);
1038 void WidgetKeyboardEvent::GetAccessKeyCandidates(
1039 nsTArray<uint32_t>& aCandidates) const {
1040 MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
1042 // return the lower cased charCode candidates for access keys.
1043 // the priority of the charCodes are:
1044 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
1045 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
1046 uint32_t pseudoCharCode = PseudoCharCode();
1047 if (pseudoCharCode) {
1048 uint32_t ch = pseudoCharCode;
1049 if (IS_IN_BMP(ch)) {
1050 ch = ToLowerCase(static_cast<char16_t>(ch));
1052 aCandidates.AppendElement(ch);
1054 for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
1055 uint32_t ch[2] = {mAlternativeCharCodes[i].mUnshiftedCharCode,
1056 mAlternativeCharCodes[i].mShiftedCharCode};
1057 for (uint32_t j = 0; j < 2; ++j) {
1058 if (!ch[j]) {
1059 continue;
1061 if (IS_IN_BMP(ch[j])) {
1062 ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
1064 // Don't append the charcode that was already appended.
1065 if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
1066 aCandidates.AppendElement(ch[j]);
1070 // Special case for "Space" key. With some keyboard layouts, "Space" with
1071 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1072 // we should guarantee that the key press works as an ASCII white space key
1073 // press. However, if the space key is assigned to a function key, it
1074 // shouldn't work as a space key.
1075 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
1076 mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
1077 aCandidates.AppendElement(' ');
1081 // mask values for ui.key.chromeAccess and ui.key.contentAccess
1082 #define NS_MODIFIER_SHIFT 1
1083 #define NS_MODIFIER_CONTROL 2
1084 #define NS_MODIFIER_ALT 4
1085 #define NS_MODIFIER_META 8
1086 #define NS_MODIFIER_OS 16
1088 static Modifiers PrefFlagsToModifiers(int32_t aPrefFlags) {
1089 Modifiers result = 0;
1090 if (aPrefFlags & NS_MODIFIER_SHIFT) {
1091 result |= MODIFIER_SHIFT;
1093 if (aPrefFlags & NS_MODIFIER_CONTROL) {
1094 result |= MODIFIER_CONTROL;
1096 if (aPrefFlags & NS_MODIFIER_ALT) {
1097 result |= MODIFIER_ALT;
1099 if (aPrefFlags & NS_MODIFIER_META) {
1100 result |= MODIFIER_META;
1102 if (aPrefFlags & NS_MODIFIER_OS) {
1103 result |= MODIFIER_OS;
1105 return result;
1108 bool WidgetKeyboardEvent::ModifiersMatchWithAccessKey(
1109 AccessKeyType aType) const {
1110 if (!ModifiersForAccessKeyMatching()) {
1111 return false;
1113 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
1116 Modifiers WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const {
1117 static const Modifiers kModifierMask = MODIFIER_SHIFT | MODIFIER_CONTROL |
1118 MODIFIER_ALT | MODIFIER_META |
1119 MODIFIER_OS;
1120 return mModifiers & kModifierMask;
1123 /* static */
1124 Modifiers WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType) {
1125 switch (StaticPrefs::ui_key_generalAccessKey()) {
1126 case -1:
1127 break; // use the individual prefs
1128 case NS_VK_SHIFT:
1129 return MODIFIER_SHIFT;
1130 case NS_VK_CONTROL:
1131 return MODIFIER_CONTROL;
1132 case NS_VK_ALT:
1133 return MODIFIER_ALT;
1134 case NS_VK_META:
1135 return MODIFIER_META;
1136 case NS_VK_WIN:
1137 return MODIFIER_OS;
1138 default:
1139 return MODIFIER_NONE;
1142 switch (aType) {
1143 case AccessKeyType::eChrome:
1144 return PrefFlagsToModifiers(StaticPrefs::ui_key_chromeAccess());
1145 case AccessKeyType::eContent:
1146 return PrefFlagsToModifiers(StaticPrefs::ui_key_contentAccess());
1147 default:
1148 return MODIFIER_NONE;
1152 /* static */
1153 void WidgetKeyboardEvent::Shutdown() {
1154 delete sKeyNameIndexHashtable;
1155 sKeyNameIndexHashtable = nullptr;
1156 delete sCodeNameIndexHashtable;
1157 sCodeNameIndexHashtable = nullptr;
1158 // Although sCommandHashtable is not a member of WidgetKeyboardEvent, but
1159 // let's delete it here since we need to do it at same time.
1160 delete sCommandHashtable;
1161 sCommandHashtable = nullptr;
1164 /* static */
1165 void WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
1166 nsAString& aKeyName) {
1167 if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
1168 aKeyName.Truncate();
1169 return;
1172 MOZ_RELEASE_ASSERT(
1173 static_cast<size_t>(aKeyNameIndex) < ArrayLength(kKeyNames),
1174 "Illegal key enumeration value");
1175 aKeyName = kKeyNames[aKeyNameIndex];
1178 /* static */
1179 void WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
1180 nsAString& aCodeName) {
1181 if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
1182 aCodeName.Truncate();
1183 return;
1186 MOZ_RELEASE_ASSERT(
1187 static_cast<size_t>(aCodeNameIndex) < ArrayLength(kCodeNames),
1188 "Illegal physical code enumeration value");
1189 aCodeName = kCodeNames[aCodeNameIndex];
1192 /* static */
1193 KeyNameIndex WidgetKeyboardEvent::GetKeyNameIndex(const nsAString& aKeyValue) {
1194 if (!sKeyNameIndexHashtable) {
1195 sKeyNameIndexHashtable = new KeyNameIndexHashtable(ArrayLength(kKeyNames));
1196 for (size_t i = 0; i < ArrayLength(kKeyNames); i++) {
1197 sKeyNameIndexHashtable->InsertOrUpdate(nsDependentString(kKeyNames[i]),
1198 static_cast<KeyNameIndex>(i));
1201 return sKeyNameIndexHashtable->MaybeGet(aKeyValue).valueOr(
1202 KEY_NAME_INDEX_USE_STRING);
1205 /* static */
1206 CodeNameIndex WidgetKeyboardEvent::GetCodeNameIndex(
1207 const nsAString& aCodeValue) {
1208 if (!sCodeNameIndexHashtable) {
1209 sCodeNameIndexHashtable =
1210 new CodeNameIndexHashtable(ArrayLength(kCodeNames));
1211 for (size_t i = 0; i < ArrayLength(kCodeNames); i++) {
1212 sCodeNameIndexHashtable->InsertOrUpdate(nsDependentString(kCodeNames[i]),
1213 static_cast<CodeNameIndex>(i));
1216 return sCodeNameIndexHashtable->MaybeGet(aCodeValue)
1217 .valueOr(CODE_NAME_INDEX_USE_STRING);
1220 /* static */
1221 uint32_t WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(
1222 CodeNameIndex aCodeNameIndex) {
1223 switch (aCodeNameIndex) {
1224 case CODE_NAME_INDEX_Semicolon: // VK_OEM_1 on Windows
1225 return dom::KeyboardEvent_Binding::DOM_VK_SEMICOLON;
1226 case CODE_NAME_INDEX_Equal: // VK_OEM_PLUS on Windows
1227 return dom::KeyboardEvent_Binding::DOM_VK_EQUALS;
1228 case CODE_NAME_INDEX_Comma: // VK_OEM_COMMA on Windows
1229 return dom::KeyboardEvent_Binding::DOM_VK_COMMA;
1230 case CODE_NAME_INDEX_Minus: // VK_OEM_MINUS on Windows
1231 return dom::KeyboardEvent_Binding::DOM_VK_HYPHEN_MINUS;
1232 case CODE_NAME_INDEX_Period: // VK_OEM_PERIOD on Windows
1233 return dom::KeyboardEvent_Binding::DOM_VK_PERIOD;
1234 case CODE_NAME_INDEX_Slash: // VK_OEM_2 on Windows
1235 return dom::KeyboardEvent_Binding::DOM_VK_SLASH;
1236 case CODE_NAME_INDEX_Backquote: // VK_OEM_3 on Windows
1237 return dom::KeyboardEvent_Binding::DOM_VK_BACK_QUOTE;
1238 case CODE_NAME_INDEX_BracketLeft: // VK_OEM_4 on Windows
1239 return dom::KeyboardEvent_Binding::DOM_VK_OPEN_BRACKET;
1240 case CODE_NAME_INDEX_Backslash: // VK_OEM_5 on Windows
1241 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1242 case CODE_NAME_INDEX_BracketRight: // VK_OEM_6 on Windows
1243 return dom::KeyboardEvent_Binding::DOM_VK_CLOSE_BRACKET;
1244 case CODE_NAME_INDEX_Quote: // VK_OEM_7 on Windows
1245 return dom::KeyboardEvent_Binding::DOM_VK_QUOTE;
1246 case CODE_NAME_INDEX_IntlBackslash: // VK_OEM_5 on Windows (ABNT, etc)
1247 case CODE_NAME_INDEX_IntlYen: // VK_OEM_5 on Windows (JIS)
1248 case CODE_NAME_INDEX_IntlRo: // VK_OEM_102 on Windows
1249 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1250 default:
1251 return 0;
1255 /* static */ const char* WidgetKeyboardEvent::GetCommandStr(Command aCommand) {
1256 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1257 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) , #aCommandStr
1258 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) , ""
1259 static const char* const kCommands[] = {
1260 "" // DoNothing
1261 #include "mozilla/CommandList.h"
1263 #undef NS_DEFINE_COMMAND
1264 #undef NS_DEFINE_COMMAND_WITH_PARAM
1265 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
1267 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand) < ArrayLength(kCommands),
1268 "Illegal command enumeration value");
1269 return kCommands[static_cast<CommandInt>(aCommand)];
1272 /* static */
1273 uint32_t WidgetKeyboardEvent::ComputeLocationFromCodeValue(
1274 CodeNameIndex aCodeNameIndex) {
1275 // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1276 // but are defined by D3E spec. So, they should be uncommented when the
1277 // code values are defined in the header.
1278 switch (aCodeNameIndex) {
1279 case CODE_NAME_INDEX_AltLeft:
1280 case CODE_NAME_INDEX_ControlLeft:
1281 case CODE_NAME_INDEX_OSLeft:
1282 case CODE_NAME_INDEX_ShiftLeft:
1283 return eKeyLocationLeft;
1284 case CODE_NAME_INDEX_AltRight:
1285 case CODE_NAME_INDEX_ControlRight:
1286 case CODE_NAME_INDEX_OSRight:
1287 case CODE_NAME_INDEX_ShiftRight:
1288 return eKeyLocationRight;
1289 case CODE_NAME_INDEX_Numpad0:
1290 case CODE_NAME_INDEX_Numpad1:
1291 case CODE_NAME_INDEX_Numpad2:
1292 case CODE_NAME_INDEX_Numpad3:
1293 case CODE_NAME_INDEX_Numpad4:
1294 case CODE_NAME_INDEX_Numpad5:
1295 case CODE_NAME_INDEX_Numpad6:
1296 case CODE_NAME_INDEX_Numpad7:
1297 case CODE_NAME_INDEX_Numpad8:
1298 case CODE_NAME_INDEX_Numpad9:
1299 case CODE_NAME_INDEX_NumpadAdd:
1300 case CODE_NAME_INDEX_NumpadBackspace:
1301 case CODE_NAME_INDEX_NumpadClear:
1302 case CODE_NAME_INDEX_NumpadClearEntry:
1303 case CODE_NAME_INDEX_NumpadComma:
1304 case CODE_NAME_INDEX_NumpadDecimal:
1305 case CODE_NAME_INDEX_NumpadDivide:
1306 case CODE_NAME_INDEX_NumpadEnter:
1307 case CODE_NAME_INDEX_NumpadEqual:
1308 case CODE_NAME_INDEX_NumpadMemoryAdd:
1309 case CODE_NAME_INDEX_NumpadMemoryClear:
1310 case CODE_NAME_INDEX_NumpadMemoryRecall:
1311 case CODE_NAME_INDEX_NumpadMemoryStore:
1312 case CODE_NAME_INDEX_NumpadMemorySubtract:
1313 case CODE_NAME_INDEX_NumpadMultiply:
1314 case CODE_NAME_INDEX_NumpadParenLeft:
1315 case CODE_NAME_INDEX_NumpadParenRight:
1316 case CODE_NAME_INDEX_NumpadSubtract:
1317 return eKeyLocationNumpad;
1318 default:
1319 return eKeyLocationStandard;
1323 /* static */
1324 uint32_t WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(
1325 KeyNameIndex aKeyNameIndex) {
1326 switch (aKeyNameIndex) {
1327 case KEY_NAME_INDEX_Cancel:
1328 return dom::KeyboardEvent_Binding::DOM_VK_CANCEL;
1329 case KEY_NAME_INDEX_Help:
1330 return dom::KeyboardEvent_Binding::DOM_VK_HELP;
1331 case KEY_NAME_INDEX_Backspace:
1332 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SPACE;
1333 case KEY_NAME_INDEX_Tab:
1334 return dom::KeyboardEvent_Binding::DOM_VK_TAB;
1335 case KEY_NAME_INDEX_Clear:
1336 return dom::KeyboardEvent_Binding::DOM_VK_CLEAR;
1337 case KEY_NAME_INDEX_Enter:
1338 return dom::KeyboardEvent_Binding::DOM_VK_RETURN;
1339 case KEY_NAME_INDEX_Shift:
1340 return dom::KeyboardEvent_Binding::DOM_VK_SHIFT;
1341 case KEY_NAME_INDEX_Control:
1342 return dom::KeyboardEvent_Binding::DOM_VK_CONTROL;
1343 case KEY_NAME_INDEX_Alt:
1344 return dom::KeyboardEvent_Binding::DOM_VK_ALT;
1345 case KEY_NAME_INDEX_Pause:
1346 return dom::KeyboardEvent_Binding::DOM_VK_PAUSE;
1347 case KEY_NAME_INDEX_CapsLock:
1348 return dom::KeyboardEvent_Binding::DOM_VK_CAPS_LOCK;
1349 case KEY_NAME_INDEX_Hiragana:
1350 case KEY_NAME_INDEX_Katakana:
1351 case KEY_NAME_INDEX_HiraganaKatakana:
1352 case KEY_NAME_INDEX_KanaMode:
1353 return dom::KeyboardEvent_Binding::DOM_VK_KANA;
1354 case KEY_NAME_INDEX_HangulMode:
1355 return dom::KeyboardEvent_Binding::DOM_VK_HANGUL;
1356 case KEY_NAME_INDEX_Eisu:
1357 return dom::KeyboardEvent_Binding::DOM_VK_EISU;
1358 case KEY_NAME_INDEX_JunjaMode:
1359 return dom::KeyboardEvent_Binding::DOM_VK_JUNJA;
1360 case KEY_NAME_INDEX_FinalMode:
1361 return dom::KeyboardEvent_Binding::DOM_VK_FINAL;
1362 case KEY_NAME_INDEX_HanjaMode:
1363 return dom::KeyboardEvent_Binding::DOM_VK_HANJA;
1364 case KEY_NAME_INDEX_KanjiMode:
1365 return dom::KeyboardEvent_Binding::DOM_VK_KANJI;
1366 case KEY_NAME_INDEX_Escape:
1367 return dom::KeyboardEvent_Binding::DOM_VK_ESCAPE;
1368 case KEY_NAME_INDEX_Convert:
1369 return dom::KeyboardEvent_Binding::DOM_VK_CONVERT;
1370 case KEY_NAME_INDEX_NonConvert:
1371 return dom::KeyboardEvent_Binding::DOM_VK_NONCONVERT;
1372 case KEY_NAME_INDEX_Accept:
1373 return dom::KeyboardEvent_Binding::DOM_VK_ACCEPT;
1374 case KEY_NAME_INDEX_ModeChange:
1375 return dom::KeyboardEvent_Binding::DOM_VK_MODECHANGE;
1376 case KEY_NAME_INDEX_PageUp:
1377 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_UP;
1378 case KEY_NAME_INDEX_PageDown:
1379 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_DOWN;
1380 case KEY_NAME_INDEX_End:
1381 return dom::KeyboardEvent_Binding::DOM_VK_END;
1382 case KEY_NAME_INDEX_Home:
1383 return dom::KeyboardEvent_Binding::DOM_VK_HOME;
1384 case KEY_NAME_INDEX_ArrowLeft:
1385 return dom::KeyboardEvent_Binding::DOM_VK_LEFT;
1386 case KEY_NAME_INDEX_ArrowUp:
1387 return dom::KeyboardEvent_Binding::DOM_VK_UP;
1388 case KEY_NAME_INDEX_ArrowRight:
1389 return dom::KeyboardEvent_Binding::DOM_VK_RIGHT;
1390 case KEY_NAME_INDEX_ArrowDown:
1391 return dom::KeyboardEvent_Binding::DOM_VK_DOWN;
1392 case KEY_NAME_INDEX_Select:
1393 return dom::KeyboardEvent_Binding::DOM_VK_SELECT;
1394 case KEY_NAME_INDEX_Print:
1395 return dom::KeyboardEvent_Binding::DOM_VK_PRINT;
1396 case KEY_NAME_INDEX_Execute:
1397 return dom::KeyboardEvent_Binding::DOM_VK_EXECUTE;
1398 case KEY_NAME_INDEX_PrintScreen:
1399 return dom::KeyboardEvent_Binding::DOM_VK_PRINTSCREEN;
1400 case KEY_NAME_INDEX_Insert:
1401 return dom::KeyboardEvent_Binding::DOM_VK_INSERT;
1402 case KEY_NAME_INDEX_Delete:
1403 return dom::KeyboardEvent_Binding::DOM_VK_DELETE;
1404 case KEY_NAME_INDEX_OS:
1405 // case KEY_NAME_INDEX_Super:
1406 // case KEY_NAME_INDEX_Hyper:
1407 return dom::KeyboardEvent_Binding::DOM_VK_WIN;
1408 case KEY_NAME_INDEX_ContextMenu:
1409 return dom::KeyboardEvent_Binding::DOM_VK_CONTEXT_MENU;
1410 case KEY_NAME_INDEX_Standby:
1411 return dom::KeyboardEvent_Binding::DOM_VK_SLEEP;
1412 case KEY_NAME_INDEX_F1:
1413 return dom::KeyboardEvent_Binding::DOM_VK_F1;
1414 case KEY_NAME_INDEX_F2:
1415 return dom::KeyboardEvent_Binding::DOM_VK_F2;
1416 case KEY_NAME_INDEX_F3:
1417 return dom::KeyboardEvent_Binding::DOM_VK_F3;
1418 case KEY_NAME_INDEX_F4:
1419 return dom::KeyboardEvent_Binding::DOM_VK_F4;
1420 case KEY_NAME_INDEX_F5:
1421 return dom::KeyboardEvent_Binding::DOM_VK_F5;
1422 case KEY_NAME_INDEX_F6:
1423 return dom::KeyboardEvent_Binding::DOM_VK_F6;
1424 case KEY_NAME_INDEX_F7:
1425 return dom::KeyboardEvent_Binding::DOM_VK_F7;
1426 case KEY_NAME_INDEX_F8:
1427 return dom::KeyboardEvent_Binding::DOM_VK_F8;
1428 case KEY_NAME_INDEX_F9:
1429 return dom::KeyboardEvent_Binding::DOM_VK_F9;
1430 case KEY_NAME_INDEX_F10:
1431 return dom::KeyboardEvent_Binding::DOM_VK_F10;
1432 case KEY_NAME_INDEX_F11:
1433 return dom::KeyboardEvent_Binding::DOM_VK_F11;
1434 case KEY_NAME_INDEX_F12:
1435 return dom::KeyboardEvent_Binding::DOM_VK_F12;
1436 case KEY_NAME_INDEX_F13:
1437 return dom::KeyboardEvent_Binding::DOM_VK_F13;
1438 case KEY_NAME_INDEX_F14:
1439 return dom::KeyboardEvent_Binding::DOM_VK_F14;
1440 case KEY_NAME_INDEX_F15:
1441 return dom::KeyboardEvent_Binding::DOM_VK_F15;
1442 case KEY_NAME_INDEX_F16:
1443 return dom::KeyboardEvent_Binding::DOM_VK_F16;
1444 case KEY_NAME_INDEX_F17:
1445 return dom::KeyboardEvent_Binding::DOM_VK_F17;
1446 case KEY_NAME_INDEX_F18:
1447 return dom::KeyboardEvent_Binding::DOM_VK_F18;
1448 case KEY_NAME_INDEX_F19:
1449 return dom::KeyboardEvent_Binding::DOM_VK_F19;
1450 case KEY_NAME_INDEX_F20:
1451 return dom::KeyboardEvent_Binding::DOM_VK_F20;
1452 case KEY_NAME_INDEX_F21:
1453 return dom::KeyboardEvent_Binding::DOM_VK_F21;
1454 case KEY_NAME_INDEX_F22:
1455 return dom::KeyboardEvent_Binding::DOM_VK_F22;
1456 case KEY_NAME_INDEX_F23:
1457 return dom::KeyboardEvent_Binding::DOM_VK_F23;
1458 case KEY_NAME_INDEX_F24:
1459 return dom::KeyboardEvent_Binding::DOM_VK_F24;
1460 case KEY_NAME_INDEX_NumLock:
1461 return dom::KeyboardEvent_Binding::DOM_VK_NUM_LOCK;
1462 case KEY_NAME_INDEX_ScrollLock:
1463 return dom::KeyboardEvent_Binding::DOM_VK_SCROLL_LOCK;
1464 case KEY_NAME_INDEX_AudioVolumeMute:
1465 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_MUTE;
1466 case KEY_NAME_INDEX_AudioVolumeDown:
1467 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_DOWN;
1468 case KEY_NAME_INDEX_AudioVolumeUp:
1469 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_UP;
1470 case KEY_NAME_INDEX_Meta:
1471 return dom::KeyboardEvent_Binding::DOM_VK_META;
1472 case KEY_NAME_INDEX_AltGraph:
1473 return dom::KeyboardEvent_Binding::DOM_VK_ALTGR;
1474 case KEY_NAME_INDEX_Process:
1475 return dom::KeyboardEvent_Binding::DOM_VK_PROCESSKEY;
1476 case KEY_NAME_INDEX_Attn:
1477 return dom::KeyboardEvent_Binding::DOM_VK_ATTN;
1478 case KEY_NAME_INDEX_CrSel:
1479 return dom::KeyboardEvent_Binding::DOM_VK_CRSEL;
1480 case KEY_NAME_INDEX_ExSel:
1481 return dom::KeyboardEvent_Binding::DOM_VK_EXSEL;
1482 case KEY_NAME_INDEX_EraseEof:
1483 return dom::KeyboardEvent_Binding::DOM_VK_EREOF;
1484 case KEY_NAME_INDEX_Play:
1485 return dom::KeyboardEvent_Binding::DOM_VK_PLAY;
1486 case KEY_NAME_INDEX_ZoomToggle:
1487 case KEY_NAME_INDEX_ZoomIn:
1488 case KEY_NAME_INDEX_ZoomOut:
1489 return dom::KeyboardEvent_Binding::DOM_VK_ZOOM;
1490 default:
1491 return 0;
1495 /* static */
1496 CodeNameIndex WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex(
1497 KeyNameIndex aKeyNameIndex, const Maybe<uint32_t>& aLocation) {
1498 if (aLocation.isSome() &&
1499 aLocation.value() ==
1500 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_NUMPAD) {
1501 // On macOS, NumLock is not supported. Therefore, this handles
1502 // control key values except "Enter" only on non-macOS platforms.
1503 switch (aKeyNameIndex) {
1504 #ifndef XP_MACOSX
1505 case KEY_NAME_INDEX_Insert:
1506 return CODE_NAME_INDEX_Numpad0;
1507 case KEY_NAME_INDEX_End:
1508 return CODE_NAME_INDEX_Numpad1;
1509 case KEY_NAME_INDEX_ArrowDown:
1510 return CODE_NAME_INDEX_Numpad2;
1511 case KEY_NAME_INDEX_PageDown:
1512 return CODE_NAME_INDEX_Numpad3;
1513 case KEY_NAME_INDEX_ArrowLeft:
1514 return CODE_NAME_INDEX_Numpad4;
1515 case KEY_NAME_INDEX_Clear:
1516 // FYI: "Clear" on macOS should be DOM_KEY_LOCATION_STANDARD.
1517 return CODE_NAME_INDEX_Numpad5;
1518 case KEY_NAME_INDEX_ArrowRight:
1519 return CODE_NAME_INDEX_Numpad6;
1520 case KEY_NAME_INDEX_Home:
1521 return CODE_NAME_INDEX_Numpad7;
1522 case KEY_NAME_INDEX_ArrowUp:
1523 return CODE_NAME_INDEX_Numpad8;
1524 case KEY_NAME_INDEX_PageUp:
1525 return CODE_NAME_INDEX_Numpad9;
1526 case KEY_NAME_INDEX_Delete:
1527 return CODE_NAME_INDEX_NumpadDecimal;
1528 #endif // #ifndef XP_MACOSX
1529 case KEY_NAME_INDEX_Enter:
1530 return CODE_NAME_INDEX_NumpadEnter;
1531 default:
1532 return CODE_NAME_INDEX_UNKNOWN;
1536 if (WidgetKeyboardEvent::IsLeftOrRightModiferKeyNameIndex(aKeyNameIndex)) {
1537 if (aLocation.isSome() &&
1538 (aLocation.value() !=
1539 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_LEFT &&
1540 aLocation.value() !=
1541 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT)) {
1542 return CODE_NAME_INDEX_UNKNOWN;
1544 bool isRight =
1545 aLocation.isSome() &&
1546 aLocation.value() == dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT;
1547 switch (aKeyNameIndex) {
1548 case KEY_NAME_INDEX_Alt:
1549 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1550 case KEY_NAME_INDEX_Control:
1551 return isRight ? CODE_NAME_INDEX_ControlRight
1552 : CODE_NAME_INDEX_ControlLeft;
1553 case KEY_NAME_INDEX_Shift:
1554 return isRight ? CODE_NAME_INDEX_ShiftRight : CODE_NAME_INDEX_ShiftLeft;
1555 #if defined(XP_WIN)
1556 case KEY_NAME_INDEX_Meta:
1557 return CODE_NAME_INDEX_UNKNOWN;
1558 case KEY_NAME_INDEX_OS: // win key.
1559 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1560 #elif defined(XP_MACOSX) || defined(ANDROID)
1561 case KEY_NAME_INDEX_Meta: // command key.
1562 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1563 case KEY_NAME_INDEX_OS:
1564 return CODE_NAME_INDEX_UNKNOWN;
1565 #else
1566 case KEY_NAME_INDEX_Meta: // Alt + Shift.
1567 return isRight ? CODE_NAME_INDEX_AltRight : CODE_NAME_INDEX_AltLeft;
1568 case KEY_NAME_INDEX_OS: // Super/Hyper key.
1569 return isRight ? CODE_NAME_INDEX_OSRight : CODE_NAME_INDEX_OSLeft;
1570 #endif
1571 default:
1572 return CODE_NAME_INDEX_UNKNOWN;
1576 if (aLocation.isSome() &&
1577 aLocation.value() !=
1578 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_STANDARD) {
1579 return CODE_NAME_INDEX_UNKNOWN;
1582 switch (aKeyNameIndex) {
1583 // Standard section:
1584 case KEY_NAME_INDEX_Escape:
1585 return CODE_NAME_INDEX_Escape;
1586 case KEY_NAME_INDEX_Tab:
1587 return CODE_NAME_INDEX_Tab;
1588 case KEY_NAME_INDEX_CapsLock:
1589 return CODE_NAME_INDEX_CapsLock;
1590 case KEY_NAME_INDEX_ContextMenu:
1591 return CODE_NAME_INDEX_ContextMenu;
1592 case KEY_NAME_INDEX_Backspace:
1593 return CODE_NAME_INDEX_Backspace;
1594 case KEY_NAME_INDEX_Enter:
1595 return CODE_NAME_INDEX_Enter;
1596 #ifdef XP_MACOSX
1597 // Although, macOS does not fire native key event of "Fn" key, we support
1598 // Fn key event if it's sent by other apps directly.
1599 case KEY_NAME_INDEX_Fn:
1600 return CODE_NAME_INDEX_Fn;
1601 #endif // #ifdef
1603 // Arrow Pad section:
1604 case KEY_NAME_INDEX_ArrowLeft:
1605 return CODE_NAME_INDEX_ArrowLeft;
1606 case KEY_NAME_INDEX_ArrowUp:
1607 return CODE_NAME_INDEX_ArrowUp;
1608 case KEY_NAME_INDEX_ArrowDown:
1609 return CODE_NAME_INDEX_ArrowDown;
1610 case KEY_NAME_INDEX_ArrowRight:
1611 return CODE_NAME_INDEX_ArrowRight;
1613 // Control Pad section:
1614 #ifndef XP_MACOSX
1615 case KEY_NAME_INDEX_Insert:
1616 return CODE_NAME_INDEX_Insert;
1617 #else
1618 case KEY_NAME_INDEX_Help:
1619 return CODE_NAME_INDEX_Help;
1620 #endif // #ifndef XP_MACOSX #else
1621 case KEY_NAME_INDEX_Delete:
1622 return CODE_NAME_INDEX_Delete;
1623 case KEY_NAME_INDEX_Home:
1624 return CODE_NAME_INDEX_Home;
1625 case KEY_NAME_INDEX_End:
1626 return CODE_NAME_INDEX_End;
1627 case KEY_NAME_INDEX_PageUp:
1628 return CODE_NAME_INDEX_PageUp;
1629 case KEY_NAME_INDEX_PageDown:
1630 return CODE_NAME_INDEX_PageDown;
1632 // Function keys:
1633 case KEY_NAME_INDEX_F1:
1634 return CODE_NAME_INDEX_F1;
1635 case KEY_NAME_INDEX_F2:
1636 return CODE_NAME_INDEX_F2;
1637 case KEY_NAME_INDEX_F3:
1638 return CODE_NAME_INDEX_F3;
1639 case KEY_NAME_INDEX_F4:
1640 return CODE_NAME_INDEX_F4;
1641 case KEY_NAME_INDEX_F5:
1642 return CODE_NAME_INDEX_F5;
1643 case KEY_NAME_INDEX_F6:
1644 return CODE_NAME_INDEX_F6;
1645 case KEY_NAME_INDEX_F7:
1646 return CODE_NAME_INDEX_F7;
1647 case KEY_NAME_INDEX_F8:
1648 return CODE_NAME_INDEX_F8;
1649 case KEY_NAME_INDEX_F9:
1650 return CODE_NAME_INDEX_F9;
1651 case KEY_NAME_INDEX_F10:
1652 return CODE_NAME_INDEX_F10;
1653 case KEY_NAME_INDEX_F11:
1654 return CODE_NAME_INDEX_F11;
1655 case KEY_NAME_INDEX_F12:
1656 return CODE_NAME_INDEX_F12;
1657 case KEY_NAME_INDEX_F13:
1658 return CODE_NAME_INDEX_F13;
1659 case KEY_NAME_INDEX_F14:
1660 return CODE_NAME_INDEX_F14;
1661 case KEY_NAME_INDEX_F15:
1662 return CODE_NAME_INDEX_F15;
1663 case KEY_NAME_INDEX_F16:
1664 return CODE_NAME_INDEX_F16;
1665 case KEY_NAME_INDEX_F17:
1666 return CODE_NAME_INDEX_F17;
1667 case KEY_NAME_INDEX_F18:
1668 return CODE_NAME_INDEX_F18;
1669 case KEY_NAME_INDEX_F19:
1670 return CODE_NAME_INDEX_F19;
1671 case KEY_NAME_INDEX_F20:
1672 return CODE_NAME_INDEX_F20;
1673 #ifndef XP_MACOSX
1674 case KEY_NAME_INDEX_F21:
1675 return CODE_NAME_INDEX_F21;
1676 case KEY_NAME_INDEX_F22:
1677 return CODE_NAME_INDEX_F22;
1678 case KEY_NAME_INDEX_F23:
1679 return CODE_NAME_INDEX_F23;
1680 case KEY_NAME_INDEX_F24:
1681 return CODE_NAME_INDEX_F24;
1682 case KEY_NAME_INDEX_Pause:
1683 return CODE_NAME_INDEX_Pause;
1684 case KEY_NAME_INDEX_PrintScreen:
1685 return CODE_NAME_INDEX_PrintScreen;
1686 case KEY_NAME_INDEX_ScrollLock:
1687 return CODE_NAME_INDEX_ScrollLock;
1688 #endif // #ifndef XP_MACOSX
1690 // NumLock key:
1691 #ifndef XP_MACOSX
1692 case KEY_NAME_INDEX_NumLock:
1693 return CODE_NAME_INDEX_NumLock;
1694 #else
1695 case KEY_NAME_INDEX_Clear:
1696 return CODE_NAME_INDEX_NumLock;
1697 #endif // #ifndef XP_MACOSX #else
1699 // Media keys:
1700 case KEY_NAME_INDEX_AudioVolumeDown:
1701 return CODE_NAME_INDEX_VolumeDown;
1702 case KEY_NAME_INDEX_AudioVolumeMute:
1703 return CODE_NAME_INDEX_VolumeMute;
1704 case KEY_NAME_INDEX_AudioVolumeUp:
1705 return CODE_NAME_INDEX_VolumeUp;
1706 #ifndef XP_MACOSX
1707 case KEY_NAME_INDEX_BrowserBack:
1708 return CODE_NAME_INDEX_BrowserBack;
1709 case KEY_NAME_INDEX_BrowserFavorites:
1710 return CODE_NAME_INDEX_BrowserFavorites;
1711 case KEY_NAME_INDEX_BrowserForward:
1712 return CODE_NAME_INDEX_BrowserForward;
1713 case KEY_NAME_INDEX_BrowserRefresh:
1714 return CODE_NAME_INDEX_BrowserRefresh;
1715 case KEY_NAME_INDEX_BrowserSearch:
1716 return CODE_NAME_INDEX_BrowserSearch;
1717 case KEY_NAME_INDEX_BrowserStop:
1718 return CODE_NAME_INDEX_BrowserStop;
1719 case KEY_NAME_INDEX_MediaPlayPause:
1720 return CODE_NAME_INDEX_MediaPlayPause;
1721 case KEY_NAME_INDEX_MediaStop:
1722 return CODE_NAME_INDEX_MediaStop;
1723 case KEY_NAME_INDEX_MediaTrackNext:
1724 return CODE_NAME_INDEX_MediaTrackNext;
1725 case KEY_NAME_INDEX_MediaTrackPrevious:
1726 return CODE_NAME_INDEX_MediaTrackPrevious;
1727 case KEY_NAME_INDEX_LaunchApplication1:
1728 return CODE_NAME_INDEX_LaunchApp1;
1729 #endif // #ifndef XP_MACOSX
1731 // Only Windows and GTK supports the following multimedia keys.
1732 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1733 case KEY_NAME_INDEX_BrowserHome:
1734 return CODE_NAME_INDEX_BrowserHome;
1735 case KEY_NAME_INDEX_LaunchApplication2:
1736 return CODE_NAME_INDEX_LaunchApp2;
1737 #endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1739 // Only GTK and Android supports the following multimedia keys.
1740 #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1741 case KEY_NAME_INDEX_Eject:
1742 return CODE_NAME_INDEX_Eject;
1743 case KEY_NAME_INDEX_WakeUp:
1744 return CODE_NAME_INDEX_WakeUp;
1745 #endif // #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
1747 // Only Windows does not support Help key (and macOS handled above).
1748 #if !defined(XP_WIN) && !defined(XP_MACOSX)
1749 case KEY_NAME_INDEX_Help:
1750 return CODE_NAME_INDEX_Help;
1751 #endif // #if !defined(XP_WIN) && !defined(XP_MACOSX)
1753 // IME specific keys:
1754 #ifdef XP_WIN
1755 case KEY_NAME_INDEX_Convert:
1756 return CODE_NAME_INDEX_Convert;
1757 case KEY_NAME_INDEX_NonConvert:
1758 return CODE_NAME_INDEX_NonConvert;
1759 case KEY_NAME_INDEX_Alphanumeric:
1760 return CODE_NAME_INDEX_CapsLock;
1761 case KEY_NAME_INDEX_KanaMode:
1762 case KEY_NAME_INDEX_Romaji:
1763 case KEY_NAME_INDEX_Katakana:
1764 case KEY_NAME_INDEX_Hiragana:
1765 return CODE_NAME_INDEX_KanaMode;
1766 case KEY_NAME_INDEX_Hankaku:
1767 case KEY_NAME_INDEX_Zenkaku:
1768 case KEY_NAME_INDEX_KanjiMode:
1769 return CODE_NAME_INDEX_Backquote;
1770 case KEY_NAME_INDEX_HanjaMode:
1771 return CODE_NAME_INDEX_Lang2;
1772 case KEY_NAME_INDEX_HangulMode:
1773 return CODE_NAME_INDEX_Lang1;
1774 #endif // #ifdef XP_WIN
1776 #ifdef MOZ_WIDGET_GTK
1777 case KEY_NAME_INDEX_Convert:
1778 return CODE_NAME_INDEX_Convert;
1779 case KEY_NAME_INDEX_NonConvert:
1780 return CODE_NAME_INDEX_NonConvert;
1781 case KEY_NAME_INDEX_Alphanumeric:
1782 return CODE_NAME_INDEX_CapsLock;
1783 case KEY_NAME_INDEX_HiraganaKatakana:
1784 return CODE_NAME_INDEX_KanaMode;
1785 case KEY_NAME_INDEX_ZenkakuHankaku:
1786 return CODE_NAME_INDEX_Backquote;
1787 #endif // #ifdef MOZ_WIDGET_GTK
1789 #ifdef ANDROID
1790 case KEY_NAME_INDEX_Convert:
1791 return CODE_NAME_INDEX_Convert;
1792 case KEY_NAME_INDEX_NonConvert:
1793 return CODE_NAME_INDEX_NonConvert;
1794 case KEY_NAME_INDEX_HiraganaKatakana:
1795 return CODE_NAME_INDEX_KanaMode;
1796 case KEY_NAME_INDEX_ZenkakuHankaku:
1797 return CODE_NAME_INDEX_Backquote;
1798 case KEY_NAME_INDEX_Eisu:
1799 return CODE_NAME_INDEX_Lang2;
1800 case KEY_NAME_INDEX_KanjiMode:
1801 return CODE_NAME_INDEX_Lang1;
1802 #endif // #ifdef ANDROID
1804 #ifdef XP_MACOSX
1805 case KEY_NAME_INDEX_Eisu:
1806 return CODE_NAME_INDEX_Lang2;
1807 case KEY_NAME_INDEX_KanjiMode:
1808 return CODE_NAME_INDEX_Lang1;
1809 #endif // #ifdef XP_MACOSX
1811 default:
1812 return CODE_NAME_INDEX_UNKNOWN;
1816 /* static */
1817 Modifier WidgetKeyboardEvent::GetModifierForKeyName(
1818 KeyNameIndex aKeyNameIndex) {
1819 switch (aKeyNameIndex) {
1820 case KEY_NAME_INDEX_Alt:
1821 return MODIFIER_ALT;
1822 case KEY_NAME_INDEX_AltGraph:
1823 return MODIFIER_ALTGRAPH;
1824 case KEY_NAME_INDEX_CapsLock:
1825 return MODIFIER_CAPSLOCK;
1826 case KEY_NAME_INDEX_Control:
1827 return MODIFIER_CONTROL;
1828 case KEY_NAME_INDEX_Fn:
1829 return MODIFIER_FN;
1830 case KEY_NAME_INDEX_FnLock:
1831 return MODIFIER_FNLOCK;
1832 // case KEY_NAME_INDEX_Hyper:
1833 case KEY_NAME_INDEX_Meta:
1834 return MODIFIER_META;
1835 case KEY_NAME_INDEX_NumLock:
1836 return MODIFIER_NUMLOCK;
1837 case KEY_NAME_INDEX_OS:
1838 return MODIFIER_OS;
1839 case KEY_NAME_INDEX_ScrollLock:
1840 return MODIFIER_SCROLLLOCK;
1841 case KEY_NAME_INDEX_Shift:
1842 return MODIFIER_SHIFT;
1843 // case KEY_NAME_INDEX_Super:
1844 case KEY_NAME_INDEX_Symbol:
1845 return MODIFIER_SYMBOL;
1846 case KEY_NAME_INDEX_SymbolLock:
1847 return MODIFIER_SYMBOLLOCK;
1848 default:
1849 return MODIFIER_NONE;
1853 /* static */
1854 bool WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex) {
1855 switch (aKeyNameIndex) {
1856 case KEY_NAME_INDEX_CapsLock:
1857 case KEY_NAME_INDEX_FnLock:
1858 case KEY_NAME_INDEX_NumLock:
1859 case KEY_NAME_INDEX_ScrollLock:
1860 case KEY_NAME_INDEX_SymbolLock:
1861 return true;
1862 default:
1863 return false;
1867 /******************************************************************************
1868 * mozilla::InternalEditorInputEvent (TextEvents.h)
1869 ******************************************************************************/
1871 #define NS_DEFINE_INPUTTYPE(aCPPName, aDOMName) (u"" aDOMName),
1872 const char16_t* const InternalEditorInputEvent::kInputTypeNames[] = {
1873 #include "mozilla/InputTypeList.h"
1875 #undef NS_DEFINE_INPUTTYPE
1877 InternalEditorInputEvent::InputTypeHashtable*
1878 InternalEditorInputEvent::sInputTypeHashtable = nullptr;
1880 /* static */
1881 void InternalEditorInputEvent::Shutdown() {
1882 delete sInputTypeHashtable;
1883 sInputTypeHashtable = nullptr;
1886 /* static */
1887 void InternalEditorInputEvent::GetDOMInputTypeName(EditorInputType aInputType,
1888 nsAString& aInputTypeName) {
1889 if (static_cast<size_t>(aInputType) >=
1890 static_cast<size_t>(EditorInputType::eUnknown)) {
1891 aInputTypeName.Truncate();
1892 return;
1895 MOZ_RELEASE_ASSERT(
1896 static_cast<size_t>(aInputType) < ArrayLength(kInputTypeNames),
1897 "Illegal input type enumeration value");
1898 aInputTypeName.Assign(kInputTypeNames[static_cast<size_t>(aInputType)]);
1901 /* static */
1902 EditorInputType InternalEditorInputEvent::GetEditorInputType(
1903 const nsAString& aInputType) {
1904 if (aInputType.IsEmpty()) {
1905 return EditorInputType::eUnknown;
1908 if (!sInputTypeHashtable) {
1909 sInputTypeHashtable = new InputTypeHashtable(ArrayLength(kInputTypeNames));
1910 for (size_t i = 0; i < ArrayLength(kInputTypeNames); i++) {
1911 sInputTypeHashtable->InsertOrUpdate(nsDependentString(kInputTypeNames[i]),
1912 static_cast<EditorInputType>(i));
1915 return sInputTypeHashtable->MaybeGet(aInputType)
1916 .valueOr(EditorInputType::eUnknown);
1919 } // namespace mozilla