/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
void FillModifiers(Modifiers aModifiers); /** * OverwriteModifiersIfBeginsWith() assigns mModifiers with aOther between * [0] and [aOther.mLength - 1] only when mChars begins with aOther.mChars.
*/ void OverwriteModifiersIfBeginsWith(const UniCharsAndModifiers& aOther);
private:
nsAutoString mChars; // 5 is enough number for normal keyboard layout handling. On Windows, // a dead key sequence may cause inputting up to 5 characters per key press.
CopyableAutoTArray<Modifiers, 5> mModifiers;
};
uint16_t mEntries; // KeyboardLayout::AddDeadKeyTable() will allocate as many entries as // required. It is the only way to create new DeadKeyTable instances.
DeadKeyEntry mTable[1];
class VirtualKey { public: enum ShiftStateIndex : uint8_t { // 0 - Normal
eNormal = 0, // 1 - Shift
eShift, // 2 - Control
eControl, // 3 - Control + Shift
eControlShift, // 4 - Alt
eAlt, // 5 - Alt + Shift
eAltShift, // 6 - Alt + Control (AltGr)
eAltGr, // 7 - Alt + Control + Shift (AltGr + Shift)
eAltGrShift, // 8 - CapsLock
eWithCapsLock, // 9 - CapsLock + Shift
eShiftWithCapsLock, // 10 - CapsLock + Control
eControlWithCapsLock, // 11 - CapsLock + Control + Shift
eControlShiftWithCapsLock, // 12 - CapsLock + Alt
eAltWithCapsLock, // 13 - CapsLock + Alt + Shift
eAltShiftWithCapsLock, // 14 - CapsLock + Alt + Control (CapsLock + AltGr)
eAltGrWithCapsLock, // 15 - CapsLock + Alt + Control + Shift (CapsLock + AltGr + Shift)
eAltGrShiftWithCapsLock,
};
enum ShiftStateFlag {
STATE_SHIFT = 0x01,
STATE_CONTROL = 0x02,
STATE_ALT = 0x04,
STATE_CAPSLOCK = 0x08, // ShiftState needs to have AltGr state separately since this is necessary // for lossless conversion with Modifiers.
STATE_ALTGRAPH = 0x80, // Useful to remove or check Ctrl and Alt flags.
STATE_CONTROL_ALT = STATE_CONTROL | STATE_ALT,
};
/** * IsChangedByAltGr() is useful to check if a key with AltGr produces * different character(s) from the key without AltGr. * Note that this is designed for checking if a keyboard layout has AltGr * key. So, this result may not exactly correct for the key since it's * okay to fails in some edge cases when we check all keys which produce * character(s) in a layout.
*/ bool IsChangedByAltGr(ShiftState aShiftState) const {
MOZ_ASSERT(aShiftState == ToShiftStateIndex(aShiftState));
MOZ_ASSERT(IsAltGrIndex(aShiftState));
MOZ_ASSERT(IsDeadKey(aShiftState) ||
mShiftStates[aShiftState].Normal.Chars[0]); const ShiftState kShiftStateWithoutAltGr =
aShiftState - ShiftStateIndex::eAltGr; if (IsDeadKey(aShiftState) != IsDeadKey(kShiftStateWithoutAltGr)) { returnfalse;
} if (IsDeadKey(aShiftState)) { return mShiftStates[aShiftState].DeadKey.DeadChar !=
mShiftStates[kShiftStateWithoutAltGr].DeadKey.DeadChar;
} for (size_t i = 0; i < 4; i++) { if (mShiftStates[aShiftState].Normal.Chars[i] !=
mShiftStates[kShiftStateWithoutAltGr].Normal.Chars[i]) { returntrue;
} if (!mShiftStates[aShiftState].Normal.Chars[i] &&
!mShiftStates[kShiftStateWithoutAltGr].Normal.Chars[i]) { returnfalse;
}
} returnfalse;
}
/** * GetNativeUniChars() returns character(s) which is produced by the * key with given modifiers. This does NOT return proper MODIFIER_ALTGRAPH * state because this is raw accessor of the database of this key.
*/
UniCharsAndModifiers GetNativeUniChars(ShiftState aShiftState) const;
UniCharsAndModifiers GetNativeUniChars( const ModifierKeyState& aModKeyState) const { return GetNativeUniChars(ModifierKeyStateToShiftState(aModKeyState));
}
/** * GetUniChars() returns characters and modifiers which are not consumed * to input the character. * For example, if you specify Ctrl key but the key produces no character * with Ctrl, this returns character(s) which is produced by the key * without Ctrl. So, the result is useful to decide KeyboardEvent.key * value. * Another example is, if you specify Ctrl key and the key produces * different character(s) from the case without Ctrl key, this returns * the character(s) *without* MODIFIER_CONTROL. This modifier information * is useful for eKeyPress since TextEditor does not treat eKeyPress events * whose modifier includes MODIFIER_ALT and/or MODIFIER_CONTROL. * * @param aShiftState Modifiers which you want to retrieve * KeyboardEvent.key value for the key with. * If AltGr key is pressed, this should include * STATE_ALTGRAPH and should NOT include * STATE_ALT nor STATE_CONTROL. * If both Alt and Ctrl are pressed to emulate * AltGr, this should include both STATE_ALT and * STATE_CONTROL but should NOT include * MODIFIER_ALTGRAPH. * Then, this returns proper modifiers when * this key produces no character with AltGr.
*/
UniCharsAndModifiers GetUniChars(ShiftState aShiftState) const;
UniCharsAndModifiers GetUniChars(const ModifierKeyState& aModKeyState) const { return GetUniChars(ModifierKeyStateToShiftState(aModKeyState));
}
};
class MOZ_STACK_CLASS NativeKey final { friendclass KeyboardLayout;
/** * Handle WM_KEYDOWN message or WM_SYSKEYDOWN message. The instance must be * initialized with WM_KEYDOWN or WM_SYSKEYDOWN. * Returns true if dispatched keydown event or keypress event is consumed. * Otherwise, false.
*/ bool HandleKeyDownMessage(bool* aEventDispatched = nullptr) const;
/** * Handles WM_CHAR message or WM_SYSCHAR message. The instance must be * initialized with them. * Returns true if dispatched keypress event is consumed. Otherwise, false.
*/ bool HandleCharMessage(bool* aEventDispatched = nullptr) const;
/** * Handles keyup message. Returns true if the event is consumed. * Otherwise, false.
*/ bool HandleKeyUpMessage(bool* aEventDispatched = nullptr) const;
/** * Handles WM_APPCOMMAND message. Returns true if the event is consumed. * Otherwise, false.
*/ bool HandleAppCommandMessage() const;
/** * Callback of TextEventDispatcherListener::WillDispatchKeyboardEvent(). * This method sets alternative char codes of aKeyboardEvent.
*/ void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyboardEvent,
uint32_t aIndex);
/** * Returns true if aChar is a control character which shouldn't be inputted * into focused text editor.
*/ staticbool IsControlChar(char16_t aChar);
/** * GenericVirtualKeyCode() returns virtual keycode which cannot distinguish * position of modifier keys. E.g., VK_CONTROL for both ControlLeft and * ControlRight.
*/
uint8_t GenericVirtualKeyCode() const { return mOriginalVirtualKeyCode; }
/** * SpecificVirtualKeyCode() returns virtual keycode which can distinguish * position of modifier keys. E.g., returns VK_LCONTROL or VK_RCONTROL * instead of VK_CONTROL. If the key message is synthesized with not * enough information, this prefers left position's keycode.
*/
uint8_t SpecificVirtualKeyCode() const { return mVirtualKeyCode; }
private:
NativeKey* mLastInstance; // mRemovingMsg is set at removing a char message from // GetFollowingCharMessage().
MSG mRemovingMsg; // mReceivedMsg is set when another instance starts to handle the message // unexpectedly.
MSG mReceivedMsg;
RefPtr<nsWindow> mWidget;
RefPtr<TextEventDispatcher> mDispatcher;
HKL mKeyboardLayout;
MSG mMsg; // mFollowingCharMsgs stores WM_CHAR, WM_SYSCHAR, WM_DEADCHAR or // WM_SYSDEADCHAR message which follows WM_KEYDOWN. // Note that the stored messaged are already removed from the queue. // FYI: 5 is enough number for usual keyboard layout handling. On Windows, // a dead key sequence may cause inputting up to 5 characters per key press.
AutoTArray<MSG, 5> mFollowingCharMsgs; // mRemovedOddCharMsgs stores WM_CHAR messages which are caused by ATOK or // WXG (they are Japanese IME) when the user tries to do "Kakutei-undo" // (it means "undo the last commit").
nsTArray<MSG> mRemovedOddCharMsgs; // If dispatching eKeyDown or eKeyPress event causes focus change, // the instance shouldn't handle remaning char messages. For checking it, // this should store first focused window.
HWND mFocusedWndBeforeDispatch;
// mVirtualKeyCode distinguishes left key or right key of modifier key.
uint8_t mVirtualKeyCode; // mOriginalVirtualKeyCode doesn't distinguish left key or right key of // modifier key. However, if the given keycode is VK_PROCESS, it's resolved // to a keycode before it's handled by IME.
uint8_t mOriginalVirtualKeyCode;
// mCommittedChars indicates the inputted characters which is committed by // the key. If dead key fail to composite a character, mCommittedChars // indicates both the dead characters and the base characters.
UniCharsAndModifiers mCommittedCharsAndModifiers;
// Following strings are computed by // ComputeInputtingStringWithKeyboardLayout() which is typically called // before dispatching keydown event. // mInputtingStringAndModifiers's string is the string to be // inputted into the focused editor and its modifier state is proper // modifier state for inputting the string into the editor.
UniCharsAndModifiers mInputtingStringAndModifiers; // mShiftedString is the string to be inputted into the editor with // current modifier state with active shift state.
UniCharsAndModifiers mShiftedString; // mUnshiftedString is the string to be inputted into the editor with // current modifier state without shift state.
UniCharsAndModifiers mUnshiftedString; // Following integers are computed by // ComputeInputtingStringWithKeyboardLayout() which is typically called // before dispatching keydown event. The meaning of these values is same // as charCode.
uint32_t mShiftedLatinChar;
uint32_t mUnshiftedLatinChar;
WORD mScanCode; bool mIsExtended; // mIsRepeat is true if the key message is caused by the auto-repeat // feature. bool mIsRepeat; bool mIsDeadKey; // mIsPrintableKey is true if the key may be a printable key without // any modifier keys. Otherwise, false. // Please note that the event may not cause any text input even if this // is true. E.g., it might be dead key state or Ctrl key may be pressed. bool mIsPrintableKey; // mIsSkippableInRemoteProcess is false if the key event shouldn't be // skipped in the remote process even if it's too old event. bool mIsSkippableInRemoteProcess; // mCharMessageHasGone is true if the message is a keydown message and // it's followed by at least one char message but it's gone at removing // from the queue. This could occur if PeekMessage() or something is // hooked by odd tool. bool mCharMessageHasGone; // mIsOverridingKeyboardLayout is true if the instance temporarily overriding // keyboard layout with specified by the constructor. bool mIsOverridingKeyboardLayout; // mCanIgnoreModifierStateAtKeyPress is true if it's allowed to remove // Ctrl or Alt modifier state at dispatching eKeyPress. bool mCanIgnoreModifierStateAtKeyPress;
nsTArray<FakeCharMsg>* mFakeCharMsgs;
// When a keydown event is dispatched at handling WM_APPCOMMAND, the computed // virtual keycode is set to this. Even if we consume WM_APPCOMMAND message, // Windows may send WM_KEYDOWN and WM_KEYUP message for them. // At that time, we should not dispatch key events for them. static uint8_t sDispatchedKeyOfAppCommand;
NativeKey() {
MOZ_CRASH("The default constructor of NativeKey isn't available");
}
/** * InitIsSkippableForKeyOrChar() initializes mIsSkippableInRemoteProcess with * mIsRepeat and previous key message information. So, this must be called * after mIsRepeat is initialized.
*/ void InitIsSkippableForKeyOrChar(const MSG& aLastKeyMSG);
/** * InitCommittedCharsAndModifiersWithFollowingCharMessages() initializes * mCommittedCharsAndModifiers with mFollowingCharMsgs and mModKeyState. * If mFollowingCharMsgs includes non-printable char messages, they are * ignored (skipped).
*/ void InitCommittedCharsAndModifiersWithFollowingCharMessages();
UINT GetScanCodeWithExtendedFlag() const;
// The result is one of eKeyLocation*.
uint32_t GetKeyLocation() const;
/** * RemoveFollowingOddCharMessages() removes odd WM_CHAR messages from the * queue when IsIMEDoingKakuteiUndo() returns true.
*/ void RemoveFollowingOddCharMessages();
/** * "Kakutei-Undo" of ATOK or WXG (both of them are Japanese IME) causes * strange WM_KEYDOWN/WM_KEYUP/WM_CHAR message pattern. So, when this * returns true, the caller needs to be careful for processing the messages.
*/ bool IsIMEDoingKakuteiUndo() const;
/** * This returns true if user types a number key in numpad with Alt key * to input a Unicode character from its scalar value. * Note that inputting Unicode scalar value is available without NumLock. * Therefore, this returns true even if user presses a function key on * numpad without NumLock, but that may be intended to perform a shortcut * key like Alt + Home.
*/ bool MaybeTypingUnicodeScalarValue() const { return !mIsExtended && IsSysKeyDownOrKeyUpMessage() && IsAlt() &&
!IsControl() && !IsShift() &&
((mScanCode >= 0x004F && mScanCode <= 0x0052) || // Numpad0-3
(mScanCode >= 0x004B && mScanCode <= 0x004D) || // Numpad4-6
(mScanCode >= 0x0047 && mScanCode <= 0x0049)); // Numpad7-9
}
/** * IsReservedBySystem() returns true if the key combination is reserved by * the system. Even if it's consumed by web apps, the message should be * sent to next wndproc.
*/ bool IsReservedBySystem() const;
/** * GetFollowingCharMessage() returns following char message of handling * keydown event. If the message is found, this method returns true. * Otherwise, returns false. * * WARNING: Even if this returns true, aCharMsg may be WM_NULL or its * hwnd may be different window.
*/ bool GetFollowingCharMessage(MSG& aCharMsg);
/** * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK.
*/
uint8_t ComputeVirtualKeyCodeFromScanCode() const;
/** * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK_EX.
*/
uint8_t ComputeVirtualKeyCodeFromScanCodeEx() const;
/** * Wraps MapVirtualKeyEx() with MAPVK_VK_TO_VSC_EX or MAPVK_VK_TO_VSC.
*/
uint16_t ComputeScanCodeExFromVirtualKeyCode(UINT aVirtualKeyCode) const;
/** * Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK and MAPVK_VK_TO_CHAR.
*/
char16_t ComputeUnicharFromScanCode() const;
/** * Initializes the aKeyEvent with the information stored in the instance.
*/
nsEventStatus InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, const ModifierKeyState& aModKeyState) const;
nsEventStatus InitKeyEvent(WidgetKeyboardEvent& aKeyEvent) const;
/** * Dispatches a command event for aEventCommand. * Returns true if the event is consumed. Otherwise, false.
*/ bool DispatchCommandEvent(uint32_t aEventCommand) const;
/** * DispatchKeyPressEventsWithoutCharMessage() dispatches keypress event(s) * without char messages. So, this should be used only when there are no * following char messages.
*/ bool DispatchKeyPressEventsWithoutCharMessage() const;
/** * Checkes whether the key event down message is handled without following * WM_CHAR messages. For example, if following WM_CHAR message indicates * control character input, the WM_CHAR message is unclear whether it's * caused by a printable key with Ctrl or just a function key such as Enter * or Backspace.
*/ bool NeedsToHandleWithoutFollowingCharMessages() const;
/** * ComputeInputtingStringWithKeyboardLayout() computes string to be inputted * with the key and the modifier state, without shift state and with shift * state.
*/ void ComputeInputtingStringWithKeyboardLayout();
/** * IsFocusedWindowChanged() returns true if focused window is changed * after the instance is created.
*/ bool IsFocusedWindowChanged() const { return mFocusedWndBeforeDispatch != ::GetFocus();
}
/** * Handles WM_CHAR message or WM_SYSCHAR message. The instance must be * initialized with WM_KEYDOWN, WM_SYSKEYDOWN or them. * Returns true if dispatched keypress event is consumed. Otherwise, false.
*/ bool HandleCharMessage(const MSG& aCharMsg, bool* aEventDispatched = nullptr) const;
// Calls of PeekMessage() from NativeKey might cause nested message handling // due to (perhaps) odd API hook. NativeKey should do nothing if given // message is tried to be retrieved by another instance.
/** * sLatestInstacne is a pointer to the newest instance of NativeKey which is * handling a key or char message(s).
*/ static NativeKey* sLatestInstance;
staticconst MSG sEmptyMSG;
static MSG sLastKeyOrCharMSG;
static MSG sLastKeyMSG;
// Set to non-zero if we receive a WM_KEYDOWN message which introduces only // a high surrogate. Then, it'll be cleared when next keydown or char message // is received. static char16_t sPendingHighSurrogate;
public: /** * Returns last key or char MSG. If no MSG has been received yet, the result * is empty MSG (i.e., .message is WM_NULL).
*/ staticconst MSG& LastKeyOrCharMSG() { return sLastKeyOrCharMSG; }
};
class KeyboardLayout { public: static KeyboardLayout* GetInstance(); staticvoid Shutdown();
/** * GetLayout() returns a keyboard layout which has already been loaded in the * singleton instance or active keyboard layout.
*/ static HKL GetLayout() { if (!sInstance || sInstance->mIsPendingToRestoreKeyboardLayout) { return ::GetKeyboardLayout(0);
} return sInstance->mKeyboardLayout;
}
/** * GetLoadedLayout() returns a keyboard layout which was loaded in the * singleton instance. This may be different from the active keyboard layout * on the system if we override the keyboard layout for synthesizing native * key events for tests.
*/
HKL GetLoadedLayout() { return mKeyboardLayout; }
/** * GetLoadedLayoutName() returns the name of the loaded keyboard layout in the * singleton instance.
*/
nsCString GetLoadedLayoutName() { return KeyboardLayout::GetLayoutName(mKeyboardLayout);
}
/** * HasAltGr() returns true if the keyboard layout's AltRight key is AltGr * key.
*/ bool HasAltGr() const { return mHasAltGr; }
/** * IsDeadKey() returns true if aVirtualKey is a dead key with aModKeyState. * This method isn't stateful.
*/ bool IsDeadKey(uint8_t aVirtualKey, const ModifierKeyState& aModKeyState) const; bool IsDeadKey(const NativeKey& aNativeKey) const { return IsDeadKey(aNativeKey.GenericVirtualKeyCode(),
aNativeKey.ModifierKeyStateRef());
}
/** * IsInDeadKeySequence() returns true when it's in a dead key sequence. * It starts when a dead key is down and ends when another key down causes * inactivating the dead key state.
*/ bool IsInDeadKeySequence() const { return !mActiveDeadKeys.IsEmpty(); }
/** * GetUniCharsAndModifiers() returns characters which are inputted by * aVirtualKey with aModKeyState. This method isn't stateful. * Note that if the combination causes text input, the result's Ctrl and * Alt key state are never active.
*/
UniCharsAndModifiers GetUniCharsAndModifiers(
uint8_t aVirtualKey, const ModifierKeyState& aModKeyState) const {
VirtualKey::ShiftState shiftState =
VirtualKey::ModifierKeyStateToShiftState(aModKeyState); return GetUniCharsAndModifiers(aVirtualKey, shiftState);
}
UniCharsAndModifiers GetUniCharsAndModifiers( const NativeKey& aNativeKey) const { return GetUniCharsAndModifiers(aNativeKey.GenericVirtualKeyCode(),
aNativeKey.GetShiftState());
}
/** * OnLayoutChange() must be called before the first keydown message is * received. LoadLayout() changes the keyboard state, that causes breaking * dead key state. Therefore, we need to load the layout before the first * keydown message.
*/ void OnLayoutChange(HKL aKeyboardLayout) {
MOZ_ASSERT(!mIsOverridden);
LoadLayout(aKeyboardLayout);
}
/** * ConvertNativeKeyCodeToKeyNameIndex() returns KeyNameIndex value for * non-printable keys (except some special keys like space key).
*/
KeyNameIndex ConvertNativeKeyCodeToKeyNameIndex(uint8_t aVirtualKey) const;
/** * ConvertScanCodeToCodeNameIndex() returns CodeNameIndex value for * the given scan code. aScanCode can be over 0xE000 since this method * doesn't use Windows API.
*/ static CodeNameIndex ConvertScanCodeToCodeNameIndex(UINT aScanCode);
/** * This wraps MapVirtualKeyEx() API with MAPVK_VK_TO_VSC.
*/
WORD ComputeScanCodeForVirtualKeyCode(uint8_t aVirtualKeyCode) const;
VirtualKey mVirtualKeys[NS_NUM_OF_KEYS] = {};
DeadKeyTableListEntry* mDeadKeyTableListHead = nullptr; // When mActiveDeadKeys is empty, it's not in dead key sequence. // Otherwise, it contains virtual keycodes which are pressed in current // dead key sequence.
nsTArray<uint8_t> mActiveDeadKeys; // mDeadKeyShiftStates is always same length as mActiveDeadKeys. // This stores shift states at pressing each dead key stored in // mActiveDeadKeys.
nsTArray<VirtualKey::ShiftState> mDeadKeyShiftStates;
/** * Loads the specified keyboard layout. This method always clear the dead key * state.
*/ void LoadLayout(HKL aLayout);
/** * Gets the keyboard layout name of aLayout. Be careful, this may be too * slow to call at handling user input.
*/ static nsCString GetLayoutName(HKL aLayout);
/** * InitNativeKey() must be called when actually widget receives WM_KEYDOWN or * WM_KEYUP. This method is stateful. This saves current dead key state at * WM_KEYDOWN. Additionally, computes current inputted character(s) and set * them to the aNativeKey.
*/ void InitNativeKey(NativeKey& aNativeKey);
/** * MaybeInitNativeKeyAsDeadKey() initializes aNativeKey only when aNativeKey * is a dead key's event. * When it's not in a dead key sequence, this activates the dead key state. * When it's in a dead key sequence, this initializes aNativeKey with a * composite character or a preceding dead char and a dead char which should * be caused by aNativeKey. * Returns true when this initializes aNativeKey. Otherwise, false.
*/ bool MaybeInitNativeKeyAsDeadKey(NativeKey& aNativeKey);
/** * MaybeInitNativeKeyWithCompositeChar() may initialize aNativeKey with * proper composite character when dead key produces a composite character. * Otherwise, just returns false.
*/ bool MaybeInitNativeKeyWithCompositeChar(NativeKey& aNativeKey);
/** * See the comment of GetUniCharsAndModifiers() below.
*/
UniCharsAndModifiers GetUniCharsAndModifiers(
uint8_t aVirtualKey, VirtualKey::ShiftState aShiftState) const;
/** * GetDeadUniCharsAndModifiers() returns dead chars which are stored in * current dead key sequence. So, this is stateful.
*/
UniCharsAndModifiers GetDeadUniCharsAndModifiers() const;
/** * GetCompositeChar() returns a composite character with dead character * caused by mActiveDeadKeys, mDeadKeyShiftStates and a base character * (aBaseChar). * If the combination of the dead character and the base character doesn't * cause a composite character, this returns 0.
*/
char16_t GetCompositeChar(char16_t aBaseChar) const;
// NativeKey class should access InitNativeKey() directly, but it shouldn't // be available outside of NativeKey. So, let's make NativeKey a friend // class of this. friendclass NativeKey;
};
class RedirectedKeyDownMessageManager { public: /* * If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is * a redirected message, NativeKey::DispatchKeyDownAndKeyPressEvent() * prevents to dispatch eKeyDown event because it has been dispatched * before the message was redirected. However, in some cases, WM_*KEYDOWN * message handler may not handle actually. Then, the message handler needs * to forget the redirected message and remove WM_CHAR message or WM_SYSCHAR * message for the redirected keydown message. AutoFlusher class is a helper * class for doing it. This must be created in the stack.
*/ class MOZ_STACK_CLASS AutoFlusher final { public:
AutoFlusher(nsWindow* aWidget, const MSG& aMsg)
: mCancel(!RedirectedKeyDownMessageManager::IsRedirectedMessage(aMsg)),
mWidget(aWidget),
mMsg(aMsg) {}
~AutoFlusher() { if (mCancel) { return;
} // Prevent unnecessary keypress event if (!mWidget->Destroyed()) {
RedirectedKeyDownMessageManager::RemoveNextCharMessage(mMsg.hwnd);
} // Foreget the redirected message
RedirectedKeyDownMessageManager::Forget();
}
/** * RemoveNextCharMessage() should be called by WM_KEYDOWN or WM_SYSKEYDOWM * message handler. If there is no WM_(SYS)CHAR message for it, this * method does nothing. * NOTE: WM_(SYS)CHAR message is posted by TranslateMessage() API which is * called in message loop. So, WM_(SYS)KEYDOWN message should have * WM_(SYS)CHAR message in the queue if the keydown event causes character * input.
*/ staticvoid RemoveNextCharMessage(HWND aWnd);
private: // sRedirectedKeyDownMsg is WM_KEYDOWN message or WM_SYSKEYDOWN message which // is reirected with SendInput() API by // widget::NativeKey::DispatchKeyDownAndKeyPressEvent() static MSG sRedirectedKeyDownMsg; staticbool sDefaultPreventedOfRedirectedMsg;
};
} // namespace widget
} // namespace mozilla
#endif
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.