WidgetEventImpl.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107
  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/. */
  5. #include "gfxPrefs.h"
  6. #include "mozilla/BasicEvents.h"
  7. #include "mozilla/ContentEvents.h"
  8. #include "mozilla/InternalMutationEvent.h"
  9. #include "mozilla/MiscEvents.h"
  10. #include "mozilla/MouseEvents.h"
  11. #include "mozilla/Preferences.h"
  12. #include "mozilla/TextEvents.h"
  13. #include "mozilla/TouchEvents.h"
  14. #include "nsIDOMEventTarget.h"
  15. #include "nsPrintfCString.h"
  16. namespace mozilla {
  17. /******************************************************************************
  18. * Global helper methods
  19. ******************************************************************************/
  20. const char*
  21. ToChar(EventMessage aEventMessage)
  22. {
  23. switch (aEventMessage) {
  24. #define NS_EVENT_MESSAGE(aMessage) \
  25. case aMessage: \
  26. return #aMessage;
  27. #include "mozilla/EventMessageList.h"
  28. #undef NS_EVENT_MESSAGE
  29. default:
  30. return "illegal event message";
  31. }
  32. }
  33. const char*
  34. ToChar(EventClassID aEventClassID)
  35. {
  36. switch (aEventClassID) {
  37. #define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
  38. case eBasic##aName##Class: \
  39. return "eBasic" #aName "Class";
  40. #define NS_EVENT_CLASS(aPrefix, aName) \
  41. case e##aName##Class: \
  42. return "e" #aName "Class";
  43. #include "mozilla/EventClassList.h"
  44. #undef NS_EVENT_CLASS
  45. #undef NS_ROOT_EVENT_CLASS
  46. default:
  47. return "illegal event class ID";
  48. }
  49. }
  50. const nsCString
  51. ToString(KeyNameIndex aKeyNameIndex)
  52. {
  53. if (aKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
  54. return NS_LITERAL_CSTRING("USE_STRING");
  55. }
  56. nsAutoString keyName;
  57. WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex, keyName);
  58. return NS_ConvertUTF16toUTF8(keyName);
  59. }
  60. const nsCString
  61. ToString(CodeNameIndex aCodeNameIndex)
  62. {
  63. if (aCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
  64. return NS_LITERAL_CSTRING("USE_STRING");
  65. }
  66. nsAutoString codeName;
  67. WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex, codeName);
  68. return NS_ConvertUTF16toUTF8(codeName);
  69. }
  70. const nsCString
  71. GetDOMKeyCodeName(uint32_t aKeyCode)
  72. {
  73. switch (aKeyCode) {
  74. #define NS_DISALLOW_SAME_KEYCODE
  75. #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
  76. case aDOMKeyCode: \
  77. return NS_LITERAL_CSTRING(#aDOMKeyName);
  78. #include "mozilla/VirtualKeyCodeList.h"
  79. #undef NS_DEFINE_VK
  80. #undef NS_DISALLOW_SAME_KEYCODE
  81. default:
  82. return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode);
  83. }
  84. }
  85. bool
  86. IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeType)
  87. {
  88. switch (static_cast<TextRangeType>(aRawTextRangeType)) {
  89. case TextRangeType::eUninitialized:
  90. case TextRangeType::eCaret:
  91. case TextRangeType::eRawClause:
  92. case TextRangeType::eSelectedRawClause:
  93. case TextRangeType::eConvertedClause:
  94. case TextRangeType::eSelectedClause:
  95. return true;
  96. default:
  97. return false;
  98. }
  99. }
  100. RawTextRangeType
  101. ToRawTextRangeType(TextRangeType aTextRangeType)
  102. {
  103. return static_cast<RawTextRangeType>(aTextRangeType);
  104. }
  105. TextRangeType
  106. ToTextRangeType(RawTextRangeType aRawTextRangeType)
  107. {
  108. MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType));
  109. return static_cast<TextRangeType>(aRawTextRangeType);
  110. }
  111. const char*
  112. ToChar(TextRangeType aTextRangeType)
  113. {
  114. switch (aTextRangeType) {
  115. case TextRangeType::eUninitialized:
  116. return "TextRangeType::eUninitialized";
  117. case TextRangeType::eCaret:
  118. return "TextRangeType::eCaret";
  119. case TextRangeType::eRawClause:
  120. return "TextRangeType::eRawClause";
  121. case TextRangeType::eSelectedRawClause:
  122. return "TextRangeType::eSelectedRawClause";
  123. case TextRangeType::eConvertedClause:
  124. return "TextRangeType::eConvertedClause";
  125. case TextRangeType::eSelectedClause:
  126. return "TextRangeType::eSelectedClause";
  127. default:
  128. return "Invalid TextRangeType";
  129. }
  130. }
  131. SelectionType
  132. ToSelectionType(TextRangeType aTextRangeType)
  133. {
  134. switch (aTextRangeType) {
  135. case TextRangeType::eRawClause:
  136. return SelectionType::eIMERawClause;
  137. case TextRangeType::eSelectedRawClause:
  138. return SelectionType::eIMESelectedRawClause;
  139. case TextRangeType::eConvertedClause:
  140. return SelectionType::eIMEConvertedClause;
  141. case TextRangeType::eSelectedClause:
  142. return SelectionType::eIMESelectedClause;
  143. default:
  144. MOZ_CRASH("TextRangeType is invalid");
  145. return SelectionType::eNormal;
  146. }
  147. }
  148. /******************************************************************************
  149. * As*Event() implementation
  150. ******************************************************************************/
  151. #define NS_ROOT_EVENT_CLASS(aPrefix, aName)
  152. #define NS_EVENT_CLASS(aPrefix, aName) \
  153. aPrefix##aName* \
  154. WidgetEvent::As##aName() \
  155. { \
  156. return nullptr; \
  157. } \
  158. \
  159. const aPrefix##aName* \
  160. WidgetEvent::As##aName() const \
  161. { \
  162. return const_cast<WidgetEvent*>(this)->As##aName(); \
  163. }
  164. #include "mozilla/EventClassList.h"
  165. #undef NS_EVENT_CLASS
  166. #undef NS_ROOT_EVENT_CLASS
  167. /******************************************************************************
  168. * mozilla::WidgetEvent
  169. *
  170. * Event struct type checking methods.
  171. ******************************************************************************/
  172. bool
  173. WidgetEvent::IsQueryContentEvent() const
  174. {
  175. return mClass == eQueryContentEventClass;
  176. }
  177. bool
  178. WidgetEvent::IsSelectionEvent() const
  179. {
  180. return mClass == eSelectionEventClass;
  181. }
  182. bool
  183. WidgetEvent::IsContentCommandEvent() const
  184. {
  185. return mClass == eContentCommandEventClass;
  186. }
  187. bool
  188. WidgetEvent::IsNativeEventDelivererForPlugin() const
  189. {
  190. return mClass == ePluginEventClass;
  191. }
  192. /******************************************************************************
  193. * mozilla::WidgetEvent
  194. *
  195. * Event message checking methods.
  196. ******************************************************************************/
  197. bool
  198. WidgetEvent::HasMouseEventMessage() const
  199. {
  200. switch (mMessage) {
  201. case eMouseDown:
  202. case eMouseUp:
  203. case eMouseClick:
  204. case eMouseDoubleClick:
  205. case eMouseAuxClick:
  206. case eMouseEnterIntoWidget:
  207. case eMouseExitFromWidget:
  208. case eMouseActivate:
  209. case eMouseOver:
  210. case eMouseOut:
  211. case eMouseHitTest:
  212. case eMouseMove:
  213. return true;
  214. default:
  215. return false;
  216. }
  217. }
  218. bool
  219. WidgetEvent::HasDragEventMessage() const
  220. {
  221. switch (mMessage) {
  222. case eDragEnter:
  223. case eDragOver:
  224. case eDragExit:
  225. case eDrag:
  226. case eDragEnd:
  227. case eDragStart:
  228. case eDrop:
  229. case eDragLeave:
  230. return true;
  231. default:
  232. return false;
  233. }
  234. }
  235. bool
  236. WidgetEvent::HasKeyEventMessage() const
  237. {
  238. switch (mMessage) {
  239. case eKeyDown:
  240. case eKeyPress:
  241. case eKeyUp:
  242. case eKeyDownOnPlugin:
  243. case eKeyUpOnPlugin:
  244. case eBeforeKeyDown:
  245. case eBeforeKeyUp:
  246. case eAfterKeyDown:
  247. case eAfterKeyUp:
  248. case eAccessKeyNotFound:
  249. return true;
  250. default:
  251. return false;
  252. }
  253. }
  254. bool
  255. WidgetEvent::HasIMEEventMessage() const
  256. {
  257. switch (mMessage) {
  258. case eCompositionStart:
  259. case eCompositionEnd:
  260. case eCompositionUpdate:
  261. case eCompositionChange:
  262. case eCompositionCommitAsIs:
  263. case eCompositionCommit:
  264. return true;
  265. default:
  266. return false;
  267. }
  268. }
  269. bool
  270. WidgetEvent::HasPluginActivationEventMessage() const
  271. {
  272. return mMessage == ePluginActivate ||
  273. mMessage == ePluginFocus;
  274. }
  275. /******************************************************************************
  276. * mozilla::WidgetEvent
  277. *
  278. * Specific event checking methods.
  279. ******************************************************************************/
  280. bool
  281. WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
  282. {
  283. const WidgetPluginEvent* pluginEvent = AsPluginEvent();
  284. return pluginEvent && pluginEvent->mRetargetToFocusedDocument;
  285. }
  286. bool
  287. WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const
  288. {
  289. const WidgetPluginEvent* pluginEvent = AsPluginEvent();
  290. return pluginEvent && !pluginEvent->mRetargetToFocusedDocument;
  291. }
  292. bool
  293. WidgetEvent::IsIMERelatedEvent() const
  294. {
  295. return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
  296. }
  297. bool
  298. WidgetEvent::IsUsingCoordinates() const
  299. {
  300. const WidgetMouseEvent* mouseEvent = AsMouseEvent();
  301. if (mouseEvent) {
  302. return !mouseEvent->IsContextMenuKeyEvent();
  303. }
  304. return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
  305. !HasPluginActivationEventMessage() &&
  306. !IsNativeEventDelivererForPlugin() &&
  307. !IsContentCommandEvent();
  308. }
  309. bool
  310. WidgetEvent::IsTargetedAtFocusedWindow() const
  311. {
  312. const WidgetMouseEvent* mouseEvent = AsMouseEvent();
  313. if (mouseEvent) {
  314. return mouseEvent->IsContextMenuKeyEvent();
  315. }
  316. return HasKeyEventMessage() || IsIMERelatedEvent() ||
  317. IsContentCommandEvent() ||
  318. IsRetargetedNativeEventDelivererForPlugin();
  319. }
  320. bool
  321. WidgetEvent::IsTargetedAtFocusedContent() const
  322. {
  323. const WidgetMouseEvent* mouseEvent = AsMouseEvent();
  324. if (mouseEvent) {
  325. return mouseEvent->IsContextMenuKeyEvent();
  326. }
  327. return HasKeyEventMessage() || IsIMERelatedEvent() ||
  328. IsRetargetedNativeEventDelivererForPlugin();
  329. }
  330. bool
  331. WidgetEvent::IsAllowedToDispatchDOMEvent() const
  332. {
  333. switch (mClass) {
  334. case eMouseEventClass:
  335. if (mMessage == eMouseTouchDrag) {
  336. return false;
  337. }
  338. MOZ_FALLTHROUGH;
  339. case ePointerEventClass:
  340. // We want synthesized mouse moves to cause mouseover and mouseout
  341. // DOM events (EventStateManager::PreHandleEvent), but not mousemove
  342. // DOM events.
  343. // Synthesized button up events also do not cause DOM events because they
  344. // do not have a reliable mRefPoint.
  345. return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
  346. case eWheelEventClass: {
  347. // wheel event whose all delta values are zero by user pref applied, it
  348. // shouldn't cause a DOM event.
  349. const WidgetWheelEvent* wheelEvent = AsWheelEvent();
  350. return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
  351. wheelEvent->mDeltaZ != 0.0;
  352. }
  353. // Following events are handled in EventStateManager, so, we don't need to
  354. // dispatch DOM event for them into the DOM tree.
  355. case eQueryContentEventClass:
  356. case eSelectionEventClass:
  357. case eContentCommandEventClass:
  358. return false;
  359. default:
  360. return true;
  361. }
  362. }
  363. /******************************************************************************
  364. * mozilla::WidgetEvent
  365. *
  366. * Misc methods.
  367. ******************************************************************************/
  368. static dom::EventTarget*
  369. GetTargetForDOMEvent(nsIDOMEventTarget* aTarget)
  370. {
  371. return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
  372. }
  373. dom::EventTarget*
  374. WidgetEvent::GetDOMEventTarget() const
  375. {
  376. return GetTargetForDOMEvent(mTarget);
  377. }
  378. dom::EventTarget*
  379. WidgetEvent::GetCurrentDOMEventTarget() const
  380. {
  381. return GetTargetForDOMEvent(mCurrentTarget);
  382. }
  383. dom::EventTarget*
  384. WidgetEvent::GetOriginalDOMEventTarget() const
  385. {
  386. if (mOriginalTarget) {
  387. return GetTargetForDOMEvent(mOriginalTarget);
  388. }
  389. return GetDOMEventTarget();
  390. }
  391. /******************************************************************************
  392. * mozilla::WidgetInputEvent
  393. ******************************************************************************/
  394. /* static */
  395. Modifier
  396. WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName)
  397. {
  398. if (aDOMKeyName.EqualsLiteral("Accel")) {
  399. return AccelModifier();
  400. }
  401. KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName);
  402. return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex);
  403. }
  404. /* static */
  405. Modifier
  406. WidgetInputEvent::AccelModifier()
  407. {
  408. static Modifier sAccelModifier = MODIFIER_NONE;
  409. if (sAccelModifier == MODIFIER_NONE) {
  410. switch (Preferences::GetInt("ui.key.accelKey", 0)) {
  411. case nsIDOMKeyEvent::DOM_VK_META:
  412. sAccelModifier = MODIFIER_META;
  413. break;
  414. case nsIDOMKeyEvent::DOM_VK_WIN:
  415. sAccelModifier = MODIFIER_OS;
  416. break;
  417. case nsIDOMKeyEvent::DOM_VK_ALT:
  418. sAccelModifier = MODIFIER_ALT;
  419. break;
  420. case nsIDOMKeyEvent::DOM_VK_CONTROL:
  421. sAccelModifier = MODIFIER_CONTROL;
  422. break;
  423. default:
  424. sAccelModifier = MODIFIER_CONTROL;
  425. break;
  426. }
  427. }
  428. return sAccelModifier;
  429. }
  430. /******************************************************************************
  431. * mozilla::WidgetWheelEvent (MouseEvents.h)
  432. ******************************************************************************/
  433. /* static */ double
  434. WidgetWheelEvent::ComputeOverriddenDelta(double aDelta, bool aIsForVertical)
  435. {
  436. if (!gfxPrefs::MouseWheelHasRootScrollDeltaOverride()) {
  437. return aDelta;
  438. }
  439. int32_t intFactor = aIsForVertical
  440. ? gfxPrefs::MouseWheelRootScrollVerticalFactor()
  441. : gfxPrefs::MouseWheelRootScrollHorizontalFactor();
  442. // Making the scroll speed slower doesn't make sense. So, ignore odd factor
  443. // which is less than 1.0.
  444. if (intFactor <= 100) {
  445. return aDelta;
  446. }
  447. double factor = static_cast<double>(intFactor) / 100;
  448. return aDelta * factor;
  449. }
  450. double
  451. WidgetWheelEvent::OverriddenDeltaX() const
  452. {
  453. if (!mAllowToOverrideSystemScrollSpeed) {
  454. return mDeltaX;
  455. }
  456. return ComputeOverriddenDelta(mDeltaX, false);
  457. }
  458. double
  459. WidgetWheelEvent::OverriddenDeltaY() const
  460. {
  461. if (!mAllowToOverrideSystemScrollSpeed) {
  462. return mDeltaY;
  463. }
  464. return ComputeOverriddenDelta(mDeltaY, true);
  465. }
  466. /******************************************************************************
  467. * mozilla::WidgetKeyboardEvent (TextEvents.h)
  468. ******************************************************************************/
  469. #define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
  470. const char16_t* const WidgetKeyboardEvent::kKeyNames[] = {
  471. #include "mozilla/KeyNameList.h"
  472. };
  473. #undef NS_DEFINE_KEYNAME
  474. #define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
  475. (u"" aDOMCodeName),
  476. const char16_t* const WidgetKeyboardEvent::kCodeNames[] = {
  477. #include "mozilla/PhysicalKeyCodeNameList.h"
  478. };
  479. #undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
  480. WidgetKeyboardEvent::KeyNameIndexHashtable*
  481. WidgetKeyboardEvent::sKeyNameIndexHashtable = nullptr;
  482. WidgetKeyboardEvent::CodeNameIndexHashtable*
  483. WidgetKeyboardEvent::sCodeNameIndexHashtable = nullptr;
  484. bool
  485. WidgetKeyboardEvent::ShouldCauseKeypressEvents() const
  486. {
  487. // Currently, we don't dispatch keypress events of modifier keys and
  488. // dead keys.
  489. switch (mKeyNameIndex) {
  490. case KEY_NAME_INDEX_Alt:
  491. case KEY_NAME_INDEX_AltGraph:
  492. case KEY_NAME_INDEX_CapsLock:
  493. case KEY_NAME_INDEX_Control:
  494. case KEY_NAME_INDEX_Fn:
  495. case KEY_NAME_INDEX_FnLock:
  496. // case KEY_NAME_INDEX_Hyper:
  497. case KEY_NAME_INDEX_Meta:
  498. case KEY_NAME_INDEX_NumLock:
  499. case KEY_NAME_INDEX_OS:
  500. case KEY_NAME_INDEX_ScrollLock:
  501. case KEY_NAME_INDEX_Shift:
  502. // case KEY_NAME_INDEX_Super:
  503. case KEY_NAME_INDEX_Symbol:
  504. case KEY_NAME_INDEX_SymbolLock:
  505. case KEY_NAME_INDEX_Dead:
  506. return false;
  507. default:
  508. return true;
  509. }
  510. }
  511. static bool
  512. HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates)
  513. {
  514. for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
  515. uint32_t ch = aCandidates[i].mCharCode;
  516. if (ch >= '0' && ch <= '9')
  517. return true;
  518. }
  519. return false;
  520. }
  521. static bool
  522. CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2)
  523. {
  524. return aChar1 == aChar2 ||
  525. (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
  526. ToLowerCase(static_cast<char16_t>(aChar1)) ==
  527. ToLowerCase(static_cast<char16_t>(aChar2)));
  528. }
  529. static bool
  530. IsCaseChangeableChar(uint32_t aChar)
  531. {
  532. return IS_IN_BMP(aChar) &&
  533. ToLowerCase(static_cast<char16_t>(aChar)) !=
  534. ToUpperCase(static_cast<char16_t>(aChar));
  535. }
  536. void
  537. WidgetKeyboardEvent::GetShortcutKeyCandidates(
  538. ShortcutKeyCandidateArray& aCandidates)
  539. {
  540. MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
  541. // ShortcutKeyCandidate::mCharCode is a candidate charCode.
  542. // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
  543. // execute a command with/without shift key state. If this is TRUE, the
  544. // shifted key state should be ignored. Otherwise, don't ignore the state.
  545. // the priority of the charCodes are (shift key is not pressed):
  546. // 0: PseudoCharCode()/false,
  547. // 1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
  548. // the priority of the charCodes are (shift key is pressed):
  549. // 0: PseudoCharCode()/false,
  550. // 1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
  551. // 3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
  552. uint32_t pseudoCharCode = PseudoCharCode();
  553. if (pseudoCharCode) {
  554. ShortcutKeyCandidate key(pseudoCharCode, false);
  555. aCandidates.AppendElement(key);
  556. }
  557. uint32_t len = mAlternativeCharCodes.Length();
  558. if (!IsShift()) {
  559. for (uint32_t i = 0; i < len; ++i) {
  560. uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
  561. if (!ch || ch == pseudoCharCode) {
  562. continue;
  563. }
  564. ShortcutKeyCandidate key(ch, false);
  565. aCandidates.AppendElement(key);
  566. }
  567. // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
  568. // this keyboard layout is AZERTY or similar layout, probably.
  569. // In this case, Accel+[0-9] should be accessible without shift key.
  570. // However, the priority should be lowest.
  571. if (!HasASCIIDigit(aCandidates)) {
  572. for (uint32_t i = 0; i < len; ++i) {
  573. uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
  574. if (ch >= '0' && ch <= '9') {
  575. ShortcutKeyCandidate key(ch, false);
  576. aCandidates.AppendElement(key);
  577. break;
  578. }
  579. }
  580. }
  581. } else {
  582. for (uint32_t i = 0; i < len; ++i) {
  583. uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
  584. if (!ch) {
  585. continue;
  586. }
  587. if (ch != pseudoCharCode) {
  588. ShortcutKeyCandidate key(ch, false);
  589. aCandidates.AppendElement(key);
  590. }
  591. // If the char is an alphabet, the shift key state should not be
  592. // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
  593. // And checking the charCode is same as unshiftedCharCode too.
  594. // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
  595. uint32_t unshiftCh = mAlternativeCharCodes[i].mUnshiftedCharCode;
  596. if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
  597. continue;
  598. }
  599. // On the Hebrew keyboard layout on Windows, the unshifted char is a
  600. // localized character but the shifted char is a Latin alphabet,
  601. // then, we should not execute without the shift state. See bug 433192.
  602. if (IsCaseChangeableChar(ch)) {
  603. continue;
  604. }
  605. // Setting the alternative charCode candidates for retry without shift
  606. // key state only when the shift key is pressed.
  607. ShortcutKeyCandidate key(ch, true);
  608. aCandidates.AppendElement(key);
  609. }
  610. }
  611. // Special case for "Space" key. With some keyboard layouts, "Space" with
  612. // or without Shift key causes non-ASCII space. For such keyboard layouts,
  613. // we should guarantee that the key press works as an ASCII white space key
  614. // press. However, if the space key is assigned to a function key, it
  615. // shouldn't work as a space key.
  616. if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
  617. mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
  618. ShortcutKeyCandidate spaceKey(' ', false);
  619. aCandidates.AppendElement(spaceKey);
  620. }
  621. }
  622. void
  623. WidgetKeyboardEvent::GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates)
  624. {
  625. MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
  626. // return the lower cased charCode candidates for access keys.
  627. // the priority of the charCodes are:
  628. // 0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
  629. // 3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
  630. if (mCharCode) {
  631. uint32_t ch = mCharCode;
  632. if (IS_IN_BMP(ch)) {
  633. ch = ToLowerCase(static_cast<char16_t>(ch));
  634. }
  635. aCandidates.AppendElement(ch);
  636. }
  637. for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
  638. uint32_t ch[2] =
  639. { mAlternativeCharCodes[i].mUnshiftedCharCode,
  640. mAlternativeCharCodes[i].mShiftedCharCode };
  641. for (uint32_t j = 0; j < 2; ++j) {
  642. if (!ch[j]) {
  643. continue;
  644. }
  645. if (IS_IN_BMP(ch[j])) {
  646. ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
  647. }
  648. // Don't append the mCharCode that was already appended.
  649. if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
  650. aCandidates.AppendElement(ch[j]);
  651. }
  652. }
  653. }
  654. // Special case for "Space" key. With some keyboard layouts, "Space" with
  655. // or without Shift key causes non-ASCII space. For such keyboard layouts,
  656. // we should guarantee that the key press works as an ASCII white space key
  657. // press. However, if the space key is assigned to a function key, it
  658. // shouldn't work as a space key.
  659. if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
  660. mCodeNameIndex == CODE_NAME_INDEX_Space && mCharCode != ' ') {
  661. aCandidates.AppendElement(' ');
  662. }
  663. return;
  664. }
  665. /* static */ void
  666. WidgetKeyboardEvent::Shutdown()
  667. {
  668. delete sKeyNameIndexHashtable;
  669. sKeyNameIndexHashtable = nullptr;
  670. delete sCodeNameIndexHashtable;
  671. sCodeNameIndexHashtable = nullptr;
  672. }
  673. /* static */ void
  674. WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
  675. nsAString& aKeyName)
  676. {
  677. if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
  678. aKeyName.Truncate();
  679. return;
  680. }
  681. MOZ_RELEASE_ASSERT(static_cast<size_t>(aKeyNameIndex) <
  682. ArrayLength(kKeyNames),
  683. "Illegal key enumeration value");
  684. aKeyName = kKeyNames[aKeyNameIndex];
  685. }
  686. /* static */ void
  687. WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
  688. nsAString& aCodeName)
  689. {
  690. if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
  691. aCodeName.Truncate();
  692. return;
  693. }
  694. MOZ_RELEASE_ASSERT(static_cast<size_t>(aCodeNameIndex) <
  695. ArrayLength(kCodeNames),
  696. "Illegal physical code enumeration value");
  697. aCodeName = kCodeNames[aCodeNameIndex];
  698. }
  699. /* static */ KeyNameIndex
  700. WidgetKeyboardEvent::GetKeyNameIndex(const nsAString& aKeyValue)
  701. {
  702. if (!sKeyNameIndexHashtable) {
  703. sKeyNameIndexHashtable =
  704. new KeyNameIndexHashtable(ArrayLength(kKeyNames));
  705. for (size_t i = 0; i < ArrayLength(kKeyNames); i++) {
  706. sKeyNameIndexHashtable->Put(nsDependentString(kKeyNames[i]),
  707. static_cast<KeyNameIndex>(i));
  708. }
  709. }
  710. KeyNameIndex result = KEY_NAME_INDEX_USE_STRING;
  711. sKeyNameIndexHashtable->Get(aKeyValue, &result);
  712. return result;
  713. }
  714. /* static */ CodeNameIndex
  715. WidgetKeyboardEvent::GetCodeNameIndex(const nsAString& aCodeValue)
  716. {
  717. if (!sCodeNameIndexHashtable) {
  718. sCodeNameIndexHashtable =
  719. new CodeNameIndexHashtable(ArrayLength(kCodeNames));
  720. for (size_t i = 0; i < ArrayLength(kCodeNames); i++) {
  721. sCodeNameIndexHashtable->Put(nsDependentString(kCodeNames[i]),
  722. static_cast<CodeNameIndex>(i));
  723. }
  724. }
  725. CodeNameIndex result = CODE_NAME_INDEX_USE_STRING;
  726. sCodeNameIndexHashtable->Get(aCodeValue, &result);
  727. return result;
  728. }
  729. /* static */ const char*
  730. WidgetKeyboardEvent::GetCommandStr(Command aCommand)
  731. {
  732. #define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
  733. static const char* const kCommands[] = {
  734. "" // CommandDoNothing
  735. #include "mozilla/CommandList.h"
  736. };
  737. #undef NS_DEFINE_COMMAND
  738. MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand) < ArrayLength(kCommands),
  739. "Illegal command enumeration value");
  740. return kCommands[aCommand];
  741. }
  742. /* static */ uint32_t
  743. WidgetKeyboardEvent::ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex)
  744. {
  745. // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
  746. // but are defined by D3E spec. So, they should be uncommented when the
  747. // code values are defined in the header.
  748. switch (aCodeNameIndex) {
  749. case CODE_NAME_INDEX_AltLeft:
  750. case CODE_NAME_INDEX_ControlLeft:
  751. case CODE_NAME_INDEX_OSLeft:
  752. case CODE_NAME_INDEX_ShiftLeft:
  753. return nsIDOMKeyEvent::DOM_KEY_LOCATION_LEFT;
  754. case CODE_NAME_INDEX_AltRight:
  755. case CODE_NAME_INDEX_ControlRight:
  756. case CODE_NAME_INDEX_OSRight:
  757. case CODE_NAME_INDEX_ShiftRight:
  758. return nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT;
  759. case CODE_NAME_INDEX_Numpad0:
  760. case CODE_NAME_INDEX_Numpad1:
  761. case CODE_NAME_INDEX_Numpad2:
  762. case CODE_NAME_INDEX_Numpad3:
  763. case CODE_NAME_INDEX_Numpad4:
  764. case CODE_NAME_INDEX_Numpad5:
  765. case CODE_NAME_INDEX_Numpad6:
  766. case CODE_NAME_INDEX_Numpad7:
  767. case CODE_NAME_INDEX_Numpad8:
  768. case CODE_NAME_INDEX_Numpad9:
  769. case CODE_NAME_INDEX_NumpadAdd:
  770. case CODE_NAME_INDEX_NumpadBackspace:
  771. case CODE_NAME_INDEX_NumpadClear:
  772. case CODE_NAME_INDEX_NumpadClearEntry:
  773. case CODE_NAME_INDEX_NumpadComma:
  774. case CODE_NAME_INDEX_NumpadDecimal:
  775. case CODE_NAME_INDEX_NumpadDivide:
  776. case CODE_NAME_INDEX_NumpadEnter:
  777. case CODE_NAME_INDEX_NumpadEqual:
  778. case CODE_NAME_INDEX_NumpadMemoryAdd:
  779. case CODE_NAME_INDEX_NumpadMemoryClear:
  780. case CODE_NAME_INDEX_NumpadMemoryRecall:
  781. case CODE_NAME_INDEX_NumpadMemoryStore:
  782. case CODE_NAME_INDEX_NumpadMemorySubtract:
  783. case CODE_NAME_INDEX_NumpadMultiply:
  784. case CODE_NAME_INDEX_NumpadParenLeft:
  785. case CODE_NAME_INDEX_NumpadParenRight:
  786. case CODE_NAME_INDEX_NumpadSubtract:
  787. return nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
  788. default:
  789. return nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD;
  790. }
  791. }
  792. /* static */ uint32_t
  793. WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex)
  794. {
  795. switch (aKeyNameIndex) {
  796. case KEY_NAME_INDEX_Cancel:
  797. return nsIDOMKeyEvent::DOM_VK_CANCEL;
  798. case KEY_NAME_INDEX_Help:
  799. return nsIDOMKeyEvent::DOM_VK_HELP;
  800. case KEY_NAME_INDEX_Backspace:
  801. return nsIDOMKeyEvent::DOM_VK_BACK_SPACE;
  802. case KEY_NAME_INDEX_Tab:
  803. return nsIDOMKeyEvent::DOM_VK_TAB;
  804. case KEY_NAME_INDEX_Clear:
  805. return nsIDOMKeyEvent::DOM_VK_CLEAR;
  806. case KEY_NAME_INDEX_Enter:
  807. return nsIDOMKeyEvent::DOM_VK_RETURN;
  808. case KEY_NAME_INDEX_Shift:
  809. return nsIDOMKeyEvent::DOM_VK_SHIFT;
  810. case KEY_NAME_INDEX_Control:
  811. return nsIDOMKeyEvent::DOM_VK_CONTROL;
  812. case KEY_NAME_INDEX_Alt:
  813. return nsIDOMKeyEvent::DOM_VK_ALT;
  814. case KEY_NAME_INDEX_Pause:
  815. return nsIDOMKeyEvent::DOM_VK_PAUSE;
  816. case KEY_NAME_INDEX_CapsLock:
  817. return nsIDOMKeyEvent::DOM_VK_CAPS_LOCK;
  818. case KEY_NAME_INDEX_Hiragana:
  819. case KEY_NAME_INDEX_Katakana:
  820. case KEY_NAME_INDEX_HiraganaKatakana:
  821. case KEY_NAME_INDEX_KanaMode:
  822. return nsIDOMKeyEvent::DOM_VK_KANA;
  823. case KEY_NAME_INDEX_HangulMode:
  824. return nsIDOMKeyEvent::DOM_VK_HANGUL;
  825. case KEY_NAME_INDEX_Eisu:
  826. return nsIDOMKeyEvent::DOM_VK_EISU;
  827. case KEY_NAME_INDEX_JunjaMode:
  828. return nsIDOMKeyEvent::DOM_VK_JUNJA;
  829. case KEY_NAME_INDEX_FinalMode:
  830. return nsIDOMKeyEvent::DOM_VK_FINAL;
  831. case KEY_NAME_INDEX_HanjaMode:
  832. return nsIDOMKeyEvent::DOM_VK_HANJA;
  833. case KEY_NAME_INDEX_KanjiMode:
  834. return nsIDOMKeyEvent::DOM_VK_KANJI;
  835. case KEY_NAME_INDEX_Escape:
  836. return nsIDOMKeyEvent::DOM_VK_ESCAPE;
  837. case KEY_NAME_INDEX_Convert:
  838. return nsIDOMKeyEvent::DOM_VK_CONVERT;
  839. case KEY_NAME_INDEX_NonConvert:
  840. return nsIDOMKeyEvent::DOM_VK_NONCONVERT;
  841. case KEY_NAME_INDEX_Accept:
  842. return nsIDOMKeyEvent::DOM_VK_ACCEPT;
  843. case KEY_NAME_INDEX_ModeChange:
  844. return nsIDOMKeyEvent::DOM_VK_MODECHANGE;
  845. case KEY_NAME_INDEX_PageUp:
  846. return nsIDOMKeyEvent::DOM_VK_PAGE_UP;
  847. case KEY_NAME_INDEX_PageDown:
  848. return nsIDOMKeyEvent::DOM_VK_PAGE_DOWN;
  849. case KEY_NAME_INDEX_End:
  850. return nsIDOMKeyEvent::DOM_VK_END;
  851. case KEY_NAME_INDEX_Home:
  852. return nsIDOMKeyEvent::DOM_VK_HOME;
  853. case KEY_NAME_INDEX_ArrowLeft:
  854. return nsIDOMKeyEvent::DOM_VK_LEFT;
  855. case KEY_NAME_INDEX_ArrowUp:
  856. return nsIDOMKeyEvent::DOM_VK_UP;
  857. case KEY_NAME_INDEX_ArrowRight:
  858. return nsIDOMKeyEvent::DOM_VK_RIGHT;
  859. case KEY_NAME_INDEX_ArrowDown:
  860. return nsIDOMKeyEvent::DOM_VK_DOWN;
  861. case KEY_NAME_INDEX_Select:
  862. return nsIDOMKeyEvent::DOM_VK_SELECT;
  863. case KEY_NAME_INDEX_Print:
  864. return nsIDOMKeyEvent::DOM_VK_PRINT;
  865. case KEY_NAME_INDEX_Execute:
  866. return nsIDOMKeyEvent::DOM_VK_EXECUTE;
  867. case KEY_NAME_INDEX_PrintScreen:
  868. return nsIDOMKeyEvent::DOM_VK_PRINTSCREEN;
  869. case KEY_NAME_INDEX_Insert:
  870. return nsIDOMKeyEvent::DOM_VK_INSERT;
  871. case KEY_NAME_INDEX_Delete:
  872. return nsIDOMKeyEvent::DOM_VK_DELETE;
  873. case KEY_NAME_INDEX_OS:
  874. // case KEY_NAME_INDEX_Super:
  875. // case KEY_NAME_INDEX_Hyper:
  876. return nsIDOMKeyEvent::DOM_VK_WIN;
  877. case KEY_NAME_INDEX_ContextMenu:
  878. return nsIDOMKeyEvent::DOM_VK_CONTEXT_MENU;
  879. case KEY_NAME_INDEX_Standby:
  880. return nsIDOMKeyEvent::DOM_VK_SLEEP;
  881. case KEY_NAME_INDEX_F1:
  882. return nsIDOMKeyEvent::DOM_VK_F1;
  883. case KEY_NAME_INDEX_F2:
  884. return nsIDOMKeyEvent::DOM_VK_F2;
  885. case KEY_NAME_INDEX_F3:
  886. return nsIDOMKeyEvent::DOM_VK_F3;
  887. case KEY_NAME_INDEX_F4:
  888. return nsIDOMKeyEvent::DOM_VK_F4;
  889. case KEY_NAME_INDEX_F5:
  890. return nsIDOMKeyEvent::DOM_VK_F5;
  891. case KEY_NAME_INDEX_F6:
  892. return nsIDOMKeyEvent::DOM_VK_F6;
  893. case KEY_NAME_INDEX_F7:
  894. return nsIDOMKeyEvent::DOM_VK_F7;
  895. case KEY_NAME_INDEX_F8:
  896. return nsIDOMKeyEvent::DOM_VK_F8;
  897. case KEY_NAME_INDEX_F9:
  898. return nsIDOMKeyEvent::DOM_VK_F9;
  899. case KEY_NAME_INDEX_F10:
  900. return nsIDOMKeyEvent::DOM_VK_F10;
  901. case KEY_NAME_INDEX_F11:
  902. return nsIDOMKeyEvent::DOM_VK_F11;
  903. case KEY_NAME_INDEX_F12:
  904. return nsIDOMKeyEvent::DOM_VK_F12;
  905. case KEY_NAME_INDEX_F13:
  906. return nsIDOMKeyEvent::DOM_VK_F13;
  907. case KEY_NAME_INDEX_F14:
  908. return nsIDOMKeyEvent::DOM_VK_F14;
  909. case KEY_NAME_INDEX_F15:
  910. return nsIDOMKeyEvent::DOM_VK_F15;
  911. case KEY_NAME_INDEX_F16:
  912. return nsIDOMKeyEvent::DOM_VK_F16;
  913. case KEY_NAME_INDEX_F17:
  914. return nsIDOMKeyEvent::DOM_VK_F17;
  915. case KEY_NAME_INDEX_F18:
  916. return nsIDOMKeyEvent::DOM_VK_F18;
  917. case KEY_NAME_INDEX_F19:
  918. return nsIDOMKeyEvent::DOM_VK_F19;
  919. case KEY_NAME_INDEX_F20:
  920. return nsIDOMKeyEvent::DOM_VK_F20;
  921. case KEY_NAME_INDEX_F21:
  922. return nsIDOMKeyEvent::DOM_VK_F21;
  923. case KEY_NAME_INDEX_F22:
  924. return nsIDOMKeyEvent::DOM_VK_F22;
  925. case KEY_NAME_INDEX_F23:
  926. return nsIDOMKeyEvent::DOM_VK_F23;
  927. case KEY_NAME_INDEX_F24:
  928. return nsIDOMKeyEvent::DOM_VK_F24;
  929. case KEY_NAME_INDEX_NumLock:
  930. return nsIDOMKeyEvent::DOM_VK_NUM_LOCK;
  931. case KEY_NAME_INDEX_ScrollLock:
  932. return nsIDOMKeyEvent::DOM_VK_SCROLL_LOCK;
  933. case KEY_NAME_INDEX_AudioVolumeMute:
  934. return nsIDOMKeyEvent::DOM_VK_VOLUME_MUTE;
  935. case KEY_NAME_INDEX_AudioVolumeDown:
  936. return nsIDOMKeyEvent::DOM_VK_VOLUME_DOWN;
  937. case KEY_NAME_INDEX_AudioVolumeUp:
  938. return nsIDOMKeyEvent::DOM_VK_VOLUME_UP;
  939. case KEY_NAME_INDEX_Meta:
  940. return nsIDOMKeyEvent::DOM_VK_META;
  941. case KEY_NAME_INDEX_AltGraph:
  942. return nsIDOMKeyEvent::DOM_VK_ALTGR;
  943. case KEY_NAME_INDEX_Attn:
  944. return nsIDOMKeyEvent::DOM_VK_ATTN;
  945. case KEY_NAME_INDEX_CrSel:
  946. return nsIDOMKeyEvent::DOM_VK_CRSEL;
  947. case KEY_NAME_INDEX_ExSel:
  948. return nsIDOMKeyEvent::DOM_VK_EXSEL;
  949. case KEY_NAME_INDEX_EraseEof:
  950. return nsIDOMKeyEvent::DOM_VK_EREOF;
  951. case KEY_NAME_INDEX_Play:
  952. return nsIDOMKeyEvent::DOM_VK_PLAY;
  953. case KEY_NAME_INDEX_ZoomToggle:
  954. case KEY_NAME_INDEX_ZoomIn:
  955. case KEY_NAME_INDEX_ZoomOut:
  956. return nsIDOMKeyEvent::DOM_VK_ZOOM;
  957. default:
  958. return 0;
  959. }
  960. }
  961. /* static */ Modifier
  962. WidgetKeyboardEvent::GetModifierForKeyName(KeyNameIndex aKeyNameIndex)
  963. {
  964. switch (aKeyNameIndex) {
  965. case KEY_NAME_INDEX_Alt:
  966. return MODIFIER_ALT;
  967. case KEY_NAME_INDEX_AltGraph:
  968. return MODIFIER_ALTGRAPH;
  969. case KEY_NAME_INDEX_CapsLock:
  970. return MODIFIER_CAPSLOCK;
  971. case KEY_NAME_INDEX_Control:
  972. return MODIFIER_CONTROL;
  973. case KEY_NAME_INDEX_Fn:
  974. return MODIFIER_FN;
  975. case KEY_NAME_INDEX_FnLock:
  976. return MODIFIER_FNLOCK;
  977. // case KEY_NAME_INDEX_Hyper:
  978. case KEY_NAME_INDEX_Meta:
  979. return MODIFIER_META;
  980. case KEY_NAME_INDEX_NumLock:
  981. return MODIFIER_NUMLOCK;
  982. case KEY_NAME_INDEX_OS:
  983. return MODIFIER_OS;
  984. case KEY_NAME_INDEX_ScrollLock:
  985. return MODIFIER_SCROLLLOCK;
  986. case KEY_NAME_INDEX_Shift:
  987. return MODIFIER_SHIFT;
  988. // case KEY_NAME_INDEX_Super:
  989. case KEY_NAME_INDEX_Symbol:
  990. return MODIFIER_SYMBOL;
  991. case KEY_NAME_INDEX_SymbolLock:
  992. return MODIFIER_SYMBOLLOCK;
  993. default:
  994. return MODIFIER_NONE;
  995. }
  996. }
  997. /* static */ bool
  998. WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex)
  999. {
  1000. switch (aKeyNameIndex) {
  1001. case KEY_NAME_INDEX_CapsLock:
  1002. case KEY_NAME_INDEX_FnLock:
  1003. case KEY_NAME_INDEX_NumLock:
  1004. case KEY_NAME_INDEX_ScrollLock:
  1005. case KEY_NAME_INDEX_SymbolLock:
  1006. return true;
  1007. default:
  1008. return false;
  1009. }
  1010. }
  1011. } // namespace mozilla