1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
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"
17 # include <X11/XKBlib.h>
20 # include <gdk/gdkwayland.h>
21 # include <xkbcommon/xkbcommon.h>
23 #include "X11UndefineNone.h"
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.
44 * Compute an our DOM keycode from a GDK keyval.
46 static uint32_t ComputeDOMKeyCode(const GdkEventKey
* aGdkKeyEvent
);
49 * Compute a DOM key name index from aGdkKeyEvent.
51 static KeyNameIndex
ComputeDOMKeyNameIndex(const GdkEventKey
* aGdkKeyEvent
);
54 * Compute a DOM code name index from aGdkKeyEvent.
56 static CodeNameIndex
ComputeDOMCodeNameIndex(const GdkEventKey
* aGdkKeyEvent
);
58 static guint
ConvertGeckoKeyCodeToGDKKeyval(const nsAString
& aKeyCode
);
61 * We need to translate modifiers masks from Gdk to Gecko.
62 * MappedModifier is a table of mapped modifiers, we ignore other
66 NOT_MODIFIER
= 0x0000,
81 * MappedModifiers is used for combination of MappedModifier.
82 * E.g., |MappedModifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
84 typedef uint32_t MappedModifiers
;
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();
97 * Utility function to compute current keyboard modifiers for
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
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
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
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.
144 static bool DispatchKeyDownOrKeyUpEvent(nsWindow
* aWindow
,
145 GdkEventKey
* aGdkKeyEvent
,
146 bool aIsProcessedByIME
,
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
155 * @param aIsCancelled [Out] true if the default is prevented.
156 * @return true if eKeyDown event is actually dispatched.
159 static bool DispatchKeyDownOrKeyUpEvent(nsWindow
* aWindow
,
160 WidgetKeyboardEvent
& aKeyboardEvent
,
164 * GDK_KEY_PRESS event handler.
166 * @param aWindow The window to dispatch eKeyDown event (and maybe
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
192 static void WillDispatchKeyboardEvent(WidgetKeyboardEvent
& aKeyEvent
,
193 GdkEventKey
* aGdkKeyEvent
);
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
221 static void EnsureInstance();
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();
237 * GetInstance() returns a KeymapWrapper instance.
239 * @return A singleton instance of KeymapWrapper.
241 static KeymapWrapper
* GetInstance();
249 * Initializing methods.
253 void InitXKBExtension();
254 void InitBySystemSettingsX11();
257 void InitBySystemSettingsWayland();
261 * mModifierKeys stores each hardware key information.
264 guint mHardwareKeycode
;
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.
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
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
313 * @param aGdkModifierState GDK's modifier states.
314 * @return TRUE if aGdkModifierType indicates all of
315 * modifiers in aModifier are active.
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
;
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
;
342 * Pointer of the singleton instance.
344 static KeymapWrapper
* sInstance
;
347 * Auto key repeat management.
349 static guint sLastRepeatableHardwareKeyCode
;
351 static Time sLastRepeatableKeyTime
;
353 enum RepeatState
{ NOT_PRESSED
, FIRST_PRESS
, REPEATING
};
354 static RepeatState sRepeatState
;
357 * IsAutoRepeatableKey() returns true if the key supports auto repeat.
360 bool IsAutoRepeatableKey(guint aHardwareKeyCode
);
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
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
);
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
,
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
);
493 * Utility function to set Xkb modifier key mask.
495 void SetModifierMask(xkb_keymap
* aKeymap
, ModifierIndex aModifierIndex
,
496 const char* aModifierName
);
500 static wl_seat
* sSeat
;
502 static wl_keyboard
* sKeyboard
;
503 wl_surface
* mFocusSurface
= nullptr;
504 uint32_t mFocusSerial
= 0;
508 } // namespace widget
509 } // namespace mozilla
511 #endif /* __nsGdkKeyUtils_h__ */