widget/windows/KeyboardLayout.h

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:33084d4076c4
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 KeyboardLayout_h__
7 #define KeyboardLayout_h__
8
9 #include "nscore.h"
10 #include "nsAutoPtr.h"
11 #include "nsString.h"
12 #include "nsWindowBase.h"
13 #include "nsWindowDefs.h"
14 #include "mozilla/Attributes.h"
15 #include "mozilla/EventForwards.h"
16 #include <windows.h>
17
18 #define NS_NUM_OF_KEYS 70
19
20 #define VK_OEM_1 0xBA // ';:' for US
21 #define VK_OEM_PLUS 0xBB // '+' any country
22 #define VK_OEM_COMMA 0xBC
23 #define VK_OEM_MINUS 0xBD // '-' any country
24 #define VK_OEM_PERIOD 0xBE
25 #define VK_OEM_2 0xBF
26 #define VK_OEM_3 0xC0
27 // '/?' for Brazilian (ABNT)
28 #define VK_ABNT_C1 0xC1
29 // Separator in Numpad for Brazilian (ABNT) or JIS keyboard for Mac.
30 #define VK_ABNT_C2 0xC2
31 #define VK_OEM_4 0xDB
32 #define VK_OEM_5 0xDC
33 #define VK_OEM_6 0xDD
34 #define VK_OEM_7 0xDE
35 #define VK_OEM_8 0xDF
36 #define VK_OEM_102 0xE2
37 #define VK_OEM_CLEAR 0xFE
38
39 class nsIIdleServiceInternal;
40 struct nsModifierKeyState;
41
42 namespace mozilla {
43 namespace widget {
44
45 static const uint32_t sModifierKeyMap[][3] = {
46 { nsIWidget::CAPS_LOCK, VK_CAPITAL, 0 },
47 { nsIWidget::NUM_LOCK, VK_NUMLOCK, 0 },
48 { nsIWidget::SHIFT_L, VK_SHIFT, VK_LSHIFT },
49 { nsIWidget::SHIFT_R, VK_SHIFT, VK_RSHIFT },
50 { nsIWidget::CTRL_L, VK_CONTROL, VK_LCONTROL },
51 { nsIWidget::CTRL_R, VK_CONTROL, VK_RCONTROL },
52 { nsIWidget::ALT_L, VK_MENU, VK_LMENU },
53 { nsIWidget::ALT_R, VK_MENU, VK_RMENU }
54 };
55
56 class KeyboardLayout;
57
58 class ModifierKeyState
59 {
60 public:
61 ModifierKeyState();
62 ModifierKeyState(bool aIsShiftDown, bool aIsControlDown, bool aIsAltDown);
63 ModifierKeyState(Modifiers aModifiers);
64
65 MOZ_ALWAYS_INLINE void Update();
66
67 MOZ_ALWAYS_INLINE void Unset(Modifiers aRemovingModifiers);
68 void Set(Modifiers aAddingModifiers);
69
70 void InitInputEvent(WidgetInputEvent& aInputEvent) const;
71
72 bool IsShift() const;
73 bool IsControl() const;
74 MOZ_ALWAYS_INLINE bool IsAlt() const;
75 MOZ_ALWAYS_INLINE bool IsAltGr() const;
76 MOZ_ALWAYS_INLINE bool IsWin() const;
77
78 MOZ_ALWAYS_INLINE bool IsCapsLocked() const;
79 MOZ_ALWAYS_INLINE bool IsNumLocked() const;
80 MOZ_ALWAYS_INLINE bool IsScrollLocked() const;
81
82 MOZ_ALWAYS_INLINE Modifiers GetModifiers() const;
83
84 private:
85 Modifiers mModifiers;
86
87 MOZ_ALWAYS_INLINE void EnsureAltGr();
88
89 void InitMouseEvent(WidgetInputEvent& aMouseEvent) const;
90 };
91
92 struct UniCharsAndModifiers
93 {
94 // Dead-key + up to 4 characters
95 char16_t mChars[5];
96 Modifiers mModifiers[5];
97 uint32_t mLength;
98
99 UniCharsAndModifiers() : mLength(0) {}
100 UniCharsAndModifiers operator+(const UniCharsAndModifiers& aOther) const;
101 UniCharsAndModifiers& operator+=(const UniCharsAndModifiers& aOther);
102
103 /**
104 * Append a pair of unicode character and the final modifier.
105 */
106 void Append(char16_t aUniChar, Modifiers aModifiers);
107 void Clear() { mLength = 0; }
108 bool IsEmpty() const { return !mLength; }
109
110 void FillModifiers(Modifiers aModifiers);
111
112 bool UniCharsEqual(const UniCharsAndModifiers& aOther) const;
113 bool UniCharsCaseInsensitiveEqual(const UniCharsAndModifiers& aOther) const;
114
115 nsString ToString() const { return nsString(mChars, mLength); }
116 };
117
118 struct DeadKeyEntry;
119 class DeadKeyTable;
120
121
122 class VirtualKey
123 {
124 public:
125 // 0 - Normal
126 // 1 - Shift
127 // 2 - Control
128 // 3 - Control + Shift
129 // 4 - Alt
130 // 5 - Alt + Shift
131 // 6 - Alt + Control (AltGr)
132 // 7 - Alt + Control + Shift (AltGr + Shift)
133 // 8 - CapsLock
134 // 9 - CapsLock + Shift
135 // 10 - CapsLock + Control
136 // 11 - CapsLock + Control + Shift
137 // 12 - CapsLock + Alt
138 // 13 - CapsLock + Alt + Shift
139 // 14 - CapsLock + Alt + Control (CapsLock + AltGr)
140 // 15 - CapsLock + Alt + Control + Shift (CapsLock + AltGr + Shift)
141
142 enum ShiftStateFlag
143 {
144 STATE_SHIFT = 0x01,
145 STATE_CONTROL = 0x02,
146 STATE_ALT = 0x04,
147 STATE_CAPSLOCK = 0x08
148 };
149
150 typedef uint8_t ShiftState;
151
152 static ShiftState ModifiersToShiftState(Modifiers aModifiers);
153 static Modifiers ShiftStateToModifiers(ShiftState aShiftState);
154
155 private:
156 union KeyShiftState
157 {
158 struct
159 {
160 char16_t Chars[4];
161 } Normal;
162 struct
163 {
164 const DeadKeyTable* Table;
165 char16_t DeadChar;
166 } DeadKey;
167 };
168
169 KeyShiftState mShiftStates[16];
170 uint16_t mIsDeadKey;
171
172 void SetDeadKey(ShiftState aShiftState, bool aIsDeadKey)
173 {
174 if (aIsDeadKey) {
175 mIsDeadKey |= 1 << aShiftState;
176 } else {
177 mIsDeadKey &= ~(1 << aShiftState);
178 }
179 }
180
181 public:
182 static void FillKbdState(PBYTE aKbdState, const ShiftState aShiftState);
183
184 bool IsDeadKey(ShiftState aShiftState) const
185 {
186 return (mIsDeadKey & (1 << aShiftState)) != 0;
187 }
188
189 void AttachDeadKeyTable(ShiftState aShiftState,
190 const DeadKeyTable* aDeadKeyTable)
191 {
192 mShiftStates[aShiftState].DeadKey.Table = aDeadKeyTable;
193 }
194
195 void SetNormalChars(ShiftState aShiftState, const char16_t* aChars,
196 uint32_t aNumOfChars);
197 void SetDeadChar(ShiftState aShiftState, char16_t aDeadChar);
198 const DeadKeyTable* MatchingDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
199 uint32_t aEntries) const;
200 inline char16_t GetCompositeChar(ShiftState aShiftState,
201 char16_t aBaseChar) const;
202 UniCharsAndModifiers GetNativeUniChars(ShiftState aShiftState) const;
203 UniCharsAndModifiers GetUniChars(ShiftState aShiftState) const;
204 };
205
206 class MOZ_STACK_CLASS NativeKey
207 {
208 friend class KeyboardLayout;
209
210 public:
211 struct FakeCharMsg
212 {
213 UINT mCharCode;
214 UINT mScanCode;
215 bool mIsDeadKey;
216 bool mConsumed;
217
218 FakeCharMsg() :
219 mCharCode(0), mScanCode(0), mIsDeadKey(false), mConsumed(false)
220 {
221 }
222
223 MSG GetCharMsg(HWND aWnd) const
224 {
225 MSG msg;
226 msg.hwnd = aWnd;
227 msg.message = mIsDeadKey ? WM_DEADCHAR : WM_CHAR;
228 msg.wParam = static_cast<WPARAM>(mCharCode);
229 msg.lParam = static_cast<LPARAM>(mScanCode << 16);
230 msg.time = 0;
231 msg.pt.x = msg.pt.y = 0;
232 return msg;
233 }
234 };
235
236 NativeKey(nsWindowBase* aWidget,
237 const MSG& aKeyOrCharMessage,
238 const ModifierKeyState& aModKeyState,
239 nsTArray<FakeCharMsg>* aFakeCharMsgs = nullptr);
240
241 /**
242 * Handle WM_KEYDOWN message or WM_SYSKEYDOWN message. The instance must be
243 * initialized with WM_KEYDOWN or WM_SYSKEYDOWN.
244 * Returns true if dispatched keydown event or keypress event is consumed.
245 * Otherwise, false.
246 */
247 bool HandleKeyDownMessage(bool* aEventDispatched = nullptr) const;
248
249 /**
250 * Handles WM_CHAR message or WM_SYSCHAR message. The instance must be
251 * initialized with WM_KEYDOWN, WM_SYSKEYDOWN or them.
252 * Returns true if dispatched keypress event is consumed. Otherwise, false.
253 */
254 bool HandleCharMessage(const MSG& aCharMsg,
255 bool* aEventDispatched = nullptr) const;
256
257 /**
258 * Handles keyup message. Returns true if the event is consumed.
259 * Otherwise, false.
260 */
261 bool HandleKeyUpMessage(bool* aEventDispatched = nullptr) const;
262
263 private:
264 nsRefPtr<nsWindowBase> mWidget;
265 HKL mKeyboardLayout;
266 MSG mMsg;
267
268 uint32_t mDOMKeyCode;
269 KeyNameIndex mKeyNameIndex;
270
271 ModifierKeyState mModKeyState;
272
273 // mVirtualKeyCode distinguishes left key or right key of modifier key.
274 uint8_t mVirtualKeyCode;
275 // mOriginalVirtualKeyCode doesn't distinguish left key or right key of
276 // modifier key. However, if the given keycode is VK_PROCESS, it's resolved
277 // to a keycode before it's handled by IME.
278 uint8_t mOriginalVirtualKeyCode;
279
280 // mCommittedChars indicates the inputted characters which is committed by
281 // the key. If dead key fail to composite a character, mCommittedChars
282 // indicates both the dead characters and the base characters.
283 UniCharsAndModifiers mCommittedCharsAndModifiers;
284
285 WORD mScanCode;
286 bool mIsExtended;
287 bool mIsDeadKey;
288 // mIsPrintableKey is true if the key may be a printable key without
289 // any modifier keys. Otherwise, false.
290 // Please note that the event may not cause any text input even if this
291 // is true. E.g., it might be dead key state or Ctrl key may be pressed.
292 bool mIsPrintableKey;
293
294 nsTArray<FakeCharMsg>* mFakeCharMsgs;
295
296 NativeKey()
297 {
298 MOZ_CRASH("The default constructor of NativeKey isn't available");
299 }
300
301 /**
302 * Returns true if the key event is caused by auto repeat.
303 */
304 bool IsRepeat() const
305 {
306 switch (mMsg.message) {
307 case WM_KEYDOWN:
308 case WM_SYSKEYDOWN:
309 case WM_CHAR:
310 case WM_SYSCHAR:
311 case WM_DEADCHAR:
312 case WM_SYSDEADCHAR:
313 return ((mMsg.lParam & (1 << 30)) != 0);
314 default:
315 return false;
316 }
317 }
318
319 UINT GetScanCodeWithExtendedFlag() const;
320
321 // The result is one of nsIDOMKeyEvent::DOM_KEY_LOCATION_*.
322 uint32_t GetKeyLocation() const;
323
324 /**
325 * "Kakutei-Undo" of ATOK or WXG (both of them are Japanese IME) causes
326 * strange WM_KEYDOWN/WM_KEYUP/WM_CHAR message pattern. So, when this
327 * returns true, the caller needs to be careful for processing the messages.
328 */
329 bool IsIMEDoingKakuteiUndo() const;
330
331 bool IsKeyDownMessage() const
332 {
333 return (mMsg.message == WM_KEYDOWN || mMsg.message == WM_SYSKEYDOWN);
334 }
335 bool IsKeyUpMessage() const
336 {
337 return (mMsg.message == WM_KEYUP || mMsg.message == WM_SYSKEYUP);
338 }
339 bool IsPrintableCharMessage(const MSG& aMSG) const
340 {
341 return IsPrintableCharMessage(aMSG.message);
342 }
343 bool IsPrintableCharMessage(UINT aMessage) const
344 {
345 return (aMessage == WM_CHAR || aMessage == WM_SYSCHAR);
346 }
347 bool IsCharMessage(const MSG& aMSG) const
348 {
349 return IsCharMessage(aMSG.message);
350 }
351 bool IsCharMessage(UINT aMessage) const
352 {
353 return (IsPrintableCharMessage(aMessage) || IsDeadCharMessage(aMessage));
354 }
355 bool IsDeadCharMessage(const MSG& aMSG) const
356 {
357 return IsDeadCharMessage(aMSG.message);
358 }
359 bool IsDeadCharMessage(UINT aMessage) const
360 {
361 return (aMessage == WM_DEADCHAR || aMessage == WM_SYSDEADCHAR);
362 }
363 bool IsSysCharMessage(const MSG& aMSG) const
364 {
365 return IsSysCharMessage(aMSG.message);
366 }
367 bool IsSysCharMessage(UINT aMessage) const
368 {
369 return (aMessage == WM_SYSCHAR || aMessage == WM_SYSDEADCHAR);
370 }
371 bool MayBeSameCharMessage(const MSG& aCharMsg1, const MSG& aCharMsg2) const;
372 bool IsFollowedByDeadCharMessage() const;
373
374 /**
375 * GetFollowingCharMessage() returns following char message of handling
376 * keydown event. If the message is found, this method returns true.
377 * Otherwise, returns false.
378 *
379 * WARNING: Even if this returns true, aCharMsg may be WM_NULL or its
380 * hwnd may be different window.
381 */
382 bool GetFollowingCharMessage(MSG& aCharMsg) const;
383
384 /**
385 * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK.
386 */
387 uint8_t ComputeVirtualKeyCodeFromScanCode() const;
388
389 /**
390 * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK_EX.
391 */
392 uint8_t ComputeVirtualKeyCodeFromScanCodeEx() const;
393
394 /**
395 * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK and MAPVK_VK_TO_CHAR.
396 */
397 char16_t ComputeUnicharFromScanCode() const;
398
399 /**
400 * Initializes the aKeyEvent with the information stored in the instance.
401 */
402 void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
403 const ModifierKeyState& aModKeyState) const;
404 void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent) const;
405
406 /**
407 * Dispatches the key event. Returns true if the event is consumed.
408 * Otherwise, false.
409 */
410 bool DispatchKeyEvent(WidgetKeyboardEvent& aKeyEvent,
411 const MSG* aMsgSentToPlugin = nullptr) const;
412
413 /**
414 * DispatchKeyPressEventsWithKeyboardLayout() dispatches keypress event(s)
415 * with the information provided by KeyboardLayout class.
416 */
417 bool DispatchKeyPressEventsWithKeyboardLayout() const;
418
419 /**
420 * Remove all following WM_CHAR, WM_SYSCHAR and WM_DEADCHAR messages for the
421 * WM_KEYDOWN or WM_SYSKEYDOWN message. Additionally, dispatches plugin
422 * events if it's necessary.
423 * Returns true if the widget is destroyed. Otherwise, false.
424 */
425 bool DispatchPluginEventsAndDiscardsCharMessages() const;
426
427 /**
428 * DispatchKeyPressEventForFollowingCharMessage() dispatches keypress event
429 * for following WM_*CHAR message which is removed and set to aCharMsg.
430 * Returns true if the event is consumed. Otherwise, false.
431 */
432 bool DispatchKeyPressEventForFollowingCharMessage(const MSG& aCharMsg) const;
433
434 /**
435 * Checkes whether the key event down message is handled without following
436 * WM_CHAR messages. For example, if following WM_CHAR message indicates
437 * control character input, the WM_CHAR message is unclear whether it's
438 * caused by a printable key with Ctrl or just a function key such as Enter
439 * or Backspace.
440 */
441 bool NeedsToHandleWithoutFollowingCharMessages() const;
442 };
443
444 class KeyboardLayout
445 {
446 friend class NativeKey;
447
448 private:
449 KeyboardLayout();
450 ~KeyboardLayout();
451
452 static KeyboardLayout* sInstance;
453 static nsIIdleServiceInternal* sIdleService;
454
455 struct DeadKeyTableListEntry
456 {
457 DeadKeyTableListEntry* next;
458 uint8_t data[1];
459 };
460
461 HKL mKeyboardLayout;
462
463 VirtualKey mVirtualKeys[NS_NUM_OF_KEYS];
464 DeadKeyTableListEntry* mDeadKeyTableListHead;
465 int32_t mActiveDeadKey; // -1 = no active dead-key
466 VirtualKey::ShiftState mDeadKeyShiftState;
467
468 bool mIsOverridden : 1;
469 bool mIsPendingToRestoreKeyboardLayout : 1;
470
471 static inline int32_t GetKeyIndex(uint8_t aVirtualKey);
472 static int CompareDeadKeyEntries(const void* aArg1, const void* aArg2,
473 void* aData);
474 static bool AddDeadKeyEntry(char16_t aBaseChar, char16_t aCompositeChar,
475 DeadKeyEntry* aDeadKeyArray, uint32_t aEntries);
476 bool EnsureDeadKeyActive(bool aIsActive, uint8_t aDeadKey,
477 const PBYTE aDeadKeyKbdState);
478 uint32_t GetDeadKeyCombinations(uint8_t aDeadKey,
479 const PBYTE aDeadKeyKbdState,
480 uint16_t aShiftStatesWithBaseChars,
481 DeadKeyEntry* aDeadKeyArray,
482 uint32_t aMaxEntries);
483 void DeactivateDeadKeyState();
484 const DeadKeyTable* AddDeadKeyTable(const DeadKeyEntry* aDeadKeyArray,
485 uint32_t aEntries);
486 void ReleaseDeadKeyTables();
487
488 /**
489 * Loads the specified keyboard layout. This method always clear the dead key
490 * state.
491 */
492 void LoadLayout(HKL aLayout);
493
494 /**
495 * InitNativeKey() must be called when actually widget receives WM_KEYDOWN or
496 * WM_KEYUP. This method is stateful. This saves current dead key state at
497 * WM_KEYDOWN. Additionally, computes current inputted character(s) and set
498 * them to the aNativeKey.
499 */
500 void InitNativeKey(NativeKey& aNativeKey,
501 const ModifierKeyState& aModKeyState);
502
503 public:
504 static KeyboardLayout* GetInstance();
505 static void Shutdown();
506 static void NotifyIdleServiceOfUserActivity();
507
508 static bool IsPrintableCharKey(uint8_t aVirtualKey);
509
510 /**
511 * IsDeadKey() returns true if aVirtualKey is a dead key with aModKeyState.
512 * This method isn't stateful.
513 */
514 bool IsDeadKey(uint8_t aVirtualKey,
515 const ModifierKeyState& aModKeyState) const;
516
517 /**
518 * GetUniCharsAndModifiers() returns characters which is inputted by the
519 * aVirtualKey with aModKeyState. This method isn't stateful.
520 */
521 UniCharsAndModifiers GetUniCharsAndModifiers(
522 uint8_t aVirtualKey,
523 const ModifierKeyState& aModKeyState) const;
524
525 /**
526 * OnLayoutChange() must be called before the first keydown message is
527 * received. LoadLayout() changes the keyboard state, that causes breaking
528 * dead key state. Therefore, we need to load the layout before the first
529 * keydown message.
530 */
531 void OnLayoutChange(HKL aKeyboardLayout)
532 {
533 MOZ_ASSERT(!mIsOverridden);
534 LoadLayout(aKeyboardLayout);
535 }
536
537 /**
538 * OverrideLayout() loads the specified keyboard layout.
539 */
540 void OverrideLayout(HKL aLayout)
541 {
542 mIsOverridden = true;
543 LoadLayout(aLayout);
544 }
545
546 /**
547 * RestoreLayout() loads the current keyboard layout of the thread.
548 */
549 void RestoreLayout()
550 {
551 mIsOverridden = false;
552 mIsPendingToRestoreKeyboardLayout = true;
553 }
554
555 uint32_t ConvertNativeKeyCodeToDOMKeyCode(UINT aNativeKeyCode) const;
556
557 /**
558 * ConvertNativeKeyCodeToKeyNameIndex() returns KeyNameIndex value for
559 * non-printable keys (except some special keys like space key).
560 */
561 KeyNameIndex ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const;
562
563 HKL GetLayout() const
564 {
565 return mIsPendingToRestoreKeyboardLayout ? ::GetKeyboardLayout(0) :
566 mKeyboardLayout;
567 }
568
569 /**
570 * This wraps MapVirtualKeyEx() API with MAPVK_VK_TO_VSC.
571 */
572 WORD ComputeScanCodeForVirtualKeyCode(uint8_t aVirtualKeyCode) const;
573
574 /**
575 * Implementation of nsIWidget::SynthesizeNativeKeyEvent().
576 */
577 nsresult SynthesizeNativeKeyEvent(nsWindowBase* aWidget,
578 int32_t aNativeKeyboardLayout,
579 int32_t aNativeKeyCode,
580 uint32_t aModifierFlags,
581 const nsAString& aCharacters,
582 const nsAString& aUnmodifiedCharacters);
583 };
584
585 class RedirectedKeyDownMessageManager
586 {
587 public:
588 /*
589 * If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is
590 * a redirected message, NativeKey::DispatchKeyDownAndKeyPressEvent()
591 * prevents to dispatch NS_KEY_DOWN event because it has been dispatched
592 * before the message was redirected. However, in some cases, WM_*KEYDOWN
593 * message handler may not handle actually. Then, the message handler needs
594 * to forget the redirected message and remove WM_CHAR message or WM_SYSCHAR
595 * message for the redirected keydown message. AutoFlusher class is a helper
596 * class for doing it. This must be created in the stack.
597 */
598 class MOZ_STACK_CLASS AutoFlusher MOZ_FINAL
599 {
600 public:
601 AutoFlusher(nsWindowBase* aWidget, const MSG &aMsg) :
602 mCancel(!RedirectedKeyDownMessageManager::IsRedirectedMessage(aMsg)),
603 mWidget(aWidget), mMsg(aMsg)
604 {
605 }
606
607 ~AutoFlusher()
608 {
609 if (mCancel) {
610 return;
611 }
612 // Prevent unnecessary keypress event
613 if (!mWidget->Destroyed()) {
614 RedirectedKeyDownMessageManager::RemoveNextCharMessage(mMsg.hwnd);
615 }
616 // Foreget the redirected message
617 RedirectedKeyDownMessageManager::Forget();
618 }
619
620 void Cancel() { mCancel = true; }
621
622 private:
623 bool mCancel;
624 nsRefPtr<nsWindowBase> mWidget;
625 const MSG &mMsg;
626 };
627
628 static void WillRedirect(const MSG& aMsg, bool aDefualtPrevented)
629 {
630 sRedirectedKeyDownMsg = aMsg;
631 sDefaultPreventedOfRedirectedMsg = aDefualtPrevented;
632 }
633
634 static void Forget()
635 {
636 sRedirectedKeyDownMsg.message = WM_NULL;
637 }
638
639 static void PreventDefault() { sDefaultPreventedOfRedirectedMsg = true; }
640 static bool DefaultPrevented() { return sDefaultPreventedOfRedirectedMsg; }
641
642 static bool IsRedirectedMessage(const MSG& aMsg);
643
644 /**
645 * RemoveNextCharMessage() should be called by WM_KEYDOWN or WM_SYSKEYDOWM
646 * message handler. If there is no WM_(SYS)CHAR message for it, this
647 * method does nothing.
648 * NOTE: WM_(SYS)CHAR message is posted by TranslateMessage() API which is
649 * called in message loop. So, WM_(SYS)KEYDOWN message should have
650 * WM_(SYS)CHAR message in the queue if the keydown event causes character
651 * input.
652 */
653 static void RemoveNextCharMessage(HWND aWnd);
654
655 private:
656 // sRedirectedKeyDownMsg is WM_KEYDOWN message or WM_SYSKEYDOWN message which
657 // is reirected with SendInput() API by
658 // widget::NativeKey::DispatchKeyDownAndKeyPressEvent()
659 static MSG sRedirectedKeyDownMsg;
660 static bool sDefaultPreventedOfRedirectedMsg;
661 };
662
663 } // namespace widget
664 } // namespace mozilla
665
666 #endif

mercurial