widget/gtk/nsGtkKeyUtils.h

Thu, 15 Jan 2015 15:59:08 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 15:59:08 +0100
branch
TOR_BUG_9701
changeset 10
ac0c01689b40
permissions
-rw-r--r--

Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial