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/. */
7 #include "mozilla/BasicEvents.h"
8 #include "mozilla/ContentEvents.h"
9 #include "mozilla/EventStateManager.h"
10 #include "mozilla/InternalMutationEvent.h"
11 #include "mozilla/MiscEvents.h"
12 #include "mozilla/MouseEvents.h"
13 #include "mozilla/Preferences.h"
14 #include "mozilla/TextEvents.h"
15 #include "mozilla/TouchEvents.h"
16 #include "nsIContent.h"
17 #include "nsIDOMEventTarget.h"
18 #include "nsPrintfCString.h"
22 /******************************************************************************
23 * Global helper methods
24 ******************************************************************************/
27 ToChar(EventMessage aEventMessage
)
29 switch (aEventMessage
) {
31 #define NS_EVENT_MESSAGE(aMessage) \
35 #include "mozilla/EventMessageList.h"
37 #undef NS_EVENT_MESSAGE
39 return "illegal event message";
44 ToChar(EventClassID aEventClassID
)
46 switch (aEventClassID
) {
48 #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
49 case eBasic##aName##Class: \
50 return "eBasic" #aName "Class";
52 #define NS_EVENT_CLASS(aPrefix, aName) \
53 case e##aName##Class: \
54 return "e" #aName "Class";
56 #include "mozilla/EventClassList.h"
59 #undef NS_ROOT_EVENT_CLASS
61 return "illegal event class ID";
66 ToString(KeyNameIndex aKeyNameIndex
)
68 if (aKeyNameIndex
== KEY_NAME_INDEX_USE_STRING
) {
69 return NS_LITERAL_CSTRING("USE_STRING");
72 WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex
, keyName
);
73 return NS_ConvertUTF16toUTF8(keyName
);
77 ToString(CodeNameIndex aCodeNameIndex
)
79 if (aCodeNameIndex
== CODE_NAME_INDEX_USE_STRING
) {
80 return NS_LITERAL_CSTRING("USE_STRING");
82 nsAutoString codeName
;
83 WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex
, codeName
);
84 return NS_ConvertUTF16toUTF8(codeName
);
88 GetDOMKeyCodeName(uint32_t aKeyCode
)
91 #define NS_DISALLOW_SAME_KEYCODE
92 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
94 return NS_LITERAL_CSTRING(#aDOMKeyName);
96 #include "mozilla/VirtualKeyCodeList.h"
99 #undef NS_DISALLOW_SAME_KEYCODE
102 return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode
);
107 IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeType
)
109 switch (static_cast<TextRangeType
>(aRawTextRangeType
)) {
110 case TextRangeType::eUninitialized
:
111 case TextRangeType::eCaret
:
112 case TextRangeType::eRawClause
:
113 case TextRangeType::eSelectedRawClause
:
114 case TextRangeType::eConvertedClause
:
115 case TextRangeType::eSelectedClause
:
123 ToRawTextRangeType(TextRangeType aTextRangeType
)
125 return static_cast<RawTextRangeType
>(aTextRangeType
);
129 ToTextRangeType(RawTextRangeType aRawTextRangeType
)
131 MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType
));
132 return static_cast<TextRangeType
>(aRawTextRangeType
);
136 ToChar(TextRangeType aTextRangeType
)
138 switch (aTextRangeType
) {
139 case TextRangeType::eUninitialized
:
140 return "TextRangeType::eUninitialized";
141 case TextRangeType::eCaret
:
142 return "TextRangeType::eCaret";
143 case TextRangeType::eRawClause
:
144 return "TextRangeType::eRawClause";
145 case TextRangeType::eSelectedRawClause
:
146 return "TextRangeType::eSelectedRawClause";
147 case TextRangeType::eConvertedClause
:
148 return "TextRangeType::eConvertedClause";
149 case TextRangeType::eSelectedClause
:
150 return "TextRangeType::eSelectedClause";
152 return "Invalid TextRangeType";
157 ToSelectionType(TextRangeType aTextRangeType
)
159 switch (aTextRangeType
) {
160 case TextRangeType::eRawClause
:
161 return SelectionType::eIMERawClause
;
162 case TextRangeType::eSelectedRawClause
:
163 return SelectionType::eIMESelectedRawClause
;
164 case TextRangeType::eConvertedClause
:
165 return SelectionType::eIMEConvertedClause
;
166 case TextRangeType::eSelectedClause
:
167 return SelectionType::eIMESelectedClause
;
169 MOZ_CRASH("TextRangeType is invalid");
170 return SelectionType::eNormal
;
174 /******************************************************************************
175 * As*Event() implementation
176 ******************************************************************************/
178 #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
179 #define NS_EVENT_CLASS(aPrefix, aName) \
181 WidgetEvent::As##aName() \
186 const aPrefix##aName* \
187 WidgetEvent::As##aName() const \
189 return const_cast<WidgetEvent*>(this)->As##aName(); \
192 #include "mozilla/EventClassList.h"
194 #undef NS_EVENT_CLASS
195 #undef NS_ROOT_EVENT_CLASS
197 /******************************************************************************
198 * mozilla::WidgetEvent
200 * Event struct type checking methods.
201 ******************************************************************************/
204 WidgetEvent::IsQueryContentEvent() const
206 return mClass
== eQueryContentEventClass
;
210 WidgetEvent::IsSelectionEvent() const
212 return mClass
== eSelectionEventClass
;
216 WidgetEvent::IsContentCommandEvent() const
218 return mClass
== eContentCommandEventClass
;
222 WidgetEvent::IsNativeEventDelivererForPlugin() const
224 return mClass
== ePluginEventClass
;
228 /******************************************************************************
229 * mozilla::WidgetEvent
231 * Event message checking methods.
232 ******************************************************************************/
235 WidgetEvent::HasMouseEventMessage() const
241 case eMouseDoubleClick
:
243 case eMouseEnterIntoWidget
:
244 case eMouseExitFromWidget
:
257 WidgetEvent::HasDragEventMessage() const
275 WidgetEvent::HasKeyEventMessage() const
281 case eKeyDownOnPlugin
:
283 case eAccessKeyNotFound
:
291 WidgetEvent::HasIMEEventMessage() const
294 case eCompositionStart
:
295 case eCompositionEnd
:
296 case eCompositionUpdate
:
297 case eCompositionChange
:
298 case eCompositionCommitAsIs
:
299 case eCompositionCommit
:
307 WidgetEvent::HasPluginActivationEventMessage() const
309 return mMessage
== ePluginActivate
||
310 mMessage
== ePluginFocus
;
313 /******************************************************************************
314 * mozilla::WidgetEvent
316 * Specific event checking methods.
317 ******************************************************************************/
320 WidgetEvent::CanBeSentToRemoteProcess() const
322 // If this event is explicitly marked as shouldn't be sent to remote process,
323 // just return false.
324 if (IsCrossProcessForwardingStopped()) {
328 if (mClass
== eKeyboardEventClass
||
329 mClass
== eWheelEventClass
) {
338 case eMouseEnterIntoWidget
:
339 case eMouseExitFromWidget
:
340 case eMouseTouchDrag
:
355 WidgetEvent::WillBeSentToRemoteProcess() const
357 // This event won't be posted to remote process if it's already explicitly
359 if (IsCrossProcessForwardingStopped()) {
363 // When mOriginalTarget is nullptr, this method shouldn't be used.
364 if (NS_WARN_IF(!mOriginalTarget
)) {
368 nsCOMPtr
<nsIContent
> originalTarget
= do_QueryInterface(mOriginalTarget
);
369 return EventStateManager::IsRemoteTarget(originalTarget
);
373 WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
375 const WidgetPluginEvent
* pluginEvent
= AsPluginEvent();
376 return pluginEvent
&& pluginEvent
->mRetargetToFocusedDocument
;
380 WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const
382 const WidgetPluginEvent
* pluginEvent
= AsPluginEvent();
383 return pluginEvent
&& !pluginEvent
->mRetargetToFocusedDocument
;
387 WidgetEvent::IsIMERelatedEvent() const
389 return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
393 WidgetEvent::IsUsingCoordinates() const
395 const WidgetMouseEvent
* mouseEvent
= AsMouseEvent();
397 return !mouseEvent
->IsContextMenuKeyEvent();
399 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
400 !HasPluginActivationEventMessage() &&
401 !IsNativeEventDelivererForPlugin() &&
402 !IsContentCommandEvent();
406 WidgetEvent::IsTargetedAtFocusedWindow() const
408 const WidgetMouseEvent
* mouseEvent
= AsMouseEvent();
410 return mouseEvent
->IsContextMenuKeyEvent();
412 return HasKeyEventMessage() || IsIMERelatedEvent() ||
413 IsContentCommandEvent() ||
414 IsRetargetedNativeEventDelivererForPlugin();
418 WidgetEvent::IsTargetedAtFocusedContent() const
420 const WidgetMouseEvent
* mouseEvent
= AsMouseEvent();
422 return mouseEvent
->IsContextMenuKeyEvent();
424 return HasKeyEventMessage() || IsIMERelatedEvent() ||
425 IsRetargetedNativeEventDelivererForPlugin();
429 WidgetEvent::IsAllowedToDispatchDOMEvent() const
432 case eMouseEventClass
:
433 // When content PreventDefault on ePointerDown, we will stop dispatching
434 // the subsequent mouse events (eMouseDown, eMouseUp, eMouseMove). But we
435 // still need the mouse events to be handled in EventStateManager to
436 // generate other events (e.g. eMouseClick). So we only stop dispatching
438 if (DefaultPreventedByContent() &&
439 (mMessage
== eMouseMove
|| mMessage
== eMouseDown
||
440 mMessage
== eMouseUp
)) {
443 if (mMessage
== eMouseTouchDrag
) {
447 case ePointerEventClass
:
448 // We want synthesized mouse moves to cause mouseover and mouseout
449 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
451 // Synthesized button up events also do not cause DOM events because they
452 // do not have a reliable mRefPoint.
453 return AsMouseEvent()->mReason
== WidgetMouseEvent::eReal
;
455 case eWheelEventClass
: {
456 // wheel event whose all delta values are zero by user pref applied, it
457 // shouldn't cause a DOM event.
458 const WidgetWheelEvent
* wheelEvent
= AsWheelEvent();
459 return wheelEvent
->mDeltaX
!= 0.0 || wheelEvent
->mDeltaY
!= 0.0 ||
460 wheelEvent
->mDeltaZ
!= 0.0;
462 case eTouchEventClass
:
463 return mMessage
!= eTouchPointerCancel
;
464 // Following events are handled in EventStateManager, so, we don't need to
465 // dispatch DOM event for them into the DOM tree.
466 case eQueryContentEventClass
:
467 case eSelectionEventClass
:
468 case eContentCommandEventClass
:
477 WidgetEvent::IsAllowedToDispatchInSystemGroup() const
479 // We don't expect to implement default behaviors with pointer events because
480 // if we do, prevent default on mouse events can't prevent default behaviors
482 return mClass
!= ePointerEventClass
;
485 /******************************************************************************
486 * mozilla::WidgetEvent
489 ******************************************************************************/
491 static dom::EventTarget
*
492 GetTargetForDOMEvent(nsIDOMEventTarget
* aTarget
)
494 return aTarget
? aTarget
->GetTargetForDOMEvent() : nullptr;
498 WidgetEvent::GetDOMEventTarget() const
500 return GetTargetForDOMEvent(mTarget
);
504 WidgetEvent::GetCurrentDOMEventTarget() const
506 return GetTargetForDOMEvent(mCurrentTarget
);
510 WidgetEvent::GetOriginalDOMEventTarget() const
512 if (mOriginalTarget
) {
513 return GetTargetForDOMEvent(mOriginalTarget
);
515 return GetDOMEventTarget();
518 /******************************************************************************
519 * mozilla::WidgetInputEvent
520 ******************************************************************************/
524 WidgetInputEvent::GetModifier(const nsAString
& aDOMKeyName
)
526 if (aDOMKeyName
.EqualsLiteral("Accel")) {
527 return AccelModifier();
529 KeyNameIndex keyNameIndex
= WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName
);
530 return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex
);
535 WidgetInputEvent::AccelModifier()
537 static Modifier sAccelModifier
= MODIFIER_NONE
;
538 if (sAccelModifier
== MODIFIER_NONE
) {
539 switch (Preferences::GetInt("ui.key.accelKey", 0)) {
540 case nsIDOMKeyEvent::DOM_VK_META
:
541 sAccelModifier
= MODIFIER_META
;
543 case nsIDOMKeyEvent::DOM_VK_WIN
:
544 sAccelModifier
= MODIFIER_OS
;
546 case nsIDOMKeyEvent::DOM_VK_ALT
:
547 sAccelModifier
= MODIFIER_ALT
;
549 case nsIDOMKeyEvent::DOM_VK_CONTROL
:
550 sAccelModifier
= MODIFIER_CONTROL
;
554 sAccelModifier
= MODIFIER_META
;
556 sAccelModifier
= MODIFIER_CONTROL
;
561 return sAccelModifier
;
564 /******************************************************************************
565 * mozilla::WidgetWheelEvent (MouseEvents.h)
566 ******************************************************************************/
569 WidgetWheelEvent::ComputeOverriddenDelta(double aDelta
, bool aIsForVertical
)
571 if (!gfxPrefs::MouseWheelHasRootScrollDeltaOverride()) {
574 int32_t intFactor
= aIsForVertical
575 ? gfxPrefs::MouseWheelRootScrollVerticalFactor()
576 : gfxPrefs::MouseWheelRootScrollHorizontalFactor();
577 // Making the scroll speed slower doesn't make sense. So, ignore odd factor
578 // which is less than 1.0.
579 if (intFactor
<= 100) {
582 double factor
= static_cast<double>(intFactor
) / 100;
583 return aDelta
* factor
;
587 WidgetWheelEvent::OverriddenDeltaX() const
589 if (!mAllowToOverrideSystemScrollSpeed
) {
592 return ComputeOverriddenDelta(mDeltaX
, false);
596 WidgetWheelEvent::OverriddenDeltaY() const
598 if (!mAllowToOverrideSystemScrollSpeed
) {
601 return ComputeOverriddenDelta(mDeltaY
, true);
604 /******************************************************************************
605 * mozilla::WidgetKeyboardEvent (TextEvents.h)
606 ******************************************************************************/
608 #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
609 const char16_t
* const WidgetKeyboardEvent::kKeyNames
[] = {
610 #include "mozilla/KeyNameList.h"
612 #undef NS_DEFINE_KEYNAME
614 #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
616 const char16_t
* const WidgetKeyboardEvent::kCodeNames
[] = {
617 #include "mozilla/PhysicalKeyCodeNameList.h"
619 #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
621 WidgetKeyboardEvent::KeyNameIndexHashtable
*
622 WidgetKeyboardEvent::sKeyNameIndexHashtable
= nullptr;
623 WidgetKeyboardEvent::CodeNameIndexHashtable
*
624 WidgetKeyboardEvent::sCodeNameIndexHashtable
= nullptr;
627 WidgetKeyboardEvent::InitAllEditCommands()
629 // If the event was created without widget, e.g., created event in chrome
630 // script, this shouldn't execute native key bindings.
631 if (NS_WARN_IF(!mWidget
)) {
635 // This event should be trusted event here and we shouldn't expose native
636 // key binding information to web contents with untrusted events.
637 if (NS_WARN_IF(!IsTrusted())) {
641 MOZ_ASSERT(XRE_IsParentProcess(),
642 "It's too expensive to retrieve all edit commands from remote process");
643 MOZ_ASSERT(!AreAllEditCommandsInitialized(),
644 "Shouldn't be called two or more times");
646 InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor
);
647 InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor
);
648 InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor
);
652 WidgetKeyboardEvent::InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType
)
654 if (NS_WARN_IF(!mWidget
) || NS_WARN_IF(!IsTrusted())) {
658 bool& initialized
= IsEditCommandsInitializedRef(aType
);
662 nsTArray
<CommandInt
>& commands
= EditCommandsRef(aType
);
663 mWidget
->GetEditCommands(aType
, *this, commands
);
668 WidgetKeyboardEvent::ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType
,
669 DoCommandCallback aCallback
,
672 // If the event was created without widget, e.g., created event in chrome
673 // script, this shouldn't execute native key bindings.
674 if (NS_WARN_IF(!mWidget
)) {
678 // This event should be trusted event here and we shouldn't expose native
679 // key binding information to web contents with untrusted events.
680 if (NS_WARN_IF(!IsTrusted())) {
684 InitEditCommandsFor(aType
);
686 const nsTArray
<CommandInt
>& commands
= EditCommandsRef(aType
);
687 if (commands
.IsEmpty()) {
691 for (CommandInt command
: commands
) {
692 aCallback(static_cast<Command
>(command
), aCallbackData
);
698 WidgetKeyboardEvent::ShouldCauseKeypressEvents() const
700 // Currently, we don't dispatch keypress events of modifier keys and
702 switch (mKeyNameIndex
) {
703 case KEY_NAME_INDEX_Alt
:
704 case KEY_NAME_INDEX_AltGraph
:
705 case KEY_NAME_INDEX_CapsLock
:
706 case KEY_NAME_INDEX_Control
:
707 case KEY_NAME_INDEX_Fn
:
708 case KEY_NAME_INDEX_FnLock
:
709 // case KEY_NAME_INDEX_Hyper:
710 case KEY_NAME_INDEX_Meta
:
711 case KEY_NAME_INDEX_NumLock
:
712 case KEY_NAME_INDEX_OS
:
713 case KEY_NAME_INDEX_ScrollLock
:
714 case KEY_NAME_INDEX_Shift
:
715 // case KEY_NAME_INDEX_Super:
716 case KEY_NAME_INDEX_Symbol
:
717 case KEY_NAME_INDEX_SymbolLock
:
718 case KEY_NAME_INDEX_Dead
:
726 HasASCIIDigit(const ShortcutKeyCandidateArray
& aCandidates
)
728 for (uint32_t i
= 0; i
< aCandidates
.Length(); ++i
) {
729 uint32_t ch
= aCandidates
[i
].mCharCode
;
730 if (ch
>= '0' && ch
<= '9')
737 CharsCaseInsensitiveEqual(uint32_t aChar1
, uint32_t aChar2
)
739 return aChar1
== aChar2
||
740 (IS_IN_BMP(aChar1
) && IS_IN_BMP(aChar2
) &&
741 ToLowerCase(static_cast<char16_t
>(aChar1
)) ==
742 ToLowerCase(static_cast<char16_t
>(aChar2
)));
746 IsCaseChangeableChar(uint32_t aChar
)
748 return IS_IN_BMP(aChar
) &&
749 ToLowerCase(static_cast<char16_t
>(aChar
)) !=
750 ToUpperCase(static_cast<char16_t
>(aChar
));
754 WidgetKeyboardEvent::GetShortcutKeyCandidates(
755 ShortcutKeyCandidateArray
& aCandidates
) const
757 MOZ_ASSERT(aCandidates
.IsEmpty(), "aCandidates must be empty");
759 // ShortcutKeyCandidate::mCharCode is a candidate charCode.
760 // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
761 // execute a command with/without shift key state. If this is TRUE, the
762 // shifted key state should be ignored. Otherwise, don't ignore the state.
763 // the priority of the charCodes are (shift key is not pressed):
764 // 0: PseudoCharCode()/false,
765 // 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
766 // the priority of the charCodes are (shift key is pressed):
767 // 0: PseudoCharCode()/false,
768 // 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
769 // 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
770 uint32_t pseudoCharCode
= PseudoCharCode();
771 if (pseudoCharCode
) {
772 ShortcutKeyCandidate
key(pseudoCharCode
, false);
773 aCandidates
.AppendElement(key
);
776 uint32_t len
= mAlternativeCharCodes
.Length();
778 for (uint32_t i
= 0; i
< len
; ++i
) {
779 uint32_t ch
= mAlternativeCharCodes
[i
].mUnshiftedCharCode
;
780 if (!ch
|| ch
== pseudoCharCode
) {
783 ShortcutKeyCandidate
key(ch
, false);
784 aCandidates
.AppendElement(key
);
786 // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
787 // this keyboard layout is AZERTY or similar layout, probably.
788 // In this case, Accel+[0-9] should be accessible without shift key.
789 // However, the priority should be lowest.
790 if (!HasASCIIDigit(aCandidates
)) {
791 for (uint32_t i
= 0; i
< len
; ++i
) {
792 uint32_t ch
= mAlternativeCharCodes
[i
].mShiftedCharCode
;
793 if (ch
>= '0' && ch
<= '9') {
794 ShortcutKeyCandidate
key(ch
, false);
795 aCandidates
.AppendElement(key
);
801 for (uint32_t i
= 0; i
< len
; ++i
) {
802 uint32_t ch
= mAlternativeCharCodes
[i
].mShiftedCharCode
;
807 if (ch
!= pseudoCharCode
) {
808 ShortcutKeyCandidate
key(ch
, false);
809 aCandidates
.AppendElement(key
);
812 // If the char is an alphabet, the shift key state should not be
813 // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
815 // And checking the charCode is same as unshiftedCharCode too.
816 // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
817 uint32_t unshiftCh
= mAlternativeCharCodes
[i
].mUnshiftedCharCode
;
818 if (CharsCaseInsensitiveEqual(ch
, unshiftCh
)) {
822 // On the Hebrew keyboard layout on Windows, the unshifted char is a
823 // localized character but the shifted char is a Latin alphabet,
824 // then, we should not execute without the shift state. See bug 433192.
825 if (IsCaseChangeableChar(ch
)) {
829 // Setting the alternative charCode candidates for retry without shift
830 // key state only when the shift key is pressed.
831 ShortcutKeyCandidate
key(ch
, true);
832 aCandidates
.AppendElement(key
);
836 // Special case for "Space" key. With some keyboard layouts, "Space" with
837 // or without Shift key causes non-ASCII space. For such keyboard layouts,
838 // we should guarantee that the key press works as an ASCII white space key
839 // press. However, if the space key is assigned to a function key, it
840 // shouldn't work as a space key.
841 if (mKeyNameIndex
== KEY_NAME_INDEX_USE_STRING
&&
842 mCodeNameIndex
== CODE_NAME_INDEX_Space
&& pseudoCharCode
!= ' ') {
843 ShortcutKeyCandidate
spaceKey(' ', false);
844 aCandidates
.AppendElement(spaceKey
);
849 WidgetKeyboardEvent::GetAccessKeyCandidates(nsTArray
<uint32_t>& aCandidates
) const
851 MOZ_ASSERT(aCandidates
.IsEmpty(), "aCandidates must be empty");
853 // return the lower cased charCode candidates for access keys.
854 // the priority of the charCodes are:
855 // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
856 // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
858 uint32_t ch
= mCharCode
;
860 ch
= ToLowerCase(static_cast<char16_t
>(ch
));
862 aCandidates
.AppendElement(ch
);
864 for (uint32_t i
= 0; i
< mAlternativeCharCodes
.Length(); ++i
) {
866 { mAlternativeCharCodes
[i
].mUnshiftedCharCode
,
867 mAlternativeCharCodes
[i
].mShiftedCharCode
};
868 for (uint32_t j
= 0; j
< 2; ++j
) {
872 if (IS_IN_BMP(ch
[j
])) {
873 ch
[j
] = ToLowerCase(static_cast<char16_t
>(ch
[j
]));
875 // Don't append the mCharCode that was already appended.
876 if (aCandidates
.IndexOf(ch
[j
]) == aCandidates
.NoIndex
) {
877 aCandidates
.AppendElement(ch
[j
]);
881 // Special case for "Space" key. With some keyboard layouts, "Space" with
882 // or without Shift key causes non-ASCII space. For such keyboard layouts,
883 // we should guarantee that the key press works as an ASCII white space key
884 // press. However, if the space key is assigned to a function key, it
885 // shouldn't work as a space key.
886 if (mKeyNameIndex
== KEY_NAME_INDEX_USE_STRING
&&
887 mCodeNameIndex
== CODE_NAME_INDEX_Space
&& mCharCode
!= ' ') {
888 aCandidates
.AppendElement(' ');
892 // mask values for ui.key.chromeAccess and ui.key.contentAccess
893 #define NS_MODIFIER_SHIFT 1
894 #define NS_MODIFIER_CONTROL 2
895 #define NS_MODIFIER_ALT 4
896 #define NS_MODIFIER_META 8
897 #define NS_MODIFIER_OS 16
899 static Modifiers
PrefFlagsToModifiers(int32_t aPrefFlags
)
901 Modifiers result
= 0;
902 if (aPrefFlags
& NS_MODIFIER_SHIFT
) {
903 result
|= MODIFIER_SHIFT
;
905 if (aPrefFlags
& NS_MODIFIER_CONTROL
) {
906 result
|= MODIFIER_CONTROL
;
908 if (aPrefFlags
& NS_MODIFIER_ALT
) {
909 result
|= MODIFIER_ALT
;
911 if (aPrefFlags
& NS_MODIFIER_META
) {
912 result
|= MODIFIER_META
;
914 if (aPrefFlags
& NS_MODIFIER_OS
) {
915 result
|= MODIFIER_OS
;
921 WidgetKeyboardEvent::ModifiersMatchWithAccessKey(AccessKeyType aType
) const
923 if (!ModifiersForAccessKeyMatching()) {
926 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType
);
930 WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const
932 static const Modifiers kModifierMask
=
933 MODIFIER_SHIFT
| MODIFIER_CONTROL
|
934 MODIFIER_ALT
| MODIFIER_META
| MODIFIER_OS
;
935 return mModifiers
& kModifierMask
;
940 WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType
)
942 switch (GenericAccessModifierKeyPref()) {
944 break; // use the individual prefs
946 return MODIFIER_SHIFT
;
948 return MODIFIER_CONTROL
;
952 return MODIFIER_META
;
956 return MODIFIER_NONE
;
960 case AccessKeyType::eChrome
:
961 return PrefFlagsToModifiers(ChromeAccessModifierMaskPref());
962 case AccessKeyType::eContent
:
963 return PrefFlagsToModifiers(ContentAccessModifierMaskPref());
965 return MODIFIER_NONE
;
971 WidgetKeyboardEvent::GenericAccessModifierKeyPref()
973 static bool sInitialized
= false;
974 static int32_t sValue
= -1;
977 Preferences::AddIntVarCache(&sValue
, "ui.key.generalAccessKey", sValue
);
978 sInitialized
= NS_SUCCEEDED(rv
);
979 MOZ_ASSERT(sInitialized
);
986 WidgetKeyboardEvent::ChromeAccessModifierMaskPref()
988 static bool sInitialized
= false;
989 static int32_t sValue
= 0;
992 Preferences::AddIntVarCache(&sValue
, "ui.key.chromeAccess", sValue
);
993 sInitialized
= NS_SUCCEEDED(rv
);
994 MOZ_ASSERT(sInitialized
);
1001 WidgetKeyboardEvent::ContentAccessModifierMaskPref()
1003 static bool sInitialized
= false;
1004 static int32_t sValue
= 0;
1005 if (!sInitialized
) {
1007 Preferences::AddIntVarCache(&sValue
, "ui.key.contentAccess", sValue
);
1008 sInitialized
= NS_SUCCEEDED(rv
);
1009 MOZ_ASSERT(sInitialized
);
1015 WidgetKeyboardEvent::Shutdown()
1017 delete sKeyNameIndexHashtable
;
1018 sKeyNameIndexHashtable
= nullptr;
1019 delete sCodeNameIndexHashtable
;
1020 sCodeNameIndexHashtable
= nullptr;
1024 WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex
,
1025 nsAString
& aKeyName
)
1027 if (aKeyNameIndex
>= KEY_NAME_INDEX_USE_STRING
) {
1028 aKeyName
.Truncate();
1032 MOZ_RELEASE_ASSERT(static_cast<size_t>(aKeyNameIndex
) <
1033 ArrayLength(kKeyNames
),
1034 "Illegal key enumeration value");
1035 aKeyName
= kKeyNames
[aKeyNameIndex
];
1039 WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex
,
1040 nsAString
& aCodeName
)
1042 if (aCodeNameIndex
>= CODE_NAME_INDEX_USE_STRING
) {
1043 aCodeName
.Truncate();
1047 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCodeNameIndex
) <
1048 ArrayLength(kCodeNames
),
1049 "Illegal physical code enumeration value");
1050 aCodeName
= kCodeNames
[aCodeNameIndex
];
1053 /* static */ KeyNameIndex
1054 WidgetKeyboardEvent::GetKeyNameIndex(const nsAString
& aKeyValue
)
1056 if (!sKeyNameIndexHashtable
) {
1057 sKeyNameIndexHashtable
=
1058 new KeyNameIndexHashtable(ArrayLength(kKeyNames
));
1059 for (size_t i
= 0; i
< ArrayLength(kKeyNames
); i
++) {
1060 sKeyNameIndexHashtable
->Put(nsDependentString(kKeyNames
[i
]),
1061 static_cast<KeyNameIndex
>(i
));
1064 KeyNameIndex result
= KEY_NAME_INDEX_USE_STRING
;
1065 sKeyNameIndexHashtable
->Get(aKeyValue
, &result
);
1069 /* static */ CodeNameIndex
1070 WidgetKeyboardEvent::GetCodeNameIndex(const nsAString
& aCodeValue
)
1072 if (!sCodeNameIndexHashtable
) {
1073 sCodeNameIndexHashtable
=
1074 new CodeNameIndexHashtable(ArrayLength(kCodeNames
));
1075 for (size_t i
= 0; i
< ArrayLength(kCodeNames
); i
++) {
1076 sCodeNameIndexHashtable
->Put(nsDependentString(kCodeNames
[i
]),
1077 static_cast<CodeNameIndex
>(i
));
1080 CodeNameIndex result
= CODE_NAME_INDEX_USE_STRING
;
1081 sCodeNameIndexHashtable
->Get(aCodeValue
, &result
);
1085 /* static */ const char*
1086 WidgetKeyboardEvent::GetCommandStr(Command aCommand
)
1088 #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1089 static const char* const kCommands
[] = {
1090 "" // CommandDoNothing
1091 #include "mozilla/CommandList.h"
1093 #undef NS_DEFINE_COMMAND
1095 MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand
) < ArrayLength(kCommands
),
1096 "Illegal command enumeration value");
1097 return kCommands
[aCommand
];
1100 /* static */ uint32_t
1101 WidgetKeyboardEvent::ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex
)
1103 // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1104 // but are defined by D3E spec. So, they should be uncommented when the
1105 // code values are defined in the header.
1106 switch (aCodeNameIndex
) {
1107 case CODE_NAME_INDEX_AltLeft
:
1108 case CODE_NAME_INDEX_ControlLeft
:
1109 case CODE_NAME_INDEX_OSLeft
:
1110 case CODE_NAME_INDEX_ShiftLeft
:
1111 return eKeyLocationLeft
;
1112 case CODE_NAME_INDEX_AltRight
:
1113 case CODE_NAME_INDEX_ControlRight
:
1114 case CODE_NAME_INDEX_OSRight
:
1115 case CODE_NAME_INDEX_ShiftRight
:
1116 return eKeyLocationRight
;
1117 case CODE_NAME_INDEX_Numpad0
:
1118 case CODE_NAME_INDEX_Numpad1
:
1119 case CODE_NAME_INDEX_Numpad2
:
1120 case CODE_NAME_INDEX_Numpad3
:
1121 case CODE_NAME_INDEX_Numpad4
:
1122 case CODE_NAME_INDEX_Numpad5
:
1123 case CODE_NAME_INDEX_Numpad6
:
1124 case CODE_NAME_INDEX_Numpad7
:
1125 case CODE_NAME_INDEX_Numpad8
:
1126 case CODE_NAME_INDEX_Numpad9
:
1127 case CODE_NAME_INDEX_NumpadAdd
:
1128 case CODE_NAME_INDEX_NumpadBackspace
:
1129 case CODE_NAME_INDEX_NumpadClear
:
1130 case CODE_NAME_INDEX_NumpadClearEntry
:
1131 case CODE_NAME_INDEX_NumpadComma
:
1132 case CODE_NAME_INDEX_NumpadDecimal
:
1133 case CODE_NAME_INDEX_NumpadDivide
:
1134 case CODE_NAME_INDEX_NumpadEnter
:
1135 case CODE_NAME_INDEX_NumpadEqual
:
1136 case CODE_NAME_INDEX_NumpadMemoryAdd
:
1137 case CODE_NAME_INDEX_NumpadMemoryClear
:
1138 case CODE_NAME_INDEX_NumpadMemoryRecall
:
1139 case CODE_NAME_INDEX_NumpadMemoryStore
:
1140 case CODE_NAME_INDEX_NumpadMemorySubtract
:
1141 case CODE_NAME_INDEX_NumpadMultiply
:
1142 case CODE_NAME_INDEX_NumpadParenLeft
:
1143 case CODE_NAME_INDEX_NumpadParenRight
:
1144 case CODE_NAME_INDEX_NumpadSubtract
:
1145 return eKeyLocationNumpad
;
1147 return eKeyLocationStandard
;
1151 /* static */ uint32_t
1152 WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex
)
1154 switch (aKeyNameIndex
) {
1155 case KEY_NAME_INDEX_Cancel
:
1156 return nsIDOMKeyEvent::DOM_VK_CANCEL
;
1157 case KEY_NAME_INDEX_Help
:
1158 return nsIDOMKeyEvent::DOM_VK_HELP
;
1159 case KEY_NAME_INDEX_Backspace
:
1160 return nsIDOMKeyEvent::DOM_VK_BACK_SPACE
;
1161 case KEY_NAME_INDEX_Tab
:
1162 return nsIDOMKeyEvent::DOM_VK_TAB
;
1163 case KEY_NAME_INDEX_Clear
:
1164 return nsIDOMKeyEvent::DOM_VK_CLEAR
;
1165 case KEY_NAME_INDEX_Enter
:
1166 return nsIDOMKeyEvent::DOM_VK_RETURN
;
1167 case KEY_NAME_INDEX_Shift
:
1168 return nsIDOMKeyEvent::DOM_VK_SHIFT
;
1169 case KEY_NAME_INDEX_Control
:
1170 return nsIDOMKeyEvent::DOM_VK_CONTROL
;
1171 case KEY_NAME_INDEX_Alt
:
1172 return nsIDOMKeyEvent::DOM_VK_ALT
;
1173 case KEY_NAME_INDEX_Pause
:
1174 return nsIDOMKeyEvent::DOM_VK_PAUSE
;
1175 case KEY_NAME_INDEX_CapsLock
:
1176 return nsIDOMKeyEvent::DOM_VK_CAPS_LOCK
;
1177 case KEY_NAME_INDEX_Hiragana
:
1178 case KEY_NAME_INDEX_Katakana
:
1179 case KEY_NAME_INDEX_HiraganaKatakana
:
1180 case KEY_NAME_INDEX_KanaMode
:
1181 return nsIDOMKeyEvent::DOM_VK_KANA
;
1182 case KEY_NAME_INDEX_HangulMode
:
1183 return nsIDOMKeyEvent::DOM_VK_HANGUL
;
1184 case KEY_NAME_INDEX_Eisu
:
1185 return nsIDOMKeyEvent::DOM_VK_EISU
;
1186 case KEY_NAME_INDEX_JunjaMode
:
1187 return nsIDOMKeyEvent::DOM_VK_JUNJA
;
1188 case KEY_NAME_INDEX_FinalMode
:
1189 return nsIDOMKeyEvent::DOM_VK_FINAL
;
1190 case KEY_NAME_INDEX_HanjaMode
:
1191 return nsIDOMKeyEvent::DOM_VK_HANJA
;
1192 case KEY_NAME_INDEX_KanjiMode
:
1193 return nsIDOMKeyEvent::DOM_VK_KANJI
;
1194 case KEY_NAME_INDEX_Escape
:
1195 return nsIDOMKeyEvent::DOM_VK_ESCAPE
;
1196 case KEY_NAME_INDEX_Convert
:
1197 return nsIDOMKeyEvent::DOM_VK_CONVERT
;
1198 case KEY_NAME_INDEX_NonConvert
:
1199 return nsIDOMKeyEvent::DOM_VK_NONCONVERT
;
1200 case KEY_NAME_INDEX_Accept
:
1201 return nsIDOMKeyEvent::DOM_VK_ACCEPT
;
1202 case KEY_NAME_INDEX_ModeChange
:
1203 return nsIDOMKeyEvent::DOM_VK_MODECHANGE
;
1204 case KEY_NAME_INDEX_PageUp
:
1205 return nsIDOMKeyEvent::DOM_VK_PAGE_UP
;
1206 case KEY_NAME_INDEX_PageDown
:
1207 return nsIDOMKeyEvent::DOM_VK_PAGE_DOWN
;
1208 case KEY_NAME_INDEX_End
:
1209 return nsIDOMKeyEvent::DOM_VK_END
;
1210 case KEY_NAME_INDEX_Home
:
1211 return nsIDOMKeyEvent::DOM_VK_HOME
;
1212 case KEY_NAME_INDEX_ArrowLeft
:
1213 return nsIDOMKeyEvent::DOM_VK_LEFT
;
1214 case KEY_NAME_INDEX_ArrowUp
:
1215 return nsIDOMKeyEvent::DOM_VK_UP
;
1216 case KEY_NAME_INDEX_ArrowRight
:
1217 return nsIDOMKeyEvent::DOM_VK_RIGHT
;
1218 case KEY_NAME_INDEX_ArrowDown
:
1219 return nsIDOMKeyEvent::DOM_VK_DOWN
;
1220 case KEY_NAME_INDEX_Select
:
1221 return nsIDOMKeyEvent::DOM_VK_SELECT
;
1222 case KEY_NAME_INDEX_Print
:
1223 return nsIDOMKeyEvent::DOM_VK_PRINT
;
1224 case KEY_NAME_INDEX_Execute
:
1225 return nsIDOMKeyEvent::DOM_VK_EXECUTE
;
1226 case KEY_NAME_INDEX_PrintScreen
:
1227 return nsIDOMKeyEvent::DOM_VK_PRINTSCREEN
;
1228 case KEY_NAME_INDEX_Insert
:
1229 return nsIDOMKeyEvent::DOM_VK_INSERT
;
1230 case KEY_NAME_INDEX_Delete
:
1231 return nsIDOMKeyEvent::DOM_VK_DELETE
;
1232 case KEY_NAME_INDEX_OS
:
1233 // case KEY_NAME_INDEX_Super:
1234 // case KEY_NAME_INDEX_Hyper:
1235 return nsIDOMKeyEvent::DOM_VK_WIN
;
1236 case KEY_NAME_INDEX_ContextMenu
:
1237 return nsIDOMKeyEvent::DOM_VK_CONTEXT_MENU
;
1238 case KEY_NAME_INDEX_Standby
:
1239 return nsIDOMKeyEvent::DOM_VK_SLEEP
;
1240 case KEY_NAME_INDEX_F1
:
1241 return nsIDOMKeyEvent::DOM_VK_F1
;
1242 case KEY_NAME_INDEX_F2
:
1243 return nsIDOMKeyEvent::DOM_VK_F2
;
1244 case KEY_NAME_INDEX_F3
:
1245 return nsIDOMKeyEvent::DOM_VK_F3
;
1246 case KEY_NAME_INDEX_F4
:
1247 return nsIDOMKeyEvent::DOM_VK_F4
;
1248 case KEY_NAME_INDEX_F5
:
1249 return nsIDOMKeyEvent::DOM_VK_F5
;
1250 case KEY_NAME_INDEX_F6
:
1251 return nsIDOMKeyEvent::DOM_VK_F6
;
1252 case KEY_NAME_INDEX_F7
:
1253 return nsIDOMKeyEvent::DOM_VK_F7
;
1254 case KEY_NAME_INDEX_F8
:
1255 return nsIDOMKeyEvent::DOM_VK_F8
;
1256 case KEY_NAME_INDEX_F9
:
1257 return nsIDOMKeyEvent::DOM_VK_F9
;
1258 case KEY_NAME_INDEX_F10
:
1259 return nsIDOMKeyEvent::DOM_VK_F10
;
1260 case KEY_NAME_INDEX_F11
:
1261 return nsIDOMKeyEvent::DOM_VK_F11
;
1262 case KEY_NAME_INDEX_F12
:
1263 return nsIDOMKeyEvent::DOM_VK_F12
;
1264 case KEY_NAME_INDEX_F13
:
1265 return nsIDOMKeyEvent::DOM_VK_F13
;
1266 case KEY_NAME_INDEX_F14
:
1267 return nsIDOMKeyEvent::DOM_VK_F14
;
1268 case KEY_NAME_INDEX_F15
:
1269 return nsIDOMKeyEvent::DOM_VK_F15
;
1270 case KEY_NAME_INDEX_F16
:
1271 return nsIDOMKeyEvent::DOM_VK_F16
;
1272 case KEY_NAME_INDEX_F17
:
1273 return nsIDOMKeyEvent::DOM_VK_F17
;
1274 case KEY_NAME_INDEX_F18
:
1275 return nsIDOMKeyEvent::DOM_VK_F18
;
1276 case KEY_NAME_INDEX_F19
:
1277 return nsIDOMKeyEvent::DOM_VK_F19
;
1278 case KEY_NAME_INDEX_F20
:
1279 return nsIDOMKeyEvent::DOM_VK_F20
;
1280 case KEY_NAME_INDEX_F21
:
1281 return nsIDOMKeyEvent::DOM_VK_F21
;
1282 case KEY_NAME_INDEX_F22
:
1283 return nsIDOMKeyEvent::DOM_VK_F22
;
1284 case KEY_NAME_INDEX_F23
:
1285 return nsIDOMKeyEvent::DOM_VK_F23
;
1286 case KEY_NAME_INDEX_F24
:
1287 return nsIDOMKeyEvent::DOM_VK_F24
;
1288 case KEY_NAME_INDEX_NumLock
:
1289 return nsIDOMKeyEvent::DOM_VK_NUM_LOCK
;
1290 case KEY_NAME_INDEX_ScrollLock
:
1291 return nsIDOMKeyEvent::DOM_VK_SCROLL_LOCK
;
1292 case KEY_NAME_INDEX_AudioVolumeMute
:
1293 return nsIDOMKeyEvent::DOM_VK_VOLUME_MUTE
;
1294 case KEY_NAME_INDEX_AudioVolumeDown
:
1295 return nsIDOMKeyEvent::DOM_VK_VOLUME_DOWN
;
1296 case KEY_NAME_INDEX_AudioVolumeUp
:
1297 return nsIDOMKeyEvent::DOM_VK_VOLUME_UP
;
1298 case KEY_NAME_INDEX_Meta
:
1299 return nsIDOMKeyEvent::DOM_VK_META
;
1300 case KEY_NAME_INDEX_AltGraph
:
1301 return nsIDOMKeyEvent::DOM_VK_ALTGR
;
1302 case KEY_NAME_INDEX_Attn
:
1303 return nsIDOMKeyEvent::DOM_VK_ATTN
;
1304 case KEY_NAME_INDEX_CrSel
:
1305 return nsIDOMKeyEvent::DOM_VK_CRSEL
;
1306 case KEY_NAME_INDEX_ExSel
:
1307 return nsIDOMKeyEvent::DOM_VK_EXSEL
;
1308 case KEY_NAME_INDEX_EraseEof
:
1309 return nsIDOMKeyEvent::DOM_VK_EREOF
;
1310 case KEY_NAME_INDEX_Play
:
1311 return nsIDOMKeyEvent::DOM_VK_PLAY
;
1312 case KEY_NAME_INDEX_ZoomToggle
:
1313 case KEY_NAME_INDEX_ZoomIn
:
1314 case KEY_NAME_INDEX_ZoomOut
:
1315 return nsIDOMKeyEvent::DOM_VK_ZOOM
;
1321 /* static */ Modifier
1322 WidgetKeyboardEvent::GetModifierForKeyName(KeyNameIndex aKeyNameIndex
)
1324 switch (aKeyNameIndex
) {
1325 case KEY_NAME_INDEX_Alt
:
1326 return MODIFIER_ALT
;
1327 case KEY_NAME_INDEX_AltGraph
:
1328 return MODIFIER_ALTGRAPH
;
1329 case KEY_NAME_INDEX_CapsLock
:
1330 return MODIFIER_CAPSLOCK
;
1331 case KEY_NAME_INDEX_Control
:
1332 return MODIFIER_CONTROL
;
1333 case KEY_NAME_INDEX_Fn
:
1335 case KEY_NAME_INDEX_FnLock
:
1336 return MODIFIER_FNLOCK
;
1337 // case KEY_NAME_INDEX_Hyper:
1338 case KEY_NAME_INDEX_Meta
:
1339 return MODIFIER_META
;
1340 case KEY_NAME_INDEX_NumLock
:
1341 return MODIFIER_NUMLOCK
;
1342 case KEY_NAME_INDEX_OS
:
1344 case KEY_NAME_INDEX_ScrollLock
:
1345 return MODIFIER_SCROLLLOCK
;
1346 case KEY_NAME_INDEX_Shift
:
1347 return MODIFIER_SHIFT
;
1348 // case KEY_NAME_INDEX_Super:
1349 case KEY_NAME_INDEX_Symbol
:
1350 return MODIFIER_SYMBOL
;
1351 case KEY_NAME_INDEX_SymbolLock
:
1352 return MODIFIER_SYMBOLLOCK
;
1354 return MODIFIER_NONE
;
1359 WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex
)
1361 switch (aKeyNameIndex
) {
1362 case KEY_NAME_INDEX_CapsLock
:
1363 case KEY_NAME_INDEX_FnLock
:
1364 case KEY_NAME_INDEX_NumLock
:
1365 case KEY_NAME_INDEX_ScrollLock
:
1366 case KEY_NAME_INDEX_SymbolLock
:
1373 } // namespace mozilla