TextEvents.h 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  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. #ifndef mozilla_TextEvents_h__
  6. #define mozilla_TextEvents_h__
  7. #include <stdint.h>
  8. #include "mozilla/Assertions.h"
  9. #include "mozilla/BasicEvents.h"
  10. #include "mozilla/CheckedInt.h"
  11. #include "mozilla/EventForwards.h" // for KeyNameIndex, temporarily
  12. #include "mozilla/TextRange.h"
  13. #include "mozilla/FontRange.h"
  14. #include "nsCOMPtr.h"
  15. #include "nsIDOMKeyEvent.h"
  16. #include "nsISelectionController.h"
  17. #include "nsISelectionListener.h"
  18. #include "nsITransferable.h"
  19. #include "nsRect.h"
  20. #include "nsStringGlue.h"
  21. #include "nsTArray.h"
  22. #include "WritingModes.h"
  23. class nsStringHashKey;
  24. template<class, class> class nsDataHashtable;
  25. /******************************************************************************
  26. * virtual keycode values
  27. ******************************************************************************/
  28. enum
  29. {
  30. #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) NS_##aDOMKeyName = aDOMKeyCode,
  31. #include "mozilla/VirtualKeyCodeList.h"
  32. #undef NS_DEFINE_VK
  33. NS_VK_UNKNOWN = 0xFF
  34. };
  35. namespace mozilla {
  36. const nsCString GetDOMKeyCodeName(uint32_t aKeyCode);
  37. namespace dom {
  38. class PBrowserParent;
  39. class PBrowserChild;
  40. } // namespace dom
  41. namespace plugins {
  42. class PPluginInstanceChild;
  43. } // namespace plugins
  44. /******************************************************************************
  45. * mozilla::AlternativeCharCode
  46. *
  47. * This stores alternative charCode values of a key event with some modifiers.
  48. * The stored values proper for testing shortcut key or access key.
  49. ******************************************************************************/
  50. struct AlternativeCharCode
  51. {
  52. AlternativeCharCode() :
  53. mUnshiftedCharCode(0), mShiftedCharCode(0)
  54. {
  55. }
  56. AlternativeCharCode(uint32_t aUnshiftedCharCode, uint32_t aShiftedCharCode) :
  57. mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
  58. {
  59. }
  60. uint32_t mUnshiftedCharCode;
  61. uint32_t mShiftedCharCode;
  62. };
  63. /******************************************************************************
  64. * mozilla::ShortcutKeyCandidate
  65. *
  66. * This stores a candidate of shortcut key combination.
  67. ******************************************************************************/
  68. struct ShortcutKeyCandidate
  69. {
  70. ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
  71. : mCharCode(aCharCode)
  72. , mIgnoreShift(aIgnoreShift)
  73. {
  74. }
  75. // The mCharCode value which must match keyboard shortcut definition.
  76. uint32_t mCharCode;
  77. // true if Shift state can be ignored. Otherwise, Shift key state must
  78. // match keyboard shortcut definition.
  79. bool mIgnoreShift;
  80. };
  81. /******************************************************************************
  82. * mozilla::WidgetKeyboardEvent
  83. ******************************************************************************/
  84. class WidgetKeyboardEvent : public WidgetInputEvent
  85. {
  86. private:
  87. friend class dom::PBrowserParent;
  88. friend class dom::PBrowserChild;
  89. protected:
  90. WidgetKeyboardEvent()
  91. : mNativeKeyEvent(nullptr)
  92. , mKeyCode(0)
  93. , mCharCode(0)
  94. , mPseudoCharCode(0)
  95. , mLocation(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD)
  96. , mAccessKeyForwardedToChild(false)
  97. , mUniqueId(0)
  98. , mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
  99. , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
  100. , mInputMethodAppState(eNotHandled)
  101. , mIsChar(false)
  102. , mIsRepeat(false)
  103. , mIsComposing(false)
  104. , mIsReserved(false)
  105. , mIsSynthesizedByTIP(false)
  106. {
  107. }
  108. public:
  109. virtual WidgetKeyboardEvent* AsKeyboardEvent() override { return this; }
  110. WidgetKeyboardEvent(bool aIsTrusted, EventMessage aMessage,
  111. nsIWidget* aWidget,
  112. EventClassID aEventClassID = eKeyboardEventClass)
  113. : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
  114. , mNativeKeyEvent(nullptr)
  115. , mKeyCode(0)
  116. , mCharCode(0)
  117. , mPseudoCharCode(0)
  118. , mLocation(nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD)
  119. , mAccessKeyForwardedToChild(false)
  120. , mUniqueId(0)
  121. , mKeyNameIndex(mozilla::KEY_NAME_INDEX_Unidentified)
  122. , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
  123. , mInputMethodAppState(eNotHandled)
  124. , mIsChar(false)
  125. , mIsRepeat(false)
  126. , mIsComposing(false)
  127. , mIsReserved(false)
  128. , mIsSynthesizedByTIP(false)
  129. {
  130. // If this is a keyboard event on a plugin, it shouldn't fired on content.
  131. mFlags.mOnlySystemGroupDispatchInContent =
  132. mFlags.mNoCrossProcessBoundaryForwarding = IsKeyEventOnPlugin();
  133. }
  134. static bool IsKeyDownOrKeyDownOnPlugin(EventMessage aMessage)
  135. {
  136. return aMessage == eKeyDown || aMessage == eKeyDownOnPlugin;
  137. }
  138. bool IsKeyDownOrKeyDownOnPlugin() const
  139. {
  140. return IsKeyDownOrKeyDownOnPlugin(mMessage);
  141. }
  142. static bool IsKeyUpOrKeyUpOnPlugin(EventMessage aMessage)
  143. {
  144. return aMessage == eKeyUp || aMessage == eKeyUpOnPlugin;
  145. }
  146. bool IsKeyUpOrKeyUpOnPlugin() const
  147. {
  148. return IsKeyUpOrKeyUpOnPlugin(mMessage);
  149. }
  150. static bool IsKeyEventOnPlugin(EventMessage aMessage)
  151. {
  152. return aMessage == eKeyDownOnPlugin || aMessage == eKeyUpOnPlugin;
  153. }
  154. bool IsKeyEventOnPlugin() const
  155. {
  156. return IsKeyEventOnPlugin(mMessage);
  157. }
  158. virtual WidgetEvent* Duplicate() const override
  159. {
  160. MOZ_ASSERT(mClass == eKeyboardEventClass,
  161. "Duplicate() must be overridden by sub class");
  162. // Not copying widget, it is a weak reference.
  163. WidgetKeyboardEvent* result =
  164. new WidgetKeyboardEvent(false, mMessage, nullptr);
  165. result->AssignKeyEventData(*this, true);
  166. result->mFlags = mFlags;
  167. return result;
  168. }
  169. // OS translated Unicode chars which are used for accesskey and accelkey
  170. // handling. The handlers will try from first character to last character.
  171. nsTArray<AlternativeCharCode> mAlternativeCharCodes;
  172. // DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
  173. nsString mKeyValue;
  174. // DOM KeyboardEvent.code only when mCodeNameIndex is
  175. // CODE_NAME_INDEX_USE_STRING.
  176. nsString mCodeValue;
  177. // OS-specific native event can optionally be preserved
  178. void* mNativeKeyEvent;
  179. // A DOM keyCode value or 0. If a keypress event whose mCharCode is 0, this
  180. // should be 0.
  181. uint32_t mKeyCode;
  182. // If the instance is a keypress event of a printable key, this is a UTF-16
  183. // value of the key. Otherwise, 0. This value must not be a control
  184. // character when some modifiers are active. Then, this value should be an
  185. // unmodified value except Shift and AltGr.
  186. uint32_t mCharCode;
  187. // mPseudoCharCode is valid only when mMessage is an eKeyDown event.
  188. // This stores mCharCode value of keypress event which is fired with same
  189. // key value and same modifier state.
  190. uint32_t mPseudoCharCode;
  191. // One of nsIDOMKeyEvent::DOM_KEY_LOCATION_*
  192. uint32_t mLocation;
  193. // True if accesskey handling was forwarded to the child via
  194. // TabParent::HandleAccessKey. In this case, parent process menu access key
  195. // handling should be delayed until it is determined that there exists no
  196. // overriding access key in the content process.
  197. bool mAccessKeyForwardedToChild;
  198. // Unique id associated with a keydown / keypress event. Used in identifing
  199. // keypress events for removal from async event dispatch queue in metrofx
  200. // after preventDefault is called on keydown events. It's ok if this wraps
  201. // over long periods.
  202. uint32_t mUniqueId;
  203. // DOM KeyboardEvent.key
  204. KeyNameIndex mKeyNameIndex;
  205. // DOM KeyboardEvent.code
  206. CodeNameIndex mCodeNameIndex;
  207. // Indicates that the event is being handled by input method app
  208. typedef uint8_t InputMethodAppStateType;
  209. enum InputMethodAppState : InputMethodAppStateType
  210. {
  211. eNotHandled, // not yet handled by intput method app
  212. eHandling, // being handled by intput method app
  213. eHandled // handled by input method app
  214. };
  215. InputMethodAppState mInputMethodAppState;
  216. // Indicates whether the event signifies a printable character
  217. bool mIsChar;
  218. // Indicates whether the event is generated by auto repeat or not.
  219. // if this is keyup event, always false.
  220. bool mIsRepeat;
  221. // Indicates whether the event is generated during IME (or deadkey)
  222. // composition. This is initialized by EventStateManager. So, key event
  223. // dispatchers don't need to initialize this.
  224. bool mIsComposing;
  225. // Indicates if the key combination is reserved by chrome. This is set by
  226. // nsXBLWindowKeyHandler at capturing phase of the default event group.
  227. bool mIsReserved;
  228. // Indicates whether the event is synthesized from Text Input Processor
  229. // or an actual event from nsAppShell.
  230. bool mIsSynthesizedByTIP;
  231. // If the key should cause keypress events, this returns true.
  232. // Otherwise, false.
  233. bool ShouldCauseKeypressEvents() const;
  234. // mCharCode value of non-eKeyPress events is always 0. However, if
  235. // non-eKeyPress event has one or more alternative char code values,
  236. // its first item should be the mCharCode value of following eKeyPress event.
  237. // PseudoCharCode() returns mCharCode value for eKeyPress event,
  238. // the first alternative char code value of non-eKeyPress event or 0.
  239. uint32_t PseudoCharCode() const
  240. {
  241. return mMessage == eKeyPress ? mCharCode : mPseudoCharCode;
  242. }
  243. void SetCharCode(uint32_t aCharCode)
  244. {
  245. if (mMessage == eKeyPress) {
  246. mCharCode = aCharCode;
  247. } else {
  248. mPseudoCharCode = aCharCode;
  249. }
  250. }
  251. void GetDOMKeyName(nsAString& aKeyName)
  252. {
  253. if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
  254. aKeyName = mKeyValue;
  255. return;
  256. }
  257. GetDOMKeyName(mKeyNameIndex, aKeyName);
  258. }
  259. void GetDOMCodeName(nsAString& aCodeName)
  260. {
  261. if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
  262. aCodeName = mCodeValue;
  263. return;
  264. }
  265. GetDOMCodeName(mCodeNameIndex, aCodeName);
  266. }
  267. bool IsModifierKeyEvent() const
  268. {
  269. return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE;
  270. }
  271. /**
  272. * Get the candidates for shortcut key.
  273. *
  274. * @param aCandidates [out] the candidate shortcut key combination list.
  275. * the first item is most preferred.
  276. */
  277. void GetShortcutKeyCandidates(ShortcutKeyCandidateArray& aCandidates);
  278. /**
  279. * Get the candidates for access key.
  280. *
  281. * @param aCandidates [out] the candidate access key list.
  282. * the first item is most preferred.
  283. */
  284. void GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates);
  285. static void Shutdown();
  286. /**
  287. * ComputeLocationFromCodeValue() returns one of .mLocation value
  288. * (nsIDOMKeyEvent::DOM_KEY_LOCATION_*) which is the most preferred value
  289. * for the specified specified code value.
  290. */
  291. static uint32_t ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex);
  292. /**
  293. * ComputeKeyCodeFromKeyNameIndex() return a .mKeyCode value which can be
  294. * mapped from the specified key value. Note that this returns 0 if the
  295. * key name index is KEY_NAME_INDEX_Unidentified or KEY_NAME_INDEX_USE_STRING.
  296. * This means that this method is useful only for non-printable keys.
  297. */
  298. static uint32_t ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex);
  299. /**
  300. * GetModifierForKeyName() returns a value of Modifier which is activated
  301. * by the aKeyNameIndex.
  302. */
  303. static Modifier GetModifierForKeyName(KeyNameIndex aKeyNameIndex);
  304. /**
  305. * IsLockableModifier() returns true if aKeyNameIndex is a lockable modifier
  306. * key such as CapsLock and NumLock.
  307. */
  308. static bool IsLockableModifier(KeyNameIndex aKeyNameIndex);
  309. static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
  310. nsAString& aKeyName);
  311. static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
  312. nsAString& aCodeName);
  313. static KeyNameIndex GetKeyNameIndex(const nsAString& aKeyValue);
  314. static CodeNameIndex GetCodeNameIndex(const nsAString& aCodeValue);
  315. static const char* GetCommandStr(Command aCommand);
  316. void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
  317. {
  318. AssignInputEventData(aEvent, aCopyTargets);
  319. mKeyCode = aEvent.mKeyCode;
  320. mCharCode = aEvent.mCharCode;
  321. mPseudoCharCode = aEvent.mPseudoCharCode;
  322. mLocation = aEvent.mLocation;
  323. mAlternativeCharCodes = aEvent.mAlternativeCharCodes;
  324. mIsChar = aEvent.mIsChar;
  325. mIsRepeat = aEvent.mIsRepeat;
  326. mIsComposing = aEvent.mIsComposing;
  327. mIsReserved = aEvent.mIsReserved;
  328. mAccessKeyForwardedToChild = aEvent.mAccessKeyForwardedToChild;
  329. mKeyNameIndex = aEvent.mKeyNameIndex;
  330. mCodeNameIndex = aEvent.mCodeNameIndex;
  331. mKeyValue = aEvent.mKeyValue;
  332. mCodeValue = aEvent.mCodeValue;
  333. // Don't copy mNativeKeyEvent because it may be referred after its instance
  334. // is destroyed.
  335. mNativeKeyEvent = nullptr;
  336. mUniqueId = aEvent.mUniqueId;
  337. mInputMethodAppState = aEvent.mInputMethodAppState;
  338. mIsSynthesizedByTIP = aEvent.mIsSynthesizedByTIP;
  339. }
  340. private:
  341. static const char16_t* const kKeyNames[];
  342. static const char16_t* const kCodeNames[];
  343. typedef nsDataHashtable<nsStringHashKey,
  344. KeyNameIndex> KeyNameIndexHashtable;
  345. typedef nsDataHashtable<nsStringHashKey,
  346. CodeNameIndex> CodeNameIndexHashtable;
  347. static KeyNameIndexHashtable* sKeyNameIndexHashtable;
  348. static CodeNameIndexHashtable* sCodeNameIndexHashtable;
  349. };
  350. /******************************************************************************
  351. * mozilla::InternalBeforeAfterKeyboardEvent
  352. *
  353. * This is extended from WidgetKeyboardEvent and is mapped to DOM event
  354. * "BeforeAfterKeyboardEvent".
  355. *
  356. * Event mMessage: eBeforeKeyDown
  357. * eBeforeKeyUp
  358. * eAfterKeyDown
  359. * eAfterKeyUp
  360. ******************************************************************************/
  361. class InternalBeforeAfterKeyboardEvent : public WidgetKeyboardEvent
  362. {
  363. private:
  364. friend class dom::PBrowserParent;
  365. friend class dom::PBrowserChild;
  366. InternalBeforeAfterKeyboardEvent()
  367. {
  368. }
  369. public:
  370. // Extra member for InternalBeforeAfterKeyboardEvent. Indicates whether
  371. // default actions of keydown/keyup event is prevented.
  372. Nullable<bool> mEmbeddedCancelled;
  373. virtual InternalBeforeAfterKeyboardEvent* AsBeforeAfterKeyboardEvent() override
  374. {
  375. return this;
  376. }
  377. InternalBeforeAfterKeyboardEvent(bool aIsTrusted, EventMessage aMessage,
  378. nsIWidget* aWidget)
  379. : WidgetKeyboardEvent(aIsTrusted, aMessage, aWidget,
  380. eBeforeAfterKeyboardEventClass)
  381. {
  382. }
  383. virtual WidgetEvent* Duplicate() const override
  384. {
  385. MOZ_ASSERT(mClass == eBeforeAfterKeyboardEventClass,
  386. "Duplicate() must be overridden by sub class");
  387. // Not copying widget, it is a weak reference.
  388. InternalBeforeAfterKeyboardEvent* result =
  389. new InternalBeforeAfterKeyboardEvent(false, mMessage, nullptr);
  390. result->AssignBeforeAfterKeyEventData(*this, true);
  391. result->mFlags = mFlags;
  392. return result;
  393. }
  394. void AssignBeforeAfterKeyEventData(
  395. const InternalBeforeAfterKeyboardEvent& aEvent,
  396. bool aCopyTargets)
  397. {
  398. AssignKeyEventData(aEvent, aCopyTargets);
  399. mEmbeddedCancelled = aEvent.mEmbeddedCancelled;
  400. }
  401. void AssignBeforeAfterKeyEventData(
  402. const WidgetKeyboardEvent& aEvent,
  403. bool aCopyTargets)
  404. {
  405. AssignKeyEventData(aEvent, aCopyTargets);
  406. }
  407. };
  408. /******************************************************************************
  409. * mozilla::WidgetCompositionEvent
  410. ******************************************************************************/
  411. class WidgetCompositionEvent : public WidgetGUIEvent
  412. {
  413. private:
  414. friend class mozilla::dom::PBrowserParent;
  415. friend class mozilla::dom::PBrowserChild;
  416. WidgetCompositionEvent()
  417. {
  418. }
  419. public:
  420. virtual WidgetCompositionEvent* AsCompositionEvent() override
  421. {
  422. return this;
  423. }
  424. WidgetCompositionEvent(bool aIsTrusted, EventMessage aMessage,
  425. nsIWidget* aWidget)
  426. : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
  427. , mNativeIMEContext(aWidget)
  428. , mOriginalMessage(eVoidEvent)
  429. {
  430. }
  431. virtual WidgetEvent* Duplicate() const override
  432. {
  433. MOZ_ASSERT(mClass == eCompositionEventClass,
  434. "Duplicate() must be overridden by sub class");
  435. // Not copying widget, it is a weak reference.
  436. WidgetCompositionEvent* result =
  437. new WidgetCompositionEvent(false, mMessage, nullptr);
  438. result->AssignCompositionEventData(*this, true);
  439. result->mFlags = mFlags;
  440. return result;
  441. }
  442. // The composition string or the commit string. If the instance is a
  443. // compositionstart event, this is initialized with selected text by
  444. // TextComposition automatically.
  445. nsString mData;
  446. RefPtr<TextRangeArray> mRanges;
  447. // mNativeIMEContext stores the native IME context which causes the
  448. // composition event.
  449. widget::NativeIMEContext mNativeIMEContext;
  450. // If the instance is a clone of another event, mOriginalMessage stores
  451. // the another event's mMessage.
  452. EventMessage mOriginalMessage;
  453. void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
  454. bool aCopyTargets)
  455. {
  456. AssignGUIEventData(aEvent, aCopyTargets);
  457. mData = aEvent.mData;
  458. mOriginalMessage = aEvent.mOriginalMessage;
  459. mRanges = aEvent.mRanges;
  460. // Currently, we don't need to copy the other members because they are
  461. // for internal use only (not available from JS).
  462. }
  463. bool IsComposing() const
  464. {
  465. return mRanges && mRanges->IsComposing();
  466. }
  467. uint32_t TargetClauseOffset() const
  468. {
  469. return mRanges ? mRanges->TargetClauseOffset() : 0;
  470. }
  471. uint32_t TargetClauseLength() const
  472. {
  473. uint32_t length = UINT32_MAX;
  474. if (mRanges) {
  475. length = mRanges->TargetClauseLength();
  476. }
  477. return length == UINT32_MAX ? mData.Length() : length;
  478. }
  479. uint32_t RangeCount() const
  480. {
  481. return mRanges ? mRanges->Length() : 0;
  482. }
  483. bool CausesDOMTextEvent() const
  484. {
  485. return mMessage == eCompositionChange ||
  486. mMessage == eCompositionCommit ||
  487. mMessage == eCompositionCommitAsIs;
  488. }
  489. bool CausesDOMCompositionEndEvent() const
  490. {
  491. return mMessage == eCompositionEnd ||
  492. mMessage == eCompositionCommit ||
  493. mMessage == eCompositionCommitAsIs;
  494. }
  495. bool IsFollowedByCompositionEnd() const
  496. {
  497. return IsFollowedByCompositionEnd(mOriginalMessage);
  498. }
  499. static bool IsFollowedByCompositionEnd(EventMessage aEventMessage)
  500. {
  501. return aEventMessage == eCompositionCommit ||
  502. aEventMessage == eCompositionCommitAsIs;
  503. }
  504. };
  505. /******************************************************************************
  506. * mozilla::WidgetQueryContentEvent
  507. ******************************************************************************/
  508. class WidgetQueryContentEvent : public WidgetGUIEvent
  509. {
  510. private:
  511. friend class dom::PBrowserParent;
  512. friend class dom::PBrowserChild;
  513. WidgetQueryContentEvent()
  514. : mSucceeded(false)
  515. , mUseNativeLineBreak(true)
  516. , mWithFontRanges(false)
  517. {
  518. MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
  519. }
  520. public:
  521. virtual WidgetQueryContentEvent* AsQueryContentEvent() override
  522. {
  523. return this;
  524. }
  525. WidgetQueryContentEvent(bool aIsTrusted, EventMessage aMessage,
  526. nsIWidget* aWidget)
  527. : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eQueryContentEventClass)
  528. , mSucceeded(false)
  529. , mUseNativeLineBreak(true)
  530. , mWithFontRanges(false)
  531. {
  532. }
  533. WidgetQueryContentEvent(EventMessage aMessage,
  534. const WidgetQueryContentEvent& aOtherEvent)
  535. : WidgetGUIEvent(aOtherEvent.IsTrusted(), aMessage,
  536. const_cast<nsIWidget*>(aOtherEvent.mWidget.get()),
  537. eQueryContentEventClass)
  538. , mSucceeded(false)
  539. , mUseNativeLineBreak(aOtherEvent.mUseNativeLineBreak)
  540. , mWithFontRanges(false)
  541. {
  542. }
  543. virtual WidgetEvent* Duplicate() const override
  544. {
  545. // This event isn't an internal event of any DOM event.
  546. NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
  547. "WidgetQueryContentEvent needs to support Duplicate()");
  548. MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
  549. }
  550. struct Options final
  551. {
  552. bool mUseNativeLineBreak;
  553. bool mRelativeToInsertionPoint;
  554. explicit Options()
  555. : mUseNativeLineBreak(true)
  556. , mRelativeToInsertionPoint(false)
  557. {
  558. }
  559. explicit Options(const WidgetQueryContentEvent& aEvent)
  560. : mUseNativeLineBreak(aEvent.mUseNativeLineBreak)
  561. , mRelativeToInsertionPoint(aEvent.mInput.mRelativeToInsertionPoint)
  562. {
  563. }
  564. };
  565. void Init(const Options& aOptions)
  566. {
  567. mUseNativeLineBreak = aOptions.mUseNativeLineBreak;
  568. mInput.mRelativeToInsertionPoint = aOptions.mRelativeToInsertionPoint;
  569. MOZ_ASSERT(mInput.IsValidEventMessage(mMessage));
  570. }
  571. void InitForQueryTextContent(int64_t aOffset, uint32_t aLength,
  572. const Options& aOptions = Options())
  573. {
  574. NS_ASSERTION(mMessage == eQueryTextContent,
  575. "wrong initializer is called");
  576. mInput.mOffset = aOffset;
  577. mInput.mLength = aLength;
  578. Init(aOptions);
  579. MOZ_ASSERT(mInput.IsValidOffset());
  580. }
  581. void InitForQueryCaretRect(int64_t aOffset,
  582. const Options& aOptions = Options())
  583. {
  584. NS_ASSERTION(mMessage == eQueryCaretRect,
  585. "wrong initializer is called");
  586. mInput.mOffset = aOffset;
  587. Init(aOptions);
  588. MOZ_ASSERT(mInput.IsValidOffset());
  589. }
  590. void InitForQueryTextRect(int64_t aOffset, uint32_t aLength,
  591. const Options& aOptions = Options())
  592. {
  593. NS_ASSERTION(mMessage == eQueryTextRect,
  594. "wrong initializer is called");
  595. mInput.mOffset = aOffset;
  596. mInput.mLength = aLength;
  597. Init(aOptions);
  598. MOZ_ASSERT(mInput.IsValidOffset());
  599. }
  600. void InitForQuerySelectedText(SelectionType aSelectionType,
  601. const Options& aOptions = Options())
  602. {
  603. MOZ_ASSERT(mMessage == eQuerySelectedText);
  604. MOZ_ASSERT(aSelectionType != SelectionType::eNone);
  605. mInput.mSelectionType = aSelectionType;
  606. Init(aOptions);
  607. }
  608. void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
  609. {
  610. NS_ASSERTION(mMessage == eQueryDOMWidgetHittest,
  611. "wrong initializer is called");
  612. mRefPoint = aPoint;
  613. }
  614. void InitForQueryTextRectArray(uint32_t aOffset, uint32_t aLength,
  615. const Options& aOptions = Options())
  616. {
  617. NS_ASSERTION(mMessage == eQueryTextRectArray,
  618. "wrong initializer is called");
  619. mInput.mOffset = aOffset;
  620. mInput.mLength = aLength;
  621. Init(aOptions);
  622. }
  623. void RequestFontRanges()
  624. {
  625. NS_ASSERTION(mMessage == eQueryTextContent,
  626. "not querying text content");
  627. mWithFontRanges = true;
  628. }
  629. uint32_t GetSelectionStart(void) const
  630. {
  631. NS_ASSERTION(mMessage == eQuerySelectedText,
  632. "not querying selection");
  633. return mReply.mOffset + (mReply.mReversed ? mReply.mString.Length() : 0);
  634. }
  635. uint32_t GetSelectionEnd(void) const
  636. {
  637. NS_ASSERTION(mMessage == eQuerySelectedText,
  638. "not querying selection");
  639. return mReply.mOffset + (mReply.mReversed ? 0 : mReply.mString.Length());
  640. }
  641. mozilla::WritingMode GetWritingMode(void) const
  642. {
  643. NS_ASSERTION(mMessage == eQuerySelectedText ||
  644. mMessage == eQueryCaretRect ||
  645. mMessage == eQueryTextRect,
  646. "not querying selection or text rect");
  647. return mReply.mWritingMode;
  648. }
  649. bool mSucceeded;
  650. bool mUseNativeLineBreak;
  651. bool mWithFontRanges;
  652. struct Input final
  653. {
  654. uint32_t EndOffset() const
  655. {
  656. CheckedInt<uint32_t> endOffset =
  657. CheckedInt<uint32_t>(mOffset) + mLength;
  658. return NS_WARN_IF(!endOffset.isValid()) ? UINT32_MAX : endOffset.value();
  659. }
  660. int64_t mOffset;
  661. uint32_t mLength;
  662. SelectionType mSelectionType;
  663. // If mOffset is true, mOffset is relative to the start offset of
  664. // composition if there is, otherwise, the start of the first selection
  665. // range.
  666. bool mRelativeToInsertionPoint;
  667. Input()
  668. : mOffset(0)
  669. , mLength(0)
  670. , mSelectionType(SelectionType::eNormal)
  671. , mRelativeToInsertionPoint(false)
  672. {
  673. }
  674. bool IsValidOffset() const
  675. {
  676. return mRelativeToInsertionPoint || mOffset >= 0;
  677. }
  678. bool IsValidEventMessage(EventMessage aEventMessage) const
  679. {
  680. if (!mRelativeToInsertionPoint) {
  681. return true;
  682. }
  683. switch (aEventMessage) {
  684. case eQueryTextContent:
  685. case eQueryCaretRect:
  686. case eQueryTextRect:
  687. return true;
  688. default:
  689. return false;
  690. }
  691. }
  692. bool MakeOffsetAbsolute(uint32_t aInsertionPointOffset)
  693. {
  694. if (NS_WARN_IF(!mRelativeToInsertionPoint)) {
  695. return true;
  696. }
  697. mRelativeToInsertionPoint = false;
  698. // If mOffset + aInsertionPointOffset becomes negative value,
  699. // we should assume the absolute offset is 0.
  700. if (mOffset < 0 && -mOffset > aInsertionPointOffset) {
  701. mOffset = 0;
  702. return true;
  703. }
  704. // Otherwise, we don't allow too large offset.
  705. CheckedInt<uint32_t> absOffset = mOffset + aInsertionPointOffset;
  706. if (NS_WARN_IF(!absOffset.isValid())) {
  707. mOffset = UINT32_MAX;
  708. return false;
  709. }
  710. mOffset = absOffset.value();
  711. return true;
  712. }
  713. } mInput;
  714. struct Reply final
  715. {
  716. void* mContentsRoot;
  717. uint32_t mOffset;
  718. // mTentativeCaretOffset is used by only eQueryCharacterAtPoint.
  719. // This is the offset where caret would be if user clicked at the mRefPoint.
  720. uint32_t mTentativeCaretOffset;
  721. nsString mString;
  722. // mRect is used by eQueryTextRect, eQueryCaretRect, eQueryCharacterAtPoint
  723. // and eQueryEditorRect. The coordinates is system coordinates relative to
  724. // the top level widget of mFocusedWidget. E.g., if a <xul:panel> which
  725. // is owned by a window has focused editor, the offset of mRect is relative
  726. // to the owner window, not the <xul:panel>.
  727. mozilla::LayoutDeviceIntRect mRect;
  728. // The return widget has the caret. This is set at all query events.
  729. nsIWidget* mFocusedWidget;
  730. // mozilla::WritingMode value at the end (focus) of the selection
  731. mozilla::WritingMode mWritingMode;
  732. // Used by eQuerySelectionAsTransferable
  733. nsCOMPtr<nsITransferable> mTransferable;
  734. // Used by eQueryTextContent with font ranges requested
  735. AutoTArray<mozilla::FontRange, 1> mFontRanges;
  736. // Used by eQueryTextRectArray
  737. nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
  738. // true if selection is reversed (end < start)
  739. bool mReversed;
  740. // true if the selection exists
  741. bool mHasSelection;
  742. // true if DOM element under mouse belongs to widget
  743. bool mWidgetIsHit;
  744. Reply()
  745. : mContentsRoot(nullptr)
  746. , mOffset(NOT_FOUND)
  747. , mTentativeCaretOffset(NOT_FOUND)
  748. , mFocusedWidget(nullptr)
  749. , mReversed(false)
  750. , mHasSelection(false)
  751. , mWidgetIsHit(false)
  752. {
  753. }
  754. } mReply;
  755. enum
  756. {
  757. NOT_FOUND = UINT32_MAX
  758. };
  759. // values of mComputedScrollAction
  760. enum
  761. {
  762. SCROLL_ACTION_NONE,
  763. SCROLL_ACTION_LINE,
  764. SCROLL_ACTION_PAGE
  765. };
  766. };
  767. /******************************************************************************
  768. * mozilla::WidgetSelectionEvent
  769. ******************************************************************************/
  770. class WidgetSelectionEvent : public WidgetGUIEvent
  771. {
  772. private:
  773. friend class mozilla::dom::PBrowserParent;
  774. friend class mozilla::dom::PBrowserChild;
  775. WidgetSelectionEvent()
  776. : mOffset(0)
  777. , mLength(0)
  778. , mReversed(false)
  779. , mExpandToClusterBoundary(true)
  780. , mSucceeded(false)
  781. , mUseNativeLineBreak(true)
  782. {
  783. }
  784. public:
  785. virtual WidgetSelectionEvent* AsSelectionEvent() override
  786. {
  787. return this;
  788. }
  789. WidgetSelectionEvent(bool aIsTrusted, EventMessage aMessage,
  790. nsIWidget* aWidget)
  791. : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eSelectionEventClass)
  792. , mOffset(0)
  793. , mLength(0)
  794. , mReversed(false)
  795. , mExpandToClusterBoundary(true)
  796. , mSucceeded(false)
  797. , mUseNativeLineBreak(true)
  798. , mReason(nsISelectionListener::NO_REASON)
  799. {
  800. }
  801. virtual WidgetEvent* Duplicate() const override
  802. {
  803. // This event isn't an internal event of any DOM event.
  804. NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
  805. "WidgetSelectionEvent needs to support Duplicate()");
  806. MOZ_CRASH("WidgetSelectionEvent doesn't support Duplicate()");
  807. return nullptr;
  808. }
  809. // Start offset of selection
  810. uint32_t mOffset;
  811. // Length of selection
  812. uint32_t mLength;
  813. // Selection "anchor" should be in front
  814. bool mReversed;
  815. // Cluster-based or character-based
  816. bool mExpandToClusterBoundary;
  817. // true if setting selection succeeded.
  818. bool mSucceeded;
  819. // true if native line breaks are used for mOffset and mLength
  820. bool mUseNativeLineBreak;
  821. // Fennec provides eSetSelection reason codes for downstream
  822. // use in AccessibleCaret visibility logic.
  823. int16_t mReason;
  824. };
  825. /******************************************************************************
  826. * mozilla::InternalEditorInputEvent
  827. ******************************************************************************/
  828. class InternalEditorInputEvent : public InternalUIEvent
  829. {
  830. private:
  831. InternalEditorInputEvent()
  832. : mIsComposing(false)
  833. {
  834. }
  835. public:
  836. virtual InternalEditorInputEvent* AsEditorInputEvent() override
  837. {
  838. return this;
  839. }
  840. InternalEditorInputEvent(bool aIsTrusted, EventMessage aMessage,
  841. nsIWidget* aWidget)
  842. : InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass)
  843. , mIsComposing(false)
  844. {
  845. }
  846. virtual WidgetEvent* Duplicate() const override
  847. {
  848. MOZ_ASSERT(mClass == eEditorInputEventClass,
  849. "Duplicate() must be overridden by sub class");
  850. // Not copying widget, it is a weak reference.
  851. InternalEditorInputEvent* result =
  852. new InternalEditorInputEvent(false, mMessage, nullptr);
  853. result->AssignEditorInputEventData(*this, true);
  854. result->mFlags = mFlags;
  855. return result;
  856. }
  857. bool mIsComposing;
  858. void AssignEditorInputEventData(const InternalEditorInputEvent& aEvent,
  859. bool aCopyTargets)
  860. {
  861. AssignUIEventData(aEvent, aCopyTargets);
  862. mIsComposing = aEvent.mIsComposing;
  863. }
  864. };
  865. } // namespace mozilla
  866. #endif // mozilla_TextEvents_h__