Bug 1869647 - Mark hasStorageAccess.sub.https.window.html as intermittent after wpt...
[gecko.git] / widget / gtk / nsGtkKeyUtils.h
blobf19a0e1a9dd4e7a1dc551373f2e3ce05d700969a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
8 #ifndef __nsGdkKeyUtils_h__
9 #define __nsGdkKeyUtils_h__
11 #include "mozilla/EventForwards.h"
12 #include "nsIWidget.h"
13 #include "nsTArray.h"
15 #include <gdk/gdk.h>
16 #ifdef MOZ_X11
17 # include <X11/XKBlib.h>
18 #endif
19 #ifdef MOZ_WAYLAND
20 # include <gdk/gdkwayland.h>
21 # include <xkbcommon/xkbcommon.h>
22 #endif
23 #include "X11UndefineNone.h"
25 class nsWindow;
27 namespace mozilla {
28 namespace widget {
30 /**
31 * KeymapWrapper is a wrapper class of GdkKeymap. GdkKeymap doesn't support
32 * all our needs, therefore, we need to access lower level APIs.
33 * But such code is usually complex and might be slow. Against such issues,
34 * we should cache some information.
36 * This class provides only static methods. The methods is using internal
37 * singleton instance which is initialized by default GdkKeymap. When the
38 * GdkKeymap is destroyed, the singleton instance will be destroyed.
41 class KeymapWrapper {
42 public:
43 /**
44 * Compute an our DOM keycode from a GDK keyval.
46 static uint32_t ComputeDOMKeyCode(const GdkEventKey* aGdkKeyEvent);
48 /**
49 * Compute a DOM key name index from aGdkKeyEvent.
51 static KeyNameIndex ComputeDOMKeyNameIndex(const GdkEventKey* aGdkKeyEvent);
53 /**
54 * Compute a DOM code name index from aGdkKeyEvent.
56 static CodeNameIndex ComputeDOMCodeNameIndex(const GdkEventKey* aGdkKeyEvent);
58 /**
59 * Modifier is list of modifiers which we support in widget level.
61 enum Modifier {
62 NOT_MODIFIER = 0x0000,
63 CAPS_LOCK = 0x0001,
64 NUM_LOCK = 0x0002,
65 SCROLL_LOCK = 0x0004,
66 SHIFT = 0x0008,
67 CTRL = 0x0010,
68 ALT = 0x0020,
69 META = 0x0040,
70 SUPER = 0x0080,
71 HYPER = 0x0100,
72 LEVEL3 = 0x0200,
73 LEVEL5 = 0x0400
76 /**
77 * Modifiers is used for combination of Modifier.
78 * E.g., |Modifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
80 typedef uint32_t Modifiers;
82 /**
83 * GetCurrentModifierState() returns current modifier key state.
84 * The "current" means actual state of hardware keyboard when this is
85 * called. I.e., if some key events are not still dispatched by GDK,
86 * the state may mismatch with GdkEventKey::state.
88 * @return Current modifier key state.
90 static guint GetCurrentModifierState();
92 /**
93 * AreModifiersCurrentlyActive() checks the "current" modifier state
94 * on aGdkWindow with the keymap of the singleton instance.
96 * @param aModifiers One or more of Modifier values except
97 * NOT_MODIFIER.
98 * @return TRUE if all of modifieres in aModifiers are
99 * active. Otherwise, FALSE.
101 static bool AreModifiersCurrentlyActive(Modifiers aModifiers);
104 * Utility function to compute current keyboard modifiers for
105 * WidgetInputEvent
107 static uint32_t ComputeCurrentKeyModifiers();
110 * Utility function to covert platform modifier state to keyboard modifiers
111 * of WidgetInputEvent
113 static uint32_t ComputeKeyModifiers(guint aModifierState);
116 * Convert native modifiers for `nsIWidget::SynthesizeNative*()` to
117 * GDK's state.
119 static guint ConvertWidgetModifierToGdkState(
120 nsIWidget::Modifiers aNativeModifiers);
123 * InitInputEvent() initializes the aInputEvent with aModifierState.
125 static void InitInputEvent(WidgetInputEvent& aInputEvent,
126 guint aModifierState);
129 * InitKeyEvent() intializes aKeyEvent's modifier key related members
130 * and keycode related values.
132 * @param aKeyEvent It's an WidgetKeyboardEvent which needs to be
133 * initialized.
134 * @param aGdkKeyEvent A native GDK key event.
135 * @param aIsProcessedByIME true if aGdkKeyEvent is handled by IME.
137 static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
138 GdkEventKey* aGdkKeyEvent, bool aIsProcessedByIME);
141 * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event.
143 * @param aWindow The window to dispatch a keyboard event.
144 * @param aGdkKeyEvent A native GDK_KEY_PRESS or GDK_KEY_RELEASE
145 * event.
146 * @param aIsProcessedByIME true if the event is handled by IME.
147 * @param aIsCancelled [Out] true if the default is prevented.
148 * @return true if eKeyDown event is actually dispatched.
149 * Otherwise, false.
151 static bool DispatchKeyDownOrKeyUpEvent(nsWindow* aWindow,
152 GdkEventKey* aGdkKeyEvent,
153 bool aIsProcessedByIME,
154 bool* aIsCancelled);
157 * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event.
159 * @param aWindow The window to dispatch aKeyboardEvent.
160 * @param aKeyboardEvent An eKeyDown or eKeyUp event. This will be
161 * dispatched as is.
162 * @param aIsCancelled [Out] true if the default is prevented.
163 * @return true if eKeyDown event is actually dispatched.
164 * Otherwise, false.
166 static bool DispatchKeyDownOrKeyUpEvent(nsWindow* aWindow,
167 WidgetKeyboardEvent& aKeyboardEvent,
168 bool* aIsCancelled);
171 * GDK_KEY_PRESS event handler.
173 * @param aWindow The window to dispatch eKeyDown event (and maybe
174 * eKeyPress events).
175 * @param aGdkKeyEvent Receivied GDK_KEY_PRESS event.
177 static void HandleKeyPressEvent(nsWindow* aWindow, GdkEventKey* aGdkKeyEvent);
180 * GDK_KEY_RELEASE event handler.
182 * @param aWindow The window to dispatch eKeyUp event.
183 * @param aGdkKeyEvent Receivied GDK_KEY_RELEASE event.
184 * @return true if an event is dispatched. Otherwise, false.
186 static bool HandleKeyReleaseEvent(nsWindow* aWindow,
187 GdkEventKey* aGdkKeyEvent);
190 * WillDispatchKeyboardEvent() is called via
191 * TextEventDispatcherListener::WillDispatchKeyboardEvent().
193 * @param aKeyEvent An instance of KeyboardEvent which will be
194 * dispatched. This method should set charCode
195 * and alternative char codes if it's necessary.
196 * @param aGdkKeyEvent A GdkEventKey instance which caused the
197 * aKeyEvent.
199 static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent,
200 GdkEventKey* aGdkKeyEvent);
202 #ifdef MOZ_WAYLAND
204 * Utility function to set all supported modifier masks
205 * from xkb_keymap. We call that from Wayland backend routines.
207 static void SetModifierMasks(xkb_keymap* aKeymap);
210 * Wayland global focus handlers
212 static void SetFocusIn(wl_surface* aFocusSurface, uint32_t aFocusSerial);
213 static void SetFocusOut(wl_surface* aFocusSurface);
214 static void GetFocusInfo(wl_surface** aFocusSurface, uint32_t* aFocusSerial);
216 static void SetSeat(wl_seat* aSeat, int aId);
217 static void ClearSeat(int aId);
218 static wl_seat* GetSeat();
220 static void SetKeyboard(wl_keyboard* aKeyboard);
221 static wl_keyboard* GetKeyboard();
222 static void ClearKeyboard();
225 * EnsureInstance() is provided on Wayland to register Wayland callbacks
226 * early.
228 static void EnsureInstance();
229 #endif
232 * ResetKeyboard is called on keymap changes from OnKeysChanged and
233 * keyboard_handle_keymap to prepare for keymap changes.
235 static void ResetKeyboard();
238 * Destroys the singleton KeymapWrapper instance, if it exists.
240 static void Shutdown();
242 private:
244 * GetInstance() returns a KeymapWrapper instance.
246 * @return A singleton instance of KeymapWrapper.
248 static KeymapWrapper* GetInstance();
250 KeymapWrapper();
251 ~KeymapWrapper();
253 bool mInitialized;
256 * Initializing methods.
258 void Init();
259 #ifdef MOZ_X11
260 void InitXKBExtension();
261 void InitBySystemSettingsX11();
262 #endif
263 #ifdef MOZ_WAYLAND
264 void InitBySystemSettingsWayland();
265 #endif
268 * mModifierKeys stores each hardware key information.
270 struct ModifierKey {
271 guint mHardwareKeycode;
272 guint mMask;
274 explicit ModifierKey(guint aHardwareKeycode)
275 : mHardwareKeycode(aHardwareKeycode), mMask(0) {}
277 nsTArray<ModifierKey> mModifierKeys;
280 * GetModifierKey() returns modifier key information of the hardware
281 * keycode. If the key isn't a modifier key, returns nullptr.
283 ModifierKey* GetModifierKey(guint aHardwareKeycode);
286 * mModifierMasks is bit masks for each modifier. The index should be one
287 * of ModifierIndex values.
289 enum ModifierIndex {
290 INDEX_NUM_LOCK,
291 INDEX_SCROLL_LOCK,
292 INDEX_ALT,
293 INDEX_META,
294 INDEX_SUPER,
295 INDEX_HYPER,
296 INDEX_LEVEL3,
297 INDEX_LEVEL5,
298 COUNT_OF_MODIFIER_INDEX
300 guint mModifierMasks[COUNT_OF_MODIFIER_INDEX];
302 guint GetModifierMask(Modifier aModifier) const;
305 * @param aGdkKeyval A GDK defined modifier key value such as
306 * GDK_Shift_L.
307 * @return Returns Modifier values for aGdkKeyval.
308 * If the given key code isn't a modifier key,
309 * returns NOT_MODIFIER.
311 static Modifier GetModifierForGDKKeyval(guint aGdkKeyval);
313 static const char* GetModifierName(Modifier aModifier);
316 * AreModifiersActive() just checks whether aModifierState indicates
317 * all modifiers in aModifiers are active or not.
319 * @param aModifiers One or more of Modifier values except
320 * NOT_MODIFIER.
321 * @param aModifierState GDK's modifier states.
322 * @return TRUE if aGdkModifierType indecates all of
323 * modifiers in aModifier are active.
324 * Otherwise, FALSE.
326 static bool AreModifiersActive(Modifiers aModifiers, guint aModifierState);
329 * mGdkKeymap is a wrapped instance by this class.
331 GdkKeymap* mGdkKeymap;
334 * The base event code of XKB extension.
336 int mXKBBaseEventCode;
338 #ifdef MOZ_X11
340 * Only auto_repeats[] stores valid value. If you need to use other
341 * members, you need to listen notification events for them.
342 * See a call of XkbSelectEventDetails() with XkbControlsNotify in
343 * InitXKBExtension().
345 XKeyboardState mKeyboardState;
346 #endif
349 * Pointer of the singleton instance.
351 static KeymapWrapper* sInstance;
354 * Auto key repeat management.
356 static guint sLastRepeatableHardwareKeyCode;
357 #ifdef MOZ_X11
358 static Time sLastRepeatableKeyTime;
359 #endif
360 enum RepeatState { NOT_PRESSED, FIRST_PRESS, REPEATING };
361 static RepeatState sRepeatState;
364 * IsAutoRepeatableKey() returns true if the key supports auto repeat.
365 * Otherwise, false.
367 bool IsAutoRepeatableKey(guint aHardwareKeyCode);
370 * Signal handlers.
372 static void OnKeysChanged(GdkKeymap* aKeymap, KeymapWrapper* aKeymapWrapper);
373 static void OnDirectionChanged(GdkKeymap* aGdkKeymap,
374 KeymapWrapper* aKeymapWrapper);
376 gulong mOnKeysChangedSignalHandle;
377 gulong mOnDirectionChangedSignalHandle;
380 * GetCharCodeFor() Computes what character is inputted by the key event
381 * with aModifierState and aGroup.
383 * @param aGdkKeyEvent Native key event, must not be nullptr.
384 * @param aModifierState Combination of GdkModifierType which you
385 * want to test with aGdkKeyEvent.
386 * @param aGroup Set group in the mGdkKeymap.
387 * @return charCode which is inputted by aGdkKeyEvent.
388 * If failed, this returns 0.
390 static uint32_t GetCharCodeFor(const GdkEventKey* aGdkKeyEvent);
391 uint32_t GetCharCodeFor(const GdkEventKey* aGdkKeyEvent, guint aModifierState,
392 gint aGroup);
395 * GetUnmodifiedCharCodeFor() computes what character is inputted by the
396 * key event without Ctrl/Alt/Meta/Super/Hyper modifiers.
397 * If Level3 or Level5 Shift causes no character input, this also ignores
398 * them.
400 * @param aGdkKeyEvent Native key event, must not be nullptr.
401 * @return charCode which is computed without modifiers
402 * which prevent text input.
404 uint32_t GetUnmodifiedCharCodeFor(const GdkEventKey* aGdkKeyEvent);
407 * GetKeyLevel() returns level of the aGdkKeyEvent in mGdkKeymap.
409 * @param aGdkKeyEvent Native key event, must not be nullptr.
410 * @return Using level. Typically, this is 0 or 1.
411 * If failed, this returns -1.
413 gint GetKeyLevel(GdkEventKey* aGdkKeyEvent);
416 * GetFirstLatinGroup() returns group of mGdkKeymap which can input an
417 * ASCII character by GDK_A.
419 * @return group value of GdkEventKey.
421 gint GetFirstLatinGroup();
424 * IsLatinGroup() checkes whether the keyboard layout of aGroup is
425 * ASCII alphabet inputtable or not.
427 * @param aGroup The group value of GdkEventKey.
428 * @return TRUE if the keyboard layout can input
429 * ASCII alphabet. Otherwise, FALSE.
431 bool IsLatinGroup(guint8 aGroup);
434 * IsBasicLatinLetterOrNumeral() Checks whether the aCharCode is an
435 * alphabet or a numeric character in ASCII.
437 * @param aCharCode Charcode which you want to test.
438 * @return TRUE if aCharCode is an alphabet or a numeric
439 * in ASCII range. Otherwise, FALSE.
441 static bool IsBasicLatinLetterOrNumeral(uint32_t aCharCode);
444 * IsPrintableASCIICharacter() checks whether the aCharCode is a printable
445 * ASCII character. I.e., returns false if aCharCode is a control
446 * character even in an ASCII character.
448 static bool IsPrintableASCIICharacter(uint32_t aCharCode) {
449 return aCharCode >= 0x20 && aCharCode <= 0x7E;
453 * GetGDKKeyvalWithoutModifier() returns the keyval for aGdkKeyEvent when
454 * ignoring the modifier state except NumLock. (NumLock is a key to change
455 * some key's meaning.)
457 static guint GetGDKKeyvalWithoutModifier(const GdkEventKey* aGdkKeyEvent);
460 * GetDOMKeyCodeFromKeyPairs() returns DOM keycode for aGdkKeyval if
461 * it's in KeyPair table.
463 static uint32_t GetDOMKeyCodeFromKeyPairs(guint aGdkKeyval);
465 #ifdef MOZ_X11
467 * FilterEvents() listens all events on all our windows.
468 * Be careful, this may make damage to performance if you add expensive
469 * code in this method.
471 static GdkFilterReturn FilterEvents(GdkXEvent* aXEvent, GdkEvent* aGdkEvent,
472 gpointer aData);
473 #endif
476 * MaybeDispatchContextMenuEvent() may dispatch eContextMenu event if
477 * the given key combination should cause opening context menu.
479 * @param aWindow The window to dispatch a contextmenu event.
480 * @param aEvent The native key event.
481 * @return true if this method dispatched eContextMenu
482 * event. Otherwise, false.
483 * Be aware, when this returns true, the
484 * widget may have been destroyed.
486 static bool MaybeDispatchContextMenuEvent(nsWindow* aWindow,
487 const GdkEventKey* aEvent);
490 * See the document of WillDispatchKeyboardEvent().
492 void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent,
493 GdkEventKey* aGdkKeyEvent);
495 static guint GetModifierState(GdkEventKey* aGdkKeyEvent,
496 KeymapWrapper* aWrapper);
498 #ifdef MOZ_WAYLAND
500 * Utility function to set Xkb modifier key mask.
502 void SetModifierMask(xkb_keymap* aKeymap, ModifierIndex aModifierIndex,
503 const char* aModifierName);
504 #endif
506 #ifdef MOZ_WAYLAND
507 static wl_seat* sSeat;
508 static int sSeatID;
509 static wl_keyboard* sKeyboard;
510 wl_surface* mFocusSurface = nullptr;
511 uint32_t mFocusSerial = 0;
512 #endif
515 } // namespace widget
516 } // namespace mozilla
518 #endif /* __nsGdkKeyUtils_h__ */