From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- widget/gtk/nsGtkKeyUtils.h | 360 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 widget/gtk/nsGtkKeyUtils.h (limited to 'widget/gtk/nsGtkKeyUtils.h') diff --git a/widget/gtk/nsGtkKeyUtils.h b/widget/gtk/nsGtkKeyUtils.h new file mode 100644 index 000000000..67528d817 --- /dev/null +++ b/widget/gtk/nsGtkKeyUtils.h @@ -0,0 +1,360 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:expandtab:shiftwidth=4:tabstop=4: + */ +/* 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/. */ + +#ifndef __nsGdkKeyUtils_h__ +#define __nsGdkKeyUtils_h__ + +#include "nsTArray.h" +#include "mozilla/EventForwards.h" + +#include +#include + +namespace mozilla { +namespace widget { + +/** + * KeymapWrapper is a wrapper class of GdkKeymap. GdkKeymap doesn't support + * all our needs, therefore, we need to access lower level APIs. + * But such code is usually complex and might be slow. Against such issues, + * we should cache some information. + * + * This class provides only static methods. The methods is using internal + * singleton instance which is initialized by default GdkKeymap. When the + * GdkKeymap is destroyed, the singleton instance will be destroyed. + */ + +class KeymapWrapper +{ +public: + /** + * Compute an our DOM keycode from a GDK keyval. + */ + static uint32_t ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent); + + /** + * Compute a DOM key name index from aGdkKeyEvent. + */ + KeyNameIndex ComputeDOMKeyNameIndex(const GdkEventKey* aGdkKeyEvent); + + /** + * Compute a DOM code name index from aGdkKeyEvent. + */ + static CodeNameIndex ComputeDOMCodeNameIndex( + const GdkEventKey* aGdkKeyEvent); + + /** + * Modifier is list of modifiers which we support in widget level. + */ + enum Modifier { + NOT_MODIFIER = 0x0000, + CAPS_LOCK = 0x0001, + NUM_LOCK = 0x0002, + SCROLL_LOCK = 0x0004, + SHIFT = 0x0008, + CTRL = 0x0010, + ALT = 0x0020, + META = 0x0040, + SUPER = 0x0080, + HYPER = 0x0100, + LEVEL3 = 0x0200, + LEVEL5 = 0x0400 + }; + + /** + * Modifiers is used for combination of Modifier. + * E.g., |Modifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl. + */ + typedef uint32_t Modifiers; + + /** + * GetCurrentModifierState() returns current modifier key state. + * The "current" means actual state of hardware keyboard when this is + * called. I.e., if some key events are not still dispatched by GDK, + * the state may mismatch with GdkEventKey::state. + * + * @return Current modifier key state. + */ + static guint GetCurrentModifierState(); + + /** + * AreModifiersCurrentlyActive() checks the "current" modifier state + * on aGdkWindow with the keymap of the singleton instance. + * + * @param aModifiers One or more of Modifier values except + * NOT_MODIFIER. + * @return TRUE if all of modifieres in aModifiers are + * active. Otherwise, FALSE. + */ + static bool AreModifiersCurrentlyActive(Modifiers aModifiers); + + /** + * AreModifiersActive() just checks whether aModifierState indicates + * all modifiers in aModifiers are active or not. + * + * @param aModifiers One or more of Modifier values except + * NOT_MODIFIER. + * @param aModifierState GDK's modifier states. + * @return TRUE if aGdkModifierType indecates all of + * modifiers in aModifier are active. + * Otherwise, FALSE. + */ + static bool AreModifiersActive(Modifiers aModifiers, + guint aModifierState); + + /** + * InitInputEvent() initializes the aInputEvent with aModifierState. + */ + static void InitInputEvent(WidgetInputEvent& aInputEvent, + guint aModifierState); + + /** + * InitKeyEvent() intializes aKeyEvent's modifier key related members + * and keycode related values. + * + * @param aKeyEvent It's an WidgetKeyboardEvent which needs to be + * initialized. + * @param aGdkKeyEvent A native GDK key event. + */ + static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent, + GdkEventKey* aGdkKeyEvent); + + /** + * WillDispatchKeyboardEvent() is called via + * TextEventDispatcherListener::WillDispatchKeyboardEvent(). + * + * @param aKeyEvent An instance of KeyboardEvent which will be + * dispatched. This method should set charCode + * and alternative char codes if it's necessary. + * @param aGdkKeyEvent A GdkEventKey instance which caused the + * aKeyEvent. + */ + static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent, + GdkEventKey* aGdkKeyEvent); + + /** + * Destroys the singleton KeymapWrapper instance, if it exists. + */ + static void Shutdown(); + +protected: + + /** + * GetInstance() returns a KeymapWrapper instance. + * + * @return A singleton instance of KeymapWrapper. + */ + static KeymapWrapper* GetInstance(); + + KeymapWrapper(); + ~KeymapWrapper(); + + bool mInitialized; + + /** + * Initializing methods. + */ + void Init(); + void InitXKBExtension(); + void InitBySystemSettings(); + + /** + * mModifierKeys stores each hardware key information. + */ + struct ModifierKey { + guint mHardwareKeycode; + guint mMask; + + explicit ModifierKey(guint aHardwareKeycode) : + mHardwareKeycode(aHardwareKeycode), mMask(0) + { + } + }; + nsTArray mModifierKeys; + + /** + * GetModifierKey() returns modifier key information of the hardware + * keycode. If the key isn't a modifier key, returns nullptr. + */ + ModifierKey* GetModifierKey(guint aHardwareKeycode); + + /** + * mModifierMasks is bit masks for each modifier. The index should be one + * of ModifierIndex values. + */ + enum ModifierIndex { + INDEX_NUM_LOCK, + INDEX_SCROLL_LOCK, + INDEX_ALT, + INDEX_META, + INDEX_SUPER, + INDEX_HYPER, + INDEX_LEVEL3, + INDEX_LEVEL5, + COUNT_OF_MODIFIER_INDEX + }; + guint mModifierMasks[COUNT_OF_MODIFIER_INDEX]; + + guint GetModifierMask(Modifier aModifier) const; + + /** + * @param aGdkKeyval A GDK defined modifier key value such as + * GDK_Shift_L. + * @return Returns Modifier values for aGdkKeyval. + * If the given key code isn't a modifier key, + * returns NOT_MODIFIER. + */ + static Modifier GetModifierForGDKKeyval(guint aGdkKeyval); + + static const char* GetModifierName(Modifier aModifier); + + /** + * mGdkKeymap is a wrapped instance by this class. + */ + GdkKeymap* mGdkKeymap; + + /** + * The base event code of XKB extension. + */ + int mXKBBaseEventCode; + + /** + * Only auto_repeats[] stores valid value. If you need to use other + * members, you need to listen notification events for them. + * See a call of XkbSelectEventDetails() with XkbControlsNotify in + * InitXKBExtension(). + */ + XKeyboardState mKeyboardState; + + /** + * Pointer of the singleton instance. + */ + static KeymapWrapper* sInstance; + + /** + * Auto key repeat management. + */ + static guint sLastRepeatableHardwareKeyCode; + enum RepeatState + { + NOT_PRESSED, + FIRST_PRESS, + REPEATING + }; + static RepeatState sRepeatState; + + /** + * IsAutoRepeatableKey() returns true if the key supports auto repeat. + * Otherwise, false. + */ + bool IsAutoRepeatableKey(guint aHardwareKeyCode); + + /** + * Signal handlers. + */ + static void OnKeysChanged(GdkKeymap* aKeymap, KeymapWrapper* aKeymapWrapper); + static void OnDirectionChanged(GdkKeymap *aGdkKeymap, + KeymapWrapper* aKeymapWrapper); + + /** + * GetCharCodeFor() Computes what character is inputted by the key event + * with aModifierState and aGroup. + * + * @param aGdkKeyEvent Native key event, must not be nullptr. + * @param aModifierState Combination of GdkModifierType which you + * want to test with aGdkKeyEvent. + * @param aGroup Set group in the mGdkKeymap. + * @return charCode which is inputted by aGdkKeyEvent. + * If failed, this returns 0. + */ + static uint32_t GetCharCodeFor(const GdkEventKey *aGdkKeyEvent); + uint32_t GetCharCodeFor(const GdkEventKey *aGdkKeyEvent, + guint aModifierState, + gint aGroup); + + /** + * GetUnmodifiedCharCodeFor() computes what character is inputted by the + * key event without Ctrl/Alt/Meta/Super/Hyper modifiers. + * If Level3 or Level5 Shift causes no character input, this also ignores + * them. + * + * @param aGdkKeyEvent Native key event, must not be nullptr. + * @return charCode which is computed without modifiers + * which prevent text input. + */ + uint32_t GetUnmodifiedCharCodeFor(const GdkEventKey* aGdkKeyEvent); + + /** + * GetKeyLevel() returns level of the aGdkKeyEvent in mGdkKeymap. + * + * @param aGdkKeyEvent Native key event, must not be nullptr. + * @return Using level. Typically, this is 0 or 1. + * If failed, this returns -1. + */ + gint GetKeyLevel(GdkEventKey *aGdkKeyEvent); + + /** + * GetFirstLatinGroup() returns group of mGdkKeymap which can input an + * ASCII character by GDK_A. + * + * @return group value of GdkEventKey. + */ + gint GetFirstLatinGroup(); + + /** + * IsLatinGroup() checkes whether the keyboard layout of aGroup is + * ASCII alphabet inputtable or not. + * + * @param aGroup The group value of GdkEventKey. + * @return TRUE if the keyboard layout can input + * ASCII alphabet. Otherwise, FALSE. + */ + bool IsLatinGroup(guint8 aGroup); + + /** + * IsBasicLatinLetterOrNumeral() Checks whether the aCharCode is an + * alphabet or a numeric character in ASCII. + * + * @param aCharCode Charcode which you want to test. + * @return TRUE if aCharCode is an alphabet or a numeric + * in ASCII range. Otherwise, FALSE. + */ + static bool IsBasicLatinLetterOrNumeral(uint32_t aCharCode); + + /** + * GetGDKKeyvalWithoutModifier() returns the keyval for aGdkKeyEvent when + * ignoring the modifier state except NumLock. (NumLock is a key to change + * some key's meaning.) + */ + static guint GetGDKKeyvalWithoutModifier(const GdkEventKey *aGdkKeyEvent); + + /** + * GetDOMKeyCodeFromKeyPairs() returns DOM keycode for aGdkKeyval if + * it's in KeyPair table. + */ + static uint32_t GetDOMKeyCodeFromKeyPairs(guint aGdkKeyval); + + /** + * FilterEvents() listens all events on all our windows. + * Be careful, this may make damage to performance if you add expensive + * code in this method. + */ + static GdkFilterReturn FilterEvents(GdkXEvent* aXEvent, + GdkEvent* aGdkEvent, + gpointer aData); + + /** + * See the document of WillDispatchKeyboardEvent(). + */ + void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent, + GdkEventKey* aGdkKeyEvent); +}; + +} // namespace widget +} // namespace mozilla + +#endif /* __nsGdkKeyUtils_h__ */ -- cgit v1.2.3