widget/gtk/nsGtkKeyUtils.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/widget/gtk/nsGtkKeyUtils.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,351 @@
     1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     1.5 +/* vim:expandtab:shiftwidth=4:tabstop=4:
     1.6 + */
     1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#ifndef __nsGdkKeyUtils_h__
    1.12 +#define __nsGdkKeyUtils_h__
    1.13 +
    1.14 +#include "nsTArray.h"
    1.15 +#include "mozilla/EventForwards.h"
    1.16 +
    1.17 +#include <gdk/gdk.h>
    1.18 +#include <X11/XKBlib.h>
    1.19 +
    1.20 +namespace mozilla {
    1.21 +namespace widget {
    1.22 +
    1.23 +/**
    1.24 + *  KeymapWrapper is a wrapper class of GdkKeymap.  GdkKeymap doesn't support
    1.25 + *  all our needs, therefore, we need to access lower level APIs.
    1.26 + *  But such code is usually complex and might be slow.  Against such issues,
    1.27 + *  we should cache some information.
    1.28 + *
    1.29 + *  This class provides only static methods.  The methods is using internal
    1.30 + *  singleton instance which is initialized by default GdkKeymap.  When the
    1.31 + *  GdkKeymap is destroyed, the singleton instance will be destroyed.
    1.32 + */
    1.33 +
    1.34 +class KeymapWrapper
    1.35 +{
    1.36 +public:
    1.37 +    /**
    1.38 +     * Compute an our DOM keycode from a GDK keyval.
    1.39 +     */
    1.40 +    static uint32_t ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent);
    1.41 +
    1.42 +    /**
    1.43 +     * Compute a DOM key name index from aGdkKeyEvent.
    1.44 +     */
    1.45 +    KeyNameIndex ComputeDOMKeyNameIndex(const GdkEventKey* aGdkKeyEvent);
    1.46 +
    1.47 +    /**
    1.48 +     * Modifier is list of modifiers which we support in widget level.
    1.49 +     */
    1.50 +    enum Modifier {
    1.51 +        NOT_MODIFIER       = 0x0000,
    1.52 +        CAPS_LOCK          = 0x0001,
    1.53 +        NUM_LOCK           = 0x0002,
    1.54 +        SCROLL_LOCK        = 0x0004,
    1.55 +        SHIFT              = 0x0008,
    1.56 +        CTRL               = 0x0010,
    1.57 +        ALT                = 0x0020,
    1.58 +        META               = 0x0040,
    1.59 +        SUPER              = 0x0080,
    1.60 +        HYPER              = 0x0100,
    1.61 +        LEVEL3             = 0x0200,
    1.62 +        LEVEL5             = 0x0400
    1.63 +    };
    1.64 +
    1.65 +    /**
    1.66 +     * Modifiers is used for combination of Modifier.
    1.67 +     * E.g., |Modifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
    1.68 +     */
    1.69 +    typedef uint32_t Modifiers;
    1.70 +
    1.71 +    /**
    1.72 +     * GetCurrentModifierState() returns current modifier key state.
    1.73 +     * The "current" means actual state of hardware keyboard when this is
    1.74 +     * called.  I.e., if some key events are not still dispatched by GDK,
    1.75 +     * the state may mismatch with GdkEventKey::state.
    1.76 +     *
    1.77 +     * @return                  Current modifier key state.
    1.78 +     */
    1.79 +    static guint GetCurrentModifierState();
    1.80 +
    1.81 +    /**
    1.82 +     * AreModifiersCurrentlyActive() checks the "current" modifier state
    1.83 +     * on aGdkWindow with the keymap of the singleton instance.
    1.84 +     *
    1.85 +     * @param aModifiers        One or more of Modifier values except
    1.86 +     *                          NOT_MODIFIER.
    1.87 +     * @return                  TRUE if all of modifieres in aModifiers are
    1.88 +     *                          active.  Otherwise, FALSE.
    1.89 +     */
    1.90 +    static bool AreModifiersCurrentlyActive(Modifiers aModifiers);
    1.91 +
    1.92 +    /**
    1.93 +     * AreModifiersActive() just checks whether aModifierState indicates
    1.94 +     * all modifiers in aModifiers are active or not.
    1.95 +     *
    1.96 +     * @param aModifiers        One or more of Modifier values except
    1.97 +     *                          NOT_MODIFIER.
    1.98 +     * @param aModifierState    GDK's modifier states.
    1.99 +     * @return                  TRUE if aGdkModifierType indecates all of
   1.100 +     *                          modifiers in aModifier are active.
   1.101 +     *                          Otherwise, FALSE.
   1.102 +     */
   1.103 +    static bool AreModifiersActive(Modifiers aModifiers,
   1.104 +                                   guint aModifierState);
   1.105 +
   1.106 +    /**
   1.107 +     * InitInputEvent() initializes the aInputEvent with aModifierState.
   1.108 +     */
   1.109 +    static void InitInputEvent(WidgetInputEvent& aInputEvent,
   1.110 +                               guint aModifierState);
   1.111 +
   1.112 +    /**
   1.113 +     * InitKeyEvent() intializes aKeyEvent's modifier key related members
   1.114 +     * and keycode related values.
   1.115 +     *
   1.116 +     * @param aKeyEvent         It's an WidgetKeyboardEvent which needs to be
   1.117 +     *                          initialized.
   1.118 +     * @param aGdkKeyEvent      A native GDK key event.
   1.119 +     */
   1.120 +    static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
   1.121 +                             GdkEventKey* aGdkKeyEvent);
   1.122 +
   1.123 +    /**
   1.124 +     * IsKeyPressEventNecessary() returns TRUE when aGdkKeyEvent should cause
   1.125 +     * a DOM keypress event.  Otherwise, FALSE.
   1.126 +     */
   1.127 +    static bool IsKeyPressEventNecessary(GdkEventKey* aGdkKeyEvent);
   1.128 +
   1.129 +protected:
   1.130 +
   1.131 +    /**
   1.132 +     * GetInstance() returns a KeymapWrapper instance.
   1.133 +     *
   1.134 +     * @return                  A singleton instance of KeymapWrapper.
   1.135 +     */
   1.136 +    static KeymapWrapper* GetInstance();
   1.137 +
   1.138 +    KeymapWrapper();
   1.139 +    ~KeymapWrapper();
   1.140 +
   1.141 +    bool mInitialized;
   1.142 +
   1.143 +    /**
   1.144 +     * Initializing methods.
   1.145 +     */
   1.146 +    void Init();
   1.147 +    void InitXKBExtension();
   1.148 +    void InitBySystemSettings();
   1.149 +
   1.150 +    /**
   1.151 +     * mModifierKeys stores each hardware key information.
   1.152 +     */
   1.153 +    struct ModifierKey {
   1.154 +        guint mHardwareKeycode;
   1.155 +        guint mMask;
   1.156 +
   1.157 +        ModifierKey(guint aHardwareKeycode) :
   1.158 +          mHardwareKeycode(aHardwareKeycode), mMask(0)
   1.159 +        {
   1.160 +        }
   1.161 +    };
   1.162 +    nsTArray<ModifierKey> mModifierKeys;
   1.163 +
   1.164 +    /**
   1.165 +     * GetModifierKey() returns modifier key information of the hardware
   1.166 +     * keycode.  If the key isn't a modifier key, returns nullptr.
   1.167 +     */
   1.168 +    ModifierKey* GetModifierKey(guint aHardwareKeycode);
   1.169 +
   1.170 +    /**
   1.171 +     * mModifierMasks is bit masks for each modifier.  The index should be one
   1.172 +     * of ModifierIndex values.
   1.173 +     */
   1.174 +    enum ModifierIndex {
   1.175 +        INDEX_NUM_LOCK,
   1.176 +        INDEX_SCROLL_LOCK,
   1.177 +        INDEX_ALT,
   1.178 +        INDEX_META,
   1.179 +        INDEX_SUPER,
   1.180 +        INDEX_HYPER,
   1.181 +        INDEX_LEVEL3,
   1.182 +        INDEX_LEVEL5,
   1.183 +        COUNT_OF_MODIFIER_INDEX
   1.184 +    };
   1.185 +    guint mModifierMasks[COUNT_OF_MODIFIER_INDEX];
   1.186 +
   1.187 +    guint GetModifierMask(Modifier aModifier) const;
   1.188 +
   1.189 +    /**
   1.190 +     * @param aGdkKeyval        A GDK defined modifier key value such as
   1.191 +     *                          GDK_Shift_L.
   1.192 +     * @return                  Returns Modifier values for aGdkKeyval.
   1.193 +     *                          If the given key code isn't a modifier key,
   1.194 +     *                          returns NOT_MODIFIER.
   1.195 +     */
   1.196 +    static Modifier GetModifierForGDKKeyval(guint aGdkKeyval);
   1.197 +
   1.198 +#ifdef PR_LOGGING
   1.199 +    static const char* GetModifierName(Modifier aModifier);
   1.200 +#endif // PR_LOGGING
   1.201 +
   1.202 +    /**
   1.203 +     * mGdkKeymap is a wrapped instance by this class.
   1.204 +     */
   1.205 +    GdkKeymap* mGdkKeymap;
   1.206 +
   1.207 +    /**
   1.208 +     * The base event code of XKB extension.
   1.209 +     */
   1.210 +    int mXKBBaseEventCode;
   1.211 +
   1.212 +    /**
   1.213 +     * Only auto_repeats[] stores valid value.  If you need to use other
   1.214 +     * members, you need to listen notification events for them.
   1.215 +     * See a call of XkbSelectEventDetails() with XkbControlsNotify in
   1.216 +     * InitXKBExtension().
   1.217 +     */
   1.218 +    XKeyboardState mKeyboardState;
   1.219 +
   1.220 +    /**
   1.221 +     * Pointer of the singleton instance.
   1.222 +     */
   1.223 +    static KeymapWrapper* sInstance;
   1.224 +
   1.225 +    /**
   1.226 +     * Auto key repeat management.
   1.227 +     */
   1.228 +    static guint sLastRepeatableHardwareKeyCode;
   1.229 +    enum RepeatState
   1.230 +    {
   1.231 +        NOT_PRESSED,
   1.232 +        FIRST_PRESS,
   1.233 +        REPEATING
   1.234 +    };
   1.235 +    static RepeatState sRepeatState;
   1.236 +
   1.237 +    /**
   1.238 +     * IsAutoRepeatableKey() returns true if the key supports auto repeat.
   1.239 +     * Otherwise, false.
   1.240 +     */
   1.241 +    bool IsAutoRepeatableKey(guint aHardwareKeyCode);
   1.242 +
   1.243 +    /**
   1.244 +     * Signal handlers.
   1.245 +     */
   1.246 +    static void OnKeysChanged(GdkKeymap* aKeymap, KeymapWrapper* aKeymapWrapper);
   1.247 +    static void OnDestroyKeymap(KeymapWrapper* aKeymapWrapper,
   1.248 +                                GdkKeymap *aGdkKeymap);
   1.249 +
   1.250 +    /**
   1.251 +     * GetCharCodeFor() Computes what character is inputted by the key event
   1.252 +     * with aModifierState and aGroup.
   1.253 +     *
   1.254 +     * @param aGdkKeyEvent      Native key event, must not be nullptr.
   1.255 +     * @param aModifierState    Combination of GdkModifierType which you
   1.256 +     *                          want to test with aGdkKeyEvent.
   1.257 +     * @param aGroup            Set group in the mGdkKeymap.
   1.258 +     * @return                  charCode which is inputted by aGdkKeyEvent.
   1.259 +     *                          If failed, this returns 0.
   1.260 +     */
   1.261 +    static uint32_t GetCharCodeFor(const GdkEventKey *aGdkKeyEvent);
   1.262 +    uint32_t GetCharCodeFor(const GdkEventKey *aGdkKeyEvent,
   1.263 +                            guint aModifierState,
   1.264 +                            gint aGroup);
   1.265 +
   1.266 +    /**
   1.267 +     * GetUnmodifiedCharCodeFor() computes what character is inputted by the
   1.268 +     * key event without Ctrl/Alt/Meta/Super/Hyper modifiers.
   1.269 +     * If Level3 or Level5 Shift causes no character input, this also ignores
   1.270 +     * them.
   1.271 +     *
   1.272 +     * @param aGdkKeyEvent      Native key event, must not be nullptr.
   1.273 +     * @return                  charCode which is computed without modifiers
   1.274 +     *                          which prevent text input.
   1.275 +     */
   1.276 +    uint32_t GetUnmodifiedCharCodeFor(const GdkEventKey* aGdkKeyEvent);
   1.277 +
   1.278 +    /**
   1.279 +     * GetKeyLevel() returns level of the aGdkKeyEvent in mGdkKeymap.
   1.280 +     *
   1.281 +     * @param aGdkKeyEvent      Native key event, must not be nullptr.
   1.282 +     * @return                  Using level.  Typically, this is 0 or 1.
   1.283 +     *                          If failed, this returns -1.
   1.284 +     */
   1.285 +    gint GetKeyLevel(GdkEventKey *aGdkKeyEvent);
   1.286 +
   1.287 +    /**
   1.288 +     * GetFirstLatinGroup() returns group of mGdkKeymap which can input an
   1.289 +     * ASCII character by GDK_A.
   1.290 +     *
   1.291 +     * @return                  group value of GdkEventKey.
   1.292 +     */
   1.293 +    gint GetFirstLatinGroup();
   1.294 +
   1.295 +    /**
   1.296 +     * IsLatinGroup() checkes whether the keyboard layout of aGroup is
   1.297 +     * ASCII alphabet inputtable or not.
   1.298 +     *
   1.299 +     * @param aGroup            The group value of GdkEventKey.
   1.300 +     * @return                  TRUE if the keyboard layout can input
   1.301 +     *                          ASCII alphabet.  Otherwise, FALSE.
   1.302 +     */
   1.303 +    bool IsLatinGroup(guint8 aGroup);
   1.304 +
   1.305 +    /**
   1.306 +     * IsBasicLatinLetterOrNumeral() Checks whether the aCharCode is an
   1.307 +     * alphabet or a numeric character in ASCII.
   1.308 +     *
   1.309 +     * @param aCharCode         Charcode which you want to test.
   1.310 +     * @return                  TRUE if aCharCode is an alphabet or a numeric
   1.311 +     *                          in ASCII range.  Otherwise, FALSE.
   1.312 +     */
   1.313 +    static bool IsBasicLatinLetterOrNumeral(uint32_t aCharCode);
   1.314 +
   1.315 +    /**
   1.316 +     * GetGDKKeyvalWithoutModifier() returns the keyval for aGdkKeyEvent when
   1.317 +     * ignoring the modifier state except NumLock. (NumLock is a key to change
   1.318 +     * some key's meaning.)
   1.319 +     */
   1.320 +    static guint GetGDKKeyvalWithoutModifier(const GdkEventKey *aGdkKeyEvent);
   1.321 +
   1.322 +    /**
   1.323 +     * GetDOMKeyCodeFromKeyPairs() returns DOM keycode for aGdkKeyval if
   1.324 +     * it's in KeyPair table.
   1.325 +     */
   1.326 +    static uint32_t GetDOMKeyCodeFromKeyPairs(guint aGdkKeyval);
   1.327 +
   1.328 +    /**
   1.329 +     * InitKeypressEvent() intializes keyCode, charCode and
   1.330 +     * alternativeCharCodes of keypress event.
   1.331 +     *
   1.332 +     * @param aKeyEvent         An NS_KEY_PRESS event, must not be nullptr.
   1.333 +     *                          The modifier related members and keyCode must
   1.334 +     *                          be initialized already.
   1.335 +     * @param aGdkKeyEvent      A native key event which causes dispatching
   1.336 +     *                          aKeyEvent.
   1.337 +     */
   1.338 +    void InitKeypressEvent(WidgetKeyboardEvent& aKeyEvent,
   1.339 +                           GdkEventKey* aGdkKeyEvent);
   1.340 +
   1.341 +    /**
   1.342 +     * FilterEvents() listens all events on all our windows.
   1.343 +     * Be careful, this may make damage to performance if you add expensive
   1.344 +     * code in this method.
   1.345 +     */
   1.346 +    static GdkFilterReturn FilterEvents(GdkXEvent* aXEvent,
   1.347 +                                        GdkEvent* aGdkEvent,
   1.348 +                                        gpointer aData);
   1.349 +};
   1.350 +
   1.351 +} // namespace widget
   1.352 +} // namespace mozilla
   1.353 +
   1.354 +#endif /* __nsGdkKeyUtils_h__ */

mercurial