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/EventForwards.h"
16 #include "mozilla/EventStateManager.h"
17 #include "mozilla/InternalMutationEvent.h"
18 #include "mozilla/Maybe.h"
19 #include "mozilla/Preferences.h"
20 #include "mozilla/StaticPrefs_dom.h"
21 #include "mozilla/StaticPrefs_mousewheel.h"
22 #include "mozilla/StaticPrefs_ui.h"
23 #include "mozilla/WritingModes.h"
24 #include "mozilla/dom/KeyboardEventBinding.h"
25 #include "mozilla/dom/MouseEventBinding.h"
26 #include "mozilla/dom/WheelEventBinding.h"
27 #include "nsCommandParams.h"
28 #include "nsContentUtils.h"
29 #include "nsIContent.h"
30 #include "nsIDragSession.h"
31 #include "nsMathUtils.h"
32 #include "nsPrintfCString.h"
36 # include "winnetwk.h"
38 # include "WinUtils.h"
39 #endif // #if defined (XP_WIN)
41 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
42 # include "NativeKeyBindings.h"
43 #endif // #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
47 /******************************************************************************
48 * Global helper methods
49 ******************************************************************************/
51 const char* ToChar(EventMessage aEventMessage
) {
52 switch (aEventMessage
) {
53 #define NS_EVENT_MESSAGE(aMessage) \
57 #include "mozilla/EventMessageList.h"
59 #undef NS_EVENT_MESSAGE
61 return "illegal event message";
65 bool IsPointerEventMessage(EventMessage aMessage
) {
75 case ePointerGotCapture
:
76 case ePointerLostCapture
:
78 case ePointerAuxClick
:
86 bool IsPointerEventMessageOriginallyMouseEventMessage(EventMessage aMessage
) {
87 return aMessage
== ePointerClick
|| aMessage
== ePointerAuxClick
||
88 aMessage
== eContextMenu
;
91 bool IsForbiddenDispatchingToNonElementContent(EventMessage aMessage
) {
93 // Keyboard event target should be an Element node
97 // Mouse event target should be an Element node
101 case eMouseEnterIntoWidget
:
102 case eMouseExitFromWidget
:
103 case eMouseDoubleClick
:
110 case eMouseTouchDrag
:
112 case eMouseExploreByTouch
:
113 // Pointer event target should be an Element node
115 case ePointerAuxClick
:
124 case ePointerGotCapture
:
125 case ePointerLostCapture
:
127 // Drag event target should be an Element node
136 case eQueryDropTargetHittest
:
137 // case mouse wheel related message target should be an Element node
138 case eLegacyMouseLineOrPageScroll
:
139 case eLegacyMousePixelScroll
:
141 // Composition event message target should be an Element node
142 case eCompositionStart
:
143 case eCompositionEnd
:
144 case eCompositionUpdate
:
145 case eCompositionChange
:
146 case eCompositionCommitAsIs
:
147 case eCompositionCommit
:
148 case eCompositionCommitRequestHandled
:
149 // Gesture event target should be an Element node
150 case eSwipeGestureMayStart
:
151 case eSwipeGestureStart
:
152 case eSwipeGestureUpdate
:
153 case eSwipeGestureEnd
:
155 case eMagnifyGestureStart
:
156 case eMagnifyGestureUpdate
:
157 case eMagnifyGesture
:
158 case eRotateGestureStart
:
159 case eRotateGestureUpdate
:
162 case ePressTapGesture
:
164 case eEdgeUICanceled
:
165 case eEdgeUICompleted
:
166 // Touch event target should be an Element node
171 case eTouchPointerCancel
:
179 const char* ToChar(EventClassID aEventClassID
) {
180 switch (aEventClassID
) {
181 #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
182 case eBasic##aName##Class: \
183 return "eBasic" #aName "Class";
185 #define NS_EVENT_CLASS(aPrefix, aName) \
186 case e##aName##Class: \
187 return "e" #aName "Class";
189 #include "mozilla/EventClassList.h"
191 #undef NS_EVENT_CLASS
192 #undef NS_ROOT_EVENT_CLASS
194 return "illegal event class ID";
198 const nsCString
ToString(KeyNameIndex aKeyNameIndex
) {
199 if (aKeyNameIndex
== KEY_NAME_INDEX_USE_STRING
) {
200 return "USE_STRING"_ns
;
202 nsAutoString keyName
;
203 WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex
, keyName
);
204 return NS_ConvertUTF16toUTF8(keyName
);
207 const nsCString
ToString(CodeNameIndex aCodeNameIndex
) {
208 if (aCodeNameIndex
== CODE_NAME_INDEX_USE_STRING
) {
209 return "USE_STRING"_ns
;
211 nsAutoString codeName
;
212 WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex
, codeName
);
213 return NS_ConvertUTF16toUTF8(codeName
);
216 const char* ToChar(Command aCommand
) {
217 if (aCommand
== Command::DoNothing
) {
218 return "CommandDoNothing";
222 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
223 case Command::aName: \
224 return "Command::" #aName;
225 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) \
226 case Command::aName: \
227 return "Command::" #aName;
228 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) \
229 case Command::aName: \
230 return "Command::" #aName;
232 #include "mozilla/CommandList.h"
234 #undef NS_DEFINE_COMMAND
235 #undef NS_DEFINE_COMMAND_WITH_PARAM
236 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
239 return "illegal command value";
243 const nsCString
GetDOMKeyCodeName(uint32_t aKeyCode
) {
245 #define NS_DISALLOW_SAME_KEYCODE
246 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
248 return nsLiteralCString(#aDOMKeyName);
250 #include "mozilla/VirtualKeyCodeList.h"
253 #undef NS_DISALLOW_SAME_KEYCODE
256 return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode
);
260 /******************************************************************************
261 * non class method implementation
262 ******************************************************************************/
264 static nsTHashMap
<nsDepCharHashKey
, Command
>* sCommandHashtable
= nullptr;
266 Command
GetInternalCommand(const char* aCommandName
,
267 const nsCommandParams
* aCommandParams
) {
269 return Command::DoNothing
;
272 // Special cases for "cmd_align". It's mapped to multiple internal commands
273 // with additional param. Therefore, we cannot handle it with the hashtable.
274 if (!strcmp(aCommandName
, "cmd_align")) {
275 if (!aCommandParams
) {
276 // Note that if this is called by EditorCommand::IsCommandEnabled(),
277 // it cannot set aCommandParams. So, don't warn in this case even though
278 // this is illegal case for DoCommandParams().
279 return Command::FormatJustify
;
281 nsAutoCString cValue
;
282 nsresult rv
= aCommandParams
->GetCString("state_attribute", cValue
);
284 nsString value
; // Avoid copying the string buffer with using nsString.
285 rv
= aCommandParams
->GetString("state_attribute", value
);
287 return Command::FormatJustifyNone
;
289 CopyUTF16toUTF8(value
, cValue
);
291 if (cValue
.LowerCaseEqualsASCII("left")) {
292 return Command::FormatJustifyLeft
;
294 if (cValue
.LowerCaseEqualsASCII("right")) {
295 return Command::FormatJustifyRight
;
297 if (cValue
.LowerCaseEqualsASCII("center")) {
298 return Command::FormatJustifyCenter
;
300 if (cValue
.LowerCaseEqualsASCII("justify")) {
301 return Command::FormatJustifyFull
;
303 if (cValue
.IsEmpty()) {
304 return Command::FormatJustifyNone
;
306 return Command::DoNothing
;
309 if (!sCommandHashtable
) {
310 sCommandHashtable
= new nsTHashMap
<nsDepCharHashKey
, Command
>();
311 #define NS_DEFINE_COMMAND(aName, aCommandStr) \
312 sCommandHashtable->InsertOrUpdate(#aCommandStr, Command::aName);
314 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam)
316 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName)
318 #include "mozilla/CommandList.h"
320 #undef NS_DEFINE_COMMAND
321 #undef NS_DEFINE_COMMAND_WITH_PARAM
322 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
324 Command command
= Command::DoNothing
;
325 if (!sCommandHashtable
->Get(aCommandName
, &command
)) {
326 return Command::DoNothing
;
331 /******************************************************************************
332 * As*Event() implementation
333 ******************************************************************************/
335 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
336 #define NS_EVENT_CLASS(aPrefix, aName) \
337 aPrefix##aName* WidgetEvent::As##aName() { return nullptr; } \
339 const aPrefix##aName* WidgetEvent::As##aName() const { \
340 return const_cast<WidgetEvent*>(this)->As##aName(); \
343 #include "mozilla/EventClassList.h"
345 #undef NS_EVENT_CLASS
346 #undef NS_ROOT_EVENT_CLASS
348 /******************************************************************************
349 * mozilla::WidgetEvent
351 * Event struct type checking methods.
352 ******************************************************************************/
354 bool WidgetEvent::IsQueryContentEvent() const {
355 return mClass
== eQueryContentEventClass
;
358 bool WidgetEvent::IsSelectionEvent() const {
359 return mClass
== eSelectionEventClass
;
362 bool WidgetEvent::IsContentCommandEvent() const {
363 return mClass
== eContentCommandEventClass
;
366 /******************************************************************************
367 * mozilla::WidgetEvent
369 * Event message checking methods.
370 ******************************************************************************/
372 bool WidgetEvent::HasMouseEventMessage() const {
376 case eMouseDoubleClick
:
377 case eMouseEnterIntoWidget
:
378 case eMouseExitFromWidget
:
385 // TODO: Perhaps, we should rename this method.
387 case ePointerAuxClick
:
394 bool WidgetEvent::IsMouseEventClassOrHasClickRelatedPointerEvent() const {
395 return mClass
== eMouseEventClass
||
396 IsPointerEventMessageOriginallyMouseEventMessage(mMessage
);
399 bool WidgetEvent::HasDragEventMessage() const {
416 bool WidgetEvent::IsKeyEventMessage(EventMessage aMessage
) {
421 case eAccessKeyNotFound
:
428 bool WidgetEvent::HasIMEEventMessage() const {
430 case eCompositionStart
:
431 case eCompositionEnd
:
432 case eCompositionUpdate
:
433 case eCompositionChange
:
434 case eCompositionCommitAsIs
:
435 case eCompositionCommit
:
442 /******************************************************************************
443 * mozilla::WidgetEvent
445 * Specific event checking methods.
446 ******************************************************************************/
448 bool WidgetEvent::CanBeSentToRemoteProcess() const {
449 // If this event is explicitly marked as shouldn't be sent to remote process,
450 // just return false.
451 if (IsCrossProcessForwardingStopped()) {
455 if (mClass
== eKeyboardEventClass
|| mClass
== eWheelEventClass
) {
463 case eMouseExploreByTouch
:
465 case eMouseEnterIntoWidget
:
466 case eMouseExitFromWidget
:
467 case eMouseTouchDrag
:
481 bool WidgetEvent::WillBeSentToRemoteProcess() const {
482 // This event won't be posted to remote process if it's already explicitly
484 if (IsCrossProcessForwardingStopped()) {
488 // When mOriginalTarget is nullptr, this method shouldn't be used.
489 if (NS_WARN_IF(!mOriginalTarget
)) {
493 return EventStateManager::IsTopLevelRemoteTarget(
494 nsIContent::FromEventTarget(mOriginalTarget
));
497 bool WidgetEvent::IsIMERelatedEvent() const {
498 return HasIMEEventMessage() ||
499 (IsQueryContentEvent() && mMessage
!= eQueryDropTargetHittest
) ||
503 bool WidgetEvent::IsUsingCoordinates() const {
504 const WidgetMouseEvent
* mouseEvent
= AsMouseEvent();
506 return !mouseEvent
->IsContextMenuKeyEvent();
508 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
509 !IsContentCommandEvent();
512 bool WidgetEvent::IsTargetedAtFocusedWindow() const {
513 const WidgetMouseEvent
* mouseEvent
= AsMouseEvent();
515 return mouseEvent
->IsContextMenuKeyEvent();
517 return HasKeyEventMessage() || IsIMERelatedEvent() || IsContentCommandEvent();
520 bool WidgetEvent::IsTargetedAtFocusedContent() const {
521 const WidgetMouseEvent
* mouseEvent
= AsMouseEvent();
523 return mouseEvent
->IsContextMenuKeyEvent();
525 return HasKeyEventMessage() || IsIMERelatedEvent();
528 bool WidgetEvent::IsAllowedToDispatchDOMEvent() const {
530 case eMouseEventClass
:
531 if (mMessage
== eMouseTouchDrag
) {
535 case ePointerEventClass
:
536 // We want synthesized mouse moves to cause mouseover and mouseout
537 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
539 // Synthesized button up events also do not cause DOM events because they
540 // do not have a reliable mRefPoint.
541 return AsMouseEvent()->mReason
== WidgetMouseEvent::eReal
;
543 case eWheelEventClass
: {
544 // wheel event whose all delta values are zero by user pref applied, it
545 // shouldn't cause a DOM event.
546 const WidgetWheelEvent
* wheelEvent
= AsWheelEvent();
547 return wheelEvent
->mDeltaX
!= 0.0 || wheelEvent
->mDeltaY
!= 0.0 ||
548 wheelEvent
->mDeltaZ
!= 0.0;
550 case eTouchEventClass
:
551 return mMessage
!= eTouchPointerCancel
;
552 // Following events are handled in EventStateManager, so, we don't need to
553 // dispatch DOM event for them into the DOM tree.
554 case eQueryContentEventClass
:
555 case eSelectionEventClass
:
556 case eContentCommandEventClass
:
564 bool WidgetEvent::IsAllowedToDispatchInSystemGroup() const {
565 // We don't expect to implement default behaviors with pointer events because
566 // if we do, prevent default on mouse events can't prevent default behaviors
568 return mClass
!= ePointerEventClass
||
569 IsPointerEventMessageOriginallyMouseEventMessage(mMessage
);
572 bool WidgetEvent::IsBlockedForFingerprintingResistance() const {
574 case eKeyboardEventClass
: {
575 const WidgetKeyboardEvent
* keyboardEvent
= AsKeyboardEvent();
577 return (keyboardEvent
->mKeyNameIndex
== KEY_NAME_INDEX_Alt
||
578 keyboardEvent
->mKeyNameIndex
== KEY_NAME_INDEX_Shift
||
579 keyboardEvent
->mKeyNameIndex
== KEY_NAME_INDEX_Control
||
580 keyboardEvent
->mKeyNameIndex
== KEY_NAME_INDEX_AltGraph
);
582 case ePointerEventClass
: {
583 if (IsPointerEventMessageOriginallyMouseEventMessage(mMessage
)) {
587 if (SPOOFED_MAX_TOUCH_POINTS
> 0) {
591 const WidgetPointerEvent
* pointerEvent
= AsPointerEvent();
593 // We suppress the pointer events if it is not primary for fingerprinting
594 // resistance. It is because of that we want to spoof any pointer event
595 // into a mouse pointer event and the mouse pointer event only has
596 // isPrimary as true.
597 return !pointerEvent
->mIsPrimary
;
604 bool WidgetEvent::AllowFlushingPendingNotifications() const {
605 if (mClass
!= eQueryContentEventClass
) {
608 // If the dispatcher does not want a flush of pending notifications, it may
609 // be caused by that it's unsafe. Therefore, we should allow handlers to
610 // flush pending things only when the dispatcher requires the latest content
612 return AsQueryContentEvent()->mNeedsToFlushLayout
;
615 bool WidgetEvent::ShouldIgnoreCapturingContent() const {
616 MOZ_ASSERT(IsUsingCoordinates());
618 if (MOZ_UNLIKELY(!IsTrusted())) {
621 return mClass
== eMouseEventClass
|| mClass
== ePointerEventClass
622 ? AsMouseEvent()->mIgnoreCapturingContent
626 /******************************************************************************
627 * mozilla::WidgetEvent
630 ******************************************************************************/
632 static dom::EventTarget
* GetTargetForDOMEvent(dom::EventTarget
* aTarget
) {
633 return aTarget
? aTarget
->GetTargetForDOMEvent() : nullptr;
636 dom::EventTarget
* WidgetEvent::GetDOMEventTarget() const {
637 return GetTargetForDOMEvent(mTarget
);
640 dom::EventTarget
* WidgetEvent::GetCurrentDOMEventTarget() const {
641 return GetTargetForDOMEvent(mCurrentTarget
);
644 dom::EventTarget
* WidgetEvent::GetOriginalDOMEventTarget() const {
645 if (mOriginalTarget
) {
646 return GetTargetForDOMEvent(mOriginalTarget
);
648 return GetDOMEventTarget();
651 void WidgetEvent::PreventDefault(bool aCalledByDefaultHandler
,
652 nsIPrincipal
* aPrincipal
) {
653 if (mMessage
== ePointerDown
) {
654 if (aCalledByDefaultHandler
) {
655 // Shouldn't prevent default on pointerdown by default handlers to stop
656 // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages
662 nsAutoString addonId
;
663 Unused
<< NS_WARN_IF(NS_FAILED(aPrincipal
->GetAddonId(addonId
)));
664 if (!addonId
.IsEmpty()) {
665 // Ignore the case that it's called by a web extension.
670 mFlags
.PreventDefault(aCalledByDefaultHandler
);
673 bool WidgetEvent::IsUserAction() const {
677 // FYI: eMouseScrollEventClass and ePointerEventClass represent
678 // user action but they are synthesized events.
680 case eKeyboardEventClass
:
681 case eCompositionEventClass
:
682 case eMouseScrollEventClass
:
683 case eWheelEventClass
:
684 case eGestureNotifyEventClass
:
685 case eSimpleGestureEventClass
:
686 case eTouchEventClass
:
687 case eCommandEventClass
:
688 case eContentCommandEventClass
:
690 case eMouseEventClass
:
691 case eDragEventClass
:
692 case ePointerEventClass
:
693 return AsMouseEvent()->IsReal();
699 /******************************************************************************
700 * mozilla::WidgetInputEvent
701 ******************************************************************************/
704 Modifier
WidgetInputEvent::GetModifier(const nsAString
& aDOMKeyName
) {
705 if (aDOMKeyName
.EqualsLiteral("Accel")) {
706 return AccelModifier();
708 KeyNameIndex keyNameIndex
= WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName
);
709 return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex
);
713 Modifier
WidgetInputEvent::AccelModifier() {
714 static Modifier sAccelModifier
= MODIFIER_NONE
;
715 if (sAccelModifier
== MODIFIER_NONE
) {
716 switch (StaticPrefs::ui_key_accelKey()) {
717 case dom::KeyboardEvent_Binding::DOM_VK_META
:
718 case dom::KeyboardEvent_Binding::DOM_VK_WIN
:
719 sAccelModifier
= MODIFIER_META
;
721 case dom::KeyboardEvent_Binding::DOM_VK_ALT
:
722 sAccelModifier
= MODIFIER_ALT
;
724 case dom::KeyboardEvent_Binding::DOM_VK_CONTROL
:
725 sAccelModifier
= MODIFIER_CONTROL
;
729 sAccelModifier
= MODIFIER_META
;
731 sAccelModifier
= MODIFIER_CONTROL
;
736 return sAccelModifier
;
739 /******************************************************************************
740 * mozilla::WidgetPointerHelper (MouseEvents.h)
741 ******************************************************************************/
744 int32_t WidgetPointerHelper::GetValidTiltValue(int32_t aTilt
) {
745 if (MOZ_LIKELY(aTilt
>= -90 && aTilt
<= 90)) {
751 while (aTilt
< -90) {
754 MOZ_ASSERT(aTilt
>= -90 && aTilt
<= 90);
759 double WidgetPointerHelper::GetValidAltitudeAngle(double aAltitudeAngle
) {
760 if (MOZ_LIKELY(aAltitudeAngle
>= 0.0 && aAltitudeAngle
<= kHalfPi
)) {
761 return aAltitudeAngle
;
763 while (aAltitudeAngle
> kHalfPi
) {
764 aAltitudeAngle
-= kHalfPi
;
766 while (aAltitudeAngle
< 0.0) {
767 aAltitudeAngle
+= kHalfPi
;
769 MOZ_ASSERT(aAltitudeAngle
>= 0.0 && aAltitudeAngle
<= kHalfPi
);
770 return aAltitudeAngle
;
774 double WidgetPointerHelper::GetValidAzimuthAngle(double aAzimuthAngle
) {
775 if (MOZ_LIKELY(aAzimuthAngle
>= 0.0 && aAzimuthAngle
<= kDoublePi
)) {
776 return aAzimuthAngle
;
778 while (aAzimuthAngle
> kDoublePi
) {
779 aAzimuthAngle
-= kDoublePi
;
781 while (aAzimuthAngle
< 0.0) {
782 aAzimuthAngle
+= kDoublePi
;
784 MOZ_ASSERT(aAzimuthAngle
>= 0.0 && aAzimuthAngle
<= kDoublePi
);
785 return aAzimuthAngle
;
789 double WidgetPointerHelper::ComputeAltitudeAngle(int32_t aTiltX
,
791 // https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
792 aTiltX
= GetValidTiltValue(aTiltX
);
793 aTiltY
= GetValidTiltValue(aTiltY
);
794 if (std::abs(aTiltX
) == 90 || std::abs(aTiltY
) == 90) {
797 const double tiltXRadians
= kPi
/ 180.0 * aTiltX
;
798 const double tiltYRadians
= kPi
/ 180.0 * aTiltY
;
800 return kHalfPi
- std::abs(tiltYRadians
);
803 return kHalfPi
- std::abs(tiltXRadians
);
805 return std::atan(1.0 /
806 NS_hypot(std::tan(tiltXRadians
), std::tan(tiltYRadians
)));
810 double WidgetPointerHelper::ComputeAzimuthAngle(int32_t aTiltX
,
812 // https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
813 aTiltX
= GetValidTiltValue(aTiltX
);
814 aTiltY
= GetValidTiltValue(aTiltY
);
819 return aTiltY
< 0 ? 3.0 * kHalfPi
: 0.0;
823 return aTiltX
< 0 ? kPi
: 0.0;
826 if (std::abs(aTiltX
) == 90 || std::abs(aTiltY
) == 90) {
830 const double tiltXRadians
= kPi
/ 180.0 * aTiltX
;
831 const double tiltYRadians
= kPi
/ 180.0 * aTiltY
;
832 const double azimuthAngle
=
833 std::atan2(std::tan(tiltYRadians
), std::tan(tiltXRadians
));
834 return azimuthAngle
< 0 ? azimuthAngle
+ kDoublePi
: azimuthAngle
;
838 double WidgetPointerHelper::ComputeTiltX(double aAltitudeAngle
,
839 double aAzimuthAngle
) {
840 // https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
841 aAltitudeAngle
= GetValidAltitudeAngle(aAltitudeAngle
);
842 aAzimuthAngle
= GetValidAzimuthAngle(aAzimuthAngle
);
843 if (aAltitudeAngle
== 0.0) {
844 if ((aAzimuthAngle
>= 0.0 && aAzimuthAngle
< kHalfPi
) ||
845 (aAzimuthAngle
> 3 * kHalfPi
&& aAzimuthAngle
<= kDoublePi
)) {
846 return 90; // pi / 2 * 180 / pi
848 if (aAzimuthAngle
> kHalfPi
&& aAzimuthAngle
< 3 * kHalfPi
) {
849 return -90; // -1 * pi / 2 * 180 / pi
851 MOZ_ASSERT(aAzimuthAngle
== kHalfPi
|| aAzimuthAngle
== 3 * kHalfPi
);
855 constexpr double radToDeg
= 180.0 / kPi
;
857 std::atan(std::cos(aAzimuthAngle
) / std::tan(aAltitudeAngle
)) * radToDeg
+
862 double WidgetPointerHelper::ComputeTiltY(double aAltitudeAngle
,
863 double aAzimuthAngle
) {
864 // https://w3c.github.io/pointerevents/#converting-between-tiltx-tilty-and-altitudeangle-azimuthangle
865 aAltitudeAngle
= GetValidAltitudeAngle(aAltitudeAngle
);
866 aAzimuthAngle
= GetValidAzimuthAngle(aAzimuthAngle
);
867 if (aAltitudeAngle
== 0.0) {
868 if (aAzimuthAngle
> 0.0 && aAzimuthAngle
< kPi
) {
869 return 90; // pi / 2 * 180 / pi
871 if (aAzimuthAngle
> kPi
&& aAzimuthAngle
< kDoublePi
) {
872 return -90; // -1 * pi / 2 * 180 / pi
874 MOZ_ASSERT(aAzimuthAngle
== 0.0 || aAzimuthAngle
== kPi
||
875 aAzimuthAngle
== kDoublePi
);
878 constexpr double radToDeg
= 180.0 / kPi
;
880 std::atan(std::sin(aAzimuthAngle
) / std::tan(aAltitudeAngle
)) * radToDeg
+
884 /******************************************************************************
885 * mozilla::WidgetMouseEventBase (MouseEvents.h)
886 ******************************************************************************/
888 bool WidgetMouseEventBase::InputSourceSupportsHover() const {
889 switch (mInputSource
) {
890 case dom::MouseEvent_Binding::MOZ_SOURCE_MOUSE
:
891 case dom::MouseEvent_Binding::MOZ_SOURCE_PEN
:
892 case dom::MouseEvent_Binding::MOZ_SOURCE_ERASER
:
894 case dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH
:
895 case dom::MouseEvent_Binding::MOZ_SOURCE_UNKNOWN
:
896 case dom::MouseEvent_Binding::MOZ_SOURCE_KEYBOARD
:
897 case dom::MouseEvent_Binding::MOZ_SOURCE_CURSOR
:
903 bool WidgetMouseEventBase::DOMEventShouldUseFractionalCoords() const {
904 if (!StaticPrefs::dom_event_pointer_fractional_coordinates_enabled()) {
905 return false; // We completely don't support fractional coordinates
907 // If we support fractional coordinates only for PointerEvent, the spec
908 // recommend that `click`, `auxclick` and `contextmenu` keep using integer
910 // https://w3c.github.io/pointerevents/#event-coordinates
911 if (mClass
== ePointerEventClass
&& mMessage
!= ePointerClick
&&
912 mMessage
!= ePointerAuxClick
&& mMessage
!= eContextMenu
) {
915 // Untrusted events can be initialized with double values. However, Chrome
916 // returns integer coordinates for non-PointerEvent instances, `click`,
917 // `auxclick` and `contextmenu`. Therefore, it may be risky to allow
918 // fractional coordinates for all untrusted events right now because web apps
919 // may initialize untrusted events with quotients.
920 // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/events/pointer_event.h;l=59-91;drc=80c2637874588837a2d656dbd79ad8f227dc67e8
921 // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/events/pointer_event.cc;l=110-117;drc=8e948282d37c0e119e3102236878d6f4d5052c16
924 dom_event_mouse_fractional_coordinates_untrusted_enabled();
926 // CSSOM suggested that MouseEvent interface can treat fractional values in
927 // all instances. However, it's risky for backward compatibility. Therefore,
928 // we don't have a plan to enable it for now.
930 StaticPrefs::dom_event_mouse_fractional_coordinates_trusted_enabled());
933 /******************************************************************************
934 * mozilla::WidgetMouseEvent (MouseEvents.h)
935 ******************************************************************************/
938 bool WidgetMouseEvent::IsMiddleClickPasteEnabled() {
939 return Preferences::GetBool("middlemouse.paste", false);
943 void WidgetMouseEvent::AssertContextMenuEventButtonConsistency() const {
944 if (mMessage
!= eContextMenu
) {
948 if (mInputSource
== dom::MouseEvent_Binding::MOZ_SOURCE_TOUCH
) {
949 NS_WARNING_ASSERTION(mButton
== MouseButton::ePrimary
,
950 "eContextMenu events by touch trigger should use "
951 "primary mouse button / touch contact");
952 } else if (mContextMenuTrigger
== eNormal
) {
953 NS_WARNING_ASSERTION(mButton
== MouseButton::eSecondary
,
954 "eContextMenu events with eNormal trigger should use "
955 "secondary mouse button");
957 NS_WARNING_ASSERTION(mButton
== MouseButton::ePrimary
,
958 "eContextMenu events with non-eNormal trigger should "
959 "use primary mouse button");
962 if (mContextMenuTrigger
== eControlClick
) {
963 NS_WARNING_ASSERTION(IsControl(),
964 "eContextMenu events with eControlClick trigger "
965 "should return true from IsControl()");
970 /******************************************************************************
971 * mozilla::WidgetDragEvent (MouseEvents.h)
972 ******************************************************************************/
974 void WidgetDragEvent::InitDropEffectForTests() {
975 MOZ_ASSERT(mFlags
.mIsSynthesizedForTests
);
978 nsCOMPtr
<nsIDragSession
> session
= nsContentUtils::GetDragSession(mWidget
);
979 if (NS_WARN_IF(!session
)) {
983 uint32_t effectAllowed
= session
->GetEffectAllowedForTests();
984 uint32_t desiredDropEffect
= nsIDragService::DRAGDROP_ACTION_NONE
;
987 desiredDropEffect
= IsMeta() ? nsIDragService::DRAGDROP_ACTION_LINK
988 : nsIDragService::DRAGDROP_ACTION_COPY
;
991 // On Linux, we know user's intention from API, but we should use
992 // same modifiers as Windows for tests because GNOME on Ubuntu use
993 // them and that makes each test simpler.
995 desiredDropEffect
= IsShift() ? nsIDragService::DRAGDROP_ACTION_LINK
996 : nsIDragService::DRAGDROP_ACTION_COPY
;
997 } else if (IsShift()) {
998 desiredDropEffect
= nsIDragService::DRAGDROP_ACTION_MOVE
;
1000 #endif // #ifdef XP_MACOSX #else
1001 // First, use modifier state for preferring action which is explicitly
1002 // specified by the synthesizer.
1003 if (!(desiredDropEffect
&= effectAllowed
)) {
1004 // Otherwise, use an action which is allowed at starting the session.
1005 desiredDropEffect
= effectAllowed
;
1007 if (desiredDropEffect
& nsIDragService::DRAGDROP_ACTION_MOVE
) {
1008 session
->SetDragAction(nsIDragService::DRAGDROP_ACTION_MOVE
);
1009 } else if (desiredDropEffect
& nsIDragService::DRAGDROP_ACTION_COPY
) {
1010 session
->SetDragAction(nsIDragService::DRAGDROP_ACTION_COPY
);
1011 } else if (desiredDropEffect
& nsIDragService::DRAGDROP_ACTION_LINK
) {
1012 session
->SetDragAction(nsIDragService::DRAGDROP_ACTION_LINK
);
1014 session
->SetDragAction(nsIDragService::DRAGDROP_ACTION_NONE
);
1018 /******************************************************************************
1019 * mozilla::WidgetWheelEvent (MouseEvents.h)
1020 ******************************************************************************/
1023 double WidgetWheelEvent::ComputeOverriddenDelta(double aDelta
,
1024 bool aIsForVertical
) {
1025 if (!StaticPrefs::mousewheel_system_scroll_override_enabled()) {
1030 ? StaticPrefs::mousewheel_system_scroll_override_vertical_factor()
1031 : StaticPrefs::mousewheel_system_scroll_override_horizontal_factor();
1032 // Making the scroll speed slower doesn't make sense. So, ignore odd factor
1033 // which is less than 1.0.
1034 if (intFactor
<= 100) {
1037 double factor
= static_cast<double>(intFactor
) / 100;
1038 return aDelta
* factor
;
1041 double WidgetWheelEvent::OverriddenDeltaX() const {
1042 if (!mAllowToOverrideSystemScrollSpeed
||
1043 mDeltaMode
!= dom::WheelEvent_Binding::DOM_DELTA_LINE
||
1044 mCustomizedByUserPrefs
) {
1047 return ComputeOverriddenDelta(mDeltaX
, false);
1050 double WidgetWheelEvent::OverriddenDeltaY() const {
1051 if (!mAllowToOverrideSystemScrollSpeed
||
1052 mDeltaMode
!= dom::WheelEvent_Binding::DOM_DELTA_LINE
||
1053 mCustomizedByUserPrefs
) {
1056 return ComputeOverriddenDelta(mDeltaY
, true);
1059 /******************************************************************************
1060 * mozilla::WidgetKeyboardEvent (TextEvents.h)
1061 ******************************************************************************/
1063 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
1064 const char16_t
* const WidgetKeyboardEvent::kKeyNames
[] = {
1065 #include "mozilla/KeyNameList.h"
1067 #undef NS_DEFINE_KEYNAME
1069 #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
1071 const char16_t
* const WidgetKeyboardEvent::kCodeNames
[] = {
1072 #include "mozilla/PhysicalKeyCodeNameList.h"
1074 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
1076 WidgetKeyboardEvent::KeyNameIndexHashtable
*
1077 WidgetKeyboardEvent::sKeyNameIndexHashtable
= nullptr;
1078 WidgetKeyboardEvent::CodeNameIndexHashtable
*
1079 WidgetKeyboardEvent::sCodeNameIndexHashtable
= nullptr;
1081 void WidgetKeyboardEvent::InitAllEditCommands(
1082 const Maybe
<WritingMode
>& aWritingMode
) {
1083 // If this event is synthesized for tests, we don't need to retrieve the
1084 // command via the main process. So, we don't need widget and can trust
1086 if (!mFlags
.mIsSynthesizedForTests
) {
1087 // If the event was created without widget, e.g., created event in chrome
1088 // script, this shouldn't execute native key bindings.
1089 if (NS_WARN_IF(!mWidget
)) {
1093 // This event should be trusted event here and we shouldn't expose native
1094 // key binding information to web contents with untrusted events.
1095 if (NS_WARN_IF(!IsTrusted())) {
1100 XRE_IsParentProcess(),
1101 "It's too expensive to retrieve all edit commands from remote process");
1102 MOZ_ASSERT(!AreAllEditCommandsInitialized(),
1103 "Shouldn't be called two or more times");
1106 DebugOnly
<bool> okIgnored
= InitEditCommandsFor(
1107 NativeKeyBindingsType::SingleLineEditor
, aWritingMode
);
1108 NS_WARNING_ASSERTION(okIgnored
,
1109 "InitEditCommandsFor(NativeKeyBindingsType::"
1110 "SingleLineEditor) failed, but ignored");
1112 InitEditCommandsFor(NativeKeyBindingsType::MultiLineEditor
, aWritingMode
);
1113 NS_WARNING_ASSERTION(okIgnored
,
1114 "InitEditCommandsFor(NativeKeyBindingsType::"
1115 "MultiLineEditor) failed, but ignored");
1117 InitEditCommandsFor(NativeKeyBindingsType::RichTextEditor
, aWritingMode
);
1118 NS_WARNING_ASSERTION(okIgnored
,
1119 "InitEditCommandsFor(NativeKeyBindingsType::"
1120 "RichTextEditor) failed, but ignored");
1123 bool WidgetKeyboardEvent::InitEditCommandsFor(
1124 NativeKeyBindingsType aType
, const Maybe
<WritingMode
>& aWritingMode
) {
1125 bool& initialized
= IsEditCommandsInitializedRef(aType
);
1129 nsTArray
<CommandInt
>& commands
= EditCommandsRef(aType
);
1131 // If this event is synthesized for tests, we shouldn't access customized
1132 // shortcut settings of the environment. Therefore, we don't need to check
1133 // whether `widget` is set or not. And we can treat synthesized events are
1135 if (mFlags
.mIsSynthesizedForTests
) {
1136 MOZ_DIAGNOSTIC_ASSERT(IsTrusted());
1137 #if defined(MOZ_WIDGET_GTK) || defined(XP_MACOSX)
1138 // TODO: We should implement `NativeKeyBindings` for Windows and Android
1139 // too in bug 1301497 for getting rid of the #if.
1140 widget::NativeKeyBindings::GetEditCommandsForTests(aType
, *this,
1141 aWritingMode
, commands
);
1147 if (NS_WARN_IF(!mWidget
) || NS_WARN_IF(!IsTrusted())) {
1150 // `nsIWidget::GetEditCommands()` will retrieve `WritingMode` at selection
1151 // again, but it should be almost zero-cost since `TextEventDispatcher`
1152 // caches the value.
1153 nsCOMPtr
<nsIWidget
> widget
= mWidget
;
1154 initialized
= widget
->GetEditCommands(aType
, *this, commands
);
1158 bool WidgetKeyboardEvent::ExecuteEditCommands(NativeKeyBindingsType aType
,
1159 DoCommandCallback aCallback
,
1160 void* aCallbackData
) {
1161 // If the event was created without widget, e.g., created event in chrome
1162 // script, this shouldn't execute native key bindings.
1163 if (NS_WARN_IF(!mWidget
)) {
1167 // This event should be trusted event here and we shouldn't expose native
1168 // key binding information to web contents with untrusted events.
1169 if (NS_WARN_IF(!IsTrusted())) {
1173 if (!IsEditCommandsInitializedRef(aType
)) {
1174 Maybe
<WritingMode
> writingMode
;
1175 if (RefPtr
<widget::TextEventDispatcher
> textEventDispatcher
=
1176 mWidget
->GetTextEventDispatcher()) {
1177 writingMode
= textEventDispatcher
->MaybeQueryWritingModeAtSelection();
1179 if (NS_WARN_IF(!InitEditCommandsFor(aType
, writingMode
))) {
1184 const nsTArray
<CommandInt
>& commands
= EditCommandsRef(aType
);
1185 if (commands
.IsEmpty()) {
1189 for (CommandInt command
: commands
) {
1190 aCallback(static_cast<Command
>(command
), aCallbackData
);
1195 bool WidgetKeyboardEvent::ShouldCauseKeypressEvents() const {
1196 // Currently, we don't dispatch keypress events of modifier keys and
1198 switch (mKeyNameIndex
) {
1199 case KEY_NAME_INDEX_Alt
:
1200 case KEY_NAME_INDEX_AltGraph
:
1201 case KEY_NAME_INDEX_CapsLock
:
1202 case KEY_NAME_INDEX_Control
:
1203 case KEY_NAME_INDEX_Fn
:
1204 case KEY_NAME_INDEX_FnLock
:
1205 // case KEY_NAME_INDEX_Hyper:
1206 case KEY_NAME_INDEX_Meta
:
1207 case KEY_NAME_INDEX_NumLock
:
1208 case KEY_NAME_INDEX_ScrollLock
:
1209 case KEY_NAME_INDEX_Shift
:
1210 // case KEY_NAME_INDEX_Super:
1211 case KEY_NAME_INDEX_Symbol
:
1212 case KEY_NAME_INDEX_SymbolLock
:
1213 case KEY_NAME_INDEX_Dead
:
1220 static bool HasASCIIDigit(const ShortcutKeyCandidateArray
& aCandidates
) {
1221 for (uint32_t i
= 0; i
< aCandidates
.Length(); ++i
) {
1222 uint32_t ch
= aCandidates
[i
].mCharCode
;
1223 if (ch
>= '0' && ch
<= '9') return true;
1228 static bool CharsCaseInsensitiveEqual(uint32_t aChar1
, uint32_t aChar2
) {
1229 return aChar1
== aChar2
|| (IS_IN_BMP(aChar1
) && IS_IN_BMP(aChar2
) &&
1230 ToLowerCase(static_cast<char16_t
>(aChar1
)) ==
1231 ToLowerCase(static_cast<char16_t
>(aChar2
)));
1234 static bool IsCaseChangeableChar(uint32_t aChar
) {
1235 return IS_IN_BMP(aChar
) && ToLowerCase(static_cast<char16_t
>(aChar
)) !=
1236 ToUpperCase(static_cast<char16_t
>(aChar
));
1239 void WidgetKeyboardEvent::GetShortcutKeyCandidates(
1240 ShortcutKeyCandidateArray
& aCandidates
) const {
1241 MOZ_ASSERT(aCandidates
.IsEmpty(), "aCandidates must be empty");
1243 using ShiftState
= ShortcutKeyCandidate::ShiftState
;
1244 using SkipIfEarlierHandlerDisabled
=
1245 ShortcutKeyCandidate::SkipIfEarlierHandlerDisabled
;
1247 // ShortcutKeyCandidate::mCharCode is a candidate charCode.
1248 // ShortcutKeyCandidate::mShiftState means the mCharCode should be tried to
1249 // execute a command with/without shift key state. If this is Ignorable,
1250 // the shifted key state should be ignored. Otherwise, don't ignore the state.
1251 // the priority of the charCodes are (shift key is not pressed):
1252 // 0: PseudoCharCode()/ShiftState::MatchExactly,
1253 // 1: unshiftedCharCodes[0]/ShiftState::MatchExactly,
1254 // 2: unshiftedCharCodes[1]/ShiftState::MatchExactly...
1255 // the priority of the charCodes are (shift key is pressed):
1256 // 0: PseudoCharCode()/ShiftState::MatchExactly,
1257 // 1: shiftedCharCodes[0]/ShiftState::MatchExactly,
1258 // 2: shiftedCharCodes[0]/ShiftState::Ignorable,
1259 // 3: shiftedCharCodes[1]/ShiftState::MatchExactly,
1260 // 4: shiftedCharCodes[1]/ShiftState::Ignorable...
1261 uint32_t pseudoCharCode
= PseudoCharCode();
1262 if (pseudoCharCode
) {
1263 ShortcutKeyCandidate
key(pseudoCharCode
, ShiftState::MatchExactly
,
1264 SkipIfEarlierHandlerDisabled::No
);
1265 aCandidates
.AppendElement(key
);
1268 uint32_t len
= mAlternativeCharCodes
.Length();
1270 for (uint32_t i
= 0; i
< len
; ++i
) {
1271 uint32_t ch
= mAlternativeCharCodes
[i
].mUnshiftedCharCode
;
1272 if (!ch
|| ch
== pseudoCharCode
) {
1275 ShortcutKeyCandidate
key(ch
, ShiftState::MatchExactly
,
1276 SkipIfEarlierHandlerDisabled::No
);
1277 aCandidates
.AppendElement(key
);
1279 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
1280 // this keyboard layout is AZERTY or similar layout, probably.
1281 // In this case, Accel+[0-9] should be accessible without shift key.
1282 // However, the priority should be lowest.
1283 if (!HasASCIIDigit(aCandidates
)) {
1284 for (uint32_t i
= 0; i
< len
; ++i
) {
1285 uint32_t ch
= mAlternativeCharCodes
[i
].mShiftedCharCode
;
1286 if (ch
>= '0' && ch
<= '9') {
1287 ShortcutKeyCandidate
key(
1288 ch
, ShiftState::MatchExactly
,
1289 // Ctrl + `-` in the French keyboard layout should not match with
1290 // Ctrl + `6` shortcut when it's already fully zoomed out.
1291 SkipIfEarlierHandlerDisabled::Yes
);
1292 aCandidates
.AppendElement(key
);
1298 for (uint32_t i
= 0; i
< len
; ++i
) {
1299 uint32_t ch
= mAlternativeCharCodes
[i
].mShiftedCharCode
;
1304 if (ch
!= pseudoCharCode
) {
1305 ShortcutKeyCandidate
key(ch
, ShiftState::MatchExactly
,
1306 SkipIfEarlierHandlerDisabled::No
);
1307 aCandidates
.AppendElement(key
);
1310 // If the char is an alphabet, the shift key state should not be
1311 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
1313 // And checking the charCode is same as unshiftedCharCode too.
1314 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
1315 uint32_t unshiftCh
= mAlternativeCharCodes
[i
].mUnshiftedCharCode
;
1316 if (CharsCaseInsensitiveEqual(ch
, unshiftCh
)) {
1320 // On the Hebrew keyboard layout on Windows, the unshifted char is a
1321 // localized character but the shifted char is a Latin alphabet,
1322 // then, we should not execute without the shift state. See bug 433192.
1323 if (IsCaseChangeableChar(ch
)) {
1327 // Setting the alternative charCode candidates for retry without shift
1328 // key state only when the shift key is pressed.
1329 ShortcutKeyCandidate
key(ch
, ShiftState::Ignorable
,
1330 SkipIfEarlierHandlerDisabled::No
);
1331 aCandidates
.AppendElement(key
);
1335 // Special case for "Space" key. With some keyboard layouts, "Space" with
1336 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1337 // we should guarantee that the key press works as an ASCII white space key
1338 // press. However, if the space key is assigned to a function key, it
1339 // shouldn't work as a space key.
1340 if (mKeyNameIndex
== KEY_NAME_INDEX_USE_STRING
&&
1341 mCodeNameIndex
== CODE_NAME_INDEX_Space
&& pseudoCharCode
!= ' ') {
1342 ShortcutKeyCandidate
spaceKey(' ', ShiftState::MatchExactly
,
1343 SkipIfEarlierHandlerDisabled::No
);
1344 aCandidates
.AppendElement(spaceKey
);
1348 void WidgetKeyboardEvent::GetAccessKeyCandidates(
1349 nsTArray
<uint32_t>& aCandidates
) const {
1350 MOZ_ASSERT(aCandidates
.IsEmpty(), "aCandidates must be empty");
1352 // return the lower cased charCode candidates for access keys.
1353 // the priority of the charCodes are:
1354 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
1355 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
1356 uint32_t pseudoCharCode
= PseudoCharCode();
1357 if (pseudoCharCode
) {
1358 uint32_t ch
= pseudoCharCode
;
1359 if (IS_IN_BMP(ch
)) {
1360 ch
= ToLowerCase(static_cast<char16_t
>(ch
));
1362 aCandidates
.AppendElement(ch
);
1364 for (uint32_t i
= 0; i
< mAlternativeCharCodes
.Length(); ++i
) {
1365 uint32_t ch
[2] = {mAlternativeCharCodes
[i
].mUnshiftedCharCode
,
1366 mAlternativeCharCodes
[i
].mShiftedCharCode
};
1367 for (uint32_t j
= 0; j
< 2; ++j
) {
1371 if (IS_IN_BMP(ch
[j
])) {
1372 ch
[j
] = ToLowerCase(static_cast<char16_t
>(ch
[j
]));
1374 // Don't append the charcode that was already appended.
1375 if (aCandidates
.IndexOf(ch
[j
]) == aCandidates
.NoIndex
) {
1376 aCandidates
.AppendElement(ch
[j
]);
1380 // Special case for "Space" key. With some keyboard layouts, "Space" with
1381 // or without Shift key causes non-ASCII space. For such keyboard layouts,
1382 // we should guarantee that the key press works as an ASCII white space key
1383 // press. However, if the space key is assigned to a function key, it
1384 // shouldn't work as a space key.
1385 if (mKeyNameIndex
== KEY_NAME_INDEX_USE_STRING
&&
1386 mCodeNameIndex
== CODE_NAME_INDEX_Space
&& pseudoCharCode
!= ' ') {
1387 aCandidates
.AppendElement(' ');
1391 // mask values for ui.key.chromeAccess and ui.key.contentAccess
1392 #define NS_MODIFIER_SHIFT 1
1393 #define NS_MODIFIER_CONTROL 2
1394 #define NS_MODIFIER_ALT 4
1395 #define NS_MODIFIER_META 8
1397 static Modifiers
PrefFlagsToModifiers(int32_t aPrefFlags
) {
1398 Modifiers result
= 0;
1399 if (aPrefFlags
& NS_MODIFIER_SHIFT
) {
1400 result
|= MODIFIER_SHIFT
;
1402 if (aPrefFlags
& NS_MODIFIER_CONTROL
) {
1403 result
|= MODIFIER_CONTROL
;
1405 if (aPrefFlags
& NS_MODIFIER_ALT
) {
1406 result
|= MODIFIER_ALT
;
1408 if (aPrefFlags
& NS_MODIFIER_META
) {
1409 result
|= MODIFIER_META
;
1414 bool WidgetKeyboardEvent::ModifiersMatchWithAccessKey(
1415 AccessKeyType aType
) const {
1416 if (!ModifiersForAccessKeyMatching()) {
1419 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType
);
1422 Modifiers
WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const {
1423 static const Modifiers kModifierMask
=
1424 MODIFIER_SHIFT
| MODIFIER_CONTROL
| MODIFIER_ALT
| MODIFIER_META
;
1425 return mModifiers
& kModifierMask
;
1429 Modifiers
WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType
) {
1430 switch (StaticPrefs::ui_key_generalAccessKey()) {
1432 break; // use the individual prefs
1434 return MODIFIER_SHIFT
;
1436 return MODIFIER_CONTROL
;
1438 return MODIFIER_ALT
;
1441 return MODIFIER_META
;
1443 return MODIFIER_NONE
;
1447 case AccessKeyType::eChrome
:
1448 return PrefFlagsToModifiers(StaticPrefs::ui_key_chromeAccess());
1449 case AccessKeyType::eContent
:
1450 return PrefFlagsToModifiers(StaticPrefs::ui_key_contentAccess());
1452 return MODIFIER_NONE
;
1457 void WidgetKeyboardEvent::Shutdown() {
1458 delete sKeyNameIndexHashtable
;
1459 sKeyNameIndexHashtable
= nullptr;
1460 delete sCodeNameIndexHashtable
;
1461 sCodeNameIndexHashtable
= nullptr;
1462 // Although sCommandHashtable is not a member of WidgetKeyboardEvent, but
1463 // let's delete it here since we need to do it at same time.
1464 delete sCommandHashtable
;
1465 sCommandHashtable
= nullptr;
1469 void WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex
,
1470 nsAString
& aKeyName
) {
1471 if (aKeyNameIndex
>= KEY_NAME_INDEX_USE_STRING
) {
1472 aKeyName
.Truncate();
1476 MOZ_RELEASE_ASSERT(static_cast<size_t>(aKeyNameIndex
) < std::size(kKeyNames
),
1477 "Illegal key enumeration value");
1478 aKeyName
= kKeyNames
[aKeyNameIndex
];
1482 void WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex
,
1483 nsAString
& aCodeName
) {
1484 if (aCodeNameIndex
>= CODE_NAME_INDEX_USE_STRING
) {
1485 aCodeName
.Truncate();
1490 static_cast<size_t>(aCodeNameIndex
) < std::size(kCodeNames
),
1491 "Illegal physical code enumeration value");
1493 // Generate some continuous runs of codes, rather than looking them up.
1494 if (aCodeNameIndex
>= CODE_NAME_INDEX_KeyA
&&
1495 aCodeNameIndex
<= CODE_NAME_INDEX_KeyZ
) {
1496 uint32_t index
= aCodeNameIndex
- CODE_NAME_INDEX_KeyA
;
1497 aCodeName
.AssignLiteral(u
"Key");
1498 aCodeName
.Append(u
'A' + index
);
1501 if (aCodeNameIndex
>= CODE_NAME_INDEX_Digit0
&&
1502 aCodeNameIndex
<= CODE_NAME_INDEX_Digit9
) {
1503 uint32_t index
= aCodeNameIndex
- CODE_NAME_INDEX_Digit0
;
1504 aCodeName
.AssignLiteral(u
"Digit");
1505 aCodeName
.AppendInt(index
);
1508 if (aCodeNameIndex
>= CODE_NAME_INDEX_Numpad0
&&
1509 aCodeNameIndex
<= CODE_NAME_INDEX_Numpad9
) {
1510 uint32_t index
= aCodeNameIndex
- CODE_NAME_INDEX_Numpad0
;
1511 aCodeName
.AssignLiteral(u
"Numpad");
1512 aCodeName
.AppendInt(index
);
1515 if (aCodeNameIndex
>= CODE_NAME_INDEX_F1
&&
1516 aCodeNameIndex
<= CODE_NAME_INDEX_F24
) {
1517 uint32_t index
= aCodeNameIndex
- CODE_NAME_INDEX_F1
;
1518 aCodeName
.Assign(u
'F');
1519 aCodeName
.AppendInt(index
+ 1);
1523 aCodeName
= kCodeNames
[aCodeNameIndex
];
1527 KeyNameIndex
WidgetKeyboardEvent::GetKeyNameIndex(const nsAString
& aKeyValue
) {
1528 if (!sKeyNameIndexHashtable
) {
1529 sKeyNameIndexHashtable
= new KeyNameIndexHashtable(std::size(kKeyNames
));
1530 for (size_t i
= 0; i
< std::size(kKeyNames
); i
++) {
1531 sKeyNameIndexHashtable
->InsertOrUpdate(nsDependentString(kKeyNames
[i
]),
1532 static_cast<KeyNameIndex
>(i
));
1535 return sKeyNameIndexHashtable
->MaybeGet(aKeyValue
).valueOr(
1536 KEY_NAME_INDEX_USE_STRING
);
1540 CodeNameIndex
WidgetKeyboardEvent::GetCodeNameIndex(
1541 const nsAString
& aCodeValue
) {
1542 if (!sCodeNameIndexHashtable
) {
1543 sCodeNameIndexHashtable
= new CodeNameIndexHashtable(std::size(kCodeNames
));
1544 for (size_t i
= 0; i
< std::size(kCodeNames
); i
++) {
1545 sCodeNameIndexHashtable
->InsertOrUpdate(nsDependentString(kCodeNames
[i
]),
1546 static_cast<CodeNameIndex
>(i
));
1549 return sCodeNameIndexHashtable
->MaybeGet(aCodeValue
)
1550 .valueOr(CODE_NAME_INDEX_USE_STRING
);
1554 uint32_t WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(
1555 CodeNameIndex aCodeNameIndex
) {
1556 switch (aCodeNameIndex
) {
1557 case CODE_NAME_INDEX_Semicolon
: // VK_OEM_1 on Windows
1558 return dom::KeyboardEvent_Binding::DOM_VK_SEMICOLON
;
1559 case CODE_NAME_INDEX_Equal
: // VK_OEM_PLUS on Windows
1560 return dom::KeyboardEvent_Binding::DOM_VK_EQUALS
;
1561 case CODE_NAME_INDEX_Comma
: // VK_OEM_COMMA on Windows
1562 return dom::KeyboardEvent_Binding::DOM_VK_COMMA
;
1563 case CODE_NAME_INDEX_Minus
: // VK_OEM_MINUS on Windows
1564 return dom::KeyboardEvent_Binding::DOM_VK_HYPHEN_MINUS
;
1565 case CODE_NAME_INDEX_Period
: // VK_OEM_PERIOD on Windows
1566 return dom::KeyboardEvent_Binding::DOM_VK_PERIOD
;
1567 case CODE_NAME_INDEX_Slash
: // VK_OEM_2 on Windows
1568 return dom::KeyboardEvent_Binding::DOM_VK_SLASH
;
1569 case CODE_NAME_INDEX_Backquote
: // VK_OEM_3 on Windows
1570 return dom::KeyboardEvent_Binding::DOM_VK_BACK_QUOTE
;
1571 case CODE_NAME_INDEX_BracketLeft
: // VK_OEM_4 on Windows
1572 return dom::KeyboardEvent_Binding::DOM_VK_OPEN_BRACKET
;
1573 case CODE_NAME_INDEX_Backslash
: // VK_OEM_5 on Windows
1574 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH
;
1575 case CODE_NAME_INDEX_BracketRight
: // VK_OEM_6 on Windows
1576 return dom::KeyboardEvent_Binding::DOM_VK_CLOSE_BRACKET
;
1577 case CODE_NAME_INDEX_Quote
: // VK_OEM_7 on Windows
1578 return dom::KeyboardEvent_Binding::DOM_VK_QUOTE
;
1579 case CODE_NAME_INDEX_IntlBackslash
: // VK_OEM_5 on Windows (ABNT, etc)
1580 case CODE_NAME_INDEX_IntlYen
: // VK_OEM_5 on Windows (JIS)
1581 case CODE_NAME_INDEX_IntlRo
: // VK_OEM_102 on Windows
1582 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH
;
1588 /* static */ const char* WidgetKeyboardEvent::GetCommandStr(Command aCommand
) {
1589 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1590 #define NS_DEFINE_COMMAND_WITH_PARAM(aName, aCommandStr, aParam) , #aCommandStr
1591 #define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) , ""
1592 static const char* const kCommands
[] = {
1594 #include "mozilla/CommandList.h"
1596 #undef NS_DEFINE_COMMAND
1597 #undef NS_DEFINE_COMMAND_WITH_PARAM
1598 #undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
1600 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand
) < std::size(kCommands
),
1601 "Illegal command enumeration value");
1602 return kCommands
[static_cast<CommandInt
>(aCommand
)];
1606 uint32_t WidgetKeyboardEvent::ComputeLocationFromCodeValue(
1607 CodeNameIndex aCodeNameIndex
) {
1608 // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1609 // but are defined by D3E spec. So, they should be uncommented when the
1610 // code values are defined in the header.
1611 switch (aCodeNameIndex
) {
1612 case CODE_NAME_INDEX_AltLeft
:
1613 case CODE_NAME_INDEX_ControlLeft
:
1614 case CODE_NAME_INDEX_MetaLeft
:
1615 case CODE_NAME_INDEX_ShiftLeft
:
1616 return eKeyLocationLeft
;
1617 case CODE_NAME_INDEX_AltRight
:
1618 case CODE_NAME_INDEX_ControlRight
:
1619 case CODE_NAME_INDEX_MetaRight
:
1620 case CODE_NAME_INDEX_ShiftRight
:
1621 return eKeyLocationRight
;
1622 case CODE_NAME_INDEX_Numpad0
:
1623 case CODE_NAME_INDEX_Numpad1
:
1624 case CODE_NAME_INDEX_Numpad2
:
1625 case CODE_NAME_INDEX_Numpad3
:
1626 case CODE_NAME_INDEX_Numpad4
:
1627 case CODE_NAME_INDEX_Numpad5
:
1628 case CODE_NAME_INDEX_Numpad6
:
1629 case CODE_NAME_INDEX_Numpad7
:
1630 case CODE_NAME_INDEX_Numpad8
:
1631 case CODE_NAME_INDEX_Numpad9
:
1632 case CODE_NAME_INDEX_NumpadAdd
:
1633 case CODE_NAME_INDEX_NumpadBackspace
:
1634 case CODE_NAME_INDEX_NumpadClear
:
1635 case CODE_NAME_INDEX_NumpadClearEntry
:
1636 case CODE_NAME_INDEX_NumpadComma
:
1637 case CODE_NAME_INDEX_NumpadDecimal
:
1638 case CODE_NAME_INDEX_NumpadDivide
:
1639 case CODE_NAME_INDEX_NumpadEnter
:
1640 case CODE_NAME_INDEX_NumpadEqual
:
1641 case CODE_NAME_INDEX_NumpadMemoryAdd
:
1642 case CODE_NAME_INDEX_NumpadMemoryClear
:
1643 case CODE_NAME_INDEX_NumpadMemoryRecall
:
1644 case CODE_NAME_INDEX_NumpadMemoryStore
:
1645 case CODE_NAME_INDEX_NumpadMemorySubtract
:
1646 case CODE_NAME_INDEX_NumpadMultiply
:
1647 case CODE_NAME_INDEX_NumpadParenLeft
:
1648 case CODE_NAME_INDEX_NumpadParenRight
:
1649 case CODE_NAME_INDEX_NumpadSubtract
:
1650 return eKeyLocationNumpad
;
1652 return eKeyLocationStandard
;
1657 uint32_t WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(
1658 KeyNameIndex aKeyNameIndex
) {
1659 switch (aKeyNameIndex
) {
1660 case KEY_NAME_INDEX_Cancel
:
1661 return dom::KeyboardEvent_Binding::DOM_VK_CANCEL
;
1662 case KEY_NAME_INDEX_Help
:
1663 return dom::KeyboardEvent_Binding::DOM_VK_HELP
;
1664 case KEY_NAME_INDEX_Backspace
:
1665 return dom::KeyboardEvent_Binding::DOM_VK_BACK_SPACE
;
1666 case KEY_NAME_INDEX_Tab
:
1667 return dom::KeyboardEvent_Binding::DOM_VK_TAB
;
1668 case KEY_NAME_INDEX_Clear
:
1669 return dom::KeyboardEvent_Binding::DOM_VK_CLEAR
;
1670 case KEY_NAME_INDEX_Enter
:
1671 return dom::KeyboardEvent_Binding::DOM_VK_RETURN
;
1672 case KEY_NAME_INDEX_Shift
:
1673 return dom::KeyboardEvent_Binding::DOM_VK_SHIFT
;
1674 case KEY_NAME_INDEX_Control
:
1675 return dom::KeyboardEvent_Binding::DOM_VK_CONTROL
;
1676 case KEY_NAME_INDEX_Alt
:
1677 return dom::KeyboardEvent_Binding::DOM_VK_ALT
;
1678 case KEY_NAME_INDEX_Pause
:
1679 return dom::KeyboardEvent_Binding::DOM_VK_PAUSE
;
1680 case KEY_NAME_INDEX_CapsLock
:
1681 return dom::KeyboardEvent_Binding::DOM_VK_CAPS_LOCK
;
1682 case KEY_NAME_INDEX_Hiragana
:
1683 case KEY_NAME_INDEX_Katakana
:
1684 case KEY_NAME_INDEX_HiraganaKatakana
:
1685 case KEY_NAME_INDEX_KanaMode
:
1686 return dom::KeyboardEvent_Binding::DOM_VK_KANA
;
1687 case KEY_NAME_INDEX_HangulMode
:
1688 return dom::KeyboardEvent_Binding::DOM_VK_HANGUL
;
1689 case KEY_NAME_INDEX_Eisu
:
1690 return dom::KeyboardEvent_Binding::DOM_VK_EISU
;
1691 case KEY_NAME_INDEX_JunjaMode
:
1692 return dom::KeyboardEvent_Binding::DOM_VK_JUNJA
;
1693 case KEY_NAME_INDEX_FinalMode
:
1694 return dom::KeyboardEvent_Binding::DOM_VK_FINAL
;
1695 case KEY_NAME_INDEX_HanjaMode
:
1696 return dom::KeyboardEvent_Binding::DOM_VK_HANJA
;
1697 case KEY_NAME_INDEX_KanjiMode
:
1698 return dom::KeyboardEvent_Binding::DOM_VK_KANJI
;
1699 case KEY_NAME_INDEX_Escape
:
1700 return dom::KeyboardEvent_Binding::DOM_VK_ESCAPE
;
1701 case KEY_NAME_INDEX_Convert
:
1702 return dom::KeyboardEvent_Binding::DOM_VK_CONVERT
;
1703 case KEY_NAME_INDEX_NonConvert
:
1704 return dom::KeyboardEvent_Binding::DOM_VK_NONCONVERT
;
1705 case KEY_NAME_INDEX_Accept
:
1706 return dom::KeyboardEvent_Binding::DOM_VK_ACCEPT
;
1707 case KEY_NAME_INDEX_ModeChange
:
1708 return dom::KeyboardEvent_Binding::DOM_VK_MODECHANGE
;
1709 case KEY_NAME_INDEX_PageUp
:
1710 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_UP
;
1711 case KEY_NAME_INDEX_PageDown
:
1712 return dom::KeyboardEvent_Binding::DOM_VK_PAGE_DOWN
;
1713 case KEY_NAME_INDEX_End
:
1714 return dom::KeyboardEvent_Binding::DOM_VK_END
;
1715 case KEY_NAME_INDEX_Home
:
1716 return dom::KeyboardEvent_Binding::DOM_VK_HOME
;
1717 case KEY_NAME_INDEX_ArrowLeft
:
1718 return dom::KeyboardEvent_Binding::DOM_VK_LEFT
;
1719 case KEY_NAME_INDEX_ArrowUp
:
1720 return dom::KeyboardEvent_Binding::DOM_VK_UP
;
1721 case KEY_NAME_INDEX_ArrowRight
:
1722 return dom::KeyboardEvent_Binding::DOM_VK_RIGHT
;
1723 case KEY_NAME_INDEX_ArrowDown
:
1724 return dom::KeyboardEvent_Binding::DOM_VK_DOWN
;
1725 case KEY_NAME_INDEX_Select
:
1726 return dom::KeyboardEvent_Binding::DOM_VK_SELECT
;
1727 case KEY_NAME_INDEX_Print
:
1728 return dom::KeyboardEvent_Binding::DOM_VK_PRINT
;
1729 case KEY_NAME_INDEX_Execute
:
1730 return dom::KeyboardEvent_Binding::DOM_VK_EXECUTE
;
1731 case KEY_NAME_INDEX_PrintScreen
:
1732 return dom::KeyboardEvent_Binding::DOM_VK_PRINTSCREEN
;
1733 case KEY_NAME_INDEX_Insert
:
1734 return dom::KeyboardEvent_Binding::DOM_VK_INSERT
;
1735 case KEY_NAME_INDEX_Delete
:
1736 return dom::KeyboardEvent_Binding::DOM_VK_DELETE
;
1737 case KEY_NAME_INDEX_ContextMenu
:
1738 return dom::KeyboardEvent_Binding::DOM_VK_CONTEXT_MENU
;
1739 case KEY_NAME_INDEX_Standby
:
1740 return dom::KeyboardEvent_Binding::DOM_VK_SLEEP
;
1741 case KEY_NAME_INDEX_F1
:
1742 return dom::KeyboardEvent_Binding::DOM_VK_F1
;
1743 case KEY_NAME_INDEX_F2
:
1744 return dom::KeyboardEvent_Binding::DOM_VK_F2
;
1745 case KEY_NAME_INDEX_F3
:
1746 return dom::KeyboardEvent_Binding::DOM_VK_F3
;
1747 case KEY_NAME_INDEX_F4
:
1748 return dom::KeyboardEvent_Binding::DOM_VK_F4
;
1749 case KEY_NAME_INDEX_F5
:
1750 return dom::KeyboardEvent_Binding::DOM_VK_F5
;
1751 case KEY_NAME_INDEX_F6
:
1752 return dom::KeyboardEvent_Binding::DOM_VK_F6
;
1753 case KEY_NAME_INDEX_F7
:
1754 return dom::KeyboardEvent_Binding::DOM_VK_F7
;
1755 case KEY_NAME_INDEX_F8
:
1756 return dom::KeyboardEvent_Binding::DOM_VK_F8
;
1757 case KEY_NAME_INDEX_F9
:
1758 return dom::KeyboardEvent_Binding::DOM_VK_F9
;
1759 case KEY_NAME_INDEX_F10
:
1760 return dom::KeyboardEvent_Binding::DOM_VK_F10
;
1761 case KEY_NAME_INDEX_F11
:
1762 return dom::KeyboardEvent_Binding::DOM_VK_F11
;
1763 case KEY_NAME_INDEX_F12
:
1764 return dom::KeyboardEvent_Binding::DOM_VK_F12
;
1765 case KEY_NAME_INDEX_F13
:
1766 return dom::KeyboardEvent_Binding::DOM_VK_F13
;
1767 case KEY_NAME_INDEX_F14
:
1768 return dom::KeyboardEvent_Binding::DOM_VK_F14
;
1769 case KEY_NAME_INDEX_F15
:
1770 return dom::KeyboardEvent_Binding::DOM_VK_F15
;
1771 case KEY_NAME_INDEX_F16
:
1772 return dom::KeyboardEvent_Binding::DOM_VK_F16
;
1773 case KEY_NAME_INDEX_F17
:
1774 return dom::KeyboardEvent_Binding::DOM_VK_F17
;
1775 case KEY_NAME_INDEX_F18
:
1776 return dom::KeyboardEvent_Binding::DOM_VK_F18
;
1777 case KEY_NAME_INDEX_F19
:
1778 return dom::KeyboardEvent_Binding::DOM_VK_F19
;
1779 case KEY_NAME_INDEX_F20
:
1780 return dom::KeyboardEvent_Binding::DOM_VK_F20
;
1781 case KEY_NAME_INDEX_F21
:
1782 return dom::KeyboardEvent_Binding::DOM_VK_F21
;
1783 case KEY_NAME_INDEX_F22
:
1784 return dom::KeyboardEvent_Binding::DOM_VK_F22
;
1785 case KEY_NAME_INDEX_F23
:
1786 return dom::KeyboardEvent_Binding::DOM_VK_F23
;
1787 case KEY_NAME_INDEX_F24
:
1788 return dom::KeyboardEvent_Binding::DOM_VK_F24
;
1789 case KEY_NAME_INDEX_NumLock
:
1790 return dom::KeyboardEvent_Binding::DOM_VK_NUM_LOCK
;
1791 case KEY_NAME_INDEX_ScrollLock
:
1792 return dom::KeyboardEvent_Binding::DOM_VK_SCROLL_LOCK
;
1793 case KEY_NAME_INDEX_AudioVolumeMute
:
1794 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_MUTE
;
1795 case KEY_NAME_INDEX_AudioVolumeDown
:
1796 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_DOWN
;
1797 case KEY_NAME_INDEX_AudioVolumeUp
:
1798 return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_UP
;
1799 case KEY_NAME_INDEX_Meta
:
1800 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
1801 return dom::KeyboardEvent_Binding::DOM_VK_WIN
;
1803 return dom::KeyboardEvent_Binding::DOM_VK_META
;
1805 case KEY_NAME_INDEX_AltGraph
:
1806 return dom::KeyboardEvent_Binding::DOM_VK_ALTGR
;
1807 case KEY_NAME_INDEX_Process
:
1808 return dom::KeyboardEvent_Binding::DOM_VK_PROCESSKEY
;
1809 case KEY_NAME_INDEX_Attn
:
1810 return dom::KeyboardEvent_Binding::DOM_VK_ATTN
;
1811 case KEY_NAME_INDEX_CrSel
:
1812 return dom::KeyboardEvent_Binding::DOM_VK_CRSEL
;
1813 case KEY_NAME_INDEX_ExSel
:
1814 return dom::KeyboardEvent_Binding::DOM_VK_EXSEL
;
1815 case KEY_NAME_INDEX_EraseEof
:
1816 return dom::KeyboardEvent_Binding::DOM_VK_EREOF
;
1817 case KEY_NAME_INDEX_Play
:
1818 return dom::KeyboardEvent_Binding::DOM_VK_PLAY
;
1819 case KEY_NAME_INDEX_ZoomToggle
:
1820 case KEY_NAME_INDEX_ZoomIn
:
1821 case KEY_NAME_INDEX_ZoomOut
:
1822 return dom::KeyboardEvent_Binding::DOM_VK_ZOOM
;
1829 CodeNameIndex
WidgetKeyboardEvent::ComputeCodeNameIndexFromKeyNameIndex(
1830 KeyNameIndex aKeyNameIndex
, const Maybe
<uint32_t>& aLocation
) {
1831 if (aLocation
.isSome() &&
1832 aLocation
.value() ==
1833 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_NUMPAD
) {
1834 // On macOS, NumLock is not supported. Therefore, this handles
1835 // control key values except "Enter" only on non-macOS platforms.
1836 switch (aKeyNameIndex
) {
1838 case KEY_NAME_INDEX_Insert
:
1839 return CODE_NAME_INDEX_Numpad0
;
1840 case KEY_NAME_INDEX_End
:
1841 return CODE_NAME_INDEX_Numpad1
;
1842 case KEY_NAME_INDEX_ArrowDown
:
1843 return CODE_NAME_INDEX_Numpad2
;
1844 case KEY_NAME_INDEX_PageDown
:
1845 return CODE_NAME_INDEX_Numpad3
;
1846 case KEY_NAME_INDEX_ArrowLeft
:
1847 return CODE_NAME_INDEX_Numpad4
;
1848 case KEY_NAME_INDEX_Clear
:
1849 // FYI: "Clear" on macOS should be DOM_KEY_LOCATION_STANDARD.
1850 return CODE_NAME_INDEX_Numpad5
;
1851 case KEY_NAME_INDEX_ArrowRight
:
1852 return CODE_NAME_INDEX_Numpad6
;
1853 case KEY_NAME_INDEX_Home
:
1854 return CODE_NAME_INDEX_Numpad7
;
1855 case KEY_NAME_INDEX_ArrowUp
:
1856 return CODE_NAME_INDEX_Numpad8
;
1857 case KEY_NAME_INDEX_PageUp
:
1858 return CODE_NAME_INDEX_Numpad9
;
1859 case KEY_NAME_INDEX_Delete
:
1860 return CODE_NAME_INDEX_NumpadDecimal
;
1861 #endif // #ifndef XP_MACOSX
1862 case KEY_NAME_INDEX_Enter
:
1863 return CODE_NAME_INDEX_NumpadEnter
;
1865 return CODE_NAME_INDEX_UNKNOWN
;
1869 if (WidgetKeyboardEvent::IsLeftOrRightModiferKeyNameIndex(aKeyNameIndex
)) {
1870 if (aLocation
.isSome() &&
1871 (aLocation
.value() !=
1872 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_LEFT
&&
1873 aLocation
.value() !=
1874 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT
)) {
1875 return CODE_NAME_INDEX_UNKNOWN
;
1878 aLocation
.isSome() &&
1879 aLocation
.value() == dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT
;
1880 switch (aKeyNameIndex
) {
1881 case KEY_NAME_INDEX_Alt
:
1882 return isRight
? CODE_NAME_INDEX_AltRight
: CODE_NAME_INDEX_AltLeft
;
1883 case KEY_NAME_INDEX_Control
:
1884 return isRight
? CODE_NAME_INDEX_ControlRight
1885 : CODE_NAME_INDEX_ControlLeft
;
1886 case KEY_NAME_INDEX_Shift
:
1887 return isRight
? CODE_NAME_INDEX_ShiftRight
: CODE_NAME_INDEX_ShiftLeft
;
1888 case KEY_NAME_INDEX_Meta
:
1889 return isRight
? CODE_NAME_INDEX_MetaRight
: CODE_NAME_INDEX_MetaLeft
;
1891 return CODE_NAME_INDEX_UNKNOWN
;
1895 if (aLocation
.isSome() &&
1896 aLocation
.value() !=
1897 dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_STANDARD
) {
1898 return CODE_NAME_INDEX_UNKNOWN
;
1901 switch (aKeyNameIndex
) {
1902 // Standard section:
1903 case KEY_NAME_INDEX_Escape
:
1904 return CODE_NAME_INDEX_Escape
;
1905 case KEY_NAME_INDEX_Tab
:
1906 return CODE_NAME_INDEX_Tab
;
1907 case KEY_NAME_INDEX_CapsLock
:
1908 return CODE_NAME_INDEX_CapsLock
;
1909 case KEY_NAME_INDEX_ContextMenu
:
1910 return CODE_NAME_INDEX_ContextMenu
;
1911 case KEY_NAME_INDEX_Backspace
:
1912 return CODE_NAME_INDEX_Backspace
;
1913 case KEY_NAME_INDEX_Enter
:
1914 return CODE_NAME_INDEX_Enter
;
1916 // Although, macOS does not fire native key event of "Fn" key, we support
1917 // Fn key event if it's sent by other apps directly.
1918 case KEY_NAME_INDEX_Fn
:
1919 return CODE_NAME_INDEX_Fn
;
1922 // Arrow Pad section:
1923 case KEY_NAME_INDEX_ArrowLeft
:
1924 return CODE_NAME_INDEX_ArrowLeft
;
1925 case KEY_NAME_INDEX_ArrowUp
:
1926 return CODE_NAME_INDEX_ArrowUp
;
1927 case KEY_NAME_INDEX_ArrowDown
:
1928 return CODE_NAME_INDEX_ArrowDown
;
1929 case KEY_NAME_INDEX_ArrowRight
:
1930 return CODE_NAME_INDEX_ArrowRight
;
1932 // Control Pad section:
1934 case KEY_NAME_INDEX_Insert
:
1935 return CODE_NAME_INDEX_Insert
;
1937 case KEY_NAME_INDEX_Help
:
1938 return CODE_NAME_INDEX_Help
;
1939 #endif // #ifndef XP_MACOSX #else
1940 case KEY_NAME_INDEX_Delete
:
1941 return CODE_NAME_INDEX_Delete
;
1942 case KEY_NAME_INDEX_Home
:
1943 return CODE_NAME_INDEX_Home
;
1944 case KEY_NAME_INDEX_End
:
1945 return CODE_NAME_INDEX_End
;
1946 case KEY_NAME_INDEX_PageUp
:
1947 return CODE_NAME_INDEX_PageUp
;
1948 case KEY_NAME_INDEX_PageDown
:
1949 return CODE_NAME_INDEX_PageDown
;
1952 case KEY_NAME_INDEX_F1
:
1953 return CODE_NAME_INDEX_F1
;
1954 case KEY_NAME_INDEX_F2
:
1955 return CODE_NAME_INDEX_F2
;
1956 case KEY_NAME_INDEX_F3
:
1957 return CODE_NAME_INDEX_F3
;
1958 case KEY_NAME_INDEX_F4
:
1959 return CODE_NAME_INDEX_F4
;
1960 case KEY_NAME_INDEX_F5
:
1961 return CODE_NAME_INDEX_F5
;
1962 case KEY_NAME_INDEX_F6
:
1963 return CODE_NAME_INDEX_F6
;
1964 case KEY_NAME_INDEX_F7
:
1965 return CODE_NAME_INDEX_F7
;
1966 case KEY_NAME_INDEX_F8
:
1967 return CODE_NAME_INDEX_F8
;
1968 case KEY_NAME_INDEX_F9
:
1969 return CODE_NAME_INDEX_F9
;
1970 case KEY_NAME_INDEX_F10
:
1971 return CODE_NAME_INDEX_F10
;
1972 case KEY_NAME_INDEX_F11
:
1973 return CODE_NAME_INDEX_F11
;
1974 case KEY_NAME_INDEX_F12
:
1975 return CODE_NAME_INDEX_F12
;
1976 case KEY_NAME_INDEX_F13
:
1977 return CODE_NAME_INDEX_F13
;
1978 case KEY_NAME_INDEX_F14
:
1979 return CODE_NAME_INDEX_F14
;
1980 case KEY_NAME_INDEX_F15
:
1981 return CODE_NAME_INDEX_F15
;
1982 case KEY_NAME_INDEX_F16
:
1983 return CODE_NAME_INDEX_F16
;
1984 case KEY_NAME_INDEX_F17
:
1985 return CODE_NAME_INDEX_F17
;
1986 case KEY_NAME_INDEX_F18
:
1987 return CODE_NAME_INDEX_F18
;
1988 case KEY_NAME_INDEX_F19
:
1989 return CODE_NAME_INDEX_F19
;
1990 case KEY_NAME_INDEX_F20
:
1991 return CODE_NAME_INDEX_F20
;
1993 case KEY_NAME_INDEX_F21
:
1994 return CODE_NAME_INDEX_F21
;
1995 case KEY_NAME_INDEX_F22
:
1996 return CODE_NAME_INDEX_F22
;
1997 case KEY_NAME_INDEX_F23
:
1998 return CODE_NAME_INDEX_F23
;
1999 case KEY_NAME_INDEX_F24
:
2000 return CODE_NAME_INDEX_F24
;
2001 case KEY_NAME_INDEX_Pause
:
2002 return CODE_NAME_INDEX_Pause
;
2003 case KEY_NAME_INDEX_PrintScreen
:
2004 return CODE_NAME_INDEX_PrintScreen
;
2005 case KEY_NAME_INDEX_ScrollLock
:
2006 return CODE_NAME_INDEX_ScrollLock
;
2007 #endif // #ifndef XP_MACOSX
2011 case KEY_NAME_INDEX_NumLock
:
2012 return CODE_NAME_INDEX_NumLock
;
2014 case KEY_NAME_INDEX_Clear
:
2015 return CODE_NAME_INDEX_NumLock
;
2016 #endif // #ifndef XP_MACOSX #else
2019 case KEY_NAME_INDEX_AudioVolumeDown
:
2020 return CODE_NAME_INDEX_VolumeDown
;
2021 case KEY_NAME_INDEX_AudioVolumeMute
:
2022 return CODE_NAME_INDEX_VolumeMute
;
2023 case KEY_NAME_INDEX_AudioVolumeUp
:
2024 return CODE_NAME_INDEX_VolumeUp
;
2026 case KEY_NAME_INDEX_BrowserBack
:
2027 return CODE_NAME_INDEX_BrowserBack
;
2028 case KEY_NAME_INDEX_BrowserFavorites
:
2029 return CODE_NAME_INDEX_BrowserFavorites
;
2030 case KEY_NAME_INDEX_BrowserForward
:
2031 return CODE_NAME_INDEX_BrowserForward
;
2032 case KEY_NAME_INDEX_BrowserRefresh
:
2033 return CODE_NAME_INDEX_BrowserRefresh
;
2034 case KEY_NAME_INDEX_BrowserSearch
:
2035 return CODE_NAME_INDEX_BrowserSearch
;
2036 case KEY_NAME_INDEX_BrowserStop
:
2037 return CODE_NAME_INDEX_BrowserStop
;
2038 case KEY_NAME_INDEX_MediaPlayPause
:
2039 return CODE_NAME_INDEX_MediaPlayPause
;
2040 case KEY_NAME_INDEX_MediaStop
:
2041 return CODE_NAME_INDEX_MediaStop
;
2042 case KEY_NAME_INDEX_MediaTrackNext
:
2043 return CODE_NAME_INDEX_MediaTrackNext
;
2044 case KEY_NAME_INDEX_MediaTrackPrevious
:
2045 return CODE_NAME_INDEX_MediaTrackPrevious
;
2046 case KEY_NAME_INDEX_LaunchApplication1
:
2047 return CODE_NAME_INDEX_LaunchApp1
;
2048 #endif // #ifndef XP_MACOSX
2050 // Only Windows and GTK supports the following multimedia keys.
2051 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
2052 case KEY_NAME_INDEX_BrowserHome
:
2053 return CODE_NAME_INDEX_BrowserHome
;
2054 case KEY_NAME_INDEX_LaunchApplication2
:
2055 return CODE_NAME_INDEX_LaunchApp2
;
2056 #endif // #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
2058 // Only GTK and Android supports the following multimedia keys.
2059 #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
2060 case KEY_NAME_INDEX_Eject
:
2061 return CODE_NAME_INDEX_Eject
;
2062 case KEY_NAME_INDEX_WakeUp
:
2063 return CODE_NAME_INDEX_WakeUp
;
2064 #endif // #if defined(MOZ_WIDGET_GTK) || defined(ANDROID)
2066 // Only Windows does not support Help key (and macOS handled above).
2067 #if !defined(XP_WIN) && !defined(XP_MACOSX)
2068 case KEY_NAME_INDEX_Help
:
2069 return CODE_NAME_INDEX_Help
;
2070 #endif // #if !defined(XP_WIN) && !defined(XP_MACOSX)
2072 // IME specific keys:
2074 case KEY_NAME_INDEX_Convert
:
2075 return CODE_NAME_INDEX_Convert
;
2076 case KEY_NAME_INDEX_NonConvert
:
2077 return CODE_NAME_INDEX_NonConvert
;
2078 case KEY_NAME_INDEX_Alphanumeric
:
2079 return CODE_NAME_INDEX_CapsLock
;
2080 case KEY_NAME_INDEX_KanaMode
:
2081 case KEY_NAME_INDEX_Romaji
:
2082 case KEY_NAME_INDEX_Katakana
:
2083 case KEY_NAME_INDEX_Hiragana
:
2084 return CODE_NAME_INDEX_KanaMode
;
2085 case KEY_NAME_INDEX_Hankaku
:
2086 case KEY_NAME_INDEX_Zenkaku
:
2087 case KEY_NAME_INDEX_KanjiMode
:
2088 return CODE_NAME_INDEX_Backquote
;
2089 case KEY_NAME_INDEX_HanjaMode
:
2090 return CODE_NAME_INDEX_Lang2
;
2091 case KEY_NAME_INDEX_HangulMode
:
2092 return CODE_NAME_INDEX_Lang1
;
2093 #endif // #ifdef XP_WIN
2095 #ifdef MOZ_WIDGET_GTK
2096 case KEY_NAME_INDEX_Convert
:
2097 return CODE_NAME_INDEX_Convert
;
2098 case KEY_NAME_INDEX_NonConvert
:
2099 return CODE_NAME_INDEX_NonConvert
;
2100 case KEY_NAME_INDEX_Alphanumeric
:
2101 return CODE_NAME_INDEX_CapsLock
;
2102 case KEY_NAME_INDEX_HiraganaKatakana
:
2103 return CODE_NAME_INDEX_KanaMode
;
2104 case KEY_NAME_INDEX_ZenkakuHankaku
:
2105 return CODE_NAME_INDEX_Backquote
;
2106 #endif // #ifdef MOZ_WIDGET_GTK
2109 case KEY_NAME_INDEX_Convert
:
2110 return CODE_NAME_INDEX_Convert
;
2111 case KEY_NAME_INDEX_NonConvert
:
2112 return CODE_NAME_INDEX_NonConvert
;
2113 case KEY_NAME_INDEX_HiraganaKatakana
:
2114 return CODE_NAME_INDEX_KanaMode
;
2115 case KEY_NAME_INDEX_ZenkakuHankaku
:
2116 return CODE_NAME_INDEX_Backquote
;
2117 case KEY_NAME_INDEX_Eisu
:
2118 return CODE_NAME_INDEX_Lang2
;
2119 case KEY_NAME_INDEX_KanjiMode
:
2120 return CODE_NAME_INDEX_Lang1
;
2121 #endif // #ifdef ANDROID
2124 case KEY_NAME_INDEX_Eisu
:
2125 return CODE_NAME_INDEX_Lang2
;
2126 case KEY_NAME_INDEX_KanjiMode
:
2127 return CODE_NAME_INDEX_Lang1
;
2128 #endif // #ifdef XP_MACOSX
2131 return CODE_NAME_INDEX_UNKNOWN
;
2136 Modifier
WidgetKeyboardEvent::GetModifierForKeyName(
2137 KeyNameIndex aKeyNameIndex
) {
2138 switch (aKeyNameIndex
) {
2139 case KEY_NAME_INDEX_Alt
:
2140 return MODIFIER_ALT
;
2141 case KEY_NAME_INDEX_AltGraph
:
2142 return MODIFIER_ALTGRAPH
;
2143 case KEY_NAME_INDEX_CapsLock
:
2144 return MODIFIER_CAPSLOCK
;
2145 case KEY_NAME_INDEX_Control
:
2146 return MODIFIER_CONTROL
;
2147 case KEY_NAME_INDEX_Fn
:
2149 case KEY_NAME_INDEX_FnLock
:
2150 return MODIFIER_FNLOCK
;
2151 // case KEY_NAME_INDEX_Hyper:
2152 case KEY_NAME_INDEX_Meta
:
2153 return MODIFIER_META
;
2154 case KEY_NAME_INDEX_NumLock
:
2155 return MODIFIER_NUMLOCK
;
2156 case KEY_NAME_INDEX_ScrollLock
:
2157 return MODIFIER_SCROLLLOCK
;
2158 case KEY_NAME_INDEX_Shift
:
2159 return MODIFIER_SHIFT
;
2160 // case KEY_NAME_INDEX_Super:
2161 case KEY_NAME_INDEX_Symbol
:
2162 return MODIFIER_SYMBOL
;
2163 case KEY_NAME_INDEX_SymbolLock
:
2164 return MODIFIER_SYMBOLLOCK
;
2166 return MODIFIER_NONE
;
2171 bool WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex
) {
2172 switch (aKeyNameIndex
) {
2173 case KEY_NAME_INDEX_CapsLock
:
2174 case KEY_NAME_INDEX_FnLock
:
2175 case KEY_NAME_INDEX_NumLock
:
2176 case KEY_NAME_INDEX_ScrollLock
:
2177 case KEY_NAME_INDEX_SymbolLock
:
2184 /******************************************************************************
2185 * mozilla::InternalEditorInputEvent (TextEvents.h)
2186 ******************************************************************************/
2188 #define NS_DEFINE_INPUTTYPE(aCPPName, aDOMName) (u"" aDOMName),
2189 const char16_t
* const InternalEditorInputEvent::kInputTypeNames
[] = {
2190 #include "mozilla/InputTypeList.h"
2192 #undef NS_DEFINE_INPUTTYPE
2194 InternalEditorInputEvent::InputTypeHashtable
*
2195 InternalEditorInputEvent::sInputTypeHashtable
= nullptr;
2198 void InternalEditorInputEvent::Shutdown() {
2199 delete sInputTypeHashtable
;
2200 sInputTypeHashtable
= nullptr;
2204 void InternalEditorInputEvent::GetDOMInputTypeName(EditorInputType aInputType
,
2205 nsAString
& aInputTypeName
) {
2206 if (static_cast<size_t>(aInputType
) >=
2207 static_cast<size_t>(EditorInputType::eUnknown
)) {
2208 aInputTypeName
.Truncate();
2213 static_cast<size_t>(aInputType
) < std::size(kInputTypeNames
),
2214 "Illegal input type enumeration value");
2215 aInputTypeName
.Assign(kInputTypeNames
[static_cast<size_t>(aInputType
)]);
2219 EditorInputType
InternalEditorInputEvent::GetEditorInputType(
2220 const nsAString
& aInputType
) {
2221 if (aInputType
.IsEmpty()) {
2222 return EditorInputType::eUnknown
;
2225 if (!sInputTypeHashtable
) {
2226 sInputTypeHashtable
= new InputTypeHashtable(std::size(kInputTypeNames
));
2227 for (size_t i
= 0; i
< std::size(kInputTypeNames
); i
++) {
2228 sInputTypeHashtable
->InsertOrUpdate(nsDependentString(kInputTypeNames
[i
]),
2229 static_cast<EditorInputType
>(i
));
2232 return sInputTypeHashtable
->MaybeGet(aInputType
)
2233 .valueOr(EditorInputType::eUnknown
);
2236 } // namespace mozilla