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
);
59 * Modifier is list of modifiers which we support in widget level.
62 NOT_MODIFIER
= 0x0000,
77 * Modifiers is used for combination of Modifier.
78 * E.g., |Modifiers modifiers = (SHIFT | CTRL);| means Shift and Ctrl.
80 typedef uint32_t Modifiers
;
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();
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
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
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
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
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
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.
151 static bool DispatchKeyDownOrKeyUpEvent(nsWindow
* aWindow
,
152 GdkEventKey
* aGdkKeyEvent
,
153 bool aIsProcessedByIME
,
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
162 * @param aIsCancelled [Out] true if the default is prevented.
163 * @return true if eKeyDown event is actually dispatched.
166 static bool DispatchKeyDownOrKeyUpEvent(nsWindow
* aWindow
,
167 WidgetKeyboardEvent
& aKeyboardEvent
,
171 * GDK_KEY_PRESS event handler.
173 * @param aWindow The window to dispatch eKeyDown event (and maybe
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
199 static void WillDispatchKeyboardEvent(WidgetKeyboardEvent
& aKeyEvent
,
200 GdkEventKey
* aGdkKeyEvent
);
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
228 static void EnsureInstance();
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();
244 * GetInstance() returns a KeymapWrapper instance.
246 * @return A singleton instance of KeymapWrapper.
248 static KeymapWrapper
* GetInstance();
256 * Initializing methods.
260 void InitXKBExtension();
261 void InitBySystemSettingsX11();
264 void InitBySystemSettingsWayland();
268 * mModifierKeys stores each hardware key information.
271 guint mHardwareKeycode
;
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.
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
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
321 * @param aModifierState GDK's modifier states.
322 * @return TRUE if aGdkModifierType indecates all of
323 * modifiers in aModifier are active.
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
;
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
;
349 * Pointer of the singleton instance.
351 static KeymapWrapper
* sInstance
;
354 * Auto key repeat management.
356 static guint sLastRepeatableHardwareKeyCode
;
358 static Time sLastRepeatableKeyTime
;
360 enum RepeatState
{ NOT_PRESSED
, FIRST_PRESS
, REPEATING
};
361 static RepeatState sRepeatState
;
364 * IsAutoRepeatableKey() returns true if the key supports auto repeat.
367 bool IsAutoRepeatableKey(guint aHardwareKeyCode
);
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
,
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
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
);
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
,
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
);
500 * Utility function to set Xkb modifier key mask.
502 void SetModifierMask(xkb_keymap
* aKeymap
, ModifierIndex aModifierIndex
,
503 const char* aModifierName
);
507 static wl_seat
* sSeat
;
509 static wl_keyboard
* sKeyboard
;
510 wl_surface
* mFocusSurface
= nullptr;
511 uint32_t mFocusSerial
= 0;
515 } // namespace widget
516 } // namespace mozilla
518 #endif /* __nsGdkKeyUtils_h__ */