Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/TextEvents.h
Line
Count
Source (jump to first uncovered line)
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::KeyboardEvent_Binding::DOM_KEY_LOCATION_STANDARD,
47
  eKeyLocationLeft     = dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_LEFT,
48
  eKeyLocationRight    = dom::KeyboardEvent_Binding::DOM_KEY_LOCATION_RIGHT,
49
  eKeyLocationNumpad   = dom::KeyboardEvent_Binding::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
  AlternativeCharCode() :
82
    mUnshiftedCharCode(0), mShiftedCharCode(0)
83
0
  {
84
0
  }
85
  AlternativeCharCode(uint32_t aUnshiftedCharCode, uint32_t aShiftedCharCode) :
86
    mUnshiftedCharCode(aUnshiftedCharCode), mShiftedCharCode(aShiftedCharCode)
87
0
  {
88
0
  }
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
    : mCharCode(0)
103
    , mIgnoreShift(0)
104
0
  {
105
0
  }
106
  ShortcutKeyCandidate(uint32_t aCharCode, bool aIgnoreShift)
107
    : mCharCode(aCharCode)
108
    , mIgnoreShift(aIgnoreShift)
109
0
  {
110
0
  }
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
    : mShift(false)
134
    , mOS(false)
135
0
  {
136
0
  }
137
};
138
139
/******************************************************************************
140
 * mozilla::WidgetKeyboardEvent
141
 ******************************************************************************/
142
143
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
  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
    , mMaybeSkippableInRemoteProcess(true)
168
    , mEditCommandsForSingleLineEditorInitialized(false)
169
    , mEditCommandsForMultiLineEditorInitialized(false)
170
    , mEditCommandsForRichTextEditorInitialized(false)
171
0
  {
172
0
  }
173
174
public:
175
0
  virtual WidgetKeyboardEvent* AsKeyboardEvent() override { return this; }
176
177
  WidgetKeyboardEvent(bool aIsTrusted, EventMessage aMessage,
178
                      nsIWidget* aWidget,
179
                      EventClassID aEventClassID = eKeyboardEventClass)
180
    : 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
    , mEditCommandsForRichTextEditorInitialized(false)
200
0
  {
201
0
    // 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
0
    }
206
0
  }
207
208
  static bool IsKeyDownOrKeyDownOnPlugin(EventMessage aMessage)
209
0
  {
210
0
    return aMessage == eKeyDown || aMessage == eKeyDownOnPlugin;
211
0
  }
212
  bool IsKeyDownOrKeyDownOnPlugin() const
213
0
  {
214
0
    return IsKeyDownOrKeyDownOnPlugin(mMessage);
215
0
  }
216
  static bool IsKeyUpOrKeyUpOnPlugin(EventMessage aMessage)
217
0
  {
218
0
    return aMessage == eKeyUp || aMessage == eKeyUpOnPlugin;
219
0
  }
220
  bool IsKeyUpOrKeyUpOnPlugin() const
221
0
  {
222
0
    return IsKeyUpOrKeyUpOnPlugin(mMessage);
223
0
  }
224
  static bool IsKeyEventOnPlugin(EventMessage aMessage)
225
0
  {
226
0
    return aMessage == eKeyDownOnPlugin || aMessage == eKeyUpOnPlugin;
227
0
  }
228
  bool IsKeyEventOnPlugin() const
229
0
  {
230
0
    return IsKeyEventOnPlugin(mMessage);
231
0
  }
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
  bool IsInputtingText() const
242
0
  {
243
0
    // NOTE: On some keyboard layout, some characters are inputted with Control
244
0
    //       key or Alt key, but at that time, widget clears the modifier flag
245
0
    //       from eKeyPress event because our TextEditor won't handle eKeyPress
246
0
    //       events as inputting text (bug 1346832).
247
0
    // NOTE: There are some complicated issues of our traditional behavior.
248
0
    //       -- On Windows, KeyboardLayout::WillDispatchKeyboardEvent() clears
249
0
    //       MODIFIER_ALT and MODIFIER_CONTROL of eKeyPress event if it
250
0
    //       should be treated as inputting a character because AltGr is
251
0
    //       represented with both Alt key and Ctrl key are pressed, and
252
0
    //       some keyboard layouts may produces a character with Ctrl key.
253
0
    //       -- On Linux, KeymapWrapper doesn't have this hack since perhaps,
254
0
    //       we don't have any bug reports that user cannot input proper
255
0
    //       character with Alt and/or Ctrl key.
256
0
    //       -- On macOS, IMEInputHandler::WillDispatchKeyboardEvent() clears
257
0
    //       MODIFIER_ALT and MDOFIEIR_CONTROL of eKeyPress event only when
258
0
    //       TextInputHandler::InsertText() has been called for the event.
259
0
    //       I.e., they are cleared only when an editor has focus (even if IME
260
0
    //       is disabled in password field or by |ime-mode: disabled;|) because
261
0
    //       TextInputHandler::InsertText() is called while
262
0
    //       TextInputHandler::HandleKeyDownEvent() calls interpretKeyEvents:
263
0
    //       to notify text input processor of Cocoa (including IME).  In other
264
0
    //       words, when we need to disable IME completey when no editor has
265
0
    //       focus, we cannot call interpretKeyEvents:.  So,
266
0
    //       TextInputHandler::InsertText() won't be called when no editor has
267
0
    //       focus so that neither MODIFIER_ALT nor MODIFIER_CONTROL is
268
0
    //       cleared.  So, fortunately, altKey and ctrlKey values of "keypress"
269
0
    //       events are same as the other browsers only when no editor has
270
0
    //       focus.
271
0
    // NOTE: As mentioned above, for compatibility with the other browsers on
272
0
    //       macOS, we should keep MODIFIER_ALT and MODIFIER_CONTROL flags of
273
0
    //       eKeyPress events when no editor has focus.  However, Alt key,
274
0
    //       labeled "option" on keyboard for Mac, is AltGraph key on the other
275
0
    //       platforms.  So, even if MODIFIER_ALT is set, we need to dispatch
276
0
    //       eKeyPress event even on web content unless mCharCode is 0.
277
0
    //       Therefore, we need to ignore MODIFIER_ALT flag here only on macOS.
278
0
    return mMessage == eKeyPress &&
279
0
           mCharCode &&
280
0
           !(mModifiers & (
281
0
#ifndef XP_MACOSX
282
0
                           // So, ignore MODIFIER_ALT only on macOS since
283
0
                           // option key is used as AltGraph key on macOS.
284
0
                           MODIFIER_ALT |
285
0
#endif // #ifndef XP_MAXOSX
286
0
                           MODIFIER_CONTROL |
287
0
                           MODIFIER_META |
288
0
                           MODIFIER_OS));
289
0
  }
290
291
  bool IsInputtingLineBreak() const
292
0
  {
293
0
    return mMessage == eKeyPress &&
294
0
           mKeyNameIndex == KEY_NAME_INDEX_Enter &&
295
0
           !(mModifiers & (MODIFIER_ALT |
296
0
                           MODIFIER_CONTROL |
297
0
                           MODIFIER_META |
298
0
                           MODIFIER_OS));
299
0
  }
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
  bool ShouldKeyPressEventBeFiredOnContent() const
307
0
  {
308
0
    MOZ_DIAGNOSTIC_ASSERT(mMessage == eKeyPress);
309
0
    if (IsInputtingText() || IsInputtingLineBreak()) {
310
0
      return true;
311
0
    }
312
0
    // Ctrl + Enter won't cause actual input in our editor.
313
0
    // However, the other browsers fire keypress event in any platforms.
314
0
    // So, for compatibility with them, we should fire keypress event for
315
0
    // Ctrl + Enter too.
316
0
    return mMessage == eKeyPress &&
317
0
           mKeyNameIndex == KEY_NAME_INDEX_Enter &&
318
0
           !(mModifiers & (MODIFIER_ALT |
319
0
                           MODIFIER_META |
320
0
                           MODIFIER_OS |
321
0
                           MODIFIER_SHIFT));
322
0
  }
323
324
  virtual WidgetEvent* Duplicate() const override
325
0
  {
326
0
    MOZ_ASSERT(mClass == eKeyboardEventClass,
327
0
               "Duplicate() must be overridden by sub class");
328
0
    // Not copying widget, it is a weak reference.
329
0
    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
0
  }
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
  bool CanSkipInRemoteProcess() const
404
0
  {
405
0
    // If this is a repeat event (i.e., generated by auto-repeat feature of
406
0
    // the platform), remove process may skip to handle it because of
407
0
    // performances reasons..  However, if it's caused by odd keyboard utils,
408
0
    // we should not ignore any key events even marked as repeated since
409
0
    // generated key sequence may be important to input proper text.  E.g.,
410
0
    // "SinhalaTamil IME" on Windows emulates dead key like input with
411
0
    // generating WM_KEYDOWN for VK_PACKET (inputting any Unicode characters
412
0
    // without keyboard layout information) and VK_BACK (Backspace) to remove
413
0
    // previous character(s) and those messages may be marked as "repeat" by
414
0
    // their bug.
415
0
    return mIsRepeat && mMaybeSkippableInRemoteProcess;
416
0
  }
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
  void PreventNativeKeyBindings()
436
0
  {
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
0
  {
451
0
    return const_cast<WidgetKeyboardEvent*>(this)->EditCommandsRef(aType);
452
0
  }
453
454
  /**
455
   * IsEditCommandsInitialized() returns true if edit commands for aType
456
   * was already initialized.  Otherwise, false.
457
   */
458
  bool IsEditCommandsInitialized(
459
         nsIWidget::NativeKeyBindingsType aType) const
460
0
  {
461
0
    return const_cast<WidgetKeyboardEvent*>(this)->
462
0
             IsEditCommandsInitializedRef(aType);
463
0
  }
464
465
#ifdef DEBUG
466
  /**
467
   * AreAllEditCommandsInitialized() returns true if edit commands for all
468
   * types were already initialized.  Otherwise, false.
469
   */
470
  bool AreAllEditCommandsInitialized() const
471
  {
472
    return mEditCommandsForSingleLineEditorInitialized &&
473
           mEditCommandsForMultiLineEditorInitialized &&
474
           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
  uint32_t PseudoCharCode() const
499
0
  {
500
0
    return mMessage == eKeyPress ? mCharCode : mPseudoCharCode;
501
0
  }
502
  void SetCharCode(uint32_t aCharCode)
503
0
  {
504
0
    if (mMessage == eKeyPress) {
505
0
      mCharCode = aCharCode;
506
0
    } else {
507
0
      mPseudoCharCode = aCharCode;
508
0
    }
509
0
  }
510
511
  void GetDOMKeyName(nsAString& aKeyName)
512
0
  {
513
0
    if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
514
0
      aKeyName = mKeyValue;
515
0
      return;
516
0
    }
517
0
    GetDOMKeyName(mKeyNameIndex, aKeyName);
518
0
  }
519
  void GetDOMCodeName(nsAString& aCodeName)
520
0
  {
521
0
    if (mCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
522
0
      aCodeName = mCodeValue;
523
0
      return;
524
0
    }
525
0
    GetDOMCodeName(mCodeNameIndex, aCodeName);
526
0
  }
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
  bool IsModifierKeyEvent() const
540
0
  {
541
0
    return GetModifierForKeyName(mKeyNameIndex) != MODIFIER_NONE;
542
0
  }
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
  void AssignKeyEventData(const WidgetKeyboardEvent& aEvent, bool aCopyTargets)
618
0
  {
619
0
    AssignInputEventData(aEvent, aCopyTargets);
620
0
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
0
    // Don't copy mNativeKeyEvent because it may be referred after its instance
633
0
    // 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
    mIsSynthesizedByTIP = aEvent.mIsSynthesizedByTIP;
645
0
    mMaybeSkippableInRemoteProcess = aEvent.mMaybeSkippableInRemoteProcess;
646
0
647
0
    // Don't copy mEditCommandsFor*Editor because it may require a lot of
648
0
    // memory space.  For example, if the event is dispatched but grabbed by
649
0
    // a JS variable, they are not necessary anymore.
650
0
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
  nsTArray<CommandInt>& EditCommandsRef(nsIWidget::NativeKeyBindingsType aType)
678
0
  {
679
0
    switch (aType) {
680
0
      case nsIWidget::NativeKeyBindingsForSingleLineEditor:
681
0
        return mEditCommandsForSingleLineEditor;
682
0
      case nsIWidget::NativeKeyBindingsForMultiLineEditor:
683
0
        return mEditCommandsForMultiLineEditor;
684
0
      case nsIWidget::NativeKeyBindingsForRichTextEditor:
685
0
        return mEditCommandsForRichTextEditor;
686
0
      default:
687
0
        MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
688
0
          "Invalid native key binding type");
689
0
    }
690
0
  }
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
  bool& IsEditCommandsInitializedRef(nsIWidget::NativeKeyBindingsType aType)
699
0
  {
700
0
    switch (aType) {
701
0
      case nsIWidget::NativeKeyBindingsForSingleLineEditor:
702
0
        return mEditCommandsForSingleLineEditorInitialized;
703
0
      case nsIWidget::NativeKeyBindingsForMultiLineEditor:
704
0
        return mEditCommandsForMultiLineEditorInitialized;
705
0
      case nsIWidget::NativeKeyBindingsForRichTextEditor:
706
0
        return mEditCommandsForRichTextEditorInitialized;
707
0
      default:
708
0
        MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(
709
0
          "Invalid native key binding type");
710
0
    }
711
0
  }
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
class WidgetCompositionEvent : public WidgetGUIEvent
723
{
724
private:
725
  friend class mozilla::dom::PBrowserParent;
726
  friend class mozilla::dom::PBrowserChild;
727
728
  WidgetCompositionEvent()
729
    : mOriginalMessage(eVoidEvent)
730
0
  {
731
0
  }
732
733
public:
734
  virtual WidgetCompositionEvent* AsCompositionEvent() override
735
0
  {
736
0
    return this;
737
0
  }
738
739
  WidgetCompositionEvent(bool aIsTrusted, EventMessage aMessage,
740
                         nsIWidget* aWidget)
741
    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eCompositionEventClass)
742
    , mNativeIMEContext(aWidget)
743
    , mOriginalMessage(eVoidEvent)
744
0
  {
745
0
  }
746
747
  virtual WidgetEvent* Duplicate() const override
748
0
  {
749
0
    MOZ_ASSERT(mClass == eCompositionEventClass,
750
0
               "Duplicate() must be overridden by sub class");
751
0
    // Not copying widget, it is a weak reference.
752
0
    WidgetCompositionEvent* result =
753
0
      new WidgetCompositionEvent(false, mMessage, nullptr);
754
0
    result->AssignCompositionEventData(*this, true);
755
0
    result->mFlags = mFlags;
756
0
    return result;
757
0
  }
758
759
  // The composition string or the commit string.  If the instance is a
760
  // compositionstart event, this is initialized with selected text by
761
  // TextComposition automatically.
762
  nsString mData;
763
764
  RefPtr<TextRangeArray> mRanges;
765
766
  // mNativeIMEContext stores the native IME context which causes the
767
  // composition event.
768
  widget::NativeIMEContext mNativeIMEContext;
769
770
  // If the instance is a clone of another event, mOriginalMessage stores
771
  // the another event's mMessage.
772
  EventMessage mOriginalMessage;
773
774
  void AssignCompositionEventData(const WidgetCompositionEvent& aEvent,
775
                                  bool aCopyTargets)
776
0
  {
777
0
    AssignGUIEventData(aEvent, aCopyTargets);
778
0
779
0
    mData = aEvent.mData;
780
0
    mOriginalMessage = aEvent.mOriginalMessage;
781
0
    mRanges = aEvent.mRanges;
782
0
783
0
    // Currently, we don't need to copy the other members because they are
784
0
    // for internal use only (not available from JS).
785
0
  }
786
787
  bool IsComposing() const
788
0
  {
789
0
    return mRanges && mRanges->IsComposing();
790
0
  }
791
792
  uint32_t TargetClauseOffset() const
793
0
  {
794
0
    return mRanges ? mRanges->TargetClauseOffset() : 0;
795
0
  }
796
797
  uint32_t TargetClauseLength() const
798
0
  {
799
0
    uint32_t length = UINT32_MAX;
800
0
    if (mRanges) {
801
0
      length = mRanges->TargetClauseLength();
802
0
    }
803
0
    return length == UINT32_MAX ? mData.Length() : length;
804
0
  }
805
806
  uint32_t RangeCount() const
807
0
  {
808
0
    return mRanges ? mRanges->Length() : 0;
809
0
  }
810
811
  bool CausesDOMTextEvent() const
812
0
  {
813
0
    return mMessage == eCompositionChange ||
814
0
           mMessage == eCompositionCommit ||
815
0
           mMessage == eCompositionCommitAsIs;
816
0
  }
817
818
  bool CausesDOMCompositionEndEvent() const
819
0
  {
820
0
    return mMessage == eCompositionEnd ||
821
0
           mMessage == eCompositionCommit ||
822
0
           mMessage == eCompositionCommitAsIs;
823
0
  }
824
825
  bool IsFollowedByCompositionEnd() const
826
0
  {
827
0
    return IsFollowedByCompositionEnd(mOriginalMessage);
828
0
  }
829
830
  static bool IsFollowedByCompositionEnd(EventMessage aEventMessage)
831
0
  {
832
0
    return aEventMessage == eCompositionCommit ||
833
0
           aEventMessage == eCompositionCommitAsIs;
834
0
  }
835
};
836
837
/******************************************************************************
838
 * mozilla::WidgetQueryContentEvent
839
 ******************************************************************************/
840
841
class WidgetQueryContentEvent : public WidgetGUIEvent
842
{
843
private:
844
  friend class dom::PBrowserParent;
845
  friend class dom::PBrowserChild;
846
847
  WidgetQueryContentEvent()
848
    : mSucceeded(false)
849
    , mUseNativeLineBreak(true)
850
    , mWithFontRanges(false)
851
0
  {
852
0
    MOZ_CRASH("WidgetQueryContentEvent is created without proper arguments");
853
0
  }
854
855
public:
856
  virtual WidgetQueryContentEvent* AsQueryContentEvent() override
857
0
  {
858
0
    return this;
859
0
  }
860
861
  WidgetQueryContentEvent(bool aIsTrusted, EventMessage aMessage,
862
                          nsIWidget* aWidget)
863
    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eQueryContentEventClass)
864
    , mSucceeded(false)
865
    , mUseNativeLineBreak(true)
866
    , mWithFontRanges(false)
867
0
  {
868
0
  }
869
870
  WidgetQueryContentEvent(EventMessage aMessage,
871
                          const WidgetQueryContentEvent& aOtherEvent)
872
    : WidgetGUIEvent(aOtherEvent.IsTrusted(), aMessage,
873
                     const_cast<nsIWidget*>(aOtherEvent.mWidget.get()),
874
                     eQueryContentEventClass)
875
    , mSucceeded(false)
876
    , mUseNativeLineBreak(aOtherEvent.mUseNativeLineBreak)
877
    , mWithFontRanges(false)
878
0
  {
879
0
  }
880
881
  virtual WidgetEvent* Duplicate() const override
882
0
  {
883
0
    // This event isn't an internal event of any DOM event.
884
0
    NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
885
0
      "WidgetQueryContentEvent needs to support Duplicate()");
886
0
    MOZ_CRASH("WidgetQueryContentEvent doesn't support Duplicate()");
887
0
  }
888
889
  struct Options final
890
  {
891
    bool mUseNativeLineBreak;
892
    bool mRelativeToInsertionPoint;
893
894
    explicit Options()
895
      : mUseNativeLineBreak(true)
896
      , mRelativeToInsertionPoint(false)
897
0
    {
898
0
    }
899
900
    explicit Options(const WidgetQueryContentEvent& aEvent)
901
      : mUseNativeLineBreak(aEvent.mUseNativeLineBreak)
902
      , mRelativeToInsertionPoint(aEvent.mInput.mRelativeToInsertionPoint)
903
0
    {
904
0
    }
905
  };
906
907
  void Init(const Options& aOptions)
908
0
  {
909
0
    mUseNativeLineBreak = aOptions.mUseNativeLineBreak;
910
0
    mInput.mRelativeToInsertionPoint = aOptions.mRelativeToInsertionPoint;
911
0
    MOZ_ASSERT(mInput.IsValidEventMessage(mMessage));
912
0
  }
913
914
  void InitForQueryTextContent(int64_t aOffset, uint32_t aLength,
915
                               const Options& aOptions = Options())
916
0
  {
917
0
    NS_ASSERTION(mMessage == eQueryTextContent,
918
0
                 "wrong initializer is called");
919
0
    mInput.mOffset = aOffset;
920
0
    mInput.mLength = aLength;
921
0
    Init(aOptions);
922
0
    MOZ_ASSERT(mInput.IsValidOffset());
923
0
  }
924
925
  void InitForQueryCaretRect(int64_t aOffset,
926
                             const Options& aOptions = Options())
927
0
  {
928
0
    NS_ASSERTION(mMessage == eQueryCaretRect,
929
0
                 "wrong initializer is called");
930
0
    mInput.mOffset = aOffset;
931
0
    Init(aOptions);
932
0
    MOZ_ASSERT(mInput.IsValidOffset());
933
0
  }
934
935
  void InitForQueryTextRect(int64_t aOffset, uint32_t aLength,
936
                            const Options& aOptions = Options())
937
0
  {
938
0
    NS_ASSERTION(mMessage == eQueryTextRect,
939
0
                 "wrong initializer is called");
940
0
    mInput.mOffset = aOffset;
941
0
    mInput.mLength = aLength;
942
0
    Init(aOptions);
943
0
    MOZ_ASSERT(mInput.IsValidOffset());
944
0
  }
945
946
  void InitForQuerySelectedText(SelectionType aSelectionType,
947
                                const Options& aOptions = Options())
948
0
  {
949
0
    MOZ_ASSERT(mMessage == eQuerySelectedText);
950
0
    MOZ_ASSERT(aSelectionType != SelectionType::eNone);
951
0
    mInput.mSelectionType = aSelectionType;
952
0
    Init(aOptions);
953
0
  }
954
955
  void InitForQueryDOMWidgetHittest(const mozilla::LayoutDeviceIntPoint& aPoint)
956
0
  {
957
0
    NS_ASSERTION(mMessage == eQueryDOMWidgetHittest,
958
0
                 "wrong initializer is called");
959
0
    mRefPoint = aPoint;
960
0
  }
961
962
  void InitForQueryTextRectArray(uint32_t aOffset, uint32_t aLength,
963
                                 const Options& aOptions = Options())
964
0
  {
965
0
    NS_ASSERTION(mMessage == eQueryTextRectArray,
966
0
                 "wrong initializer is called");
967
0
    mInput.mOffset = aOffset;
968
0
    mInput.mLength = aLength;
969
0
    Init(aOptions);
970
0
  }
971
972
  void RequestFontRanges()
973
0
  {
974
0
    NS_ASSERTION(mMessage == eQueryTextContent,
975
0
                 "not querying text content");
976
0
    mWithFontRanges = true;
977
0
  }
978
979
  uint32_t GetSelectionStart(void) const
980
0
  {
981
0
    NS_ASSERTION(mMessage == eQuerySelectedText,
982
0
                 "not querying selection");
983
0
    return mReply.mOffset + (mReply.mReversed ? mReply.mString.Length() : 0);
984
0
  }
985
986
  uint32_t GetSelectionEnd(void) const
987
0
  {
988
0
    NS_ASSERTION(mMessage == eQuerySelectedText,
989
0
                 "not querying selection");
990
0
    return mReply.mOffset + (mReply.mReversed ? 0 : mReply.mString.Length());
991
0
  }
992
993
  mozilla::WritingMode GetWritingMode(void) const
994
0
  {
995
0
    NS_ASSERTION(mMessage == eQuerySelectedText ||
996
0
                 mMessage == eQueryCaretRect ||
997
0
                 mMessage == eQueryTextRect,
998
0
                 "not querying selection or text rect");
999
0
    return mReply.mWritingMode;
1000
0
  }
1001
1002
  bool mSucceeded;
1003
  bool mUseNativeLineBreak;
1004
  bool mWithFontRanges;
1005
  struct Input final
1006
  {
1007
    uint32_t EndOffset() const
1008
0
    {
1009
0
      CheckedInt<uint32_t> endOffset =
1010
0
        CheckedInt<uint32_t>(mOffset) + mLength;
1011
0
      return NS_WARN_IF(!endOffset.isValid()) ? UINT32_MAX : endOffset.value();
1012
0
    }
1013
1014
    int64_t mOffset;
1015
    uint32_t mLength;
1016
    SelectionType mSelectionType;
1017
    // If mOffset is true, mOffset is relative to the start offset of
1018
    // composition if there is, otherwise, the start of the first selection
1019
    // range.
1020
    bool mRelativeToInsertionPoint;
1021
1022
    Input()
1023
      : mOffset(0)
1024
      , mLength(0)
1025
      , mSelectionType(SelectionType::eNormal)
1026
      , mRelativeToInsertionPoint(false)
1027
0
    {
1028
0
    }
1029
1030
    bool IsValidOffset() const
1031
0
    {
1032
0
      return mRelativeToInsertionPoint || mOffset >= 0;
1033
0
    }
1034
    bool IsValidEventMessage(EventMessage aEventMessage) const
1035
0
    {
1036
0
      if (!mRelativeToInsertionPoint) {
1037
0
        return true;
1038
0
      }
1039
0
      switch (aEventMessage) {
1040
0
        case eQueryTextContent:
1041
0
        case eQueryCaretRect:
1042
0
        case eQueryTextRect:
1043
0
          return true;
1044
0
        default:
1045
0
          return false;
1046
0
      }
1047
0
    }
1048
    bool MakeOffsetAbsolute(uint32_t aInsertionPointOffset)
1049
0
    {
1050
0
      if (NS_WARN_IF(!mRelativeToInsertionPoint)) {
1051
0
        return true;
1052
0
      }
1053
0
      mRelativeToInsertionPoint = false;
1054
0
      // If mOffset + aInsertionPointOffset becomes negative value,
1055
0
      // we should assume the absolute offset is 0.
1056
0
      if (mOffset < 0 && -mOffset > aInsertionPointOffset) {
1057
0
        mOffset = 0;
1058
0
        return true;
1059
0
      }
1060
0
      // Otherwise, we don't allow too large offset.
1061
0
      CheckedInt<uint32_t> absOffset = mOffset + aInsertionPointOffset;
1062
0
      if (NS_WARN_IF(!absOffset.isValid())) {
1063
0
        mOffset = UINT32_MAX;
1064
0
        return false;
1065
0
      }
1066
0
      mOffset = absOffset.value();
1067
0
      return true;
1068
0
    }
1069
  } mInput;
1070
1071
  struct Reply final
1072
  {
1073
    void* mContentsRoot;
1074
    uint32_t mOffset;
1075
    // mTentativeCaretOffset is used by only eQueryCharacterAtPoint.
1076
    // This is the offset where caret would be if user clicked at the mRefPoint.
1077
    uint32_t mTentativeCaretOffset;
1078
    nsString mString;
1079
    // mRect is used by eQueryTextRect, eQueryCaretRect, eQueryCharacterAtPoint
1080
    // and eQueryEditorRect. The coordinates is system coordinates relative to
1081
    // the top level widget of mFocusedWidget.  E.g., if a <xul:panel> which
1082
    // is owned by a window has focused editor, the offset of mRect is relative
1083
    // to the owner window, not the <xul:panel>.
1084
    mozilla::LayoutDeviceIntRect mRect;
1085
    // The return widget has the caret. This is set at all query events.
1086
    nsIWidget* mFocusedWidget;
1087
    // mozilla::WritingMode value at the end (focus) of the selection
1088
    mozilla::WritingMode mWritingMode;
1089
    // Used by eQuerySelectionAsTransferable
1090
    nsCOMPtr<nsITransferable> mTransferable;
1091
    // Used by eQueryTextContent with font ranges requested
1092
    AutoTArray<mozilla::FontRange, 1> mFontRanges;
1093
    // Used by eQueryTextRectArray
1094
    nsTArray<mozilla::LayoutDeviceIntRect> mRectArray;
1095
    // true if selection is reversed (end < start)
1096
    bool mReversed;
1097
    // true if the selection exists
1098
    bool mHasSelection;
1099
    // true if DOM element under mouse belongs to widget
1100
    bool mWidgetIsHit;
1101
1102
    Reply()
1103
      : mContentsRoot(nullptr)
1104
      , mOffset(NOT_FOUND)
1105
      , mTentativeCaretOffset(NOT_FOUND)
1106
      , mFocusedWidget(nullptr)
1107
      , mReversed(false)
1108
      , mHasSelection(false)
1109
      , mWidgetIsHit(false)
1110
0
    {
1111
0
    }
1112
  } mReply;
1113
1114
  enum
1115
  {
1116
    NOT_FOUND = UINT32_MAX
1117
  };
1118
1119
  // values of mComputedScrollAction
1120
  enum
1121
  {
1122
    SCROLL_ACTION_NONE,
1123
    SCROLL_ACTION_LINE,
1124
    SCROLL_ACTION_PAGE
1125
  };
1126
};
1127
1128
/******************************************************************************
1129
 * mozilla::WidgetSelectionEvent
1130
 ******************************************************************************/
1131
1132
class WidgetSelectionEvent : public WidgetGUIEvent
1133
{
1134
private:
1135
  friend class mozilla::dom::PBrowserParent;
1136
  friend class mozilla::dom::PBrowserChild;
1137
1138
  WidgetSelectionEvent()
1139
    : mOffset(0)
1140
    , mLength(0)
1141
    , mReversed(false)
1142
    , mExpandToClusterBoundary(true)
1143
    , mSucceeded(false)
1144
    , mUseNativeLineBreak(true)
1145
    , mReason(nsISelectionListener::NO_REASON)
1146
0
  {
1147
0
  }
1148
1149
public:
1150
  virtual WidgetSelectionEvent* AsSelectionEvent() override
1151
0
  {
1152
0
    return this;
1153
0
  }
1154
1155
  WidgetSelectionEvent(bool aIsTrusted, EventMessage aMessage,
1156
                       nsIWidget* aWidget)
1157
    : WidgetGUIEvent(aIsTrusted, aMessage, aWidget, eSelectionEventClass)
1158
    , mOffset(0)
1159
    , mLength(0)
1160
    , mReversed(false)
1161
    , mExpandToClusterBoundary(true)
1162
    , mSucceeded(false)
1163
    , mUseNativeLineBreak(true)
1164
    , mReason(nsISelectionListener::NO_REASON)
1165
0
  {
1166
0
  }
1167
1168
  virtual WidgetEvent* Duplicate() const override
1169
0
  {
1170
0
    // This event isn't an internal event of any DOM event.
1171
0
    NS_ASSERTION(!IsAllowedToDispatchDOMEvent(),
1172
0
      "WidgetSelectionEvent needs to support Duplicate()");
1173
0
    MOZ_CRASH("WidgetSelectionEvent doesn't support Duplicate()");
1174
0
    return nullptr;
1175
0
  }
1176
1177
  // Start offset of selection
1178
  uint32_t mOffset;
1179
  // Length of selection
1180
  uint32_t mLength;
1181
  // Selection "anchor" should be in front
1182
  bool mReversed;
1183
  // Cluster-based or character-based
1184
  bool mExpandToClusterBoundary;
1185
  // true if setting selection succeeded.
1186
  bool mSucceeded;
1187
  // true if native line breaks are used for mOffset and mLength
1188
  bool mUseNativeLineBreak;
1189
  // Fennec provides eSetSelection reason codes for downstream
1190
  // use in AccessibleCaret visibility logic.
1191
  int16_t mReason;
1192
};
1193
1194
/******************************************************************************
1195
 * mozilla::InternalEditorInputEvent
1196
 ******************************************************************************/
1197
1198
class InternalEditorInputEvent : public InternalUIEvent
1199
{
1200
private:
1201
  InternalEditorInputEvent()
1202
    : mIsComposing(false)
1203
0
  {
1204
0
  }
1205
1206
public:
1207
  virtual InternalEditorInputEvent* AsEditorInputEvent() override
1208
0
  {
1209
0
    return this;
1210
0
  }
1211
1212
  InternalEditorInputEvent(bool aIsTrusted, EventMessage aMessage,
1213
                           nsIWidget* aWidget = nullptr)
1214
    : InternalUIEvent(aIsTrusted, aMessage, aWidget, eEditorInputEventClass)
1215
    , mIsComposing(false)
1216
0
  {
1217
0
  }
1218
1219
  virtual WidgetEvent* Duplicate() const override
1220
0
  {
1221
0
    MOZ_ASSERT(mClass == eEditorInputEventClass,
1222
0
               "Duplicate() must be overridden by sub class");
1223
0
    // Not copying widget, it is a weak reference.
1224
0
    InternalEditorInputEvent* result =
1225
0
      new InternalEditorInputEvent(false, mMessage, nullptr);
1226
0
    result->AssignEditorInputEventData(*this, true);
1227
0
    result->mFlags = mFlags;
1228
0
    return result;
1229
0
  }
1230
1231
  bool mIsComposing;
1232
1233
  void AssignEditorInputEventData(const InternalEditorInputEvent& aEvent,
1234
                                  bool aCopyTargets)
1235
0
  {
1236
0
    AssignUIEventData(aEvent, aCopyTargets);
1237
0
1238
0
    mIsComposing = aEvent.mIsComposing;
1239
0
  }
1240
};
1241
1242
} // namespace mozilla
1243
1244
#endif // mozilla_TextEvents_h__