Line data Source code
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 :
6 : #ifndef mozilla_TextEvents_h__
7 : #define mozilla_TextEvents_h__
8 :
9 : #include <stdint.h>
10 :
11 : #include "mozilla/Assertions.h"
12 : #include "mozilla/BasicEvents.h"
13 : #include "mozilla/CheckedInt.h"
14 : #include "mozilla/EventForwards.h" // for KeyNameIndex, temporarily
15 : #include "mozilla/FontRange.h"
16 : #include "mozilla/TextRange.h"
17 : #include "mozilla/WritingModes.h"
18 : #include "mozilla/dom/KeyboardEventBinding.h"
19 : #include "nsCOMPtr.h"
20 : #include "nsISelectionController.h"
21 : #include "nsISelectionListener.h"
22 : #include "nsITransferable.h"
23 : #include "nsRect.h"
24 : #include "nsString.h"
25 : #include "nsTArray.h"
26 :
27 : class nsStringHashKey;
28 : template<class, class> class nsDataHashtable;
29 :
30 : /******************************************************************************
31 : * virtual keycode values
32 : ******************************************************************************/
33 :
34 : enum
35 : {
36 : #define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) NS_##aDOMKeyName = aDOMKeyCode,
37 : #include "mozilla/VirtualKeyCodeList.h"
38 : #undef NS_DEFINE_VK
39 : NS_VK_UNKNOWN = 0xFF
40 : };
41 :
42 : namespace mozilla {
43 :
44 : enum : uint32_t
45 : {
46 : eKeyLocationStandard = dom::KeyboardEventBinding::DOM_KEY_LOCATION_STANDARD,
47 : eKeyLocationLeft = dom::KeyboardEventBinding::DOM_KEY_LOCATION_LEFT,
48 : eKeyLocationRight = dom::KeyboardEventBinding::DOM_KEY_LOCATION_RIGHT,
49 : eKeyLocationNumpad = dom::KeyboardEventBinding::DOM_KEY_LOCATION_NUMPAD
50 : };
51 :
52 : const nsCString GetDOMKeyCodeName(uint32_t aKeyCode);
53 :
54 : namespace dom {
55 : class PBrowserParent;
56 : class PBrowserChild;
57 : } // namespace dom
58 : namespace plugins {
59 : class PPluginInstanceChild;
60 : } // namespace plugins
61 :
62 : enum class AccessKeyType
63 : {
64 : // Handle access key for chrome.
65 : eChrome,
66 : // Handle access key for content.
67 : eContent,
68 : // Don't handle access key.
69 : eNone
70 : };
71 :
72 : /******************************************************************************
73 : * mozilla::AlternativeCharCode
74 : *
75 : * This stores alternative charCode values of a key event with some modifiers.
76 : * The stored values proper for testing shortcut key or access key.
77 : ******************************************************************************/
78 :
79 : struct AlternativeCharCode
80 : {
81 0 : AlternativeCharCode() :
82 0 : mUnshiftedCharCode(0), mShiftedCharCode(0)
83 : {
84 : }
85 0 : AlternativeCharCode(uint32_t aUnshiftedCharCode, uint32_t aShiftedCharCode) :
86 0 : mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
87 : {
88 : }
89 : uint32_t mUnshiftedCharCode;
90 : uint32_t mShiftedCharCode;
91 : };
92 :
93 : /******************************************************************************
94 : * mozilla::ShortcutKeyCandidate
95 : *
96 : * This stores a candidate of shortcut key combination.
97 : ******************************************************************************/
98 :
99 : struct ShortcutKeyCandidate
100 : {
101 : ShortcutKeyCandidate()
102 0 : : mCharCode(0)
103 0 : , mIgnoreShift(0)
104 : {
105 : }
106 : ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
107 0 : : mCharCode(aCharCode)
108 0 : , mIgnoreShift(aIgnoreShift)
109 : {
110 : }
111 : // The mCharCode value which must match keyboard shortcut definition.
112 : uint32_t mCharCode;
113 : // true if Shift state can be ignored. Otherwise, Shift key state must
114 : // match keyboard shortcut definition.
115 : bool mIgnoreShift;
116 : };
117 :
118 : /******************************************************************************
119 : * mozilla::IgnoreModifierState
120 : *
121 : * This stores flags for modifiers that should be ignored when matching
122 : * XBL handlers.
123 : ******************************************************************************/
124 :
125 : struct IgnoreModifierState
126 : {
127 : // When mShift is true, Shift key state will be ignored.
128 : bool mShift;
129 : // When mOS is true, OS key state will be ignored.
130 : bool mOS;
131 :
132 : IgnoreModifierState()
133 0 : : mShift(false)
134 0 : , mOS(false)
135 : {
136 : }
137 : };
138 :
139 : /******************************************************************************
140 : * mozilla::WidgetKeyboardEvent
141 : ******************************************************************************/
142 :
143 0 : class WidgetKeyboardEvent : public WidgetInputEvent
144 : {
145 : private:
146 : friend class dom::PBrowserParent;
147 : friend class dom::PBrowserChild;
148 : friend struct IPC::ParamTraits<WidgetKeyboardEvent>;
149 :
150 : protected:
151 0 : WidgetKeyboardEvent()
152 0 : : mNativeKeyEvent(nullptr)
153 : , mKeyCode(0)
154 : , mCharCode(0)
155 : , mPseudoCharCode(0)
156 : , mLocation(eKeyLocationStandard)
157 : , mUniqueId(0)
158 : #ifdef XP_MACOSX
159 : , mNativeModifierFlags(0)
160 : , mNativeKeyCode(0)
161 : #endif // #ifdef XP_MACOSX
162 : , mKeyNameIndex(KEY_NAME_INDEX_Unidentified)
163 : , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
164 : , mIsRepeat(false)
165 : , mIsComposing(false)
166 : , mIsSynthesizedByTIP(false)
167 : , mMaybeSkippableInRemoteProcess(true)
168 : , mEditCommandsForSingleLineEditorInitialized(false)
169 : , mEditCommandsForMultiLineEditorInitialized(false)
170 0 : , mEditCommandsForRichTextEditorInitialized(false)
171 : {
172 0 : }
173 :
174 : public:
175 0 : virtual WidgetKeyboardEvent* AsKeyboardEvent() override { return this; }
176 :
177 0 : WidgetKeyboardEvent(bool aIsTrusted, EventMessage aMessage,
178 : nsIWidget* aWidget,
179 : EventClassID aEventClassID = eKeyboardEventClass)
180 0 : : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
181 : , mNativeKeyEvent(nullptr)
182 : , mKeyCode(0)
183 : , mCharCode(0)
184 : , mPseudoCharCode(0)
185 : , mLocation(eKeyLocationStandard)
186 : , mUniqueId(0)
187 : #ifdef XP_MACOSX
188 : , mNativeModifierFlags(0)
189 : , mNativeKeyCode(0)
190 : #endif // #ifdef XP_MACOSX
191 : , mKeyNameIndex(KEY_NAME_INDEX_Unidentified)
192 : , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
193 : , mIsRepeat(false)
194 : , mIsComposing(false)
195 : , mIsSynthesizedByTIP(false)
196 : , mMaybeSkippableInRemoteProcess(true)
197 : , mEditCommandsForSingleLineEditorInitialized(false)
198 : , mEditCommandsForMultiLineEditorInitialized(false)
199 0 : , mEditCommandsForRichTextEditorInitialized(false)
200 : {
201 : // If this is a keyboard event on a plugin, it shouldn't fired on content.
202 0 : if (IsKeyEventOnPlugin()) {
203 0 : mFlags.mOnlySystemGroupDispatchInContent = true;
204 0 : StopCrossProcessForwarding();
205 : }
206 0 : }
207 :
208 : static bool IsKeyDownOrKeyDownOnPlugin(EventMessage aMessage)
209 : {
210 0 : return aMessage == eKeyDown || aMessage == eKeyDownOnPlugin;
211 : }
212 : bool IsKeyDownOrKeyDownOnPlugin() const
213 : {
214 0 : return IsKeyDownOrKeyDownOnPlugin(mMessage);
215 : }
216 : static bool IsKeyUpOrKeyUpOnPlugin(EventMessage aMessage)
217 : {
218 0 : return aMessage == eKeyUp || aMessage == eKeyUpOnPlugin;
219 : }
220 : bool IsKeyUpOrKeyUpOnPlugin() const
221 : {
222 0 : return IsKeyUpOrKeyUpOnPlugin(mMessage);
223 : }
224 : static bool IsKeyEventOnPlugin(EventMessage aMessage)
225 : {
226 0 : return aMessage == eKeyDownOnPlugin || aMessage == eKeyUpOnPlugin;
227 : }
228 : bool IsKeyEventOnPlugin() const
229 : {
230 0 : return IsKeyEventOnPlugin(mMessage);
231 : }
232 :
233 : // IsInputtingText() and IsInputtingLineBreak() are used to check if
234 : // it should cause eKeyPress events even on web content.
235 : // UI Events defines that "keypress" event should be fired "if and only if
236 : // that key normally produces a character value".
237 : // <https://www.w3.org/TR/uievents/#event-type-keypress>
238 : // Additionally, for backward compatiblity with all existing browsers,
239 : // there is a spec issue for Enter key press.
240 : // <https://github.com/w3c/uievents/issues/183>
241 0 : bool IsInputtingText() const
242 : {
243 : // NOTE: On some keyboard layout, some characters are inputted with Control
244 : // key or Alt key, but at that time, widget clears the modifier flag
245 : // from eKeyPress event because our TextEditor won't handle eKeyPress
246 : // events as inputting text (bug 1346832).
247 : // NOTE: There are some complicated issues of our traditional behavior.
248 : // -- On Windows, KeyboardLayout::WillDispatchKeyboardEvent() clears
249 : // MODIFIER_ALT and MODIFIER_CONTROL of eKeyPress event if it
250 : // should be treated as inputting a character because AltGr is
251 : // represented with both Alt key and Ctrl key are pressed, and
252 : // some keyboard layouts may produces a character with Ctrl key.
253 : // -- On Linux, KeymapWrapper doesn't have this hack since perhaps,
254 : // we don't have any bug reports that user cannot input proper
255 : // character with Alt and/or Ctrl key.
256 : // -- On macOS, IMEInputHandler::WillDispatchKeyboardEvent() clears
257 : // MODIFIER_ALT and MDOFIEIR_CONTROL of eKeyPress event only when
258 : // TextInputHandler::InsertText() has been called for the event.
259 : // I.e., they are cleared only when an editor has focus (even if IME
260 : // is disabled in password field or by |ime-mode: disabled;|) because
261 : // TextInputHandler::InsertText() is called while
262 : // TextInputHandler::HandleKeyDownEvent() calls interpretKeyEvents:
263 : // to notify text input processor of Cocoa (including IME). In other
264 : // words, when we need to disable IME completey when no editor has
265 : // focus, we cannot call interpretKeyEvents:. So,
266 : // TextInputHandler::InsertText() won't be called when no editor has
267 : // focus so that neither MODIFIER_ALT nor MODIFIER_CONTROL is
268 : // cleared. So, fortunately, altKey and ctrlKey values of "keypress"
269 : // events are same as the other browsers only when no editor has
270 : // focus.
271 : // NOTE: As mentioned above, for compatibility with the other browsers on
272 : // macOS, we should keep MODIFIER_ALT and MODIFIER_CONTROL flags of
273 : // eKeyPress events when no editor has focus. However, Alt key,
274 : // labeled "option" on keyboard for Mac, is AltGraph key on the other
275 : // platforms. So, even if MODIFIER_ALT is set, we need to dispatch
276 : // eKeyPress event even on web content unless mCharCode is 0.
277 : // Therefore, we need to ignore MODIFIER_ALT flag here only on macOS.
278 0 : return mMessage == eKeyPress &&
279 0 : mCharCode &&
280 0 : !(mModifiers & (
281 : #ifndef XP_MACOSX
282 : // So, ignore MODIFIER_ALT only on macOS since
283 : // option key is used as AltGraph key on macOS.
284 : MODIFIER_ALT |
285 : #endif // #ifndef XP_MAXOSX
286 : MODIFIER_CONTROL |
287 : MODIFIER_META |
288 0 : MODIFIER_OS));
289 : }
290 :
291 0 : bool IsInputtingLineBreak() const
292 : {
293 0 : return mMessage == eKeyPress &&
294 0 : mKeyNameIndex == KEY_NAME_INDEX_Enter &&
295 0 : !(mModifiers & (MODIFIER_ALT |
296 : MODIFIER_CONTROL |
297 : MODIFIER_META |
298 0 : MODIFIER_OS));
299 : }
300 :
301 : /**
302 : * ShouldKeyPressEventBeFiredOnContent() should be called only when the
303 : * instance is eKeyPress event. This returns true when the eKeyPress
304 : * event should be fired even on content in the default event group.
305 : */
306 0 : bool ShouldKeyPressEventBeFiredOnContent() const
307 : {
308 0 : MOZ_DIAGNOSTIC_ASSERT(mMessage == eKeyPress);
309 0 : if (IsInputtingText() || IsInputtingLineBreak()) {
310 : return true;
311 : }
312 : // Ctrl + Enter won't cause actual input in our editor.
313 : // However, the other browsers fire keypress event in any platforms.
314 : // So, for compatibility with them, we should fire keypress event for
315 : // Ctrl + Enter too.
316 0 : return mMessage == eKeyPress &&
317 0 : mKeyNameIndex == KEY_NAME_INDEX_Enter &&
318 0 : !(mModifiers & (MODIFIER_ALT |
319 : MODIFIER_META |
320 : MODIFIER_OS |
321 : MODIFIER_SHIFT));
322 : }
323 :
324 0 : virtual WidgetEvent* Duplicate() const override
325 : {
326 0 : MOZ_ASSERT(mClass == eKeyboardEventClass,
327 : "Duplicate() must be overridden by sub class");
328 : // Not copying widget, it is a weak reference.
329 : WidgetKeyboardEvent* result =
330 0 : new WidgetKeyboardEvent(false, mMessage, nullptr);
331 0 : result->AssignKeyEventData(*this, true);
332 0 : result->mEditCommandsForSingleLineEditor = mEditCommandsForSingleLineEditor;
333 0 : result->mEditCommandsForMultiLineEditor = mEditCommandsForMultiLineEditor;
334 0 : result->mEditCommandsForRichTextEditor = mEditCommandsForRichTextEditor;
335 0 : result->mFlags = mFlags;
336 0 : return result;
337 : }
338 :
339 : // OS translated Unicode chars which are used for accesskey and accelkey
340 : // handling. The handlers will try from first character to last character.
341 : nsTArray<AlternativeCharCode> mAlternativeCharCodes;
342 : // DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
343 : nsString mKeyValue;
344 : // DOM KeyboardEvent.code only when mCodeNameIndex is
345 : // CODE_NAME_INDEX_USE_STRING.
346 : nsString mCodeValue;
347 :
348 : #ifdef XP_MACOSX
349 : // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
350 : nsString mNativeCharacters;
351 : nsString mNativeCharactersIgnoringModifiers;
352 : // If this is non-empty, create a text event for plugins instead of a
353 : // keyboard event.
354 : nsString mPluginTextEventString;
355 : #endif // #ifdef XP_MACOSX
356 :
357 : // OS-specific native event can optionally be preserved
358 : void* mNativeKeyEvent;
359 : // A DOM keyCode value or 0. If a keypress event whose mCharCode is 0, this
360 : // should be 0.
361 : uint32_t mKeyCode;
362 : // If the instance is a keypress event of a printable key, this is a UTF-16
363 : // value of the key. Otherwise, 0. This value must not be a control
364 : // character when some modifiers are active. Then, this value should be an
365 : // unmodified value except Shift and AltGr.
366 : uint32_t mCharCode;
367 : // mPseudoCharCode is valid only when mMessage is an eKeyDown event.
368 : // This stores mCharCode value of keypress event which is fired with same
369 : // key value and same modifier state.
370 : uint32_t mPseudoCharCode;
371 : // One of eKeyLocation*
372 : uint32_t mLocation;
373 : // Unique id associated with a keydown / keypress event. It's ok if this wraps
374 : // over long periods.
375 : uint32_t mUniqueId;
376 :
377 : #ifdef XP_MACOSX
378 : // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
379 : uint32_t mNativeModifierFlags;
380 : uint16_t mNativeKeyCode;
381 : #endif // #ifdef XP_MACOSX
382 :
383 : // DOM KeyboardEvent.key
384 : KeyNameIndex mKeyNameIndex;
385 : // DOM KeyboardEvent.code
386 : CodeNameIndex mCodeNameIndex;
387 :
388 : // Indicates whether the event is generated by auto repeat or not.
389 : // if this is keyup event, always false.
390 : bool mIsRepeat;
391 : // Indicates whether the event is generated during IME (or deadkey)
392 : // composition. This is initialized by EventStateManager. So, key event
393 : // dispatchers don't need to initialize this.
394 : bool mIsComposing;
395 : // Indicates whether the event is synthesized from Text Input Processor
396 : // or an actual event from nsAppShell.
397 : bool mIsSynthesizedByTIP;
398 : // Indicates whether the event is skippable in remote process.
399 : // Don't refer this member directly when you need to check this.
400 : // Use CanSkipInRemoteProcess() instead.
401 : bool mMaybeSkippableInRemoteProcess;
402 :
403 0 : bool CanSkipInRemoteProcess() const
404 : {
405 : // If this is a repeat event (i.e., generated by auto-repeat feature of
406 : // the platform), remove process may skip to handle it because of
407 : // performances reasons.. However, if it's caused by odd keyboard utils,
408 : // we should not ignore any key events even marked as repeated since
409 : // generated key sequence may be important to input proper text. E.g.,
410 : // "SinhalaTamil IME" on Windows emulates dead key like input with
411 : // generating WM_KEYDOWN for VK_PACKET (inputting any Unicode characters
412 : // without keyboard layout information) and VK_BACK (Backspace) to remove
413 : // previous character(s) and those messages may be marked as "repeat" by
414 : // their bug.
415 0 : return mIsRepeat && mMaybeSkippableInRemoteProcess;
416 : }
417 :
418 : /**
419 : * Retrieves all edit commands from mWidget. This shouldn't be called when
420 : * the instance is an untrusted event, doesn't have widget or in non-chrome
421 : * process.
422 : */
423 : void InitAllEditCommands();
424 :
425 : /**
426 : * Retrieves edit commands from mWidget only for aType. This shouldn't be
427 : * called when the instance is an untrusted event or doesn't have widget.
428 : */
429 : void InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType);
430 :
431 : /**
432 : * PreventNativeKeyBindings() makes the instance to not cause any edit
433 : * actions even if it matches with a native key binding.
434 : */
435 0 : void PreventNativeKeyBindings()
436 : {
437 0 : mEditCommandsForSingleLineEditor.Clear();
438 0 : mEditCommandsForMultiLineEditor.Clear();
439 0 : mEditCommandsForRichTextEditor.Clear();
440 0 : mEditCommandsForSingleLineEditorInitialized = true;
441 0 : mEditCommandsForMultiLineEditorInitialized = true;
442 0 : mEditCommandsForRichTextEditorInitialized = true;
443 0 : }
444 :
445 : /**
446 : * EditCommandsConstRef() returns reference to edit commands for aType.
447 : */
448 : const nsTArray<CommandInt>&
449 : EditCommandsConstRef(nsIWidget::NativeKeyBindingsType aType) const
450 : {
451 0 : return const_cast<WidgetKeyboardEvent*>(this)->EditCommandsRef(aType);
452 : }
453 :
454 : /**
455 : * IsEditCommandsInitialized() returns true if edit commands for aType
456 : * was already initialized. Otherwise, false.
457 : */
458 0 : bool IsEditCommandsInitialized(
459 : nsIWidget::NativeKeyBindingsType aType) const
460 : {
461 : return const_cast<WidgetKeyboardEvent*>(this)->
462 0 : IsEditCommandsInitializedRef(aType);
463 : }
464 :
465 : #ifdef DEBUG
466 : /**
467 : * AreAllEditCommandsInitialized() returns true if edit commands for all
468 : * types were already initialized. Otherwise, false.
469 : */
470 0 : bool AreAllEditCommandsInitialized() const
471 : {
472 0 : return mEditCommandsForSingleLineEditorInitialized &&
473 0 : mEditCommandsForMultiLineEditorInitialized &&
474 0 : mEditCommandsForRichTextEditorInitialized;
475 : }
476 : #endif // #ifdef DEBUG
477 :
478 : /**
479 : * Execute edit commands for aType.
480 : *
481 : * @return true if the caller should do nothing anymore.
482 : * false, otherwise.
483 : */
484 : typedef void (*DoCommandCallback)(Command, void*);
485 : bool ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType,
486 : DoCommandCallback aCallback,
487 : void* aCallbackData);
488 :
489 : // If the key should cause keypress events, this returns true.
490 : // Otherwise, false.
491 : bool ShouldCauseKeypressEvents() const;
492 :
493 : // mCharCode value of non-eKeyPress events is always 0. However, if
494 : // non-eKeyPress event has one or more alternative char code values,
495 : // its first item should be the mCharCode value of following eKeyPress event.
496 : // PseudoCharCode() returns mCharCode value for eKeyPress event,
497 : // the first alternative char code value of non-eKeyPress event or 0.
498 0 : uint32_t PseudoCharCode() const
499 : {
500 0 : return mMessage == eKeyPress ? mCharCode : mPseudoCharCode;
501 : }
502 0 : void SetCharCode(uint32_t aCharCode)
503 : {
504 0 : if (mMessage == eKeyPress) {
505 0 : mCharCode = aCharCode;
506 : } else {
507 0 : mPseudoCharCode = aCharCode;
508 : }
509 0 : }
510 :
511 0 : void GetDOMKeyName(nsAString& aKeyName)
512 : {
513 0 : if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
514 0 : aKeyName = mKeyValue;
515 : return;
516 : }
517 0 : GetDOMKeyName(mKeyNameIndex, aKeyName);
518 : }
519 0 : void GetDOMCodeName(nsAString& aCodeName)
520 : {
521 0 : if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
522 0 : aCodeName = mCodeValue;
523 : return;
524 : }
525 0 : GetDOMCodeName(mCodeNameIndex, aCodeName);
526 : }
527 :
528 : /**
529 : * GetFallbackKeyCodeOfPunctuationKey() returns a DOM keyCode value for
530 : * aCodeNameIndex. This is keyCode value of the key when active keyboard
531 : * layout is ANSI (US), JIS or ABNT keyboard layout (the latter 2 layouts
532 : * are used only when ANSI doesn't have the key). The result is useful
533 : * if the key doesn't produce ASCII character with active keyboard layout
534 : * nor with alternative ASCII capable keyboard layout.
535 : */
536 : static uint32_t
537 : GetFallbackKeyCodeOfPunctuationKey(CodeNameIndex aCodeNameIndex);
538 :
539 0 : bool IsModifierKeyEvent() const
540 : {
541 0 : return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE;
542 : }
543 :
544 : /**
545 : * Get the candidates for shortcut key.
546 : *
547 : * @param aCandidates [out] the candidate shortcut key combination list.
548 : * the first item is most preferred.
549 : */
550 : void GetShortcutKeyCandidates(ShortcutKeyCandidateArray& aCandidates) const;
551 :
552 : /**
553 : * Get the candidates for access key.
554 : *
555 : * @param aCandidates [out] the candidate access key list.
556 : * the first item is most preferred.
557 : */
558 : void GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates) const;
559 :
560 : /**
561 : * Check whether the modifiers match with chrome access key or
562 : * content access key.
563 : */
564 : bool ModifiersMatchWithAccessKey(AccessKeyType aType) const;
565 :
566 : /**
567 : * Return active modifiers which may match with access key.
568 : * For example, even if Alt is access key modifier, then, when Control,
569 : * CapseLock and NumLock are active, this returns only MODIFIER_CONTROL.
570 : */
571 : Modifiers ModifiersForAccessKeyMatching() const;
572 :
573 : /**
574 : * Return access key modifiers.
575 : */
576 : static Modifiers AccessKeyModifiers(AccessKeyType aType);
577 :
578 : static void Shutdown();
579 :
580 : /**
581 : * ComputeLocationFromCodeValue() returns one of .mLocation value
582 : * (eKeyLocation*) which is the most preferred value for the specified code
583 : * value.
584 : */
585 : static uint32_t ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex);
586 :
587 : /**
588 : * ComputeKeyCodeFromKeyNameIndex() return a .mKeyCode value which can be
589 : * mapped from the specified key value. Note that this returns 0 if the
590 : * key name index is KEY_NAME_INDEX_Unidentified or KEY_NAME_INDEX_USE_STRING.
591 : * This means that this method is useful only for non-printable keys.
592 : */
593 : static uint32_t ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex);
594 :
595 : /**
596 : * GetModifierForKeyName() returns a value of Modifier which is activated
597 : * by the aKeyNameIndex.
598 : */
599 : static Modifier GetModifierForKeyName(KeyNameIndex aKeyNameIndex);
600 :
601 : /**
602 : * IsLockableModifier() returns true if aKeyNameIndex is a lockable modifier
603 : * key such as CapsLock and NumLock.
604 : */
605 : static bool IsLockableModifier(KeyNameIndex aKeyNameIndex);
606 :
607 : static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
608 : nsAString& aKeyName);
609 : static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
610 : nsAString& aCodeName);
611 :
612 : static KeyNameIndex GetKeyNameIndex(const nsAString& aKeyValue);
613 : static CodeNameIndex GetCodeNameIndex(const nsAString& aCodeValue);
614 :
615 : static const char* GetCommandStr(Command aCommand);
616 :
617 0 : void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
618 : {
619 0 : AssignInputEventData(aEvent, aCopyTargets);
620 :
621 0 : mKeyCode = aEvent.mKeyCode;
622 0 : mCharCode = aEvent.mCharCode;
623 0 : mPseudoCharCode = aEvent.mPseudoCharCode;
624 0 : mLocation = aEvent.mLocation;
625 0 : mAlternativeCharCodes = aEvent.mAlternativeCharCodes;
626 0 : mIsRepeat = aEvent.mIsRepeat;
627 0 : mIsComposing = aEvent.mIsComposing;
628 0 : mKeyNameIndex = aEvent.mKeyNameIndex;
629 0 : mCodeNameIndex = aEvent.mCodeNameIndex;
630 0 : mKeyValue = aEvent.mKeyValue;
631 0 : mCodeValue = aEvent.mCodeValue;
632 : // Don't copy mNativeKeyEvent because it may be referred after its instance
633 : // is destroyed.
634 0 : mNativeKeyEvent = nullptr;
635 0 : mUniqueId = aEvent.mUniqueId;
636 : #ifdef XP_MACOSX
637 : mNativeKeyCode = aEvent.mNativeKeyCode;
638 : mNativeModifierFlags = aEvent.mNativeModifierFlags;
639 : mNativeCharacters.Assign(aEvent.mNativeCharacters);
640 : mNativeCharactersIgnoringModifiers.
641 : Assign(aEvent.mNativeCharactersIgnoringModifiers);
642 : mPluginTextEventString.Assign(aEvent.mPluginTextEventString);
643 : #endif
644 0 : mIsSynthesizedByTIP = aEvent.mIsSynthesizedByTIP;
645 0 : mMaybeSkippableInRemoteProcess = aEvent.mMaybeSkippableInRemoteProcess;
646 :
647 : // Don't copy mEditCommandsFor*Editor because it may require a lot of
648 : // memory space. For example, if the event is dispatched but grabbed by
649 : // a JS variable, they are not necessary anymore.
650 :
651 0 : mEditCommandsForSingleLineEditorInitialized =
652 0 : aEvent.mEditCommandsForSingleLineEditorInitialized;
653 0 : mEditCommandsForMultiLineEditorInitialized =
654 0 : aEvent.mEditCommandsForMultiLineEditorInitialized;
655 0 : mEditCommandsForRichTextEditorInitialized =
656 0 : aEvent.mEditCommandsForRichTextEditorInitialized;
657 0 : }
658 :
659 : private:
660 : static const char16_t* const kKeyNames[];
661 : static const char16_t* const kCodeNames[];
662 : typedef nsDataHashtable<nsStringHashKey,
663 : KeyNameIndex> KeyNameIndexHashtable;
664 : typedef nsDataHashtable<nsStringHashKey,
665 : CodeNameIndex> CodeNameIndexHashtable;
666 : static KeyNameIndexHashtable* sKeyNameIndexHashtable;
667 : static CodeNameIndexHashtable* sCodeNameIndexHashtable;
668 :
669 : // mEditCommandsFor*Editor store edit commands. This should be initialized
670 : // with InitEditCommandsFor().
671 : // XXX Ideally, this should be array of Command rather than CommandInt.
672 : // However, ParamTraits isn't aware of enum array.
673 : nsTArray<CommandInt> mEditCommandsForSingleLineEditor;
674 : nsTArray<CommandInt> mEditCommandsForMultiLineEditor;
675 : nsTArray<CommandInt> mEditCommandsForRichTextEditor;
676 :
677 0 : nsTArray<CommandInt>& EditCommandsRef(nsIWidget::NativeKeyBindingsType aType)
678 : {
679 0 : switch (aType) {
680 : case nsIWidget::NativeKeyBindingsForSingleLineEditor:
681 0 : return mEditCommandsForSingleLineEditor;
682 : case nsIWidget::NativeKeyBindingsForMultiLineEditor:
683 0 : return mEditCommandsForMultiLineEditor;
684 : case nsIWidget::NativeKeyBindingsForRichTextEditor:
685 0 : return mEditCommandsForRichTextEditor;
686 : default:
687 0 : MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
688 : "Invalid native key binding type");
689 : }
690 : }
691 :
692 : // mEditCommandsFor*EditorInitialized are set to true when
693 : // InitEditCommandsFor() initializes edit commands for the type.
694 : bool mEditCommandsForSingleLineEditorInitialized;
695 : bool mEditCommandsForMultiLineEditorInitialized;
696 : bool mEditCommandsForRichTextEditorInitialized;
697 :
698 0 : bool& IsEditCommandsInitializedRef(nsIWidget::NativeKeyBindingsType aType)
699 : {
700 0 : switch (aType) {
701 : case nsIWidget::NativeKeyBindingsForSingleLineEditor:
702 0 : return mEditCommandsForSingleLineEditorInitialized;
703 : case nsIWidget::NativeKeyBindingsForMultiLineEditor:
704 0 : return mEditCommandsForMultiLineEditorInitialized;
705 : case nsIWidget::NativeKeyBindingsForRichTextEditor:
706 0 : return mEditCommandsForRichTextEditorInitialized;
707 : default:
708 0 : MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
709 : "Invalid native key binding type");
710 : }
711 : }
712 :
713 : static int32_t GenericAccessModifierKeyPref();
714 : static int32_t ChromeAccessModifierMaskPref();
715 : static int32_t ContentAccessModifierMaskPref();
716 : };
717 :
718 : /******************************************************************************
719 : * mozilla::WidgetCompositionEvent
720 : ******************************************************************************/
721 :
722 0 : class WidgetCompositionEvent : public WidgetGUIEvent
723 : {
724 : private:
725 : friend class mozilla::dom::PBrowserParent;
726 : friend class mozilla::dom::PBrowserChild;
727 :
728 0 : WidgetCompositionEvent()
729 0 : {
730 0 : }
731 :
732 : public:
733 0 : virtual WidgetCompositionEvent* AsCompositionEvent() override
734 : {
735 0 : return this;
736 : }
737 :
738 0 : WidgetCompositionEvent(bool aIsTrusted, EventMessage aMessage,
739 : nsIWidget* aWidget)
740 0 : : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
741 : , mNativeIMEContext(aWidget)
742 0 : , mOriginalMessage(eVoidEvent)
743 : {
744 0 : }
745 :
746 0 : virtual WidgetEvent* Duplicate() const override
747 : {
748 0 : MOZ_ASSERT(mClass == eCompositionEventClass,
749 : "Duplicate() must be overridden by sub class");
750 : // Not copying widget, it is a weak reference.
751 : WidgetCompositionEvent* result =
752 0 : new WidgetCompositionEvent(false, mMessage, nullptr);
753 0 : result->AssignCompositionEventData(*this, true);
754 0 : result->mFlags = mFlags;
755 0 : return result;
756 : }
757 :
758 : // The composition string or the commit string. If the instance is a
759 : // compositionstart event, this is initialized with selected text by
760 : // TextComposition automatically.
761 : nsString mData;
762 :
763 : RefPtr<TextRangeArray> mRanges;
764 :
765 : // mNativeIMEContext stores the native IME context which causes the
766 : // composition event.
767 : widget::NativeIMEContext mNativeIMEContext;
768 :
769 : // If the instance is a clone of another event, mOriginalMessage stores
770 : // the another event's mMessage.
771 : EventMessage mOriginalMessage;
772 :
773 0 : void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
774 : bool aCopyTargets)
775 : {
776 0 : AssignGUIEventData(aEvent, aCopyTargets);
777 :
778 0 : mData = aEvent.mData;
779 0 : mOriginalMessage = aEvent.mOriginalMessage;
780 0 : mRanges = aEvent.mRanges;
781 :
782 : // Currently, we don't need to copy the other members because they are
783 : // for internal use only (not available from JS).
784 0 : }
785 :
786 0 : bool IsComposing() const
787 : {
788 0 : return mRanges && mRanges->IsComposing();
789 : }
790 :
791 0 : uint32_t TargetClauseOffset() const
792 : {
793 0 : return mRanges ? mRanges->TargetClauseOffset() : 0;
794 : }
795 :
796 : uint32_t TargetClauseLength() const
797 : {
798 : uint32_t length = UINT32_MAX;
799 : if (mRanges) {
800 : length = mRanges->TargetClauseLength();
801 : }
802 : return length == UINT32_MAX ? mData.Length() : length;
803 : }
804 :
805 : uint32_t RangeCount() const
806 : {
807 : return mRanges ? mRanges->Length() : 0;
808 : }
809 :
810 0 : bool CausesDOMTextEvent() const
811 : {
812 0 : return mMessage == eCompositionChange ||
813 0 : mMessage == eCompositionCommit ||
814 0 : mMessage == eCompositionCommitAsIs;
815 : }
816 :
817 0 : bool CausesDOMCompositionEndEvent() const
818 : {
819 0 : return mMessage == eCompositionEnd ||
820 0 : mMessage == eCompositionCommit ||
821 0 : mMessage == eCompositionCommitAsIs;
822 : }
823 :
824 : bool IsFollowedByCompositionEnd() const
825 : {
826 0 : return IsFollowedByCompositionEnd(mOriginalMessage);
827 : }
828 :
829 : static bool IsFollowedByCompositionEnd(EventMessage aEventMessage)
830 : {
831 0 : return aEventMessage == eCompositionCommit ||
832 : aEventMessage == eCompositionCommitAsIs;
833 : }
834 : };
835 :
836 : /******************************************************************************
837 : * mozilla::WidgetQueryContentEvent
838 : ******************************************************************************/
839 :
840 0 : class WidgetQueryContentEvent : public WidgetGUIEvent
841 : {
842 : private:
843 : friend class dom::PBrowserParent;
844 : friend class dom::PBrowserChild;
845 :
846 : WidgetQueryContentEvent()
847 : : mSucceeded(false)
848 : , mUseNativeLineBreak(true)
849 : , mWithFontRanges(false)
850 : {
851 : MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
852 : }
853 :
854 : public:
855 0 : virtual WidgetQueryContentEvent* AsQueryContentEvent() override
856 : {
857 0 : return this;
858 : }
859 :
860 1 : WidgetQueryContentEvent(bool aIsTrusted, EventMessage aMessage,
861 : nsIWidget* aWidget)
862 1 : : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eQueryContentEventClass)
863 : , mSucceeded(false)
864 : , mUseNativeLineBreak(true)
865 2 : , mWithFontRanges(false)
866 : {
867 1 : }
868 :
869 0 : WidgetQueryContentEvent(EventMessage aMessage,
870 : const WidgetQueryContentEvent& aOtherEvent)
871 0 : : WidgetGUIEvent(aOtherEvent.IsTrusted(), aMessage,
872 : const_cast<nsIWidget*>(aOtherEvent.mWidget.get()),
873 : eQueryContentEventClass)
874 : , mSucceeded(false)
875 0 : , mUseNativeLineBreak(aOtherEvent.mUseNativeLineBreak)
876 0 : , mWithFontRanges(false)
877 : {
878 0 : }
879 :
880 0 : virtual WidgetEvent* Duplicate() const override
881 : {
882 : // This event isn't an internal event of any DOM event.
883 0 : NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
884 : "WidgetQueryContentEvent needs to support Duplicate()");
885 0 : MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
886 : }
887 :
888 : struct Options final
889 : {
890 : bool mUseNativeLineBreak;
891 : bool mRelativeToInsertionPoint;
892 :
893 : explicit Options()
894 0 : : mUseNativeLineBreak(true)
895 0 : , mRelativeToInsertionPoint(false)
896 : {
897 : }
898 :
899 : explicit Options(const WidgetQueryContentEvent& aEvent)
900 0 : : mUseNativeLineBreak(aEvent.mUseNativeLineBreak)
901 0 : , mRelativeToInsertionPoint(aEvent.mInput.mRelativeToInsertionPoint)
902 : {
903 : }
904 : };
905 :
906 0 : void Init(const Options& aOptions)
907 : {
908 0 : mUseNativeLineBreak = aOptions.mUseNativeLineBreak;
909 0 : mInput.mRelativeToInsertionPoint = aOptions.mRelativeToInsertionPoint;
910 0 : MOZ_ASSERT(mInput.IsValidEventMessage(mMessage));
911 0 : }
912 :
913 0 : void InitForQueryTextContent(int64_t aOffset, uint32_t aLength,
914 : const Options& aOptions = Options())
915 : {
916 0 : NS_ASSERTION(mMessage == eQueryTextContent,
917 : "wrong initializer is called");
918 0 : mInput.mOffset = aOffset;
919 0 : mInput.mLength = aLength;
920 0 : Init(aOptions);
921 0 : MOZ_ASSERT(mInput.IsValidOffset());
922 0 : }
923 :
924 0 : void InitForQueryCaretRect(int64_t aOffset,
925 : const Options& aOptions = Options())
926 : {
927 0 : NS_ASSERTION(mMessage == eQueryCaretRect,
928 : "wrong initializer is called");
929 0 : mInput.mOffset = aOffset;
930 0 : Init(aOptions);
931 0 : MOZ_ASSERT(mInput.IsValidOffset());
932 0 : }
933 :
934 0 : void InitForQueryTextRect(int64_t aOffset, uint32_t aLength,
935 : const Options& aOptions = Options())
936 : {
937 0 : NS_ASSERTION(mMessage == eQueryTextRect,
938 : "wrong initializer is called");
939 0 : mInput.mOffset = aOffset;
940 0 : mInput.mLength = aLength;
941 0 : Init(aOptions);
942 0 : MOZ_ASSERT(mInput.IsValidOffset());
943 0 : }
944 :
945 0 : void InitForQuerySelectedText(SelectionType aSelectionType,
946 : const Options& aOptions = Options())
947 : {
948 0 : MOZ_ASSERT(mMessage == eQuerySelectedText);
949 0 : MOZ_ASSERT(aSelectionType != SelectionType::eNone);
950 0 : mInput.mSelectionType = aSelectionType;
951 0 : Init(aOptions);
952 0 : }
953 :
954 : void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
955 : {
956 : NS_ASSERTION(mMessage == eQueryDOMWidgetHittest,
957 : "wrong initializer is called");
958 : mRefPoint = aPoint;
959 : }
960 :
961 0 : void InitForQueryTextRectArray(uint32_t aOffset, uint32_t aLength,
962 : const Options& aOptions = Options())
963 : {
964 0 : NS_ASSERTION(mMessage == eQueryTextRectArray,
965 : "wrong initializer is called");
966 0 : mInput.mOffset = aOffset;
967 0 : mInput.mLength = aLength;
968 0 : Init(aOptions);
969 0 : }
970 :
971 0 : void RequestFontRanges()
972 : {
973 0 : NS_ASSERTION(mMessage == eQueryTextContent,
974 : "not querying text content");
975 0 : mWithFontRanges = true;
976 0 : }
977 :
978 : uint32_t GetSelectionStart(void) const
979 : {
980 : NS_ASSERTION(mMessage == eQuerySelectedText,
981 : "not querying selection");
982 : return mReply.mOffset + (mReply.mReversed ? mReply.mString.Length() : 0);
983 : }
984 :
985 : uint32_t GetSelectionEnd(void) const
986 : {
987 : NS_ASSERTION(mMessage == eQuerySelectedText,
988 : "not querying selection");
989 : return mReply.mOffset + (mReply.mReversed ? 0 : mReply.mString.Length());
990 : }
991 :
992 1 : mozilla::WritingMode GetWritingMode(void) const
993 : {
994 1 : NS_ASSERTION(mMessage == eQuerySelectedText ||
995 : mMessage == eQueryCaretRect ||
996 : mMessage == eQueryTextRect,
997 : "not querying selection or text rect");
998 1 : return mReply.mWritingMode;
999 : }
1000 :
1001 : bool mSucceeded;
1002 : bool mUseNativeLineBreak;
1003 : bool mWithFontRanges;
1004 : struct Input final
1005 : {
1006 0 : uint32_t EndOffset() const
1007 : {
1008 : CheckedInt<uint32_t> endOffset =
1009 0 : CheckedInt<uint32_t>(mOffset) + mLength;
1010 0 : return NS_WARN_IF(!endOffset.isValid()) ? UINT32_MAX : endOffset.value();
1011 : }
1012 :
1013 : int64_t mOffset;
1014 : uint32_t mLength;
1015 : SelectionType mSelectionType;
1016 : // If mOffset is true, mOffset is relative to the start offset of
1017 : // composition if there is, otherwise, the start of the first selection
1018 : // range.
1019 : bool mRelativeToInsertionPoint;
1020 :
1021 : Input()
1022 1 : : mOffset(0)
1023 : , mLength(0)
1024 : , mSelectionType(SelectionType::eNormal)
1025 0 : , mRelativeToInsertionPoint(false)
1026 : {
1027 : }
1028 :
1029 1 : bool IsValidOffset() const
1030 : {
1031 1 : return mRelativeToInsertionPoint || mOffset >= 0;
1032 : }
1033 0 : bool IsValidEventMessage(EventMessage aEventMessage) const
1034 : {
1035 0 : if (!mRelativeToInsertionPoint) {
1036 : return true;
1037 : }
1038 0 : switch (aEventMessage) {
1039 : case eQueryTextContent:
1040 : case eQueryCaretRect:
1041 : case eQueryTextRect:
1042 : return true;
1043 : default:
1044 0 : return false;
1045 : }
1046 : }
1047 0 : bool MakeOffsetAbsolute(uint32_t aInsertionPointOffset)
1048 : {
1049 0 : if (NS_WARN_IF(!mRelativeToInsertionPoint)) {
1050 : return true;
1051 : }
1052 0 : mRelativeToInsertionPoint = false;
1053 : // If mOffset + aInsertionPointOffset becomes negative value,
1054 : // we should assume the absolute offset is 0.
1055 0 : if (mOffset < 0 && -mOffset > aInsertionPointOffset) {
1056 0 : mOffset = 0;
1057 0 : return true;
1058 : }
1059 : // Otherwise, we don't allow too large offset.
1060 0 : CheckedInt<uint32_t> absOffset = mOffset + aInsertionPointOffset;
1061 0 : if (NS_WARN_IF(!absOffset.isValid())) {
1062 0 : mOffset = UINT32_MAX;
1063 0 : return false;
1064 : }
1065 0 : mOffset = absOffset.value();
1066 0 : return true;
1067 : }
1068 : } mInput;
1069 :
1070 4 : struct Reply final
1071 : {
1072 : void* mContentsRoot;
1073 : uint32_t mOffset;
1074 : // mTentativeCaretOffset is used by only eQueryCharacterAtPoint.
1075 : // This is the offset where caret would be if user clicked at the mRefPoint.
1076 : uint32_t mTentativeCaretOffset;
1077 : nsString mString;
1078 : // mRect is used by eQueryTextRect, eQueryCaretRect, eQueryCharacterAtPoint
1079 : // and eQueryEditorRect. The coordinates is system coordinates relative to
1080 : // the top level widget of mFocusedWidget. E.g., if a <xul:panel> which
1081 : // is owned by a window has focused editor, the offset of mRect is relative
1082 : // to the owner window, not the <xul:panel>.
1083 : mozilla::LayoutDeviceIntRect mRect;
1084 : // The return widget has the caret. This is set at all query events.
1085 : nsIWidget* mFocusedWidget;
1086 : // mozilla::WritingMode value at the end (focus) of the selection
1087 : mozilla::WritingMode mWritingMode;
1088 : // Used by eQuerySelectionAsTransferable
1089 : nsCOMPtr<nsITransferable> mTransferable;
1090 : // Used by eQueryTextContent with font ranges requested
1091 : AutoTArray<mozilla::FontRange, 1> mFontRanges;
1092 : // Used by eQueryTextRectArray
1093 : nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
1094 : // true if selection is reversed (end < start)
1095 : bool mReversed;
1096 : // true if the selection exists
1097 : bool mHasSelection;
1098 : // true if DOM element under mouse belongs to widget
1099 : bool mWidgetIsHit;
1100 :
1101 1 : Reply()
1102 1 : : mContentsRoot(nullptr)
1103 : , mOffset(NOT_FOUND)
1104 : , mTentativeCaretOffset(NOT_FOUND)
1105 : , mFocusedWidget(nullptr)
1106 : , mReversed(false)
1107 : , mHasSelection(false)
1108 5 : , mWidgetIsHit(false)
1109 : {
1110 1 : }
1111 : } mReply;
1112 :
1113 : enum
1114 : {
1115 : NOT_FOUND = UINT32_MAX
1116 : };
1117 :
1118 : // values of mComputedScrollAction
1119 : enum
1120 : {
1121 : SCROLL_ACTION_NONE,
1122 : SCROLL_ACTION_LINE,
1123 : SCROLL_ACTION_PAGE
1124 : };
1125 : };
1126 :
1127 : /******************************************************************************
1128 : * mozilla::WidgetSelectionEvent
1129 : ******************************************************************************/
1130 :
1131 0 : class WidgetSelectionEvent : public WidgetGUIEvent
1132 : {
1133 : private:
1134 : friend class mozilla::dom::PBrowserParent;
1135 : friend class mozilla::dom::PBrowserChild;
1136 :
1137 0 : WidgetSelectionEvent()
1138 0 : : mOffset(0)
1139 : , mLength(0)
1140 : , mReversed(false)
1141 : , mExpandToClusterBoundary(true)
1142 : , mSucceeded(false)
1143 0 : , mUseNativeLineBreak(true)
1144 : {
1145 0 : }
1146 :
1147 : public:
1148 0 : virtual WidgetSelectionEvent* AsSelectionEvent() override
1149 : {
1150 0 : return this;
1151 : }
1152 :
1153 0 : WidgetSelectionEvent(bool aIsTrusted, EventMessage aMessage,
1154 : nsIWidget* aWidget)
1155 0 : : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eSelectionEventClass)
1156 : , mOffset(0)
1157 : , mLength(0)
1158 : , mReversed(false)
1159 : , mExpandToClusterBoundary(true)
1160 : , mSucceeded(false)
1161 : , mUseNativeLineBreak(true)
1162 0 : , mReason(nsISelectionListener::NO_REASON)
1163 : {
1164 0 : }
1165 :
1166 0 : virtual WidgetEvent* Duplicate() const override
1167 : {
1168 : // This event isn't an internal event of any DOM event.
1169 0 : NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
1170 : "WidgetSelectionEvent needs to support Duplicate()");
1171 0 : MOZ_CRASH("WidgetSelectionEvent doesn't support Duplicate()");
1172 : return nullptr;
1173 : }
1174 :
1175 : // Start offset of selection
1176 : uint32_t mOffset;
1177 : // Length of selection
1178 : uint32_t mLength;
1179 : // Selection "anchor" should be in front
1180 : bool mReversed;
1181 : // Cluster-based or character-based
1182 : bool mExpandToClusterBoundary;
1183 : // true if setting selection succeeded.
1184 : bool mSucceeded;
1185 : // true if native line breaks are used for mOffset and mLength
1186 : bool mUseNativeLineBreak;
1187 : // Fennec provides eSetSelection reason codes for downstream
1188 : // use in AccessibleCaret visibility logic.
1189 : int16_t mReason;
1190 : };
1191 :
1192 : /******************************************************************************
1193 : * mozilla::InternalEditorInputEvent
1194 : ******************************************************************************/
1195 :
1196 0 : class InternalEditorInputEvent : public InternalUIEvent
1197 : {
1198 : private:
1199 : InternalEditorInputEvent()
1200 : : mIsComposing(false)
1201 : {
1202 : }
1203 :
1204 : public:
1205 0 : virtual InternalEditorInputEvent* AsEditorInputEvent() override
1206 : {
1207 0 : return this;
1208 : }
1209 :
1210 0 : InternalEditorInputEvent(bool aIsTrusted, EventMessage aMessage,
1211 : nsIWidget* aWidget = nullptr)
1212 0 : : InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass)
1213 0 : , mIsComposing(false)
1214 : {
1215 0 : }
1216 :
1217 : virtual WidgetEvent* Duplicate() const override
1218 : {
1219 : MOZ_ASSERT(mClass == eEditorInputEventClass,
1220 : "Duplicate() must be overridden by sub class");
1221 : // Not copying widget, it is a weak reference.
1222 : InternalEditorInputEvent* result =
1223 : new InternalEditorInputEvent(false, mMessage, nullptr);
1224 : result->AssignEditorInputEventData(*this, true);
1225 : result->mFlags = mFlags;
1226 : return result;
1227 : }
1228 :
1229 : bool mIsComposing;
1230 :
1231 : void AssignEditorInputEventData(const InternalEditorInputEvent& aEvent,
1232 : bool aCopyTargets)
1233 : {
1234 : AssignUIEventData(aEvent, aCopyTargets);
1235 :
1236 : mIsComposing = aEvent.mIsComposing;
1237 : }
1238 : };
1239 :
1240 : } // namespace mozilla
1241 :
1242 : #endif // mozilla_TextEvents_h__
|