Bug 1376625 - Updating meta data for newly added tests r=ato
[gecko.git] / widget / WidgetEventImpl.cpp
blob03d15f5e90e2fce32a5ae88b411b134522b1cf85
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 "gfxPrefs.h"
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"
20 namespace mozilla {
22 /******************************************************************************
23 * Global helper methods
24 ******************************************************************************/
26 const char*
27 ToChar(EventMessage aEventMessage)
29 switch (aEventMessage) {
31 #define NS_EVENT_MESSAGE(aMessage) \
32 case aMessage: \
33 return #aMessage;
35 #include "mozilla/EventMessageList.h"
37 #undef NS_EVENT_MESSAGE
38 default:
39 return "illegal event message";
43 const char*
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"
58 #undef NS_EVENT_CLASS
59 #undef NS_ROOT_EVENT_CLASS
60 default:
61 return "illegal event class ID";
65 const nsCString
66 ToString(KeyNameIndex aKeyNameIndex)
68 if (aKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
69 return NS_LITERAL_CSTRING("USE_STRING");
71 nsAutoString keyName;
72 WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex, keyName);
73 return NS_ConvertUTF16toUTF8(keyName);
76 const nsCString
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);
87 const nsCString
88 GetDOMKeyCodeName(uint32_t aKeyCode)
90 switch (aKeyCode) {
91 #define NS_DISALLOW_SAME_KEYCODE
92 #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
93 case aDOMKeyCode: \
94 return NS_LITERAL_CSTRING(#aDOMKeyName);
96 #include "mozilla/VirtualKeyCodeList.h"
98 #undef NS_DEFINE_VK
99 #undef NS_DISALLOW_SAME_KEYCODE
101 default:
102 return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode);
106 bool
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:
116 return true;
117 default:
118 return false;
122 RawTextRangeType
123 ToRawTextRangeType(TextRangeType aTextRangeType)
125 return static_cast<RawTextRangeType>(aTextRangeType);
128 TextRangeType
129 ToTextRangeType(RawTextRangeType aRawTextRangeType)
131 MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType));
132 return static_cast<TextRangeType>(aRawTextRangeType);
135 const char*
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";
151 default:
152 return "Invalid TextRangeType";
156 SelectionType
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;
168 default:
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) \
180 aPrefix##aName* \
181 WidgetEvent::As##aName() \
183 return nullptr; \
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 ******************************************************************************/
203 bool
204 WidgetEvent::IsQueryContentEvent() const
206 return mClass == eQueryContentEventClass;
209 bool
210 WidgetEvent::IsSelectionEvent() const
212 return mClass == eSelectionEventClass;
215 bool
216 WidgetEvent::IsContentCommandEvent() const
218 return mClass == eContentCommandEventClass;
221 bool
222 WidgetEvent::IsNativeEventDelivererForPlugin() const
224 return mClass == ePluginEventClass;
228 /******************************************************************************
229 * mozilla::WidgetEvent
231 * Event message checking methods.
232 ******************************************************************************/
234 bool
235 WidgetEvent::HasMouseEventMessage() const
237 switch (mMessage) {
238 case eMouseDown:
239 case eMouseUp:
240 case eMouseClick:
241 case eMouseDoubleClick:
242 case eMouseAuxClick:
243 case eMouseEnterIntoWidget:
244 case eMouseExitFromWidget:
245 case eMouseActivate:
246 case eMouseOver:
247 case eMouseOut:
248 case eMouseHitTest:
249 case eMouseMove:
250 return true;
251 default:
252 return false;
256 bool
257 WidgetEvent::HasDragEventMessage() const
259 switch (mMessage) {
260 case eDragEnter:
261 case eDragOver:
262 case eDragExit:
263 case eDrag:
264 case eDragEnd:
265 case eDragStart:
266 case eDrop:
267 case eDragLeave:
268 return true;
269 default:
270 return false;
274 bool
275 WidgetEvent::HasKeyEventMessage() const
277 switch (mMessage) {
278 case eKeyDown:
279 case eKeyPress:
280 case eKeyUp:
281 case eKeyDownOnPlugin:
282 case eKeyUpOnPlugin:
283 case eAccessKeyNotFound:
284 return true;
285 default:
286 return false;
290 bool
291 WidgetEvent::HasIMEEventMessage() const
293 switch (mMessage) {
294 case eCompositionStart:
295 case eCompositionEnd:
296 case eCompositionUpdate:
297 case eCompositionChange:
298 case eCompositionCommitAsIs:
299 case eCompositionCommit:
300 return true;
301 default:
302 return false;
306 bool
307 WidgetEvent::HasPluginActivationEventMessage() const
309 return mMessage == ePluginActivate ||
310 mMessage == ePluginFocus;
313 /******************************************************************************
314 * mozilla::WidgetEvent
316 * Specific event checking methods.
317 ******************************************************************************/
319 bool
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()) {
325 return false;
328 if (mClass == eKeyboardEventClass ||
329 mClass == eWheelEventClass) {
330 return true;
333 switch (mMessage) {
334 case eMouseDown:
335 case eMouseUp:
336 case eMouseMove:
337 case eContextMenu:
338 case eMouseEnterIntoWidget:
339 case eMouseExitFromWidget:
340 case eMouseTouchDrag:
341 case eTouchStart:
342 case eTouchMove:
343 case eTouchEnd:
344 case eTouchCancel:
345 case eDragOver:
346 case eDragExit:
347 case eDrop:
348 return true;
349 default:
350 return false;
354 bool
355 WidgetEvent::WillBeSentToRemoteProcess() const
357 // This event won't be posted to remote process if it's already explicitly
358 // stopped.
359 if (IsCrossProcessForwardingStopped()) {
360 return false;
363 // When mOriginalTarget is nullptr, this method shouldn't be used.
364 if (NS_WARN_IF(!mOriginalTarget)) {
365 return false;
368 nsCOMPtr<nsIContent> originalTarget = do_QueryInterface(mOriginalTarget);
369 return EventStateManager::IsRemoteTarget(originalTarget);
372 bool
373 WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
375 const WidgetPluginEvent* pluginEvent = AsPluginEvent();
376 return pluginEvent && pluginEvent->mRetargetToFocusedDocument;
379 bool
380 WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const
382 const WidgetPluginEvent* pluginEvent = AsPluginEvent();
383 return pluginEvent && !pluginEvent->mRetargetToFocusedDocument;
386 bool
387 WidgetEvent::IsIMERelatedEvent() const
389 return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
392 bool
393 WidgetEvent::IsUsingCoordinates() const
395 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
396 if (mouseEvent) {
397 return !mouseEvent->IsContextMenuKeyEvent();
399 return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
400 !HasPluginActivationEventMessage() &&
401 !IsNativeEventDelivererForPlugin() &&
402 !IsContentCommandEvent();
405 bool
406 WidgetEvent::IsTargetedAtFocusedWindow() const
408 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
409 if (mouseEvent) {
410 return mouseEvent->IsContextMenuKeyEvent();
412 return HasKeyEventMessage() || IsIMERelatedEvent() ||
413 IsContentCommandEvent() ||
414 IsRetargetedNativeEventDelivererForPlugin();
417 bool
418 WidgetEvent::IsTargetedAtFocusedContent() const
420 const WidgetMouseEvent* mouseEvent = AsMouseEvent();
421 if (mouseEvent) {
422 return mouseEvent->IsContextMenuKeyEvent();
424 return HasKeyEventMessage() || IsIMERelatedEvent() ||
425 IsRetargetedNativeEventDelivererForPlugin();
428 bool
429 WidgetEvent::IsAllowedToDispatchDOMEvent() const
431 switch (mClass) {
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
437 // them to DOM.
438 if (DefaultPreventedByContent() &&
439 (mMessage == eMouseMove || mMessage == eMouseDown ||
440 mMessage == eMouseUp)) {
441 return false;
443 if (mMessage == eMouseTouchDrag) {
444 return false;
446 MOZ_FALLTHROUGH;
447 case ePointerEventClass:
448 // We want synthesized mouse moves to cause mouseover and mouseout
449 // DOM events (EventStateManager::PreHandleEvent), but not mousemove
450 // DOM events.
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:
469 return false;
471 default:
472 return true;
476 bool
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
481 // anymore.
482 return mClass != ePointerEventClass;
485 /******************************************************************************
486 * mozilla::WidgetEvent
488 * Misc methods.
489 ******************************************************************************/
491 static dom::EventTarget*
492 GetTargetForDOMEvent(nsIDOMEventTarget* aTarget)
494 return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
497 dom::EventTarget*
498 WidgetEvent::GetDOMEventTarget() const
500 return GetTargetForDOMEvent(mTarget);
503 dom::EventTarget*
504 WidgetEvent::GetCurrentDOMEventTarget() const
506 return GetTargetForDOMEvent(mCurrentTarget);
509 dom::EventTarget*
510 WidgetEvent::GetOriginalDOMEventTarget() const
512 if (mOriginalTarget) {
513 return GetTargetForDOMEvent(mOriginalTarget);
515 return GetDOMEventTarget();
518 /******************************************************************************
519 * mozilla::WidgetInputEvent
520 ******************************************************************************/
522 /* static */
523 Modifier
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);
533 /* static */
534 Modifier
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;
542 break;
543 case nsIDOMKeyEvent::DOM_VK_WIN:
544 sAccelModifier = MODIFIER_OS;
545 break;
546 case nsIDOMKeyEvent::DOM_VK_ALT:
547 sAccelModifier = MODIFIER_ALT;
548 break;
549 case nsIDOMKeyEvent::DOM_VK_CONTROL:
550 sAccelModifier = MODIFIER_CONTROL;
551 break;
552 default:
553 #ifdef XP_MACOSX
554 sAccelModifier = MODIFIER_META;
555 #else
556 sAccelModifier = MODIFIER_CONTROL;
557 #endif
558 break;
561 return sAccelModifier;
564 /******************************************************************************
565 * mozilla::WidgetWheelEvent (MouseEvents.h)
566 ******************************************************************************/
568 /* static */ double
569 WidgetWheelEvent::ComputeOverriddenDelta(double aDelta, bool aIsForVertical)
571 if (!gfxPrefs::MouseWheelHasRootScrollDeltaOverride()) {
572 return aDelta;
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) {
580 return aDelta;
582 double factor = static_cast<double>(intFactor) / 100;
583 return aDelta * factor;
586 double
587 WidgetWheelEvent::OverriddenDeltaX() const
589 if (!mAllowToOverrideSystemScrollSpeed) {
590 return mDeltaX;
592 return ComputeOverriddenDelta(mDeltaX, false);
595 double
596 WidgetWheelEvent::OverriddenDeltaY() const
598 if (!mAllowToOverrideSystemScrollSpeed) {
599 return mDeltaY;
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) \
615 (u"" 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;
626 void
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)) {
632 return;
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())) {
638 return;
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);
651 void
652 WidgetKeyboardEvent::InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType)
654 if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
655 return;
658 bool& initialized = IsEditCommandsInitializedRef(aType);
659 if (initialized) {
660 return;
662 nsTArray<CommandInt>& commands = EditCommandsRef(aType);
663 mWidget->GetEditCommands(aType, *this, commands);
664 initialized = true;
667 bool
668 WidgetKeyboardEvent::ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType,
669 DoCommandCallback aCallback,
670 void* aCallbackData)
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)) {
675 return false;
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())) {
681 return false;
684 InitEditCommandsFor(aType);
686 const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
687 if (commands.IsEmpty()) {
688 return false;
691 for (CommandInt command : commands) {
692 aCallback(static_cast<Command>(command), aCallbackData);
694 return true;
697 bool
698 WidgetKeyboardEvent::ShouldCauseKeypressEvents() const
700 // Currently, we don't dispatch keypress events of modifier keys and
701 // dead keys.
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:
719 return false;
720 default:
721 return true;
725 static bool
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')
731 return true;
733 return false;
736 static bool
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)));
745 static bool
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));
753 void
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();
777 if (!IsShift()) {
778 for (uint32_t i = 0; i < len; ++i) {
779 uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
780 if (!ch || ch == pseudoCharCode) {
781 continue;
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);
796 break;
800 } else {
801 for (uint32_t i = 0; i < len; ++i) {
802 uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
803 if (!ch) {
804 continue;
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)) {
819 continue;
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)) {
826 continue;
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);
848 void
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],...
857 if (mCharCode) {
858 uint32_t ch = mCharCode;
859 if (IS_IN_BMP(ch)) {
860 ch = ToLowerCase(static_cast<char16_t>(ch));
862 aCandidates.AppendElement(ch);
864 for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
865 uint32_t ch[2] =
866 { mAlternativeCharCodes[i].mUnshiftedCharCode,
867 mAlternativeCharCodes[i].mShiftedCharCode };
868 for (uint32_t j = 0; j < 2; ++j) {
869 if (!ch[j]) {
870 continue;
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;
917 return result;
920 bool
921 WidgetKeyboardEvent::ModifiersMatchWithAccessKey(AccessKeyType aType) const
923 if (!ModifiersForAccessKeyMatching()) {
924 return false;
926 return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
929 Modifiers
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;
938 /* static */
939 Modifiers
940 WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType)
942 switch (GenericAccessModifierKeyPref()) {
943 case -1:
944 break; // use the individual prefs
945 case NS_VK_SHIFT:
946 return MODIFIER_SHIFT;
947 case NS_VK_CONTROL:
948 return MODIFIER_CONTROL;
949 case NS_VK_ALT:
950 return MODIFIER_ALT;
951 case NS_VK_META:
952 return MODIFIER_META;
953 case NS_VK_WIN:
954 return MODIFIER_OS;
955 default:
956 return MODIFIER_NONE;
959 switch (aType) {
960 case AccessKeyType::eChrome:
961 return PrefFlagsToModifiers(ChromeAccessModifierMaskPref());
962 case AccessKeyType::eContent:
963 return PrefFlagsToModifiers(ContentAccessModifierMaskPref());
964 default:
965 return MODIFIER_NONE;
969 /* static */
970 int32_t
971 WidgetKeyboardEvent::GenericAccessModifierKeyPref()
973 static bool sInitialized = false;
974 static int32_t sValue = -1;
975 if (!sInitialized) {
976 nsresult rv =
977 Preferences::AddIntVarCache(&sValue, "ui.key.generalAccessKey", sValue);
978 sInitialized = NS_SUCCEEDED(rv);
979 MOZ_ASSERT(sInitialized);
981 return sValue;
984 /* static */
985 int32_t
986 WidgetKeyboardEvent::ChromeAccessModifierMaskPref()
988 static bool sInitialized = false;
989 static int32_t sValue = 0;
990 if (!sInitialized) {
991 nsresult rv =
992 Preferences::AddIntVarCache(&sValue, "ui.key.chromeAccess", sValue);
993 sInitialized = NS_SUCCEEDED(rv);
994 MOZ_ASSERT(sInitialized);
996 return sValue;
999 /* static */
1000 int32_t
1001 WidgetKeyboardEvent::ContentAccessModifierMaskPref()
1003 static bool sInitialized = false;
1004 static int32_t sValue = 0;
1005 if (!sInitialized) {
1006 nsresult rv =
1007 Preferences::AddIntVarCache(&sValue, "ui.key.contentAccess", sValue);
1008 sInitialized = NS_SUCCEEDED(rv);
1009 MOZ_ASSERT(sInitialized);
1011 return sValue;
1014 /* static */ void
1015 WidgetKeyboardEvent::Shutdown()
1017 delete sKeyNameIndexHashtable;
1018 sKeyNameIndexHashtable = nullptr;
1019 delete sCodeNameIndexHashtable;
1020 sCodeNameIndexHashtable = nullptr;
1023 /* static */ void
1024 WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
1025 nsAString& aKeyName)
1027 if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
1028 aKeyName.Truncate();
1029 return;
1032 MOZ_RELEASE_ASSERT(static_cast<size_t>(aKeyNameIndex) <
1033 ArrayLength(kKeyNames),
1034 "Illegal key enumeration value");
1035 aKeyName = kKeyNames[aKeyNameIndex];
1038 /* static */ void
1039 WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
1040 nsAString& aCodeName)
1042 if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
1043 aCodeName.Truncate();
1044 return;
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);
1066 return 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);
1082 return 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;
1146 default:
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;
1316 default:
1317 return 0;
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:
1334 return MODIFIER_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:
1343 return MODIFIER_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;
1353 default:
1354 return MODIFIER_NONE;
1358 /* static */ bool
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:
1367 return true;
1368 default:
1369 return false;
1373 } // namespace mozilla