Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/widget/WidgetEventImpl.cpp
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
#include "gfxPrefs.h"
7
#include "mozilla/BasicEvents.h"
8
#include "mozilla/ContentEvents.h"
9
#include "mozilla/EventStateManager.h"
10
#include "mozilla/InternalMutationEvent.h"
11
#include "mozilla/MiscEvents.h"
12
#include "mozilla/MouseEvents.h"
13
#include "mozilla/Preferences.h"
14
#include "mozilla/TextEvents.h"
15
#include "mozilla/TouchEvents.h"
16
#include "mozilla/dom/KeyboardEventBinding.h"
17
#include "nsContentUtils.h"
18
#include "nsIContent.h"
19
#include "nsPrintfCString.h"
20
21
namespace mozilla {
22
23
/******************************************************************************
24
 * Global helper methods
25
 ******************************************************************************/
26
27
const char*
28
ToChar(EventMessage aEventMessage)
29
0
{
30
0
  switch (aEventMessage) {
31
0
32
0
#define NS_EVENT_MESSAGE(aMessage) \
33
0
    case aMessage: \
34
0
      return #aMessage;
35
0
36
0
#include "mozilla/EventMessageList.h"
37
0
38
0
#undef NS_EVENT_MESSAGE
39
0
    default:
40
0
      return "illegal event message";
41
0
  }
42
0
}
43
44
const char*
45
ToChar(EventClassID aEventClassID)
46
0
{
47
0
  switch (aEventClassID) {
48
0
49
0
#define NS_ROOT_EVENT_CLASS(aPrefix, aName) \
50
0
    case eBasic##aName##Class: \
51
0
      return "eBasic" #aName "Class";
52
0
53
0
#define NS_EVENT_CLASS(aPrefix, aName) \
54
0
    case e##aName##Class: \
55
0
      return "e" #aName "Class";
56
0
57
0
#include "mozilla/EventClassList.h"
58
0
59
0
#undef NS_EVENT_CLASS
60
0
#undef NS_ROOT_EVENT_CLASS
61
0
    default:
62
0
      return "illegal event class ID";
63
0
  }
64
0
}
65
66
const nsCString
67
ToString(KeyNameIndex aKeyNameIndex)
68
0
{
69
0
  if (aKeyNameIndex == KEY_NAME_INDEX_USE_STRING) {
70
0
    return NS_LITERAL_CSTRING("USE_STRING");
71
0
  }
72
0
  nsAutoString keyName;
73
0
  WidgetKeyboardEvent::GetDOMKeyName(aKeyNameIndex, keyName);
74
0
  return NS_ConvertUTF16toUTF8(keyName);
75
0
}
76
77
const nsCString
78
ToString(CodeNameIndex aCodeNameIndex)
79
0
{
80
0
  if (aCodeNameIndex == CODE_NAME_INDEX_USE_STRING) {
81
0
    return NS_LITERAL_CSTRING("USE_STRING");
82
0
  }
83
0
  nsAutoString codeName;
84
0
  WidgetKeyboardEvent::GetDOMCodeName(aCodeNameIndex, codeName);
85
0
  return NS_ConvertUTF16toUTF8(codeName);
86
0
}
87
88
const char*
89
ToChar(Command aCommand)
90
0
{
91
0
  if (aCommand == CommandDoNothing) {
92
0
    return "CommandDoNothing";
93
0
  }
94
0
95
0
  switch (aCommand) {
96
0
97
0
#define NS_DEFINE_COMMAND(aName, aCommandStr) \
98
0
    case Command##aName: \
99
0
      return "Command" #aName;
100
0
#define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName) \
101
0
    case Command##aName: \
102
0
      return "Command" #aName;
103
0
104
0
#include "mozilla/CommandList.h"
105
0
106
0
#undef NS_DEFINE_COMMAND
107
0
#undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
108
0
109
0
    default:
110
0
      return "illegal command value";
111
0
  }
112
0
}
113
114
const nsCString
115
GetDOMKeyCodeName(uint32_t aKeyCode)
116
0
{
117
0
  switch (aKeyCode) {
118
0
#define NS_DISALLOW_SAME_KEYCODE
119
0
#define NS_DEFINE_VK(aDOMKeyName, aDOMKeyCode) \
120
0
    case aDOMKeyCode: \
121
0
      return NS_LITERAL_CSTRING(#aDOMKeyName);
122
0
123
0
#include "mozilla/VirtualKeyCodeList.h"
124
0
125
0
#undef NS_DEFINE_VK
126
0
#undef NS_DISALLOW_SAME_KEYCODE
127
0
128
0
    default:
129
0
      return nsPrintfCString("Invalid DOM keyCode (0x%08X)", aKeyCode);
130
0
  }
131
0
}
132
133
bool
134
IsValidRawTextRangeValue(RawTextRangeType aRawTextRangeType)
135
{
136
  switch (static_cast<TextRangeType>(aRawTextRangeType)) {
137
    case TextRangeType::eUninitialized:
138
    case TextRangeType::eCaret:
139
    case TextRangeType::eRawClause:
140
    case TextRangeType::eSelectedRawClause:
141
    case TextRangeType::eConvertedClause:
142
    case TextRangeType::eSelectedClause:
143
      return true;
144
    default:
145
      return false;
146
  }
147
}
148
149
RawTextRangeType
150
ToRawTextRangeType(TextRangeType aTextRangeType)
151
0
{
152
0
  return static_cast<RawTextRangeType>(aTextRangeType);
153
0
}
154
155
TextRangeType
156
ToTextRangeType(RawTextRangeType aRawTextRangeType)
157
0
{
158
0
  MOZ_ASSERT(IsValidRawTextRangeValue(aRawTextRangeType));
159
0
  return static_cast<TextRangeType>(aRawTextRangeType);
160
0
}
161
162
const char*
163
ToChar(TextRangeType aTextRangeType)
164
{
165
  switch (aTextRangeType) {
166
    case TextRangeType::eUninitialized:
167
      return "TextRangeType::eUninitialized";
168
    case TextRangeType::eCaret:
169
      return "TextRangeType::eCaret";
170
    case TextRangeType::eRawClause:
171
      return "TextRangeType::eRawClause";
172
    case TextRangeType::eSelectedRawClause:
173
      return "TextRangeType::eSelectedRawClause";
174
    case TextRangeType::eConvertedClause:
175
      return "TextRangeType::eConvertedClause";
176
    case TextRangeType::eSelectedClause:
177
      return "TextRangeType::eSelectedClause";
178
    default:
179
      return "Invalid TextRangeType";
180
  }
181
}
182
183
SelectionType
184
ToSelectionType(TextRangeType aTextRangeType)
185
0
{
186
0
  switch (aTextRangeType) {
187
0
    case TextRangeType::eRawClause:
188
0
      return SelectionType::eIMERawClause;
189
0
    case TextRangeType::eSelectedRawClause:
190
0
      return SelectionType::eIMESelectedRawClause;
191
0
    case TextRangeType::eConvertedClause:
192
0
      return SelectionType::eIMEConvertedClause;
193
0
    case TextRangeType::eSelectedClause:
194
0
      return SelectionType::eIMESelectedClause;
195
0
    default:
196
0
      MOZ_CRASH("TextRangeType is invalid");
197
0
      return SelectionType::eNormal;
198
0
  }
199
0
}
200
201
/******************************************************************************
202
 * As*Event() implementation
203
 ******************************************************************************/
204
205
#define NS_ROOT_EVENT_CLASS(aPrefix, aName)
206
#define NS_EVENT_CLASS(aPrefix, aName) \
207
aPrefix##aName* \
208
0
WidgetEvent::As##aName() \
209
0
{ \
210
0
  return nullptr; \
211
0
} \
Unexecuted instantiation: mozilla::WidgetEvent::AsGUIEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsInputEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsUIEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsKeyboardEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsCompositionEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsQueryContentEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsSelectionEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsEditorInputEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsMouseEventBase()
Unexecuted instantiation: mozilla::WidgetEvent::AsMouseEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsDragEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsMouseScrollEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsWheelEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsPointerEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsGestureNotifyEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsSimpleGestureEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsTouchEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsScrollPortEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsScrollAreaEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsFormEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsClipboardEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsFocusEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsTransitionEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsAnimationEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsSMILTimeEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsCommandEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsContentCommandEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsPluginEvent()
Unexecuted instantiation: mozilla::WidgetEvent::AsMutationEvent()
212
\
213
const aPrefix##aName* \
214
0
WidgetEvent::As##aName() const \
215
0
{ \
216
0
  return const_cast<WidgetEvent*>(this)->As##aName(); \
217
0
}
Unexecuted instantiation: mozilla::WidgetEvent::AsGUIEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsInputEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsUIEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsKeyboardEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsCompositionEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsQueryContentEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsSelectionEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsEditorInputEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsMouseEventBase() const
Unexecuted instantiation: mozilla::WidgetEvent::AsMouseEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsDragEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsMouseScrollEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsWheelEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsPointerEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsGestureNotifyEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsSimpleGestureEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsTouchEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsScrollPortEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsScrollAreaEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsFormEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsClipboardEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsFocusEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsTransitionEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsAnimationEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsSMILTimeEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsCommandEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsContentCommandEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsPluginEvent() const
Unexecuted instantiation: mozilla::WidgetEvent::AsMutationEvent() const
218
219
#include "mozilla/EventClassList.h"
220
221
#undef NS_EVENT_CLASS
222
#undef NS_ROOT_EVENT_CLASS
223
224
/******************************************************************************
225
 * mozilla::WidgetEvent
226
 *
227
 * Event struct type checking methods.
228
 ******************************************************************************/
229
230
bool
231
WidgetEvent::IsQueryContentEvent() const
232
0
{
233
0
  return mClass == eQueryContentEventClass;
234
0
}
235
236
bool
237
WidgetEvent::IsSelectionEvent() const
238
0
{
239
0
  return mClass == eSelectionEventClass;
240
0
}
241
242
bool
243
WidgetEvent::IsContentCommandEvent() const
244
0
{
245
0
  return mClass == eContentCommandEventClass;
246
0
}
247
248
bool
249
WidgetEvent::IsNativeEventDelivererForPlugin() const
250
0
{
251
0
  return mClass == ePluginEventClass;
252
0
}
253
254
255
/******************************************************************************
256
 * mozilla::WidgetEvent
257
 *
258
 * Event message checking methods.
259
 ******************************************************************************/
260
261
bool
262
WidgetEvent::HasMouseEventMessage() const
263
{
264
  switch (mMessage) {
265
    case eMouseDown:
266
    case eMouseUp:
267
    case eMouseClick:
268
    case eMouseDoubleClick:
269
    case eMouseAuxClick:
270
    case eMouseEnterIntoWidget:
271
    case eMouseExitFromWidget:
272
    case eMouseActivate:
273
    case eMouseOver:
274
    case eMouseOut:
275
    case eMouseHitTest:
276
    case eMouseMove:
277
      return true;
278
    default:
279
      return false;
280
  }
281
}
282
283
bool
284
WidgetEvent::HasDragEventMessage() const
285
{
286
  switch (mMessage) {
287
    case eDragEnter:
288
    case eDragOver:
289
    case eDragExit:
290
    case eDrag:
291
    case eDragEnd:
292
    case eDragStart:
293
    case eDrop:
294
    case eDragLeave:
295
      return true;
296
    default:
297
      return false;
298
  }
299
}
300
301
/* static */
302
bool
303
WidgetEvent::IsKeyEventMessage(EventMessage aMessage)
304
{
305
  switch (aMessage) {
306
    case eKeyDown:
307
    case eKeyPress:
308
    case eKeyUp:
309
    case eKeyDownOnPlugin:
310
    case eKeyUpOnPlugin:
311
    case eAccessKeyNotFound:
312
      return true;
313
    default:
314
      return false;
315
  }
316
}
317
318
bool
319
WidgetEvent::HasIMEEventMessage() const
320
{
321
  switch (mMessage) {
322
    case eCompositionStart:
323
    case eCompositionEnd:
324
    case eCompositionUpdate:
325
    case eCompositionChange:
326
    case eCompositionCommitAsIs:
327
    case eCompositionCommit:
328
      return true;
329
    default:
330
      return false;
331
  }
332
}
333
334
bool
335
WidgetEvent::HasPluginActivationEventMessage() const
336
0
{
337
0
  return mMessage == ePluginActivate ||
338
0
         mMessage == ePluginFocus;
339
0
}
340
341
/******************************************************************************
342
 * mozilla::WidgetEvent
343
 *
344
 * Specific event checking methods.
345
 ******************************************************************************/
346
347
bool
348
WidgetEvent::CanBeSentToRemoteProcess() const
349
0
{
350
0
  // If this event is explicitly marked as shouldn't be sent to remote process,
351
0
  // just return false.
352
0
  if (IsCrossProcessForwardingStopped()) {
353
0
    return false;
354
0
  }
355
0
356
0
  if (mClass == eKeyboardEventClass ||
357
0
      mClass == eWheelEventClass) {
358
0
    return true;
359
0
  }
360
0
361
0
  switch (mMessage) {
362
0
    case eMouseDown:
363
0
    case eMouseUp:
364
0
    case eMouseMove:
365
0
    case eContextMenu:
366
0
    case eMouseEnterIntoWidget:
367
0
    case eMouseExitFromWidget:
368
0
    case eMouseTouchDrag:
369
0
    case eTouchStart:
370
0
    case eTouchMove:
371
0
    case eTouchEnd:
372
0
    case eTouchCancel:
373
0
    case eDragOver:
374
0
    case eDragExit:
375
0
    case eDrop:
376
0
      return true;
377
0
    default:
378
0
      return false;
379
0
  }
380
0
}
381
382
bool
383
WidgetEvent::WillBeSentToRemoteProcess() const
384
0
{
385
0
  // This event won't be posted to remote process if it's already explicitly
386
0
  // stopped.
387
0
  if (IsCrossProcessForwardingStopped()) {
388
0
    return false;
389
0
  }
390
0
391
0
  // When mOriginalTarget is nullptr, this method shouldn't be used.
392
0
  if (NS_WARN_IF(!mOriginalTarget)) {
393
0
    return false;
394
0
  }
395
0
396
0
  nsCOMPtr<nsIContent> originalTarget = do_QueryInterface(mOriginalTarget);
397
0
  return EventStateManager::IsRemoteTarget(originalTarget);
398
0
}
399
400
bool
401
WidgetEvent::IsRetargetedNativeEventDelivererForPlugin() const
402
0
{
403
0
  const WidgetPluginEvent* pluginEvent = AsPluginEvent();
404
0
  return pluginEvent && pluginEvent->mRetargetToFocusedDocument;
405
0
}
406
407
bool
408
WidgetEvent::IsNonRetargetedNativeEventDelivererForPlugin() const
409
0
{
410
0
  const WidgetPluginEvent* pluginEvent = AsPluginEvent();
411
0
  return pluginEvent && !pluginEvent->mRetargetToFocusedDocument;
412
0
}
413
414
bool
415
WidgetEvent::IsIMERelatedEvent() const
416
0
{
417
0
  return HasIMEEventMessage() || IsQueryContentEvent() || IsSelectionEvent();
418
0
}
419
420
bool
421
WidgetEvent::IsUsingCoordinates() const
422
0
{
423
0
  const WidgetMouseEvent* mouseEvent = AsMouseEvent();
424
0
  if (mouseEvent) {
425
0
    return !mouseEvent->IsContextMenuKeyEvent();
426
0
  }
427
0
  return !HasKeyEventMessage() && !IsIMERelatedEvent() &&
428
0
         !HasPluginActivationEventMessage() &&
429
0
         !IsNativeEventDelivererForPlugin() &&
430
0
         !IsContentCommandEvent();
431
0
}
432
433
bool
434
WidgetEvent::IsTargetedAtFocusedWindow() const
435
0
{
436
0
  const WidgetMouseEvent* mouseEvent = AsMouseEvent();
437
0
  if (mouseEvent) {
438
0
    return mouseEvent->IsContextMenuKeyEvent();
439
0
  }
440
0
  return HasKeyEventMessage() || IsIMERelatedEvent() ||
441
0
         IsContentCommandEvent() ||
442
0
         IsRetargetedNativeEventDelivererForPlugin();
443
0
}
444
445
bool
446
WidgetEvent::IsTargetedAtFocusedContent() const
447
0
{
448
0
  const WidgetMouseEvent* mouseEvent = AsMouseEvent();
449
0
  if (mouseEvent) {
450
0
    return mouseEvent->IsContextMenuKeyEvent();
451
0
  }
452
0
  return HasKeyEventMessage() || IsIMERelatedEvent() ||
453
0
         IsRetargetedNativeEventDelivererForPlugin();
454
0
}
455
456
bool
457
WidgetEvent::IsAllowedToDispatchDOMEvent() const
458
0
{
459
0
  switch (mClass) {
460
0
    case eMouseEventClass:
461
0
      if (mMessage == eMouseTouchDrag) {
462
0
        return false;
463
0
      }
464
0
      MOZ_FALLTHROUGH;
465
0
    case ePointerEventClass:
466
0
      // We want synthesized mouse moves to cause mouseover and mouseout
467
0
      // DOM events (EventStateManager::PreHandleEvent), but not mousemove
468
0
      // DOM events.
469
0
      // Synthesized button up events also do not cause DOM events because they
470
0
      // do not have a reliable mRefPoint.
471
0
      return AsMouseEvent()->mReason == WidgetMouseEvent::eReal;
472
0
473
0
    case eWheelEventClass: {
474
0
      // wheel event whose all delta values are zero by user pref applied, it
475
0
      // shouldn't cause a DOM event.
476
0
      const WidgetWheelEvent* wheelEvent = AsWheelEvent();
477
0
      return wheelEvent->mDeltaX != 0.0 || wheelEvent->mDeltaY != 0.0 ||
478
0
             wheelEvent->mDeltaZ != 0.0;
479
0
    }
480
0
    case eTouchEventClass:
481
0
      return mMessage != eTouchPointerCancel;
482
0
    // Following events are handled in EventStateManager, so, we don't need to
483
0
    // dispatch DOM event for them into the DOM tree.
484
0
    case eQueryContentEventClass:
485
0
    case eSelectionEventClass:
486
0
    case eContentCommandEventClass:
487
0
      return false;
488
0
489
0
    default:
490
0
      return true;
491
0
  }
492
0
}
493
494
bool
495
WidgetEvent::IsAllowedToDispatchInSystemGroup() const
496
0
{
497
0
  // We don't expect to implement default behaviors with pointer events because
498
0
  // if we do, prevent default on mouse events can't prevent default behaviors
499
0
  // anymore.
500
0
  return mClass != ePointerEventClass;
501
0
}
502
503
bool
504
WidgetEvent::IsBlockedForFingerprintingResistance() const
505
0
{
506
0
  if (mClass == eKeyboardEventClass &&
507
0
      nsContentUtils::ShouldResistFingerprinting()) {
508
0
    const WidgetKeyboardEvent* keyboardEvent = AsKeyboardEvent();
509
0
510
0
    if (keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Alt     ||
511
0
        keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Shift   ||
512
0
        keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_Control ||
513
0
        keyboardEvent->mKeyNameIndex == KEY_NAME_INDEX_AltGraph) {
514
0
      return true;
515
0
    }
516
0
  }
517
0
518
0
  return false;
519
0
}
520
521
/******************************************************************************
522
 * mozilla::WidgetEvent
523
 *
524
 * Misc methods.
525
 ******************************************************************************/
526
527
static dom::EventTarget*
528
GetTargetForDOMEvent(dom::EventTarget* aTarget)
529
0
{
530
0
  return aTarget ? aTarget->GetTargetForDOMEvent() : nullptr;
531
0
}
532
533
dom::EventTarget*
534
WidgetEvent::GetDOMEventTarget() const
535
0
{
536
0
  return GetTargetForDOMEvent(mTarget);
537
0
}
538
539
dom::EventTarget*
540
WidgetEvent::GetCurrentDOMEventTarget() const
541
0
{
542
0
  return GetTargetForDOMEvent(mCurrentTarget);
543
0
}
544
545
dom::EventTarget*
546
WidgetEvent::GetOriginalDOMEventTarget() const
547
0
{
548
0
  if (mOriginalTarget) {
549
0
    return GetTargetForDOMEvent(mOriginalTarget);
550
0
  }
551
0
  return GetDOMEventTarget();
552
0
}
553
554
void
555
WidgetEvent::PreventDefault(bool aCalledByDefaultHandler,
556
                            nsIPrincipal* aPrincipal)
557
0
{
558
0
  if (mMessage == ePointerDown) {
559
0
    if (aCalledByDefaultHandler) {
560
0
      // Shouldn't prevent default on pointerdown by default handlers to stop
561
0
      // firing legacy mouse events. Use MOZ_ASSERT to catch incorrect usages
562
0
      // in debug builds.
563
0
      MOZ_ASSERT(false);
564
0
      return;
565
0
    }
566
0
    if (aPrincipal) {
567
0
      nsAutoString addonId;
568
0
      Unused << NS_WARN_IF(NS_FAILED(aPrincipal->GetAddonId(addonId)));
569
0
      if (!addonId.IsEmpty()) {
570
0
        // Ignore the case that it's called by a web extension.
571
0
        return;
572
0
      }
573
0
    }
574
0
  }
575
0
  mFlags.PreventDefault(aCalledByDefaultHandler);
576
0
}
577
578
bool
579
WidgetEvent::IsUserAction() const
580
0
{
581
0
  if (!IsTrusted()) {
582
0
    return false;
583
0
  }
584
0
  // FYI: eMouseScrollEventClass and ePointerEventClass represent
585
0
  //      user action but they are synthesized events.
586
0
  switch (mClass) {
587
0
    case eKeyboardEventClass:
588
0
    case eCompositionEventClass:
589
0
    case eMouseScrollEventClass:
590
0
    case eWheelEventClass:
591
0
    case eGestureNotifyEventClass:
592
0
    case eSimpleGestureEventClass:
593
0
    case eTouchEventClass:
594
0
    case eCommandEventClass:
595
0
    case eContentCommandEventClass:
596
0
    case ePluginEventClass:
597
0
      return true;
598
0
    case eMouseEventClass:
599
0
    case eDragEventClass:
600
0
    case ePointerEventClass:
601
0
      return AsMouseEvent()->IsReal();
602
0
    default:
603
0
      return false;
604
0
  }
605
0
}
606
607
/******************************************************************************
608
 * mozilla::WidgetInputEvent
609
 ******************************************************************************/
610
611
/* static */
612
Modifier
613
WidgetInputEvent::GetModifier(const nsAString& aDOMKeyName)
614
0
{
615
0
  if (aDOMKeyName.EqualsLiteral("Accel")) {
616
0
    return AccelModifier();
617
0
  }
618
0
  KeyNameIndex keyNameIndex = WidgetKeyboardEvent::GetKeyNameIndex(aDOMKeyName);
619
0
  return WidgetKeyboardEvent::GetModifierForKeyName(keyNameIndex);
620
0
}
621
622
/* static */
623
Modifier
624
WidgetInputEvent::AccelModifier()
625
0
{
626
0
  static Modifier sAccelModifier = MODIFIER_NONE;
627
0
  if (sAccelModifier == MODIFIER_NONE) {
628
0
    switch (Preferences::GetInt("ui.key.accelKey", 0)) {
629
0
      case dom::KeyboardEvent_Binding::DOM_VK_META:
630
0
        sAccelModifier = MODIFIER_META;
631
0
        break;
632
0
      case dom::KeyboardEvent_Binding::DOM_VK_WIN:
633
0
        sAccelModifier = MODIFIER_OS;
634
0
        break;
635
0
      case dom::KeyboardEvent_Binding::DOM_VK_ALT:
636
0
        sAccelModifier = MODIFIER_ALT;
637
0
        break;
638
0
      case dom::KeyboardEvent_Binding::DOM_VK_CONTROL:
639
0
        sAccelModifier = MODIFIER_CONTROL;
640
0
        break;
641
0
      default:
642
#ifdef XP_MACOSX
643
        sAccelModifier = MODIFIER_META;
644
#else
645
        sAccelModifier = MODIFIER_CONTROL;
646
0
#endif
647
0
        break;
648
0
    }
649
0
  }
650
0
  return sAccelModifier;
651
0
}
652
653
/******************************************************************************
654
 * mozilla::WidgetWheelEvent (MouseEvents.h)
655
 ******************************************************************************/
656
657
/* static */ double
658
WidgetWheelEvent::ComputeOverriddenDelta(double aDelta, bool aIsForVertical)
659
0
{
660
0
  if (!gfxPrefs::MouseWheelHasRootScrollDeltaOverride()) {
661
0
    return aDelta;
662
0
  }
663
0
  int32_t intFactor = aIsForVertical
664
0
                      ? gfxPrefs::MouseWheelRootScrollVerticalFactor()
665
0
                      : gfxPrefs::MouseWheelRootScrollHorizontalFactor();
666
0
  // Making the scroll speed slower doesn't make sense. So, ignore odd factor
667
0
  // which is less than 1.0.
668
0
  if (intFactor <= 100) {
669
0
    return aDelta;
670
0
  }
671
0
  double factor = static_cast<double>(intFactor) / 100;
672
0
  return aDelta * factor;
673
0
}
674
675
double
676
WidgetWheelEvent::OverriddenDeltaX() const
677
0
{
678
0
  if (!mAllowToOverrideSystemScrollSpeed) {
679
0
    return mDeltaX;
680
0
  }
681
0
  return ComputeOverriddenDelta(mDeltaX, false);
682
0
}
683
684
double
685
WidgetWheelEvent::OverriddenDeltaY() const
686
0
{
687
0
  if (!mAllowToOverrideSystemScrollSpeed) {
688
0
    return mDeltaY;
689
0
  }
690
0
  return ComputeOverriddenDelta(mDeltaY, true);
691
0
}
692
693
/******************************************************************************
694
 * mozilla::WidgetKeyboardEvent (TextEvents.h)
695
 ******************************************************************************/
696
697
#define NS_DEFINE_KEYNAME(aCPPName, aDOMKeyName) (u"" aDOMKeyName),
698
const char16_t* const WidgetKeyboardEvent::kKeyNames[] = {
699
#include "mozilla/KeyNameList.h"
700
};
701
#undef NS_DEFINE_KEYNAME
702
703
#define NS_DEFINE_PHYSICAL_KEY_CODE_NAME(aCPPName, aDOMCodeName) \
704
    (u"" aDOMCodeName),
705
const char16_t* const WidgetKeyboardEvent::kCodeNames[] = {
706
#include "mozilla/PhysicalKeyCodeNameList.h"
707
};
708
#undef NS_DEFINE_PHYSICAL_KEY_CODE_NAME
709
710
WidgetKeyboardEvent::KeyNameIndexHashtable*
711
  WidgetKeyboardEvent::sKeyNameIndexHashtable = nullptr;
712
WidgetKeyboardEvent::CodeNameIndexHashtable*
713
  WidgetKeyboardEvent::sCodeNameIndexHashtable = nullptr;
714
715
void
716
WidgetKeyboardEvent::InitAllEditCommands()
717
0
{
718
0
  // If the event was created without widget, e.g., created event in chrome
719
0
  // script, this shouldn't execute native key bindings.
720
0
  if (NS_WARN_IF(!mWidget)) {
721
0
    return;
722
0
  }
723
0
724
0
  // This event should be trusted event here and we shouldn't expose native
725
0
  // key binding information to web contents with untrusted events.
726
0
  if (NS_WARN_IF(!IsTrusted())) {
727
0
    return;
728
0
  }
729
0
730
0
  MOZ_ASSERT(XRE_IsParentProcess(),
731
0
    "It's too expensive to retrieve all edit commands from remote process");
732
0
  MOZ_ASSERT(!AreAllEditCommandsInitialized(),
733
0
    "Shouldn't be called two or more times");
734
0
735
0
  InitEditCommandsFor(nsIWidget::NativeKeyBindingsForSingleLineEditor);
736
0
  InitEditCommandsFor(nsIWidget::NativeKeyBindingsForMultiLineEditor);
737
0
  InitEditCommandsFor(nsIWidget::NativeKeyBindingsForRichTextEditor);
738
0
}
739
740
void
741
WidgetKeyboardEvent::InitEditCommandsFor(nsIWidget::NativeKeyBindingsType aType)
742
0
{
743
0
  if (NS_WARN_IF(!mWidget) || NS_WARN_IF(!IsTrusted())) {
744
0
    return;
745
0
  }
746
0
747
0
  bool& initialized = IsEditCommandsInitializedRef(aType);
748
0
  if (initialized) {
749
0
    return;
750
0
  }
751
0
  nsTArray<CommandInt>& commands = EditCommandsRef(aType);
752
0
  mWidget->GetEditCommands(aType, *this, commands);
753
0
  initialized = true;
754
0
}
755
756
bool
757
WidgetKeyboardEvent::ExecuteEditCommands(nsIWidget::NativeKeyBindingsType aType,
758
                                         DoCommandCallback aCallback,
759
                                         void* aCallbackData)
760
0
{
761
0
  // If the event was created without widget, e.g., created event in chrome
762
0
  // script, this shouldn't execute native key bindings.
763
0
  if (NS_WARN_IF(!mWidget)) {
764
0
    return false;
765
0
  }
766
0
767
0
  // This event should be trusted event here and we shouldn't expose native
768
0
  // key binding information to web contents with untrusted events.
769
0
  if (NS_WARN_IF(!IsTrusted())) {
770
0
    return false;
771
0
  }
772
0
773
0
  InitEditCommandsFor(aType);
774
0
775
0
  const nsTArray<CommandInt>& commands = EditCommandsRef(aType);
776
0
  if (commands.IsEmpty()) {
777
0
    return false;
778
0
  }
779
0
780
0
  for (CommandInt command : commands) {
781
0
    aCallback(static_cast<Command>(command), aCallbackData);
782
0
  }
783
0
  return true;
784
0
}
785
786
bool
787
WidgetKeyboardEvent::ShouldCauseKeypressEvents() const
788
{
789
  // Currently, we don't dispatch keypress events of modifier keys and
790
  // dead keys.
791
  switch (mKeyNameIndex) {
792
    case KEY_NAME_INDEX_Alt:
793
    case KEY_NAME_INDEX_AltGraph:
794
    case KEY_NAME_INDEX_CapsLock:
795
    case KEY_NAME_INDEX_Control:
796
    case KEY_NAME_INDEX_Fn:
797
    case KEY_NAME_INDEX_FnLock:
798
    // case KEY_NAME_INDEX_Hyper:
799
    case KEY_NAME_INDEX_Meta:
800
    case KEY_NAME_INDEX_NumLock:
801
    case KEY_NAME_INDEX_OS:
802
    case KEY_NAME_INDEX_ScrollLock:
803
    case KEY_NAME_INDEX_Shift:
804
    // case KEY_NAME_INDEX_Super:
805
    case KEY_NAME_INDEX_Symbol:
806
    case KEY_NAME_INDEX_SymbolLock:
807
    case KEY_NAME_INDEX_Dead:
808
      return false;
809
    default:
810
      return true;
811
  }
812
}
813
814
static bool
815
HasASCIIDigit(const ShortcutKeyCandidateArray& aCandidates)
816
0
{
817
0
  for (uint32_t i = 0; i < aCandidates.Length(); ++i) {
818
0
    uint32_t ch = aCandidates[i].mCharCode;
819
0
    if (ch >= '0' && ch <= '9')
820
0
      return true;
821
0
  }
822
0
  return false;
823
0
}
824
825
static bool
826
CharsCaseInsensitiveEqual(uint32_t aChar1, uint32_t aChar2)
827
0
{
828
0
  return aChar1 == aChar2 ||
829
0
         (IS_IN_BMP(aChar1) && IS_IN_BMP(aChar2) &&
830
0
          ToLowerCase(static_cast<char16_t>(aChar1)) ==
831
0
            ToLowerCase(static_cast<char16_t>(aChar2)));
832
0
}
833
834
static bool
835
IsCaseChangeableChar(uint32_t aChar)
836
0
{
837
0
  return IS_IN_BMP(aChar) &&
838
0
         ToLowerCase(static_cast<char16_t>(aChar)) !=
839
0
           ToUpperCase(static_cast<char16_t>(aChar));
840
0
}
841
842
void
843
WidgetKeyboardEvent::GetShortcutKeyCandidates(
844
                       ShortcutKeyCandidateArray& aCandidates) const
845
0
{
846
0
  MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
847
0
848
0
  // ShortcutKeyCandidate::mCharCode is a candidate charCode.
849
0
  // ShortcutKeyCandidate::mIgnoreShift means the mCharCode should be tried to
850
0
  // execute a command with/without shift key state. If this is TRUE, the
851
0
  // shifted key state should be ignored. Otherwise, don't ignore the state.
852
0
  // the priority of the charCodes are (shift key is not pressed):
853
0
  //   0: PseudoCharCode()/false,
854
0
  //   1: unshiftedCharCodes[0]/false, 2: unshiftedCharCodes[1]/false...
855
0
  // the priority of the charCodes are (shift key is pressed):
856
0
  //   0: PseudoCharCode()/false,
857
0
  //   1: shiftedCharCodes[0]/false, 2: shiftedCharCodes[0]/true,
858
0
  //   3: shiftedCharCodes[1]/false, 4: shiftedCharCodes[1]/true...
859
0
  uint32_t pseudoCharCode = PseudoCharCode();
860
0
  if (pseudoCharCode) {
861
0
    ShortcutKeyCandidate key(pseudoCharCode, false);
862
0
    aCandidates.AppendElement(key);
863
0
  }
864
0
865
0
  uint32_t len = mAlternativeCharCodes.Length();
866
0
  if (!IsShift()) {
867
0
    for (uint32_t i = 0; i < len; ++i) {
868
0
      uint32_t ch = mAlternativeCharCodes[i].mUnshiftedCharCode;
869
0
      if (!ch || ch == pseudoCharCode) {
870
0
        continue;
871
0
      }
872
0
      ShortcutKeyCandidate key(ch, false);
873
0
      aCandidates.AppendElement(key);
874
0
    }
875
0
    // If unshiftedCharCodes doesn't have numeric but shiftedCharCode has it,
876
0
    // this keyboard layout is AZERTY or similar layout, probably.
877
0
    // In this case, Accel+[0-9] should be accessible without shift key.
878
0
    // However, the priority should be lowest.
879
0
    if (!HasASCIIDigit(aCandidates)) {
880
0
      for (uint32_t i = 0; i < len; ++i) {
881
0
        uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
882
0
        if (ch >= '0' && ch <= '9') {
883
0
          ShortcutKeyCandidate key(ch, false);
884
0
          aCandidates.AppendElement(key);
885
0
          break;
886
0
        }
887
0
      }
888
0
    }
889
0
  } else {
890
0
    for (uint32_t i = 0; i < len; ++i) {
891
0
      uint32_t ch = mAlternativeCharCodes[i].mShiftedCharCode;
892
0
      if (!ch) {
893
0
        continue;
894
0
      }
895
0
896
0
      if (ch != pseudoCharCode) {
897
0
        ShortcutKeyCandidate key(ch, false);
898
0
        aCandidates.AppendElement(key);
899
0
      }
900
0
901
0
      // If the char is an alphabet, the shift key state should not be
902
0
      // ignored. E.g., Ctrl+Shift+C should not execute Ctrl+C.
903
0
904
0
      // And checking the charCode is same as unshiftedCharCode too.
905
0
      // E.g., for Ctrl+Shift+(Plus of Numpad) should not run Ctrl+Plus.
906
0
      uint32_t unshiftCh = mAlternativeCharCodes[i].mUnshiftedCharCode;
907
0
      if (CharsCaseInsensitiveEqual(ch, unshiftCh)) {
908
0
        continue;
909
0
      }
910
0
911
0
      // On the Hebrew keyboard layout on Windows, the unshifted char is a
912
0
      // localized character but the shifted char is a Latin alphabet,
913
0
      // then, we should not execute without the shift state. See bug 433192.
914
0
      if (IsCaseChangeableChar(ch)) {
915
0
        continue;
916
0
      }
917
0
918
0
      // Setting the alternative charCode candidates for retry without shift
919
0
      // key state only when the shift key is pressed.
920
0
      ShortcutKeyCandidate key(ch, true);
921
0
      aCandidates.AppendElement(key);
922
0
    }
923
0
  }
924
0
925
0
  // Special case for "Space" key.  With some keyboard layouts, "Space" with
926
0
  // or without Shift key causes non-ASCII space.  For such keyboard layouts,
927
0
  // we should guarantee that the key press works as an ASCII white space key
928
0
  // press.  However, if the space key is assigned to a function key, it
929
0
  // shouldn't work as a space key.
930
0
  if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
931
0
      mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
932
0
    ShortcutKeyCandidate spaceKey(' ', false);
933
0
    aCandidates.AppendElement(spaceKey);
934
0
  }
935
0
}
936
937
void
938
WidgetKeyboardEvent::GetAccessKeyCandidates(nsTArray<uint32_t>& aCandidates) const
939
0
{
940
0
  MOZ_ASSERT(aCandidates.IsEmpty(), "aCandidates must be empty");
941
0
942
0
  // return the lower cased charCode candidates for access keys.
943
0
  // the priority of the charCodes are:
944
0
  //   0: charCode, 1: unshiftedCharCodes[0], 2: shiftedCharCodes[0]
945
0
  //   3: unshiftedCharCodes[1], 4: shiftedCharCodes[1],...
946
0
  uint32_t pseudoCharCode = PseudoCharCode();
947
0
  if (pseudoCharCode) {
948
0
    uint32_t ch = pseudoCharCode;
949
0
    if (IS_IN_BMP(ch)) {
950
0
      ch = ToLowerCase(static_cast<char16_t>(ch));
951
0
    }
952
0
    aCandidates.AppendElement(ch);
953
0
  }
954
0
  for (uint32_t i = 0; i < mAlternativeCharCodes.Length(); ++i) {
955
0
    uint32_t ch[2] =
956
0
      { mAlternativeCharCodes[i].mUnshiftedCharCode,
957
0
        mAlternativeCharCodes[i].mShiftedCharCode };
958
0
    for (uint32_t j = 0; j < 2; ++j) {
959
0
      if (!ch[j]) {
960
0
        continue;
961
0
      }
962
0
      if (IS_IN_BMP(ch[j])) {
963
0
        ch[j] = ToLowerCase(static_cast<char16_t>(ch[j]));
964
0
      }
965
0
      // Don't append the charcode that was already appended.
966
0
      if (aCandidates.IndexOf(ch[j]) == aCandidates.NoIndex) {
967
0
        aCandidates.AppendElement(ch[j]);
968
0
      }
969
0
    }
970
0
  }
971
0
  // Special case for "Space" key.  With some keyboard layouts, "Space" with
972
0
  // or without Shift key causes non-ASCII space.  For such keyboard layouts,
973
0
  // we should guarantee that the key press works as an ASCII white space key
974
0
  // press.  However, if the space key is assigned to a function key, it
975
0
  // shouldn't work as a space key.
976
0
  if (mKeyNameIndex == KEY_NAME_INDEX_USE_STRING &&
977
0
      mCodeNameIndex == CODE_NAME_INDEX_Space && pseudoCharCode != ' ') {
978
0
    aCandidates.AppendElement(' ');
979
0
  }
980
0
}
981
982
// mask values for ui.key.chromeAccess and ui.key.contentAccess
983
0
#define NS_MODIFIER_SHIFT    1
984
0
#define NS_MODIFIER_CONTROL  2
985
0
#define NS_MODIFIER_ALT      4
986
0
#define NS_MODIFIER_META     8
987
0
#define NS_MODIFIER_OS       16
988
989
static Modifiers PrefFlagsToModifiers(int32_t aPrefFlags)
990
0
{
991
0
  Modifiers result = 0;
992
0
  if (aPrefFlags & NS_MODIFIER_SHIFT) {
993
0
    result |= MODIFIER_SHIFT;
994
0
  }
995
0
  if (aPrefFlags & NS_MODIFIER_CONTROL) {
996
0
    result |= MODIFIER_CONTROL;
997
0
  }
998
0
  if (aPrefFlags & NS_MODIFIER_ALT) {
999
0
    result |= MODIFIER_ALT;
1000
0
  }
1001
0
  if (aPrefFlags & NS_MODIFIER_META) {
1002
0
    result |= MODIFIER_META;
1003
0
  }
1004
0
  if (aPrefFlags & NS_MODIFIER_OS) {
1005
0
    result |= MODIFIER_OS;
1006
0
  }
1007
0
  return result;
1008
0
}
1009
1010
bool
1011
WidgetKeyboardEvent::ModifiersMatchWithAccessKey(AccessKeyType aType) const
1012
0
{
1013
0
  if (!ModifiersForAccessKeyMatching()) {
1014
0
    return false;
1015
0
  }
1016
0
  return ModifiersForAccessKeyMatching() == AccessKeyModifiers(aType);
1017
0
}
1018
1019
Modifiers
1020
WidgetKeyboardEvent::ModifiersForAccessKeyMatching() const
1021
0
{
1022
0
  static const Modifiers kModifierMask =
1023
0
    MODIFIER_SHIFT | MODIFIER_CONTROL |
1024
0
    MODIFIER_ALT | MODIFIER_META | MODIFIER_OS;
1025
0
  return mModifiers & kModifierMask;
1026
0
}
1027
1028
/* static */
1029
Modifiers
1030
WidgetKeyboardEvent::AccessKeyModifiers(AccessKeyType aType)
1031
0
{
1032
0
  switch (GenericAccessModifierKeyPref()) {
1033
0
    case -1:
1034
0
      break; // use the individual prefs
1035
0
    case NS_VK_SHIFT:
1036
0
      return MODIFIER_SHIFT;
1037
0
    case NS_VK_CONTROL:
1038
0
      return MODIFIER_CONTROL;
1039
0
    case NS_VK_ALT:
1040
0
      return MODIFIER_ALT;
1041
0
    case NS_VK_META:
1042
0
      return MODIFIER_META;
1043
0
    case NS_VK_WIN:
1044
0
      return MODIFIER_OS;
1045
0
    default:
1046
0
      return MODIFIER_NONE;
1047
0
  }
1048
0
1049
0
  switch (aType) {
1050
0
    case AccessKeyType::eChrome:
1051
0
      return PrefFlagsToModifiers(ChromeAccessModifierMaskPref());
1052
0
    case AccessKeyType::eContent:
1053
0
      return PrefFlagsToModifiers(ContentAccessModifierMaskPref());
1054
0
    default:
1055
0
      return MODIFIER_NONE;
1056
0
  }
1057
0
}
1058
1059
/* static */
1060
int32_t
1061
WidgetKeyboardEvent::GenericAccessModifierKeyPref()
1062
0
{
1063
0
  static bool sInitialized = false;
1064
0
  static int32_t sValue = -1;
1065
0
  if (!sInitialized) {
1066
0
    nsresult rv =
1067
0
      Preferences::AddIntVarCache(&sValue, "ui.key.generalAccessKey", sValue);
1068
0
    sInitialized = NS_SUCCEEDED(rv);
1069
0
    MOZ_ASSERT(sInitialized);
1070
0
  }
1071
0
  return sValue;
1072
0
}
1073
1074
/* static */
1075
int32_t
1076
WidgetKeyboardEvent::ChromeAccessModifierMaskPref()
1077
0
{
1078
0
  static bool sInitialized = false;
1079
0
  static int32_t sValue = 0;
1080
0
  if (!sInitialized) {
1081
0
    nsresult rv =
1082
0
      Preferences::AddIntVarCache(&sValue, "ui.key.chromeAccess", sValue);
1083
0
    sInitialized = NS_SUCCEEDED(rv);
1084
0
    MOZ_ASSERT(sInitialized);
1085
0
  }
1086
0
  return sValue;
1087
0
}
1088
1089
/* static */
1090
int32_t
1091
WidgetKeyboardEvent::ContentAccessModifierMaskPref()
1092
0
{
1093
0
  static bool sInitialized = false;
1094
0
  static int32_t sValue = 0;
1095
0
  if (!sInitialized) {
1096
0
    nsresult rv =
1097
0
      Preferences::AddIntVarCache(&sValue, "ui.key.contentAccess", sValue);
1098
0
    sInitialized = NS_SUCCEEDED(rv);
1099
0
    MOZ_ASSERT(sInitialized);
1100
0
  }
1101
0
  return sValue;
1102
0
}
1103
1104
/* static */ void
1105
WidgetKeyboardEvent::Shutdown()
1106
0
{
1107
0
  delete sKeyNameIndexHashtable;
1108
0
  sKeyNameIndexHashtable = nullptr;
1109
0
  delete sCodeNameIndexHashtable;
1110
0
  sCodeNameIndexHashtable = nullptr;
1111
0
}
1112
1113
/* static */ void
1114
WidgetKeyboardEvent::GetDOMKeyName(KeyNameIndex aKeyNameIndex,
1115
                                   nsAString& aKeyName)
1116
0
{
1117
0
  if (aKeyNameIndex >= KEY_NAME_INDEX_USE_STRING) {
1118
0
    aKeyName.Truncate();
1119
0
    return;
1120
0
  }
1121
0
1122
0
  MOZ_RELEASE_ASSERT(static_cast<size_t>(aKeyNameIndex) <
1123
0
                       ArrayLength(kKeyNames),
1124
0
                     "Illegal key enumeration value");
1125
0
  aKeyName = kKeyNames[aKeyNameIndex];
1126
0
}
1127
1128
/* static */ void
1129
WidgetKeyboardEvent::GetDOMCodeName(CodeNameIndex aCodeNameIndex,
1130
                                    nsAString& aCodeName)
1131
0
{
1132
0
  if (aCodeNameIndex >= CODE_NAME_INDEX_USE_STRING) {
1133
0
    aCodeName.Truncate();
1134
0
    return;
1135
0
  }
1136
0
1137
0
  MOZ_RELEASE_ASSERT(static_cast<size_t>(aCodeNameIndex) <
1138
0
                       ArrayLength(kCodeNames),
1139
0
                     "Illegal physical code enumeration value");
1140
0
  aCodeName = kCodeNames[aCodeNameIndex];
1141
0
}
1142
1143
/* static */ KeyNameIndex
1144
WidgetKeyboardEvent::GetKeyNameIndex(const nsAString& aKeyValue)
1145
0
{
1146
0
  if (!sKeyNameIndexHashtable) {
1147
0
    sKeyNameIndexHashtable =
1148
0
      new KeyNameIndexHashtable(ArrayLength(kKeyNames));
1149
0
    for (size_t i = 0; i < ArrayLength(kKeyNames); i++) {
1150
0
      sKeyNameIndexHashtable->Put(nsDependentString(kKeyNames[i]),
1151
0
                                  static_cast<KeyNameIndex>(i));
1152
0
    }
1153
0
  }
1154
0
  KeyNameIndex result = KEY_NAME_INDEX_USE_STRING;
1155
0
  sKeyNameIndexHashtable->Get(aKeyValue, &result);
1156
0
  return result;
1157
0
}
1158
1159
/* static */ CodeNameIndex
1160
WidgetKeyboardEvent::GetCodeNameIndex(const nsAString& aCodeValue)
1161
0
{
1162
0
  if (!sCodeNameIndexHashtable) {
1163
0
    sCodeNameIndexHashtable =
1164
0
      new CodeNameIndexHashtable(ArrayLength(kCodeNames));
1165
0
    for (size_t i = 0; i < ArrayLength(kCodeNames); i++) {
1166
0
      sCodeNameIndexHashtable->Put(nsDependentString(kCodeNames[i]),
1167
0
                                   static_cast<CodeNameIndex>(i));
1168
0
    }
1169
0
  }
1170
0
  CodeNameIndex result = CODE_NAME_INDEX_USE_STRING;
1171
0
  sCodeNameIndexHashtable->Get(aCodeValue, &result);
1172
0
  return result;
1173
0
}
1174
1175
/* static */ uint32_t
1176
WidgetKeyboardEvent::GetFallbackKeyCodeOfPunctuationKey(
1177
                       CodeNameIndex aCodeNameIndex)
1178
{
1179
  switch (aCodeNameIndex) {
1180
    case CODE_NAME_INDEX_Semicolon:     // VK_OEM_1 on Windows
1181
      return dom::KeyboardEvent_Binding::DOM_VK_SEMICOLON;
1182
    case CODE_NAME_INDEX_Equal:         // VK_OEM_PLUS on Windows
1183
      return dom::KeyboardEvent_Binding::DOM_VK_EQUALS;
1184
    case CODE_NAME_INDEX_Comma:         // VK_OEM_COMMA on Windows
1185
      return dom::KeyboardEvent_Binding::DOM_VK_COMMA;
1186
    case CODE_NAME_INDEX_Minus:         // VK_OEM_MINUS on Windows
1187
      return dom::KeyboardEvent_Binding::DOM_VK_HYPHEN_MINUS;
1188
    case CODE_NAME_INDEX_Period:        // VK_OEM_PERIOD on Windows
1189
      return dom::KeyboardEvent_Binding::DOM_VK_PERIOD;
1190
    case CODE_NAME_INDEX_Slash:         // VK_OEM_2 on Windows
1191
      return dom::KeyboardEvent_Binding::DOM_VK_SLASH;
1192
    case CODE_NAME_INDEX_Backquote:     // VK_OEM_3 on Windows
1193
      return dom::KeyboardEvent_Binding::DOM_VK_BACK_QUOTE;
1194
    case CODE_NAME_INDEX_BracketLeft:   // VK_OEM_4 on Windows
1195
      return dom::KeyboardEvent_Binding::DOM_VK_OPEN_BRACKET;
1196
    case CODE_NAME_INDEX_Backslash:     // VK_OEM_5 on Windows
1197
      return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1198
    case CODE_NAME_INDEX_BracketRight:  // VK_OEM_6 on Windows
1199
      return dom::KeyboardEvent_Binding::DOM_VK_CLOSE_BRACKET;
1200
    case CODE_NAME_INDEX_Quote:         // VK_OEM_7 on Windows
1201
      return dom::KeyboardEvent_Binding::DOM_VK_QUOTE;
1202
    case CODE_NAME_INDEX_IntlBackslash: // VK_OEM_5 on Windows (ABNT, etc)
1203
    case CODE_NAME_INDEX_IntlYen:       // VK_OEM_5 on Windows (JIS)
1204
    case CODE_NAME_INDEX_IntlRo:        // VK_OEM_102 on Windows
1205
      return dom::KeyboardEvent_Binding::DOM_VK_BACK_SLASH;
1206
    default:
1207
      return 0;
1208
  }
1209
}
1210
1211
/* static */ const char*
1212
WidgetKeyboardEvent::GetCommandStr(Command aCommand)
1213
0
{
1214
0
#define NS_DEFINE_COMMAND(aName, aCommandStr) , #aCommandStr
1215
0
#define NS_DEFINE_COMMAND_NO_EXEC_COMMAND(aName)
1216
0
  static const char* const kCommands[] = {
1217
0
    "" // CommandDoNothing
1218
0
#include "mozilla/CommandList.h"
1219
0
  };
1220
0
#undef NS_DEFINE_COMMAND
1221
0
#undef NS_DEFINE_COMMAND_NO_EXEC_COMMAND
1222
0
1223
0
  MOZ_RELEASE_ASSERT(static_cast<size_t>(aCommand) < ArrayLength(kCommands),
1224
0
                     "Illegal command enumeration value");
1225
0
  return kCommands[aCommand];
1226
0
}
1227
1228
/* static */ uint32_t
1229
WidgetKeyboardEvent::ComputeLocationFromCodeValue(CodeNameIndex aCodeNameIndex)
1230
{
1231
  // Following commented out cases are not defined in PhysicalKeyCodeNameList.h
1232
  // but are defined by D3E spec.  So, they should be uncommented when the
1233
  // code values are defined in the header.
1234
  switch (aCodeNameIndex) {
1235
    case CODE_NAME_INDEX_AltLeft:
1236
    case CODE_NAME_INDEX_ControlLeft:
1237
    case CODE_NAME_INDEX_OSLeft:
1238
    case CODE_NAME_INDEX_ShiftLeft:
1239
      return eKeyLocationLeft;
1240
    case CODE_NAME_INDEX_AltRight:
1241
    case CODE_NAME_INDEX_ControlRight:
1242
    case CODE_NAME_INDEX_OSRight:
1243
    case CODE_NAME_INDEX_ShiftRight:
1244
      return eKeyLocationRight;
1245
    case CODE_NAME_INDEX_Numpad0:
1246
    case CODE_NAME_INDEX_Numpad1:
1247
    case CODE_NAME_INDEX_Numpad2:
1248
    case CODE_NAME_INDEX_Numpad3:
1249
    case CODE_NAME_INDEX_Numpad4:
1250
    case CODE_NAME_INDEX_Numpad5:
1251
    case CODE_NAME_INDEX_Numpad6:
1252
    case CODE_NAME_INDEX_Numpad7:
1253
    case CODE_NAME_INDEX_Numpad8:
1254
    case CODE_NAME_INDEX_Numpad9:
1255
    case CODE_NAME_INDEX_NumpadAdd:
1256
    case CODE_NAME_INDEX_NumpadBackspace:
1257
    case CODE_NAME_INDEX_NumpadClear:
1258
    case CODE_NAME_INDEX_NumpadClearEntry:
1259
    case CODE_NAME_INDEX_NumpadComma:
1260
    case CODE_NAME_INDEX_NumpadDecimal:
1261
    case CODE_NAME_INDEX_NumpadDivide:
1262
    case CODE_NAME_INDEX_NumpadEnter:
1263
    case CODE_NAME_INDEX_NumpadEqual:
1264
    case CODE_NAME_INDEX_NumpadMemoryAdd:
1265
    case CODE_NAME_INDEX_NumpadMemoryClear:
1266
    case CODE_NAME_INDEX_NumpadMemoryRecall:
1267
    case CODE_NAME_INDEX_NumpadMemoryStore:
1268
    case CODE_NAME_INDEX_NumpadMemorySubtract:
1269
    case CODE_NAME_INDEX_NumpadMultiply:
1270
    case CODE_NAME_INDEX_NumpadParenLeft:
1271
    case CODE_NAME_INDEX_NumpadParenRight:
1272
    case CODE_NAME_INDEX_NumpadSubtract:
1273
      return eKeyLocationNumpad;
1274
    default:
1275
      return eKeyLocationStandard;
1276
  }
1277
}
1278
1279
/* static */ uint32_t
1280
WidgetKeyboardEvent::ComputeKeyCodeFromKeyNameIndex(KeyNameIndex aKeyNameIndex)
1281
{
1282
  switch (aKeyNameIndex) {
1283
    case KEY_NAME_INDEX_Cancel:
1284
      return dom::KeyboardEvent_Binding::DOM_VK_CANCEL;
1285
    case KEY_NAME_INDEX_Help:
1286
      return dom::KeyboardEvent_Binding::DOM_VK_HELP;
1287
    case KEY_NAME_INDEX_Backspace:
1288
      return dom::KeyboardEvent_Binding::DOM_VK_BACK_SPACE;
1289
    case KEY_NAME_INDEX_Tab:
1290
      return dom::KeyboardEvent_Binding::DOM_VK_TAB;
1291
    case KEY_NAME_INDEX_Clear:
1292
      return dom::KeyboardEvent_Binding::DOM_VK_CLEAR;
1293
    case KEY_NAME_INDEX_Enter:
1294
      return dom::KeyboardEvent_Binding::DOM_VK_RETURN;
1295
    case KEY_NAME_INDEX_Shift:
1296
      return dom::KeyboardEvent_Binding::DOM_VK_SHIFT;
1297
    case KEY_NAME_INDEX_Control:
1298
      return dom::KeyboardEvent_Binding::DOM_VK_CONTROL;
1299
    case KEY_NAME_INDEX_Alt:
1300
      return dom::KeyboardEvent_Binding::DOM_VK_ALT;
1301
    case KEY_NAME_INDEX_Pause:
1302
      return dom::KeyboardEvent_Binding::DOM_VK_PAUSE;
1303
    case KEY_NAME_INDEX_CapsLock:
1304
      return dom::KeyboardEvent_Binding::DOM_VK_CAPS_LOCK;
1305
    case KEY_NAME_INDEX_Hiragana:
1306
    case KEY_NAME_INDEX_Katakana:
1307
    case KEY_NAME_INDEX_HiraganaKatakana:
1308
    case KEY_NAME_INDEX_KanaMode:
1309
      return dom::KeyboardEvent_Binding::DOM_VK_KANA;
1310
    case KEY_NAME_INDEX_HangulMode:
1311
      return dom::KeyboardEvent_Binding::DOM_VK_HANGUL;
1312
    case KEY_NAME_INDEX_Eisu:
1313
      return dom::KeyboardEvent_Binding::DOM_VK_EISU;
1314
    case KEY_NAME_INDEX_JunjaMode:
1315
      return dom::KeyboardEvent_Binding::DOM_VK_JUNJA;
1316
    case KEY_NAME_INDEX_FinalMode:
1317
      return dom::KeyboardEvent_Binding::DOM_VK_FINAL;
1318
    case KEY_NAME_INDEX_HanjaMode:
1319
      return dom::KeyboardEvent_Binding::DOM_VK_HANJA;
1320
    case KEY_NAME_INDEX_KanjiMode:
1321
      return dom::KeyboardEvent_Binding::DOM_VK_KANJI;
1322
    case KEY_NAME_INDEX_Escape:
1323
      return dom::KeyboardEvent_Binding::DOM_VK_ESCAPE;
1324
    case KEY_NAME_INDEX_Convert:
1325
      return dom::KeyboardEvent_Binding::DOM_VK_CONVERT;
1326
    case KEY_NAME_INDEX_NonConvert:
1327
      return dom::KeyboardEvent_Binding::DOM_VK_NONCONVERT;
1328
    case KEY_NAME_INDEX_Accept:
1329
      return dom::KeyboardEvent_Binding::DOM_VK_ACCEPT;
1330
    case KEY_NAME_INDEX_ModeChange:
1331
      return dom::KeyboardEvent_Binding::DOM_VK_MODECHANGE;
1332
    case KEY_NAME_INDEX_PageUp:
1333
      return dom::KeyboardEvent_Binding::DOM_VK_PAGE_UP;
1334
    case KEY_NAME_INDEX_PageDown:
1335
      return dom::KeyboardEvent_Binding::DOM_VK_PAGE_DOWN;
1336
    case KEY_NAME_INDEX_End:
1337
      return dom::KeyboardEvent_Binding::DOM_VK_END;
1338
    case KEY_NAME_INDEX_Home:
1339
      return dom::KeyboardEvent_Binding::DOM_VK_HOME;
1340
    case KEY_NAME_INDEX_ArrowLeft:
1341
      return dom::KeyboardEvent_Binding::DOM_VK_LEFT;
1342
    case KEY_NAME_INDEX_ArrowUp:
1343
      return dom::KeyboardEvent_Binding::DOM_VK_UP;
1344
    case KEY_NAME_INDEX_ArrowRight:
1345
      return dom::KeyboardEvent_Binding::DOM_VK_RIGHT;
1346
    case KEY_NAME_INDEX_ArrowDown:
1347
      return dom::KeyboardEvent_Binding::DOM_VK_DOWN;
1348
    case KEY_NAME_INDEX_Select:
1349
      return dom::KeyboardEvent_Binding::DOM_VK_SELECT;
1350
    case KEY_NAME_INDEX_Print:
1351
      return dom::KeyboardEvent_Binding::DOM_VK_PRINT;
1352
    case KEY_NAME_INDEX_Execute:
1353
      return dom::KeyboardEvent_Binding::DOM_VK_EXECUTE;
1354
    case KEY_NAME_INDEX_PrintScreen:
1355
      return dom::KeyboardEvent_Binding::DOM_VK_PRINTSCREEN;
1356
    case KEY_NAME_INDEX_Insert:
1357
      return dom::KeyboardEvent_Binding::DOM_VK_INSERT;
1358
    case KEY_NAME_INDEX_Delete:
1359
      return dom::KeyboardEvent_Binding::DOM_VK_DELETE;
1360
    case KEY_NAME_INDEX_OS:
1361
    // case KEY_NAME_INDEX_Super:
1362
    // case KEY_NAME_INDEX_Hyper:
1363
      return dom::KeyboardEvent_Binding::DOM_VK_WIN;
1364
    case KEY_NAME_INDEX_ContextMenu:
1365
      return dom::KeyboardEvent_Binding::DOM_VK_CONTEXT_MENU;
1366
    case KEY_NAME_INDEX_Standby:
1367
      return dom::KeyboardEvent_Binding::DOM_VK_SLEEP;
1368
    case KEY_NAME_INDEX_F1:
1369
      return dom::KeyboardEvent_Binding::DOM_VK_F1;
1370
    case KEY_NAME_INDEX_F2:
1371
      return dom::KeyboardEvent_Binding::DOM_VK_F2;
1372
    case KEY_NAME_INDEX_F3:
1373
      return dom::KeyboardEvent_Binding::DOM_VK_F3;
1374
    case KEY_NAME_INDEX_F4:
1375
      return dom::KeyboardEvent_Binding::DOM_VK_F4;
1376
    case KEY_NAME_INDEX_F5:
1377
      return dom::KeyboardEvent_Binding::DOM_VK_F5;
1378
    case KEY_NAME_INDEX_F6:
1379
      return dom::KeyboardEvent_Binding::DOM_VK_F6;
1380
    case KEY_NAME_INDEX_F7:
1381
      return dom::KeyboardEvent_Binding::DOM_VK_F7;
1382
    case KEY_NAME_INDEX_F8:
1383
      return dom::KeyboardEvent_Binding::DOM_VK_F8;
1384
    case KEY_NAME_INDEX_F9:
1385
      return dom::KeyboardEvent_Binding::DOM_VK_F9;
1386
    case KEY_NAME_INDEX_F10:
1387
      return dom::KeyboardEvent_Binding::DOM_VK_F10;
1388
    case KEY_NAME_INDEX_F11:
1389
      return dom::KeyboardEvent_Binding::DOM_VK_F11;
1390
    case KEY_NAME_INDEX_F12:
1391
      return dom::KeyboardEvent_Binding::DOM_VK_F12;
1392
    case KEY_NAME_INDEX_F13:
1393
      return dom::KeyboardEvent_Binding::DOM_VK_F13;
1394
    case KEY_NAME_INDEX_F14:
1395
      return dom::KeyboardEvent_Binding::DOM_VK_F14;
1396
    case KEY_NAME_INDEX_F15:
1397
      return dom::KeyboardEvent_Binding::DOM_VK_F15;
1398
    case KEY_NAME_INDEX_F16:
1399
      return dom::KeyboardEvent_Binding::DOM_VK_F16;
1400
    case KEY_NAME_INDEX_F17:
1401
      return dom::KeyboardEvent_Binding::DOM_VK_F17;
1402
    case KEY_NAME_INDEX_F18:
1403
      return dom::KeyboardEvent_Binding::DOM_VK_F18;
1404
    case KEY_NAME_INDEX_F19:
1405
      return dom::KeyboardEvent_Binding::DOM_VK_F19;
1406
    case KEY_NAME_INDEX_F20:
1407
      return dom::KeyboardEvent_Binding::DOM_VK_F20;
1408
    case KEY_NAME_INDEX_F21:
1409
      return dom::KeyboardEvent_Binding::DOM_VK_F21;
1410
    case KEY_NAME_INDEX_F22:
1411
      return dom::KeyboardEvent_Binding::DOM_VK_F22;
1412
    case KEY_NAME_INDEX_F23:
1413
      return dom::KeyboardEvent_Binding::DOM_VK_F23;
1414
    case KEY_NAME_INDEX_F24:
1415
      return dom::KeyboardEvent_Binding::DOM_VK_F24;
1416
    case KEY_NAME_INDEX_NumLock:
1417
      return dom::KeyboardEvent_Binding::DOM_VK_NUM_LOCK;
1418
    case KEY_NAME_INDEX_ScrollLock:
1419
      return dom::KeyboardEvent_Binding::DOM_VK_SCROLL_LOCK;
1420
    case KEY_NAME_INDEX_AudioVolumeMute:
1421
      return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_MUTE;
1422
    case KEY_NAME_INDEX_AudioVolumeDown:
1423
      return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_DOWN;
1424
    case KEY_NAME_INDEX_AudioVolumeUp:
1425
      return dom::KeyboardEvent_Binding::DOM_VK_VOLUME_UP;
1426
    case KEY_NAME_INDEX_Meta:
1427
      return dom::KeyboardEvent_Binding::DOM_VK_META;
1428
    case KEY_NAME_INDEX_AltGraph:
1429
      return dom::KeyboardEvent_Binding::DOM_VK_ALTGR;
1430
    case KEY_NAME_INDEX_Process:
1431
      return dom::KeyboardEvent_Binding::DOM_VK_PROCESSKEY;
1432
    case KEY_NAME_INDEX_Attn:
1433
      return dom::KeyboardEvent_Binding::DOM_VK_ATTN;
1434
    case KEY_NAME_INDEX_CrSel:
1435
      return dom::KeyboardEvent_Binding::DOM_VK_CRSEL;
1436
    case KEY_NAME_INDEX_ExSel:
1437
      return dom::KeyboardEvent_Binding::DOM_VK_EXSEL;
1438
    case KEY_NAME_INDEX_EraseEof:
1439
      return dom::KeyboardEvent_Binding::DOM_VK_EREOF;
1440
    case KEY_NAME_INDEX_Play:
1441
      return dom::KeyboardEvent_Binding::DOM_VK_PLAY;
1442
    case KEY_NAME_INDEX_ZoomToggle:
1443
    case KEY_NAME_INDEX_ZoomIn:
1444
    case KEY_NAME_INDEX_ZoomOut:
1445
      return dom::KeyboardEvent_Binding::DOM_VK_ZOOM;
1446
    default:
1447
      return 0;
1448
  }
1449
}
1450
1451
/* static */ Modifier
1452
WidgetKeyboardEvent::GetModifierForKeyName(KeyNameIndex aKeyNameIndex)
1453
{
1454
  switch (aKeyNameIndex) {
1455
    case KEY_NAME_INDEX_Alt:
1456
      return MODIFIER_ALT;
1457
    case KEY_NAME_INDEX_AltGraph:
1458
      return MODIFIER_ALTGRAPH;
1459
    case KEY_NAME_INDEX_CapsLock:
1460
      return MODIFIER_CAPSLOCK;
1461
    case KEY_NAME_INDEX_Control:
1462
      return MODIFIER_CONTROL;
1463
    case KEY_NAME_INDEX_Fn:
1464
      return MODIFIER_FN;
1465
    case KEY_NAME_INDEX_FnLock:
1466
      return MODIFIER_FNLOCK;
1467
    // case KEY_NAME_INDEX_Hyper:
1468
    case KEY_NAME_INDEX_Meta:
1469
      return MODIFIER_META;
1470
    case KEY_NAME_INDEX_NumLock:
1471
      return MODIFIER_NUMLOCK;
1472
    case KEY_NAME_INDEX_OS:
1473
      return MODIFIER_OS;
1474
    case KEY_NAME_INDEX_ScrollLock:
1475
      return MODIFIER_SCROLLLOCK;
1476
    case KEY_NAME_INDEX_Shift:
1477
      return MODIFIER_SHIFT;
1478
    // case KEY_NAME_INDEX_Super:
1479
    case KEY_NAME_INDEX_Symbol:
1480
      return MODIFIER_SYMBOL;
1481
    case KEY_NAME_INDEX_SymbolLock:
1482
      return MODIFIER_SYMBOLLOCK;
1483
    default:
1484
      return MODIFIER_NONE;
1485
  }
1486
}
1487
1488
/* static */ bool
1489
WidgetKeyboardEvent::IsLockableModifier(KeyNameIndex aKeyNameIndex)
1490
{
1491
  switch (aKeyNameIndex) {
1492
    case KEY_NAME_INDEX_CapsLock:
1493
    case KEY_NAME_INDEX_FnLock:
1494
    case KEY_NAME_INDEX_NumLock:
1495
    case KEY_NAME_INDEX_ScrollLock:
1496
    case KEY_NAME_INDEX_SymbolLock:
1497
      return true;
1498
    default:
1499
      return false;
1500
  }
1501
}
1502
1503
} // namespace mozilla