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