Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/widget/gtk/nsGtkKeyUtils.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim:expandtab:shiftwidth=4:tabstop=4:
3
 */
4
/* This Source Code Form is subject to the terms of the Mozilla Public
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
6
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8
#ifndef __nsGdkKeyUtils_h__
9
#define __nsGdkKeyUtils_h__
10
11
#include "nsTArray.h"
12
#include "mozilla/EventForwards.h"
13
14
#include <gdk/gdk.h>
15
#include <X11/XKBlib.h>
16
#ifdef MOZ_WAYLAND
17
#include <gdk/gdkwayland.h>
18
#include <xkbcommon/xkbcommon.h>
19
#endif
20
21
namespace mozilla {
22
namespace widget {
23
24
/**
25
 *  KeymapWrapper is a wrapper class of GdkKeymap.  GdkKeymap doesn't support
26
 *  all our needs, therefore, we need to access lower level APIs.
27
 *  But such code is usually complex and might be slow.  Against such issues,
28
 *  we should cache some information.
29
 *
30
 *  This class provides only static methods.  The methods is using internal
31
 *  singleton instance which is initialized by default GdkKeymap.  When the
32
 *  GdkKeymap is destroyed, the singleton instance will be destroyed.
33
 */
34
35
class KeymapWrapper
36
{
37
public:
38
    /**
39
     * Compute an our DOM keycode from a GDK keyval.
40
     */
41
    static uint32_t ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent);
42
43
    /**
44
     * Compute a DOM key name index from aGdkKeyEvent.
45
     */
46
    static KeyNameIndex ComputeDOMKeyNameIndex(const GdkEventKey* aGdkKeyEvent);
47
48
    /**
49
     * Compute a DOM code name index from aGdkKeyEvent.
50
     */
51
    static CodeNameIndex ComputeDOMCodeNameIndex(
52
                           const GdkEventKey* aGdkKeyEvent);
53
54
    /**
55
     * Modifier is list of modifiers which we support in widget level.
56
     */
57
    enum Modifier {
58
        NOT_MODIFIER       = 0x0000,
59
        CAPS_LOCK          = 0x0001,
60
        NUM_LOCK           = 0x0002,
61
        SCROLL_LOCK        = 0x0004,
62
        SHIFT              = 0x0008,
63
        CTRL               = 0x0010,
64
        ALT                = 0x0020,
65
        META               = 0x0040,
66
        SUPER              = 0x0080,
67
        HYPER              = 0x0100,
68
        LEVEL3             = 0x0200,
69
        LEVEL5             = 0x0400
70
    };
71
72
    /**
73
     * Modifiers is used for combination of Modifier.
74
     * E.g., |Modifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
75
     */
76
    typedef uint32_t Modifiers;
77
78
    /**
79
     * GetCurrentModifierState() returns current modifier key state.
80
     * The "current" means actual state of hardware keyboard when this is
81
     * called.  I.e., if some key events are not still dispatched by GDK,
82
     * the state may mismatch with GdkEventKey::state.
83
     *
84
     * @return                  Current modifier key state.
85
     */
86
    static guint GetCurrentModifierState();
87
88
    /**
89
     * AreModifiersCurrentlyActive() checks the "current" modifier state
90
     * on aGdkWindow with the keymap of the singleton instance.
91
     *
92
     * @param aModifiers        One or more of Modifier values except
93
     *                          NOT_MODIFIER.
94
     * @return                  TRUE if all of modifieres in aModifiers are
95
     *                          active.  Otherwise, FALSE.
96
     */
97
    static bool AreModifiersCurrentlyActive(Modifiers aModifiers);
98
99
    /**
100
     * AreModifiersActive() just checks whether aModifierState indicates
101
     * all modifiers in aModifiers are active or not.
102
     *
103
     * @param aModifiers        One or more of Modifier values except
104
     *                          NOT_MODIFIER.
105
     * @param aModifierState    GDK's modifier states.
106
     * @return                  TRUE if aGdkModifierType indecates all of
107
     *                          modifiers in aModifier are active.
108
     *                          Otherwise, FALSE.
109
     */
110
    static bool AreModifiersActive(Modifiers aModifiers,
111
                                   guint aModifierState);
112
113
    /**
114
     * Utility function to compute current keyboard modifiers for
115
     * WidgetInputEvent
116
     */
117
    static uint32_t ComputeCurrentKeyModifiers();
118
119
    /**
120
     * Utility function to covert platform modifier state to keyboard modifiers
121
     * of WidgetInputEvent
122
     */
123
    static uint32_t ComputeKeyModifiers(guint aModifierState);
124
125
    /**
126
     * InitInputEvent() initializes the aInputEvent with aModifierState.
127
     */
128
    static void InitInputEvent(WidgetInputEvent& aInputEvent,
129
                               guint aModifierState);
130
131
    /**
132
     * InitKeyEvent() intializes aKeyEvent's modifier key related members
133
     * and keycode related values.
134
     *
135
     * @param aKeyEvent         It's an WidgetKeyboardEvent which needs to be
136
     *                          initialized.
137
     * @param aGdkKeyEvent      A native GDK key event.
138
     * @param aIsProcessedByIME true if aGdkKeyEvent is handled by IME.
139
     */
140
    static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
141
                             GdkEventKey* aGdkKeyEvent,
142
                             bool aIsProcessedByIME);
143
144
    /**
145
     * WillDispatchKeyboardEvent() is called via
146
     * TextEventDispatcherListener::WillDispatchKeyboardEvent().
147
     *
148
     * @param aKeyEvent         An instance of KeyboardEvent which will be
149
     *                          dispatched.  This method should set charCode
150
     *                          and alternative char codes if it's necessary.
151
     * @param aGdkKeyEvent      A GdkEventKey instance which caused the
152
     *                          aKeyEvent.
153
     */
154
    static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent,
155
                                          GdkEventKey* aGdkKeyEvent);
156
157
#ifdef MOZ_WAYLAND
158
    /**
159
     * Utility function to set all supported modifier masks
160
     * from xkb_keymap. We call that from Wayland backend routines.
161
     */
162
    static void SetModifierMasks(xkb_keymap *aKeymap);
163
#endif
164
165
    /**
166
     * Destroys the singleton KeymapWrapper instance, if it exists.
167
     */
168
    static void Shutdown();
169
170
protected:
171
172
    /**
173
     * GetInstance() returns a KeymapWrapper instance.
174
     *
175
     * @return                  A singleton instance of KeymapWrapper.
176
     */
177
    static KeymapWrapper* GetInstance();
178
179
    KeymapWrapper();
180
    ~KeymapWrapper();
181
182
    bool mInitialized;
183
184
    /**
185
     * Initializing methods.
186
     */
187
    void Init();
188
    void InitXKBExtension();
189
    void InitBySystemSettingsX11();
190
#ifdef MOZ_WAYLAND
191
    void InitBySystemSettingsWayland();
192
#endif
193
194
    /**
195
     * mModifierKeys stores each hardware key information.
196
     */
197
    struct ModifierKey {
198
        guint mHardwareKeycode;
199
        guint mMask;
200
201
        explicit ModifierKey(guint aHardwareKeycode) :
202
          mHardwareKeycode(aHardwareKeycode), mMask(0)
203
0
        {
204
0
        }
205
    };
206
    nsTArray<ModifierKey> mModifierKeys;
207
208
    /**
209
     * GetModifierKey() returns modifier key information of the hardware
210
     * keycode.  If the key isn't a modifier key, returns nullptr.
211
     */
212
    ModifierKey* GetModifierKey(guint aHardwareKeycode);
213
214
    /**
215
     * mModifierMasks is bit masks for each modifier.  The index should be one
216
     * of ModifierIndex values.
217
     */
218
    enum ModifierIndex {
219
        INDEX_NUM_LOCK,
220
        INDEX_SCROLL_LOCK,
221
        INDEX_ALT,
222
        INDEX_META,
223
        INDEX_SUPER,
224
        INDEX_HYPER,
225
        INDEX_LEVEL3,
226
        INDEX_LEVEL5,
227
        COUNT_OF_MODIFIER_INDEX
228
    };
229
    guint mModifierMasks[COUNT_OF_MODIFIER_INDEX];
230
231
    guint GetModifierMask(Modifier aModifier) const;
232
233
    /**
234
     * @param aGdkKeyval        A GDK defined modifier key value such as
235
     *                          GDK_Shift_L.
236
     * @return                  Returns Modifier values for aGdkKeyval.
237
     *                          If the given key code isn't a modifier key,
238
     *                          returns NOT_MODIFIER.
239
     */
240
    static Modifier GetModifierForGDKKeyval(guint aGdkKeyval);
241
242
    static const char* GetModifierName(Modifier aModifier);
243
244
    /**
245
     * mGdkKeymap is a wrapped instance by this class.
246
     */
247
    GdkKeymap* mGdkKeymap;
248
249
    /**
250
     * The base event code of XKB extension.
251
     */
252
    int mXKBBaseEventCode;
253
254
    /**
255
     * Only auto_repeats[] stores valid value.  If you need to use other
256
     * members, you need to listen notification events for them.
257
     * See a call of XkbSelectEventDetails() with XkbControlsNotify in
258
     * InitXKBExtension().
259
     */
260
    XKeyboardState mKeyboardState;
261
262
    /**
263
     * Pointer of the singleton instance.
264
     */
265
    static KeymapWrapper* sInstance;
266
267
    /**
268
     * Auto key repeat management.
269
     */
270
    static guint sLastRepeatableHardwareKeyCode;
271
    enum RepeatState
272
    {
273
        NOT_PRESSED,
274
        FIRST_PRESS,
275
        REPEATING
276
    };
277
    static RepeatState sRepeatState;
278
279
    /**
280
     * IsAutoRepeatableKey() returns true if the key supports auto repeat.
281
     * Otherwise, false.
282
     */
283
    bool IsAutoRepeatableKey(guint aHardwareKeyCode);
284
285
    /**
286
     * Signal handlers.
287
     */
288
    static void OnKeysChanged(GdkKeymap* aKeymap, KeymapWrapper* aKeymapWrapper);
289
    static void OnDirectionChanged(GdkKeymap *aGdkKeymap,
290
                                   KeymapWrapper* aKeymapWrapper);
291
292
    /**
293
     * GetCharCodeFor() Computes what character is inputted by the key event
294
     * with aModifierState and aGroup.
295
     *
296
     * @param aGdkKeyEvent      Native key event, must not be nullptr.
297
     * @param aModifierState    Combination of GdkModifierType which you
298
     *                          want to test with aGdkKeyEvent.
299
     * @param aGroup            Set group in the mGdkKeymap.
300
     * @return                  charCode which is inputted by aGdkKeyEvent.
301
     *                          If failed, this returns 0.
302
     */
303
    static uint32_t GetCharCodeFor(const GdkEventKey *aGdkKeyEvent);
304
    uint32_t GetCharCodeFor(const GdkEventKey *aGdkKeyEvent,
305
                            guint aModifierState,
306
                            gint aGroup);
307
308
    /**
309
     * GetUnmodifiedCharCodeFor() computes what character is inputted by the
310
     * key event without Ctrl/Alt/Meta/Super/Hyper modifiers.
311
     * If Level3 or Level5 Shift causes no character input, this also ignores
312
     * them.
313
     *
314
     * @param aGdkKeyEvent      Native key event, must not be nullptr.
315
     * @return                  charCode which is computed without modifiers
316
     *                          which prevent text input.
317
     */
318
    uint32_t GetUnmodifiedCharCodeFor(const GdkEventKey* aGdkKeyEvent);
319
320
    /**
321
     * GetKeyLevel() returns level of the aGdkKeyEvent in mGdkKeymap.
322
     *
323
     * @param aGdkKeyEvent      Native key event, must not be nullptr.
324
     * @return                  Using level.  Typically, this is 0 or 1.
325
     *                          If failed, this returns -1.
326
     */
327
    gint GetKeyLevel(GdkEventKey *aGdkKeyEvent);
328
329
    /**
330
     * GetFirstLatinGroup() returns group of mGdkKeymap which can input an
331
     * ASCII character by GDK_A.
332
     *
333
     * @return                  group value of GdkEventKey.
334
     */
335
    gint GetFirstLatinGroup();
336
337
    /**
338
     * IsLatinGroup() checkes whether the keyboard layout of aGroup is
339
     * ASCII alphabet inputtable or not.
340
     *
341
     * @param aGroup            The group value of GdkEventKey.
342
     * @return                  TRUE if the keyboard layout can input
343
     *                          ASCII alphabet.  Otherwise, FALSE.
344
     */
345
    bool IsLatinGroup(guint8 aGroup);
346
347
    /**
348
     * IsBasicLatinLetterOrNumeral() Checks whether the aCharCode is an
349
     * alphabet or a numeric character in ASCII.
350
     *
351
     * @param aCharCode         Charcode which you want to test.
352
     * @return                  TRUE if aCharCode is an alphabet or a numeric
353
     *                          in ASCII range.  Otherwise, FALSE.
354
     */
355
    static bool IsBasicLatinLetterOrNumeral(uint32_t aCharCode);
356
357
    /**
358
     * IsPrintableASCIICharacter() checks whether the aCharCode is a printable
359
     * ASCII character.  I.e., returns false if aCharCode is a control
360
     * character even in an ASCII character.
361
     */
362
    static bool IsPrintableASCIICharacter(uint32_t aCharCode)
363
0
    {
364
0
      return aCharCode >= 0x20 && aCharCode <= 0x7E;
365
0
    }
366
367
    /**
368
     * GetGDKKeyvalWithoutModifier() returns the keyval for aGdkKeyEvent when
369
     * ignoring the modifier state except NumLock. (NumLock is a key to change
370
     * some key's meaning.)
371
     */
372
    static guint GetGDKKeyvalWithoutModifier(const GdkEventKey *aGdkKeyEvent);
373
374
    /**
375
     * GetDOMKeyCodeFromKeyPairs() returns DOM keycode for aGdkKeyval if
376
     * it's in KeyPair table.
377
     */
378
    static uint32_t GetDOMKeyCodeFromKeyPairs(guint aGdkKeyval);
379
380
    /**
381
     * FilterEvents() listens all events on all our windows.
382
     * Be careful, this may make damage to performance if you add expensive
383
     * code in this method.
384
     */
385
    static GdkFilterReturn FilterEvents(GdkXEvent* aXEvent,
386
                                        GdkEvent* aGdkEvent,
387
                                        gpointer aData);
388
389
    /**
390
     * See the document of WillDispatchKeyboardEvent().
391
     */
392
    void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent,
393
                                           GdkEventKey* aGdkKeyEvent);
394
395
#ifdef MOZ_WAYLAND
396
    /**
397
     * Utility function to set Xkb modifier key mask.
398
     */
399
    void SetModifierMask(xkb_keymap *aKeymap,
400
                         ModifierIndex aModifierIndex,
401
                         const char* aModifierName);
402
#endif
403
};
404
405
} // namespace widget
406
} // namespace mozilla
407
408
#endif /* __nsGdkKeyUtils_h__ */