Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / gtk / nsGtkKeyUtils.h
blobb1f1fae138713796e729f0fb08e52b03ab1b467a
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 static guint ConvertGeckoKeyCodeToGDKKeyval(const nsAString& aKeyCode);
60 /**
61 * We need to translate modifiers masks from Gdk to Gecko.
62 * MappedModifier is a table of mapped modifiers, we ignore other
63 * Gdk ones.
65 enum MappedModifier {
66 NOT_MODIFIER = 0x0000,
67 CAPS_LOCK = 0x0001,
68 NUM_LOCK = 0x0002,
69 SCROLL_LOCK = 0x0004,
70 SHIFT = 0x0008,
71 CTRL = 0x0010,
72 ALT = 0x0020,
73 META = 0x0040,
74 SUPER = 0x0080,
75 HYPER = 0x0100,
76 LEVEL3 = 0x0200,
77 LEVEL5 = 0x0400
80 /**
81 * MappedModifiers is used for combination of MappedModifier.
82 * E.g., |MappedModifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
84 typedef uint32_t MappedModifiers;
86 /**
87 * GetCurrentModifierState() returns current modifier key state.
88 * The "current" means actual state of hardware keyboard when this is
89 * called. I.e., if some key events are not still dispatched by GDK,
90 * the state may mismatch with GdkEventKey::state.
92 * @return Current modifier key state.
94 static guint GetCurrentModifierState();
96 /**
97 * Utility function to compute current keyboard modifiers for
98 * WidgetInputEvent
100 static uint32_t ComputeCurrentKeyModifiers();
103 * Utility function to covert platform modifier state to keyboard modifiers
104 * of WidgetInputEvent
106 static uint32_t ComputeKeyModifiers(guint aGdkModifierState);
109 * Convert native modifiers for `nsIWidget::SynthesizeNative*()` to
110 * GDK's state.
112 static guint ConvertWidgetModifierToGdkState(
113 nsIWidget::Modifiers aNativeModifiers);
116 * InitInputEvent() initializes the aInputEvent with aModifierState.
118 static void InitInputEvent(WidgetInputEvent& aInputEvent,
119 guint aGdkModifierState);
122 * InitKeyEvent() intializes aKeyEvent's modifier key related members
123 * and keycode related values.
125 * @param aKeyEvent It's an WidgetKeyboardEvent which needs to be
126 * initialized.
127 * @param aGdkKeyEvent A native GDK key event.
128 * @param aIsProcessedByIME true if aGdkKeyEvent is handled by IME.
130 static void InitKeyEvent(WidgetKeyboardEvent& aKeyEvent,
131 GdkEventKey* aGdkKeyEvent, bool aIsProcessedByIME);
134 * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event.
136 * @param aWindow The window to dispatch a keyboard event.
137 * @param aGdkKeyEvent A native GDK_KEY_PRESS or GDK_KEY_RELEASE
138 * event.
139 * @param aIsProcessedByIME true if the event is handled by IME.
140 * @param aIsCancelled [Out] true if the default is prevented.
141 * @return true if eKeyDown event is actually dispatched.
142 * Otherwise, false.
144 static bool DispatchKeyDownOrKeyUpEvent(nsWindow* aWindow,
145 GdkEventKey* aGdkKeyEvent,
146 bool aIsProcessedByIME,
147 bool* aIsCancelled);
150 * DispatchKeyDownOrKeyUpEvent() dispatches eKeyDown or eKeyUp event.
152 * @param aWindow The window to dispatch aKeyboardEvent.
153 * @param aKeyboardEvent An eKeyDown or eKeyUp event. This will be
154 * dispatched as is.
155 * @param aIsCancelled [Out] true if the default is prevented.
156 * @return true if eKeyDown event is actually dispatched.
157 * Otherwise, false.
159 static bool DispatchKeyDownOrKeyUpEvent(nsWindow* aWindow,
160 WidgetKeyboardEvent& aKeyboardEvent,
161 bool* aIsCancelled);
164 * GDK_KEY_PRESS event handler.
166 * @param aWindow The window to dispatch eKeyDown event (and maybe
167 * eKeyPress events).
168 * @param aGdkKeyEvent Receivied GDK_KEY_PRESS event.
170 static void HandleKeyPressEvent(nsWindow* aWindow, GdkEventKey* aGdkKeyEvent);
173 * GDK_KEY_RELEASE event handler.
175 * @param aWindow The window to dispatch eKeyUp event.
176 * @param aGdkKeyEvent Receivied GDK_KEY_RELEASE event.
177 * @return true if an event is dispatched. Otherwise, false.
179 static bool HandleKeyReleaseEvent(nsWindow* aWindow,
180 GdkEventKey* aGdkKeyEvent);
183 * WillDispatchKeyboardEvent() is called via
184 * TextEventDispatcherListener::WillDispatchKeyboardEvent().
186 * @param aKeyEvent An instance of KeyboardEvent which will be
187 * dispatched. This method should set charCode
188 * and alternative char codes if it's necessary.
189 * @param aGdkKeyEvent A GdkEventKey instance which caused the
190 * aKeyEvent.
192 static void WillDispatchKeyboardEvent(WidgetKeyboardEvent& aKeyEvent,
193 GdkEventKey* aGdkKeyEvent);
195 #ifdef MOZ_WAYLAND
197 * Utility function to set all supported modifier masks
198 * from xkb_keymap. We call that from Wayland backend routines.
200 static void SetModifierMasks(xkb_keymap* aKeymap);
203 * Wayland global focus handlers
205 static void SetFocusIn(wl_surface* aFocusSurface, uint32_t aFocusSerial);
206 static void SetFocusOut(wl_surface* aFocusSurface);
207 static void GetFocusInfo(wl_surface** aFocusSurface, uint32_t* aFocusSerial);
209 static void SetSeat(wl_seat* aSeat, int aId);
210 static void ClearSeat(int aId);
211 static wl_seat* GetSeat();
213 static void SetKeyboard(wl_keyboard* aKeyboard);
214 static wl_keyboard* GetKeyboard();
215 static void ClearKeyboard();
218 * EnsureInstance() is provided on Wayland to register Wayland callbacks
219 * early.
221 static void EnsureInstance();
222 #endif
225 * ResetKeyboard is called on keymap changes from OnKeysChanged and
226 * keyboard_handle_keymap to prepare for keymap changes.
228 static void ResetKeyboard();
231 * Destroys the singleton KeymapWrapper instance, if it exists.
233 static void Shutdown();
235 private:
237 * GetInstance() returns a KeymapWrapper instance.
239 * @return A singleton instance of KeymapWrapper.
241 static KeymapWrapper* GetInstance();
243 KeymapWrapper();
244 ~KeymapWrapper();
246 bool mInitialized;
249 * Initializing methods.
251 void Init();
252 #ifdef MOZ_X11
253 void InitXKBExtension();
254 void InitBySystemSettingsX11();
255 #endif
256 #ifdef MOZ_WAYLAND
257 void InitBySystemSettingsWayland();
258 #endif
261 * mModifierKeys stores each hardware key information.
263 struct ModifierKey {
264 guint mHardwareKeycode;
265 guint mMask;
267 explicit ModifierKey(guint aHardwareKeycode)
268 : mHardwareKeycode(aHardwareKeycode), mMask(0) {}
270 nsTArray<ModifierKey> mModifierKeys;
273 * GetModifierKey() returns modifier key information of the hardware
274 * keycode. If the key isn't a modifier key, returns nullptr.
276 ModifierKey* GetModifierKey(guint aHardwareKeycode);
279 * mModifierMasks is bit masks for each modifier. The index should be one
280 * of ModifierIndex values.
282 enum ModifierIndex {
283 INDEX_NUM_LOCK,
284 INDEX_SCROLL_LOCK,
285 INDEX_ALT,
286 INDEX_META,
287 INDEX_HYPER,
288 INDEX_LEVEL3,
289 INDEX_LEVEL5,
290 COUNT_OF_MODIFIER_INDEX
292 guint mModifierMasks[COUNT_OF_MODIFIER_INDEX];
294 guint GetGdkModifierMask(MappedModifier aModifier) const;
297 * @param aGdkKeyval A GDK defined modifier key value such as
298 * GDK_Shift_L.
299 * @return Returns MappedModifier values for aGdkKeyval.
300 * If the given key code isn't a modifier key,
301 * returns NOT_MODIFIER.
303 static MappedModifier GetModifierForGDKKeyval(guint aGdkKeyval);
305 static const char* GetModifierName(MappedModifier aModifier);
308 * AreModifiersActive() just checks whether aGdkModifierState indicates
309 * all modifiers in aModifiers are active or not.
311 * @param aModifiers One or more of MappedModifier values except
312 * NOT_MODIFIER.
313 * @param aGdkModifierState GDK's modifier states.
314 * @return TRUE if aGdkModifierType indicates all of
315 * modifiers in aModifier are active.
316 * Otherwise, FALSE.
318 static bool AreModifiersActive(MappedModifiers aModifiers,
319 guint aGdkModifierState);
322 * mGdkKeymap is a wrapped instance by this class.
324 GdkKeymap* mGdkKeymap;
327 * The base event code of XKB extension.
329 int mXKBBaseEventCode;
331 #ifdef MOZ_X11
333 * Only auto_repeats[] stores valid value. If you need to use other
334 * members, you need to listen notification events for them.
335 * See a call of XkbSelectEventDetails() with XkbControlsNotify in
336 * InitXKBExtension().
338 XKeyboardState mKeyboardState;
339 #endif
342 * Pointer of the singleton instance.
344 static KeymapWrapper* sInstance;
347 * Auto key repeat management.
349 static guint sLastRepeatableHardwareKeyCode;
350 #ifdef MOZ_X11
351 static Time sLastRepeatableKeyTime;
352 #endif
353 enum RepeatState { NOT_PRESSED, FIRST_PRESS, REPEATING };
354 static RepeatState sRepeatState;
357 * IsAutoRepeatableKey() returns true if the key supports auto repeat.
358 * Otherwise, false.
360 bool IsAutoRepeatableKey(guint aHardwareKeyCode);
363 * Signal handlers.
365 static void OnKeysChanged(GdkKeymap* aKeymap, KeymapWrapper* aKeymapWrapper);
366 static void OnDirectionChanged(GdkKeymap* aGdkKeymap,
367 KeymapWrapper* aKeymapWrapper);
369 gulong mOnKeysChangedSignalHandle;
370 gulong mOnDirectionChangedSignalHandle;
373 * GetCharCodeFor() Computes what character is inputted by the key event
374 * with aModifierState and aGroup.
376 * @param aGdkKeyEvent Native key event, must not be nullptr.
377 * @param aModifierState Combination of GdkModifierType which you
378 * want to test with aGdkKeyEvent.
379 * @param aGroup Set group in the mGdkKeymap.
380 * @return charCode which is inputted by aGdkKeyEvent.
381 * If failed, this returns 0.
383 static uint32_t GetCharCodeFor(const GdkEventKey* aGdkKeyEvent);
384 uint32_t GetCharCodeFor(const GdkEventKey* aGdkKeyEvent,
385 guint aGdkModifierState, gint aGroup);
388 * GetUnmodifiedCharCodeFor() computes what character is inputted by the
389 * key event without Ctrl/Alt/Meta/Super/Hyper modifiers.
390 * If Level3 or Level5 Shift causes no character input, this also ignores
391 * them.
393 * @param aGdkKeyEvent Native key event, must not be nullptr.
394 * @return charCode which is computed without modifiers
395 * which prevent text input.
397 uint32_t GetUnmodifiedCharCodeFor(const GdkEventKey* aGdkKeyEvent);
400 * GetKeyLevel() returns level of the aGdkKeyEvent in mGdkKeymap.
402 * @param aGdkKeyEvent Native key event, must not be nullptr.
403 * @return Using level. Typically, this is 0 or 1.
404 * If failed, this returns -1.
406 gint GetKeyLevel(GdkEventKey* aGdkKeyEvent);
409 * GetFirstLatinGroup() returns group of mGdkKeymap which can input an
410 * ASCII character by GDK_A.
412 * @return group value of GdkEventKey.
414 gint GetFirstLatinGroup();
417 * IsLatinGroup() checkes whether the keyboard layout of aGroup is
418 * ASCII alphabet inputtable or not.
420 * @param aGroup The group value of GdkEventKey.
421 * @return TRUE if the keyboard layout can input
422 * ASCII alphabet. Otherwise, FALSE.
424 bool IsLatinGroup(guint8 aGroup);
427 * IsBasicLatinLetterOrNumeral() Checks whether the aCharCode is an
428 * alphabet or a numeric character in ASCII.
430 * @param aCharCode Charcode which you want to test.
431 * @return TRUE if aCharCode is an alphabet or a numeric
432 * in ASCII range. Otherwise, FALSE.
434 static bool IsBasicLatinLetterOrNumeral(uint32_t aCharCode);
437 * IsPrintableASCIICharacter() checks whether the aCharCode is a printable
438 * ASCII character. I.e., returns false if aCharCode is a control
439 * character even in an ASCII character.
441 static bool IsPrintableASCIICharacter(uint32_t aCharCode) {
442 return aCharCode >= 0x20 && aCharCode <= 0x7E;
446 * GetGDKKeyvalWithoutModifier() returns the keyval for aGdkKeyEvent when
447 * ignoring the modifier state except NumLock. (NumLock is a key to change
448 * some key's meaning.)
450 static guint GetGDKKeyvalWithoutModifier(const GdkEventKey* aGdkKeyEvent);
453 * GetDOMKeyCodeFromKeyPairs() returns DOM keycode for aGdkKeyval if
454 * it's in KeyPair table.
456 static uint32_t GetDOMKeyCodeFromKeyPairs(guint aGdkKeyval);
458 #ifdef MOZ_X11
460 * FilterEvents() listens all events on all our windows.
461 * Be careful, this may make damage to performance if you add expensive
462 * code in this method.
464 static GdkFilterReturn FilterEvents(GdkXEvent* aXEvent, GdkEvent* aGdkEvent,
465 gpointer aData);
466 #endif
469 * MaybeDispatchContextMenuEvent() may dispatch eContextMenu event if
470 * the given key combination should cause opening context menu.
472 * @param aWindow The window to dispatch a contextmenu event.
473 * @param aEvent The native key event.
474 * @return true if this method dispatched eContextMenu
475 * event. Otherwise, false.
476 * Be aware, when this returns true, the
477 * widget may have been destroyed.
479 static bool MaybeDispatchContextMenuEvent(nsWindow* aWindow,
480 const GdkEventKey* aEvent);
483 * See the document of WillDispatchKeyboardEvent().
485 void WillDispatchKeyboardEventInternal(WidgetKeyboardEvent& aKeyEvent,
486 GdkEventKey* aGdkKeyEvent);
488 static guint GetModifierState(GdkEventKey* aGdkKeyEvent,
489 KeymapWrapper* aWrapper);
491 #ifdef MOZ_WAYLAND
493 * Utility function to set Xkb modifier key mask.
495 void SetModifierMask(xkb_keymap* aKeymap, ModifierIndex aModifierIndex,
496 const char* aModifierName);
497 #endif
499 #ifdef MOZ_WAYLAND
500 static wl_seat* sSeat;
501 static int sSeatID;
502 static wl_keyboard* sKeyboard;
503 wl_surface* mFocusSurface = nullptr;
504 uint32_t mFocusSerial = 0;
505 #endif
508 } // namespace widget
509 } // namespace mozilla
511 #endif /* __nsGdkKeyUtils_h__ */