Bug 1454293 [wpt PR 10484] - null is not the correct origin for createDocument()...
[gecko.git] / widget / TextEvents.h
blob015331e8287db032e51c96d8cdaf89e3a89e43c7
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #ifndef mozilla_TextEvents_h__
7 #define mozilla_TextEvents_h__
9 #include <stdint.h>
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"
27 class nsStringHashKey;
28 template<class, class> class nsDataHashtable;
30 /******************************************************************************
31 * virtual keycode values
32 ******************************************************************************/
34 enum
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
42 namespace mozilla {
44 enum : uint32_t
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
52 const nsCString GetDOMKeyCodeName(uint32_t aKeyCode);
54 namespace dom {
55 class PBrowserParent;
56 class PBrowserChild;
57 } // namespace dom
58 namespace plugins {
59 class PPluginInstanceChild;
60 } // namespace plugins
62 enum class AccessKeyType
64 // Handle access key for chrome.
65 eChrome,
66 // Handle access key for content.
67 eContent,
68 // Don't handle access key.
69 eNone
72 /******************************************************************************
73 * mozilla::AlternativeCharCode
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 ******************************************************************************/
79 struct AlternativeCharCode
81 AlternativeCharCode() :
82 mUnshiftedCharCode(0), mShiftedCharCode(0)
85 AlternativeCharCode(uint32_t aUnshiftedCharCode, uint32_t aShiftedCharCode) :
86 mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
89 uint32_t mUnshiftedCharCode;
90 uint32_t mShiftedCharCode;
93 /******************************************************************************
94 * mozilla::ShortcutKeyCandidate
96 * This stores a candidate of shortcut key combination.
97 ******************************************************************************/
99 struct ShortcutKeyCandidate
101 ShortcutKeyCandidate()
102 : mCharCode(0)
103 , mIgnoreShift(0)
106 ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
107 : mCharCode(aCharCode)
108 , mIgnoreShift(aIgnoreShift)
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;
118 /******************************************************************************
119 * mozilla::IgnoreModifierState
121 * This stores flags for modifiers that should be ignored when matching
122 * XBL handlers.
123 ******************************************************************************/
125 struct IgnoreModifierState
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;
132 IgnoreModifierState()
133 : mShift(false)
134 , mOS(false)
139 /******************************************************************************
140 * mozilla::WidgetKeyboardEvent
141 ******************************************************************************/
143 class WidgetKeyboardEvent : public WidgetInputEvent
145 private:
146 friend class dom::PBrowserParent;
147 friend class dom::PBrowserChild;
148 friend struct IPC::ParamTraits<WidgetKeyboardEvent>;
150 protected:
151 WidgetKeyboardEvent()
152 : 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 , mEditCommandsForSingleLineEditorInitialized(false)
168 , mEditCommandsForMultiLineEditorInitialized(false)
169 , mEditCommandsForRichTextEditorInitialized(false)
173 public:
174 virtual WidgetKeyboardEvent* AsKeyboardEvent() override { return this; }
176 WidgetKeyboardEvent(bool aIsTrusted, EventMessage aMessage,
177 nsIWidget* aWidget,
178 EventClassID aEventClassID = eKeyboardEventClass)
179 : WidgetInputEvent(aIsTrusted, aMessage, aWidget, aEventClassID)
180 , mNativeKeyEvent(nullptr)
181 , mKeyCode(0)
182 , mCharCode(0)
183 , mPseudoCharCode(0)
184 , mLocation(eKeyLocationStandard)
185 , mUniqueId(0)
186 #ifdef XP_MACOSX
187 , mNativeModifierFlags(0)
188 , mNativeKeyCode(0)
189 #endif // #ifdef XP_MACOSX
190 , mKeyNameIndex(KEY_NAME_INDEX_Unidentified)
191 , mCodeNameIndex(CODE_NAME_INDEX_UNKNOWN)
192 , mIsRepeat(false)
193 , mIsComposing(false)
194 , mIsSynthesizedByTIP(false)
195 , mEditCommandsForSingleLineEditorInitialized(false)
196 , mEditCommandsForMultiLineEditorInitialized(false)
197 , mEditCommandsForRichTextEditorInitialized(false)
199 // If this is a keyboard event on a plugin, it shouldn't fired on content.
200 if (IsKeyEventOnPlugin()) {
201 mFlags.mOnlySystemGroupDispatchInContent = true;
202 StopCrossProcessForwarding();
206 static bool IsKeyDownOrKeyDownOnPlugin(EventMessage aMessage)
208 return aMessage == eKeyDown || aMessage == eKeyDownOnPlugin;
210 bool IsKeyDownOrKeyDownOnPlugin() const
212 return IsKeyDownOrKeyDownOnPlugin(mMessage);
214 static bool IsKeyUpOrKeyUpOnPlugin(EventMessage aMessage)
216 return aMessage == eKeyUp || aMessage == eKeyUpOnPlugin;
218 bool IsKeyUpOrKeyUpOnPlugin() const
220 return IsKeyUpOrKeyUpOnPlugin(mMessage);
222 static bool IsKeyEventOnPlugin(EventMessage aMessage)
224 return aMessage == eKeyDownOnPlugin || aMessage == eKeyUpOnPlugin;
226 bool IsKeyEventOnPlugin() const
228 return IsKeyEventOnPlugin(mMessage);
231 bool IsInputtingText() const
233 // NOTE: On some keyboard layout, some characters are inputted with Control
234 // key or Alt key, but at that time, widget unset the modifier flag
235 // from eKeyPress event.
236 return mMessage == eKeyPress &&
237 mCharCode &&
238 !(mModifiers & (MODIFIER_ALT |
239 MODIFIER_CONTROL |
240 MODIFIER_META |
241 MODIFIER_OS));
244 bool IsInputtingLineBreak() const
246 return mMessage == eKeyPress &&
247 mKeyNameIndex == KEY_NAME_INDEX_Enter &&
248 !(mModifiers & (MODIFIER_ALT |
249 MODIFIER_CONTROL |
250 MODIFIER_META |
251 MODIFIER_OS));
255 * ShouldKeyPressEventBeFiredOnContent() should be called only when the
256 * instance is eKeyPress event. This returns true when the eKeyPress
257 * event should be fired even on content in the default event group.
259 bool ShouldKeyPressEventBeFiredOnContent() const
261 MOZ_DIAGNOSTIC_ASSERT(mMessage == eKeyPress);
262 if (IsInputtingText() || IsInputtingLineBreak()) {
263 return true;
265 // Ctrl + Enter won't cause actual input in our editor.
266 // However, the other browsers fire keypress event in any platforms.
267 // So, for compatibility with them, we should fire keypress event for
268 // Ctrl + Enter too.
269 return mMessage == eKeyPress &&
270 mKeyNameIndex == KEY_NAME_INDEX_Enter &&
271 !(mModifiers & (MODIFIER_ALT |
272 MODIFIER_META |
273 MODIFIER_OS |
274 MODIFIER_SHIFT));
277 virtual WidgetEvent* Duplicate() const override
279 MOZ_ASSERT(mClass == eKeyboardEventClass,
280 "Duplicate() must be overridden by sub class");
281 // Not copying widget, it is a weak reference.
282 WidgetKeyboardEvent* result =
283 new WidgetKeyboardEvent(false, mMessage, nullptr);
284 result->AssignKeyEventData(*this, true);
285 result->mEditCommandsForSingleLineEditor = mEditCommandsForSingleLineEditor;
286 result->mEditCommandsForMultiLineEditor = mEditCommandsForMultiLineEditor;
287 result->mEditCommandsForRichTextEditor = mEditCommandsForRichTextEditor;
288 result->mFlags = mFlags;
289 return result;
292 // OS translated Unicode chars which are used for accesskey and accelkey
293 // handling. The handlers will try from first character to last character.
294 nsTArray<AlternativeCharCode> mAlternativeCharCodes;
295 // DOM KeyboardEvent.key only when mKeyNameIndex is KEY_NAME_INDEX_USE_STRING.
296 nsString mKeyValue;
297 // DOM KeyboardEvent.code only when mCodeNameIndex is
298 // CODE_NAME_INDEX_USE_STRING.
299 nsString mCodeValue;
301 #ifdef XP_MACOSX
302 // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
303 nsString mNativeCharacters;
304 nsString mNativeCharactersIgnoringModifiers;
305 // If this is non-empty, create a text event for plugins instead of a
306 // keyboard event.
307 nsString mPluginTextEventString;
308 #endif // #ifdef XP_MACOSX
310 // OS-specific native event can optionally be preserved
311 void* mNativeKeyEvent;
312 // A DOM keyCode value or 0. If a keypress event whose mCharCode is 0, this
313 // should be 0.
314 uint32_t mKeyCode;
315 // If the instance is a keypress event of a printable key, this is a UTF-16
316 // value of the key. Otherwise, 0. This value must not be a control
317 // character when some modifiers are active. Then, this value should be an
318 // unmodified value except Shift and AltGr.
319 uint32_t mCharCode;
320 // mPseudoCharCode is valid only when mMessage is an eKeyDown event.
321 // This stores mCharCode value of keypress event which is fired with same
322 // key value and same modifier state.
323 uint32_t mPseudoCharCode;
324 // One of eKeyLocation*
325 uint32_t mLocation;
326 // Unique id associated with a keydown / keypress event. It's ok if this wraps
327 // over long periods.
328 uint32_t mUniqueId;
330 #ifdef XP_MACOSX
331 // Values given by a native NSEvent, for use with Cocoa NPAPI plugins.
332 uint32_t mNativeModifierFlags;
333 uint16_t mNativeKeyCode;
334 #endif // #ifdef XP_MACOSX
336 // DOM KeyboardEvent.key
337 KeyNameIndex mKeyNameIndex;
338 // DOM KeyboardEvent.code
339 CodeNameIndex mCodeNameIndex;
341 // Indicates whether the event is generated by auto repeat or not.
342 // if this is keyup event, always false.
343 bool mIsRepeat;
344 // Indicates whether the event is generated during IME (or deadkey)
345 // composition. This is initialized by EventStateManager. So, key event
346 // dispatchers don't need to initialize this.
347 bool mIsComposing;
348 // Indicates whether the event is synthesized from Text Input Processor
349 // or an actual event from nsAppShell.
350 bool mIsSynthesizedByTIP;
353 * Retrieves all edit commands from mWidget. This shouldn't be called when
354 * the instance is an untrusted event, doesn't have widget or in non-chrome
355 * process.
357 void InitAllEditCommands();
360 * Retrieves edit commands from mWidget only for aType. This shouldn't be
361 * called when the instance is an untrusted event or doesn't have widget.
363 void InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType);
366 * PreventNativeKeyBindings() makes the instance to not cause any edit
367 * actions even if it matches with a native key binding.
369 void PreventNativeKeyBindings()
371 mEditCommandsForSingleLineEditor.Clear();
372 mEditCommandsForMultiLineEditor.Clear();
373 mEditCommandsForRichTextEditor.Clear();
374 mEditCommandsForSingleLineEditorInitialized = true;
375 mEditCommandsForMultiLineEditorInitialized = true;
376 mEditCommandsForRichTextEditorInitialized = true;
380 * EditCommandsConstRef() returns reference to edit commands for aType.
382 const nsTArray<CommandInt>&
383 EditCommandsConstRef(nsIWidget::NativeKeyBindingsType aType) const
385 return const_cast<WidgetKeyboardEvent*>(this)->EditCommandsRef(aType);
389 * IsEditCommandsInitialized() returns true if edit commands for aType
390 * was already initialized. Otherwise, false.
392 bool IsEditCommandsInitialized(
393 nsIWidget::NativeKeyBindingsType aType) const
395 return const_cast<WidgetKeyboardEvent*>(this)->
396 IsEditCommandsInitializedRef(aType);
399 #ifdef DEBUG
401 * AreAllEditCommandsInitialized() returns true if edit commands for all
402 * types were already initialized. Otherwise, false.
404 bool AreAllEditCommandsInitialized() const
406 return mEditCommandsForSingleLineEditorInitialized &&
407 mEditCommandsForMultiLineEditorInitialized &&
408 mEditCommandsForRichTextEditorInitialized;
410 #endif // #ifdef DEBUG
413 * Execute edit commands for aType.
415 * @return true if the caller should do nothing anymore.
416 * false, otherwise.
418 typedef void (*DoCommandCallback)(Command, void*);
419 bool ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType,
420 DoCommandCallback aCallback,
421 void* aCallbackData);
423 // If the key should cause keypress events, this returns true.
424 // Otherwise, false.
425 bool ShouldCauseKeypressEvents() const;
427 // mCharCode value of non-eKeyPress events is always 0. However, if
428 // non-eKeyPress event has one or more alternative char code values,
429 // its first item should be the mCharCode value of following eKeyPress event.
430 // PseudoCharCode() returns mCharCode value for eKeyPress event,
431 // the first alternative char code value of non-eKeyPress event or 0.
432 uint32_t PseudoCharCode() const
434 return mMessage == eKeyPress ? mCharCode : mPseudoCharCode;
436 void SetCharCode(uint32_t aCharCode)
438 if (mMessage == eKeyPress) {
439 mCharCode = aCharCode;
440 } else {
441 mPseudoCharCode = aCharCode;
445 void GetDOMKeyName(nsAString& aKeyName)
447 if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
448 aKeyName = mKeyValue;
449 return;
451 GetDOMKeyName(mKeyNameIndex, aKeyName);
453 void GetDOMCodeName(nsAString& aCodeName)
455 if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
456 aCodeName = mCodeValue;
457 return;
459 GetDOMCodeName(mCodeNameIndex, aCodeName);
463 * GetFallbackKeyCodeOfPunctuationKey() returns a DOM keyCode value for
464 * aCodeNameIndex. This is keyCode value of the key when active keyboard
465 * layout is ANSI (US), JIS or ABNT keyboard layout (the latter 2 layouts
466 * are used only when ANSI doesn't have the key). The result is useful
467 * if the key doesn't produce ASCII character with active keyboard layout
468 * nor with alternative ASCII capable keyboard layout.
470 static uint32_t
471 GetFallbackKeyCodeOfPunctuationKey(CodeNameIndex aCodeNameIndex);
473 bool IsModifierKeyEvent() const
475 return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE;
479 * Get the candidates for shortcut key.
481 * @param aCandidates [out] the candidate shortcut key combination list.
482 * the first item is most preferred.
484 void GetShortcutKeyCandidates(ShortcutKeyCandidateArray& aCandidates) const;
487 * Get the candidates for access key.
489 * @param aCandidates [out] the candidate access key list.
490 * the first item is most preferred.
492 void GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates) const;
495 * Check whether the modifiers match with chrome access key or
496 * content access key.
498 bool ModifiersMatchWithAccessKey(AccessKeyType aType) const;
501 * Return active modifiers which may match with access key.
502 * For example, even if Alt is access key modifier, then, when Control,
503 * CapseLock and NumLock are active, this returns only MODIFIER_CONTROL.
505 Modifiers ModifiersForAccessKeyMatching() const;
508 * Return access key modifiers.
510 static Modifiers AccessKeyModifiers(AccessKeyType aType);
512 static void Shutdown();
515 * ComputeLocationFromCodeValue() returns one of .mLocation value
516 * (eKeyLocation*) which is the most preferred value for the specified code
517 * value.
519 static uint32_t ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex);
522 * ComputeKeyCodeFromKeyNameIndex() return a .mKeyCode value which can be
523 * mapped from the specified key value. Note that this returns 0 if the
524 * key name index is KEY_NAME_INDEX_Unidentified or KEY_NAME_INDEX_USE_STRING.
525 * This means that this method is useful only for non-printable keys.
527 static uint32_t ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex);
530 * GetModifierForKeyName() returns a value of Modifier which is activated
531 * by the aKeyNameIndex.
533 static Modifier GetModifierForKeyName(KeyNameIndex aKeyNameIndex);
536 * IsLockableModifier() returns true if aKeyNameIndex is a lockable modifier
537 * key such as CapsLock and NumLock.
539 static bool IsLockableModifier(KeyNameIndex aKeyNameIndex);
541 static void GetDOMKeyName(KeyNameIndex aKeyNameIndex,
542 nsAString& aKeyName);
543 static void GetDOMCodeName(CodeNameIndex aCodeNameIndex,
544 nsAString& aCodeName);
546 static KeyNameIndex GetKeyNameIndex(const nsAString& aKeyValue);
547 static CodeNameIndex GetCodeNameIndex(const nsAString& aCodeValue);
549 static const char* GetCommandStr(Command aCommand);
551 void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
553 AssignInputEventData(aEvent, aCopyTargets);
555 mKeyCode = aEvent.mKeyCode;
556 mCharCode = aEvent.mCharCode;
557 mPseudoCharCode = aEvent.mPseudoCharCode;
558 mLocation = aEvent.mLocation;
559 mAlternativeCharCodes = aEvent.mAlternativeCharCodes;
560 mIsRepeat = aEvent.mIsRepeat;
561 mIsComposing = aEvent.mIsComposing;
562 mKeyNameIndex = aEvent.mKeyNameIndex;
563 mCodeNameIndex = aEvent.mCodeNameIndex;
564 mKeyValue = aEvent.mKeyValue;
565 mCodeValue = aEvent.mCodeValue;
566 // Don't copy mNativeKeyEvent because it may be referred after its instance
567 // is destroyed.
568 mNativeKeyEvent = nullptr;
569 mUniqueId = aEvent.mUniqueId;
570 #ifdef XP_MACOSX
571 mNativeKeyCode = aEvent.mNativeKeyCode;
572 mNativeModifierFlags = aEvent.mNativeModifierFlags;
573 mNativeCharacters.Assign(aEvent.mNativeCharacters);
574 mNativeCharactersIgnoringModifiers.
575 Assign(aEvent.mNativeCharactersIgnoringModifiers);
576 mPluginTextEventString.Assign(aEvent.mPluginTextEventString);
577 #endif
578 mIsSynthesizedByTIP = aEvent.mIsSynthesizedByTIP;
580 // Don't copy mEditCommandsFor*Editor because it may require a lot of
581 // memory space. For example, if the event is dispatched but grabbed by
582 // a JS variable, they are not necessary anymore.
584 mEditCommandsForSingleLineEditorInitialized =
585 aEvent.mEditCommandsForSingleLineEditorInitialized;
586 mEditCommandsForMultiLineEditorInitialized =
587 aEvent.mEditCommandsForMultiLineEditorInitialized;
588 mEditCommandsForRichTextEditorInitialized =
589 aEvent.mEditCommandsForRichTextEditorInitialized;
592 private:
593 static const char16_t* const kKeyNames[];
594 static const char16_t* const kCodeNames[];
595 typedef nsDataHashtable<nsStringHashKey,
596 KeyNameIndex> KeyNameIndexHashtable;
597 typedef nsDataHashtable<nsStringHashKey,
598 CodeNameIndex> CodeNameIndexHashtable;
599 static KeyNameIndexHashtable* sKeyNameIndexHashtable;
600 static CodeNameIndexHashtable* sCodeNameIndexHashtable;
602 // mEditCommandsFor*Editor store edit commands. This should be initialized
603 // with InitEditCommandsFor().
604 // XXX Ideally, this should be array of Command rather than CommandInt.
605 // However, ParamTraits isn't aware of enum array.
606 nsTArray<CommandInt> mEditCommandsForSingleLineEditor;
607 nsTArray<CommandInt> mEditCommandsForMultiLineEditor;
608 nsTArray<CommandInt> mEditCommandsForRichTextEditor;
610 nsTArray<CommandInt>& EditCommandsRef(nsIWidget::NativeKeyBindingsType aType)
612 switch (aType) {
613 case nsIWidget::NativeKeyBindingsForSingleLineEditor:
614 return mEditCommandsForSingleLineEditor;
615 case nsIWidget::NativeKeyBindingsForMultiLineEditor:
616 return mEditCommandsForMultiLineEditor;
617 case nsIWidget::NativeKeyBindingsForRichTextEditor:
618 return mEditCommandsForRichTextEditor;
619 default:
620 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
621 "Invalid native key binding type");
625 // mEditCommandsFor*EditorInitialized are set to true when
626 // InitEditCommandsFor() initializes edit commands for the type.
627 bool mEditCommandsForSingleLineEditorInitialized;
628 bool mEditCommandsForMultiLineEditorInitialized;
629 bool mEditCommandsForRichTextEditorInitialized;
631 bool& IsEditCommandsInitializedRef(nsIWidget::NativeKeyBindingsType aType)
633 switch (aType) {
634 case nsIWidget::NativeKeyBindingsForSingleLineEditor:
635 return mEditCommandsForSingleLineEditorInitialized;
636 case nsIWidget::NativeKeyBindingsForMultiLineEditor:
637 return mEditCommandsForMultiLineEditorInitialized;
638 case nsIWidget::NativeKeyBindingsForRichTextEditor:
639 return mEditCommandsForRichTextEditorInitialized;
640 default:
641 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
642 "Invalid native key binding type");
646 static int32_t GenericAccessModifierKeyPref();
647 static int32_t ChromeAccessModifierMaskPref();
648 static int32_t ContentAccessModifierMaskPref();
651 /******************************************************************************
652 * mozilla::WidgetCompositionEvent
653 ******************************************************************************/
655 class WidgetCompositionEvent : public WidgetGUIEvent
657 private:
658 friend class mozilla::dom::PBrowserParent;
659 friend class mozilla::dom::PBrowserChild;
661 WidgetCompositionEvent()
665 public:
666 virtual WidgetCompositionEvent* AsCompositionEvent() override
668 return this;
671 WidgetCompositionEvent(bool aIsTrusted, EventMessage aMessage,
672 nsIWidget* aWidget)
673 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
674 , mNativeIMEContext(aWidget)
675 , mOriginalMessage(eVoidEvent)
679 virtual WidgetEvent* Duplicate() const override
681 MOZ_ASSERT(mClass == eCompositionEventClass,
682 "Duplicate() must be overridden by sub class");
683 // Not copying widget, it is a weak reference.
684 WidgetCompositionEvent* result =
685 new WidgetCompositionEvent(false, mMessage, nullptr);
686 result->AssignCompositionEventData(*this, true);
687 result->mFlags = mFlags;
688 return result;
691 // The composition string or the commit string. If the instance is a
692 // compositionstart event, this is initialized with selected text by
693 // TextComposition automatically.
694 nsString mData;
696 RefPtr<TextRangeArray> mRanges;
698 // mNativeIMEContext stores the native IME context which causes the
699 // composition event.
700 widget::NativeIMEContext mNativeIMEContext;
702 // If the instance is a clone of another event, mOriginalMessage stores
703 // the another event's mMessage.
704 EventMessage mOriginalMessage;
706 void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
707 bool aCopyTargets)
709 AssignGUIEventData(aEvent, aCopyTargets);
711 mData = aEvent.mData;
712 mOriginalMessage = aEvent.mOriginalMessage;
713 mRanges = aEvent.mRanges;
715 // Currently, we don't need to copy the other members because they are
716 // for internal use only (not available from JS).
719 bool IsComposing() const
721 return mRanges && mRanges->IsComposing();
724 uint32_t TargetClauseOffset() const
726 return mRanges ? mRanges->TargetClauseOffset() : 0;
729 uint32_t TargetClauseLength() const
731 uint32_t length = UINT32_MAX;
732 if (mRanges) {
733 length = mRanges->TargetClauseLength();
735 return length == UINT32_MAX ? mData.Length() : length;
738 uint32_t RangeCount() const
740 return mRanges ? mRanges->Length() : 0;
743 bool CausesDOMTextEvent() const
745 return mMessage == eCompositionChange ||
746 mMessage == eCompositionCommit ||
747 mMessage == eCompositionCommitAsIs;
750 bool CausesDOMCompositionEndEvent() const
752 return mMessage == eCompositionEnd ||
753 mMessage == eCompositionCommit ||
754 mMessage == eCompositionCommitAsIs;
757 bool IsFollowedByCompositionEnd() const
759 return IsFollowedByCompositionEnd(mOriginalMessage);
762 static bool IsFollowedByCompositionEnd(EventMessage aEventMessage)
764 return aEventMessage == eCompositionCommit ||
765 aEventMessage == eCompositionCommitAsIs;
769 /******************************************************************************
770 * mozilla::WidgetQueryContentEvent
771 ******************************************************************************/
773 class WidgetQueryContentEvent : public WidgetGUIEvent
775 private:
776 friend class dom::PBrowserParent;
777 friend class dom::PBrowserChild;
779 WidgetQueryContentEvent()
780 : mSucceeded(false)
781 , mUseNativeLineBreak(true)
782 , mWithFontRanges(false)
784 MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
787 public:
788 virtual WidgetQueryContentEvent* AsQueryContentEvent() override
790 return this;
793 WidgetQueryContentEvent(bool aIsTrusted, EventMessage aMessage,
794 nsIWidget* aWidget)
795 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eQueryContentEventClass)
796 , mSucceeded(false)
797 , mUseNativeLineBreak(true)
798 , mWithFontRanges(false)
802 WidgetQueryContentEvent(EventMessage aMessage,
803 const WidgetQueryContentEvent& aOtherEvent)
804 : WidgetGUIEvent(aOtherEvent.IsTrusted(), aMessage,
805 const_cast<nsIWidget*>(aOtherEvent.mWidget.get()),
806 eQueryContentEventClass)
807 , mSucceeded(false)
808 , mUseNativeLineBreak(aOtherEvent.mUseNativeLineBreak)
809 , mWithFontRanges(false)
813 virtual WidgetEvent* Duplicate() const override
815 // This event isn't an internal event of any DOM event.
816 NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
817 "WidgetQueryContentEvent needs to support Duplicate()");
818 MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
821 struct Options final
823 bool mUseNativeLineBreak;
824 bool mRelativeToInsertionPoint;
826 explicit Options()
827 : mUseNativeLineBreak(true)
828 , mRelativeToInsertionPoint(false)
832 explicit Options(const WidgetQueryContentEvent& aEvent)
833 : mUseNativeLineBreak(aEvent.mUseNativeLineBreak)
834 , mRelativeToInsertionPoint(aEvent.mInput.mRelativeToInsertionPoint)
839 void Init(const Options& aOptions)
841 mUseNativeLineBreak = aOptions.mUseNativeLineBreak;
842 mInput.mRelativeToInsertionPoint = aOptions.mRelativeToInsertionPoint;
843 MOZ_ASSERT(mInput.IsValidEventMessage(mMessage));
846 void InitForQueryTextContent(int64_t aOffset, uint32_t aLength,
847 const Options& aOptions = Options())
849 NS_ASSERTION(mMessage == eQueryTextContent,
850 "wrong initializer is called");
851 mInput.mOffset = aOffset;
852 mInput.mLength = aLength;
853 Init(aOptions);
854 MOZ_ASSERT(mInput.IsValidOffset());
857 void InitForQueryCaretRect(int64_t aOffset,
858 const Options& aOptions = Options())
860 NS_ASSERTION(mMessage == eQueryCaretRect,
861 "wrong initializer is called");
862 mInput.mOffset = aOffset;
863 Init(aOptions);
864 MOZ_ASSERT(mInput.IsValidOffset());
867 void InitForQueryTextRect(int64_t aOffset, uint32_t aLength,
868 const Options& aOptions = Options())
870 NS_ASSERTION(mMessage == eQueryTextRect,
871 "wrong initializer is called");
872 mInput.mOffset = aOffset;
873 mInput.mLength = aLength;
874 Init(aOptions);
875 MOZ_ASSERT(mInput.IsValidOffset());
878 void InitForQuerySelectedText(SelectionType aSelectionType,
879 const Options& aOptions = Options())
881 MOZ_ASSERT(mMessage == eQuerySelectedText);
882 MOZ_ASSERT(aSelectionType != SelectionType::eNone);
883 mInput.mSelectionType = aSelectionType;
884 Init(aOptions);
887 void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
889 NS_ASSERTION(mMessage == eQueryDOMWidgetHittest,
890 "wrong initializer is called");
891 mRefPoint = aPoint;
894 void InitForQueryTextRectArray(uint32_t aOffset, uint32_t aLength,
895 const Options& aOptions = Options())
897 NS_ASSERTION(mMessage == eQueryTextRectArray,
898 "wrong initializer is called");
899 mInput.mOffset = aOffset;
900 mInput.mLength = aLength;
901 Init(aOptions);
904 void RequestFontRanges()
906 NS_ASSERTION(mMessage == eQueryTextContent,
907 "not querying text content");
908 mWithFontRanges = true;
911 uint32_t GetSelectionStart(void) const
913 NS_ASSERTION(mMessage == eQuerySelectedText,
914 "not querying selection");
915 return mReply.mOffset + (mReply.mReversed ? mReply.mString.Length() : 0);
918 uint32_t GetSelectionEnd(void) const
920 NS_ASSERTION(mMessage == eQuerySelectedText,
921 "not querying selection");
922 return mReply.mOffset + (mReply.mReversed ? 0 : mReply.mString.Length());
925 mozilla::WritingMode GetWritingMode(void) const
927 NS_ASSERTION(mMessage == eQuerySelectedText ||
928 mMessage == eQueryCaretRect ||
929 mMessage == eQueryTextRect,
930 "not querying selection or text rect");
931 return mReply.mWritingMode;
934 bool mSucceeded;
935 bool mUseNativeLineBreak;
936 bool mWithFontRanges;
937 struct Input final
939 uint32_t EndOffset() const
941 CheckedInt<uint32_t> endOffset =
942 CheckedInt<uint32_t>(mOffset) + mLength;
943 return NS_WARN_IF(!endOffset.isValid()) ? UINT32_MAX : endOffset.value();
946 int64_t mOffset;
947 uint32_t mLength;
948 SelectionType mSelectionType;
949 // If mOffset is true, mOffset is relative to the start offset of
950 // composition if there is, otherwise, the start of the first selection
951 // range.
952 bool mRelativeToInsertionPoint;
954 Input()
955 : mOffset(0)
956 , mLength(0)
957 , mSelectionType(SelectionType::eNormal)
958 , mRelativeToInsertionPoint(false)
962 bool IsValidOffset() const
964 return mRelativeToInsertionPoint || mOffset >= 0;
966 bool IsValidEventMessage(EventMessage aEventMessage) const
968 if (!mRelativeToInsertionPoint) {
969 return true;
971 switch (aEventMessage) {
972 case eQueryTextContent:
973 case eQueryCaretRect:
974 case eQueryTextRect:
975 return true;
976 default:
977 return false;
980 bool MakeOffsetAbsolute(uint32_t aInsertionPointOffset)
982 if (NS_WARN_IF(!mRelativeToInsertionPoint)) {
983 return true;
985 mRelativeToInsertionPoint = false;
986 // If mOffset + aInsertionPointOffset becomes negative value,
987 // we should assume the absolute offset is 0.
988 if (mOffset < 0 && -mOffset > aInsertionPointOffset) {
989 mOffset = 0;
990 return true;
992 // Otherwise, we don't allow too large offset.
993 CheckedInt<uint32_t> absOffset = mOffset + aInsertionPointOffset;
994 if (NS_WARN_IF(!absOffset.isValid())) {
995 mOffset = UINT32_MAX;
996 return false;
998 mOffset = absOffset.value();
999 return true;
1001 } mInput;
1003 struct Reply final
1005 void* mContentsRoot;
1006 uint32_t mOffset;
1007 // mTentativeCaretOffset is used by only eQueryCharacterAtPoint.
1008 // This is the offset where caret would be if user clicked at the mRefPoint.
1009 uint32_t mTentativeCaretOffset;
1010 nsString mString;
1011 // mRect is used by eQueryTextRect, eQueryCaretRect, eQueryCharacterAtPoint
1012 // and eQueryEditorRect. The coordinates is system coordinates relative to
1013 // the top level widget of mFocusedWidget. E.g., if a <xul:panel> which
1014 // is owned by a window has focused editor, the offset of mRect is relative
1015 // to the owner window, not the <xul:panel>.
1016 mozilla::LayoutDeviceIntRect mRect;
1017 // The return widget has the caret. This is set at all query events.
1018 nsIWidget* mFocusedWidget;
1019 // mozilla::WritingMode value at the end (focus) of the selection
1020 mozilla::WritingMode mWritingMode;
1021 // Used by eQuerySelectionAsTransferable
1022 nsCOMPtr<nsITransferable> mTransferable;
1023 // Used by eQueryTextContent with font ranges requested
1024 AutoTArray<mozilla::FontRange, 1> mFontRanges;
1025 // Used by eQueryTextRectArray
1026 nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
1027 // true if selection is reversed (end < start)
1028 bool mReversed;
1029 // true if the selection exists
1030 bool mHasSelection;
1031 // true if DOM element under mouse belongs to widget
1032 bool mWidgetIsHit;
1034 Reply()
1035 : mContentsRoot(nullptr)
1036 , mOffset(NOT_FOUND)
1037 , mTentativeCaretOffset(NOT_FOUND)
1038 , mFocusedWidget(nullptr)
1039 , mReversed(false)
1040 , mHasSelection(false)
1041 , mWidgetIsHit(false)
1044 } mReply;
1046 enum
1048 NOT_FOUND = UINT32_MAX
1051 // values of mComputedScrollAction
1052 enum
1054 SCROLL_ACTION_NONE,
1055 SCROLL_ACTION_LINE,
1056 SCROLL_ACTION_PAGE
1060 /******************************************************************************
1061 * mozilla::WidgetSelectionEvent
1062 ******************************************************************************/
1064 class WidgetSelectionEvent : public WidgetGUIEvent
1066 private:
1067 friend class mozilla::dom::PBrowserParent;
1068 friend class mozilla::dom::PBrowserChild;
1070 WidgetSelectionEvent()
1071 : mOffset(0)
1072 , mLength(0)
1073 , mReversed(false)
1074 , mExpandToClusterBoundary(true)
1075 , mSucceeded(false)
1076 , mUseNativeLineBreak(true)
1080 public:
1081 virtual WidgetSelectionEvent* AsSelectionEvent() override
1083 return this;
1086 WidgetSelectionEvent(bool aIsTrusted, EventMessage aMessage,
1087 nsIWidget* aWidget)
1088 : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eSelectionEventClass)
1089 , mOffset(0)
1090 , mLength(0)
1091 , mReversed(false)
1092 , mExpandToClusterBoundary(true)
1093 , mSucceeded(false)
1094 , mUseNativeLineBreak(true)
1095 , mReason(nsISelectionListener::NO_REASON)
1099 virtual WidgetEvent* Duplicate() const override
1101 // This event isn't an internal event of any DOM event.
1102 NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
1103 "WidgetSelectionEvent needs to support Duplicate()");
1104 MOZ_CRASH("WidgetSelectionEvent doesn't support Duplicate()");
1105 return nullptr;
1108 // Start offset of selection
1109 uint32_t mOffset;
1110 // Length of selection
1111 uint32_t mLength;
1112 // Selection "anchor" should be in front
1113 bool mReversed;
1114 // Cluster-based or character-based
1115 bool mExpandToClusterBoundary;
1116 // true if setting selection succeeded.
1117 bool mSucceeded;
1118 // true if native line breaks are used for mOffset and mLength
1119 bool mUseNativeLineBreak;
1120 // Fennec provides eSetSelection reason codes for downstream
1121 // use in AccessibleCaret visibility logic.
1122 int16_t mReason;
1125 /******************************************************************************
1126 * mozilla::InternalEditorInputEvent
1127 ******************************************************************************/
1129 class InternalEditorInputEvent : public InternalUIEvent
1131 private:
1132 InternalEditorInputEvent()
1133 : mIsComposing(false)
1137 public:
1138 virtual InternalEditorInputEvent* AsEditorInputEvent() override
1140 return this;
1143 InternalEditorInputEvent(bool aIsTrusted, EventMessage aMessage,
1144 nsIWidget* aWidget = nullptr)
1145 : InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass)
1146 , mIsComposing(false)
1150 virtual WidgetEvent* Duplicate() const override
1152 MOZ_ASSERT(mClass == eEditorInputEventClass,
1153 "Duplicate() must be overridden by sub class");
1154 // Not copying widget, it is a weak reference.
1155 InternalEditorInputEvent* result =
1156 new InternalEditorInputEvent(false, mMessage, nullptr);
1157 result->AssignEditorInputEventData(*this, true);
1158 result->mFlags = mFlags;
1159 return result;
1162 bool mIsComposing;
1164 void AssignEditorInputEventData(const InternalEditorInputEvent& aEvent,
1165 bool aCopyTargets)
1167 AssignUIEventData(aEvent, aCopyTargets);
1169 mIsComposing = aEvent.mIsComposing;
1173 } // namespace mozilla
1175 #endif // mozilla_TextEvents_h__