Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1777)

Side by Side Diff: webkit/api/src/gtk/WebInputEventFactory.cpp

Issue 385057: Deleted webkit/api which now lives in webkit.org (Closed)
Patch Set: Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webkit/api/src/gtk/WebFontInfo.cpp ('k') | webkit/api/src/gtk/WebScreenInfoFactory.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2006-2009 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "WebInputEventFactory.h"
33
34 #include "KeyboardCodes.h"
35 #include "KeyCodeConversion.h"
36
37 #include "WebInputEvent.h"
38
39 #include <gdk/gdk.h>
40 #include <gdk/gdkkeysyms.h>
41 #include <gtk/gtkversion.h>
42
43 #include <wtf/Assertions.h>
44
45 namespace WebKit {
46
47 static double gdkEventTimeToWebEventTime(guint32 time)
48 {
49 // Convert from time in ms to time in sec.
50 return time / 1000.0;
51 }
52
53 static int gdkStateToWebEventModifiers(guint state)
54 {
55 int modifiers = 0;
56 if (state & GDK_SHIFT_MASK)
57 modifiers |= WebInputEvent::ShiftKey;
58 if (state & GDK_CONTROL_MASK)
59 modifiers |= WebInputEvent::ControlKey;
60 if (state & GDK_MOD1_MASK)
61 modifiers |= WebInputEvent::AltKey;
62 #if GTK_CHECK_VERSION(2, 10, 0)
63 if (state & GDK_META_MASK)
64 modifiers |= WebInputEvent::MetaKey;
65 #endif
66 if (state & GDK_BUTTON1_MASK)
67 modifiers |= WebInputEvent::LeftButtonDown;
68 if (state & GDK_BUTTON2_MASK)
69 modifiers |= WebInputEvent::MiddleButtonDown;
70 if (state & GDK_BUTTON3_MASK)
71 modifiers |= WebInputEvent::RightButtonDown;
72 return modifiers;
73 }
74
75 static int gdkEventToWindowsKeyCode(const GdkEventKey* event)
76 {
77 static const unsigned int hardwareCodeToGDKKeyval[] = {
78 0, // 0x00:
79 0, // 0x01:
80 0, // 0x02:
81 0, // 0x03:
82 0, // 0x04:
83 0, // 0x05:
84 0, // 0x06:
85 0, // 0x07:
86 0, // 0x08:
87 0, // 0x09: GDK_Escape
88 GDK_1, // 0x0A: GDK_1
89 GDK_2, // 0x0B: GDK_2
90 GDK_3, // 0x0C: GDK_3
91 GDK_4, // 0x0D: GDK_4
92 GDK_5, // 0x0E: GDK_5
93 GDK_6, // 0x0F: GDK_6
94 GDK_7, // 0x10: GDK_7
95 GDK_8, // 0x11: GDK_8
96 GDK_9, // 0x12: GDK_9
97 GDK_0, // 0x13: GDK_0
98 GDK_minus, // 0x14: GDK_minus
99 GDK_equal, // 0x15: GDK_equal
100 0, // 0x16: GDK_BackSpace
101 0, // 0x17: GDK_Tab
102 GDK_q, // 0x18: GDK_q
103 GDK_w, // 0x19: GDK_w
104 GDK_e, // 0x1A: GDK_e
105 GDK_r, // 0x1B: GDK_r
106 GDK_t, // 0x1C: GDK_t
107 GDK_y, // 0x1D: GDK_y
108 GDK_u, // 0x1E: GDK_u
109 GDK_i, // 0x1F: GDK_i
110 GDK_o, // 0x20: GDK_o
111 GDK_p, // 0x21: GDK_p
112 GDK_bracketleft, // 0x22: GDK_bracketleft
113 GDK_bracketright, // 0x23: GDK_bracketright
114 0, // 0x24: GDK_Return
115 0, // 0x25: GDK_Control_L
116 GDK_a, // 0x26: GDK_a
117 GDK_s, // 0x27: GDK_s
118 GDK_d, // 0x28: GDK_d
119 GDK_f, // 0x29: GDK_f
120 GDK_g, // 0x2A: GDK_g
121 GDK_h, // 0x2B: GDK_h
122 GDK_j, // 0x2C: GDK_j
123 GDK_k, // 0x2D: GDK_k
124 GDK_l, // 0x2E: GDK_l
125 GDK_semicolon, // 0x2F: GDK_semicolon
126 GDK_apostrophe, // 0x30: GDK_apostrophe
127 GDK_grave, // 0x31: GDK_grave
128 0, // 0x32: GDK_Shift_L
129 GDK_backslash, // 0x33: GDK_backslash
130 GDK_z, // 0x34: GDK_z
131 GDK_x, // 0x35: GDK_x
132 GDK_c, // 0x36: GDK_c
133 GDK_v, // 0x37: GDK_v
134 GDK_b, // 0x38: GDK_b
135 GDK_n, // 0x39: GDK_n
136 GDK_m, // 0x3A: GDK_m
137 GDK_comma, // 0x3B: GDK_comma
138 GDK_period, // 0x3C: GDK_period
139 GDK_slash, // 0x3D: GDK_slash
140 0, // 0x3E: GDK_Shift_R
141 };
142
143 // |windowsKeyCode| has to include a valid virtual-key code even when we
144 // use non-US layouts, e.g. even when we type an 'A' key of a US keyboard
145 // on the Hebrew layout, |windowsKeyCode| should be VK_A.
146 // On the other hand, |event->keyval| value depends on the current
147 // GdkKeymap object, i.e. when we type an 'A' key of a US keyboard on
148 // the Hebrew layout, |event->keyval| becomes GDK_hebrew_shin and this
149 // WebCore::windowsKeyCodeForKeyEvent() call returns 0.
150 // To improve compatibilty with Windows, we use |event->hardware_keycode|
151 // for retrieving its Windows key-code for the keys when the
152 // WebCore::windowsKeyCodeForEvent() call returns 0.
153 // We shouldn't use |event->hardware_keycode| for keys that GdkKeymap
154 // objects cannot change because |event->hardware_keycode| doesn't change
155 // even when we change the layout options, e.g. when we swap a control
156 // key and a caps-lock key, GTK doesn't swap their
157 // |event->hardware_keycode| values but swap their |event->keyval| values.
158 int windowsKeyCode = WebCore::windowsKeyCodeForKeyEvent(event->keyval);
159 if (windowsKeyCode)
160 return windowsKeyCode;
161
162 const int tableSize = sizeof(hardwareCodeToGDKKeyval) / sizeof(hardwareCodeToGDKKeyval[0]);
163 if (event->hardware_keycode < tableSize) {
164 int keyval = hardwareCodeToGDKKeyval[event->hardware_keycode];
165 if (keyval)
166 return WebCore::windowsKeyCodeForKeyEvent(keyval);
167 }
168
169 // This key is one that keyboard-layout drivers cannot change.
170 // Use |event->keyval| to retrieve its |windowsKeyCode| value.
171 return WebCore::windowsKeyCodeForKeyEvent(event->keyval);
172 }
173
174 // Gets the corresponding control character of a specified key code. See:
175 // http://en.wikipedia.org/wiki/Control_characters
176 // We emulate Windows behavior here.
177 static WebUChar getControlCharacter(int windowsKeyCode, bool shift)
178 {
179 if (windowsKeyCode >= WebCore::VKEY_A && windowsKeyCode <= WebCore::VKEY_Z) {
180 // ctrl-A ~ ctrl-Z map to \x01 ~ \x1A
181 return windowsKeyCode - WebCore::VKEY_A + 1;
182 }
183 if (shift) {
184 // following graphics chars require shift key to input.
185 switch (windowsKeyCode) {
186 // ctrl-@ maps to \x00 (Null byte)
187 case WebCore::VKEY_2:
188 return 0;
189 // ctrl-^ maps to \x1E (Record separator, Information separator two)
190 case WebCore::VKEY_6:
191 return 0x1E;
192 // ctrl-_ maps to \x1F (Unit separator, Information separator one)
193 case WebCore::VKEY_OEM_MINUS:
194 return 0x1F;
195 // Returns 0 for all other keys to avoid inputting unexpected chars.
196 default:
197 return 0;
198 }
199 } else {
200 switch (windowsKeyCode) {
201 // ctrl-[ maps to \x1B (Escape)
202 case WebCore::VKEY_OEM_4:
203 return 0x1B;
204 // ctrl-\ maps to \x1C (File separator, Information separator four)
205 case WebCore::VKEY_OEM_5:
206 return 0x1C;
207 // ctrl-] maps to \x1D (Group separator, Information separator three)
208 case WebCore::VKEY_OEM_6:
209 return 0x1D;
210 // ctrl-Enter maps to \x0A (Line feed)
211 case WebCore::VKEY_RETURN:
212 return 0x0A;
213 // Returns 0 for all other keys to avoid inputting unexpected chars.
214 default:
215 return 0;
216 }
217 }
218 }
219
220 // WebKeyboardEvent -----------------------------------------------------------
221
222 WebKeyboardEvent WebInputEventFactory::keyboardEvent(const GdkEventKey* event)
223 {
224 WebKeyboardEvent result;
225
226 result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
227 result.modifiers = gdkStateToWebEventModifiers(event->state);
228
229 switch (event->type) {
230 case GDK_KEY_RELEASE:
231 result.type = WebInputEvent::KeyUp;
232 break;
233 case GDK_KEY_PRESS:
234 result.type = WebInputEvent::RawKeyDown;
235 break;
236 default:
237 ASSERT_NOT_REACHED();
238 }
239
240 // According to MSDN:
241 // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
242 // Key events with Alt modifier and F10 are system key events.
243 // We just emulate this behavior. It's necessary to prevent webkit from
244 // processing keypress event generated by alt-d, etc.
245 // F10 is not special on Linux, so don't treat it as system key.
246 if (result.modifiers & WebInputEvent::AltKey)
247 result.isSystemKey = true;
248
249 // The key code tells us which physical key was pressed (for example, the
250 // A key went down or up). It does not determine whether A should be lower
251 // or upper case. This is what text does, which should be the keyval.
252 result.windowsKeyCode = gdkEventToWindowsKeyCode(event);
253 result.nativeKeyCode = event->hardware_keycode;
254
255 if (result.windowsKeyCode == WebCore::VKEY_RETURN)
256 // We need to treat the enter key as a key press of character \r. This
257 // is apparently just how webkit handles it and what it expects.
258 result.unmodifiedText[0] = '\r';
259 else
260 // FIXME: fix for non BMP chars
261 result.unmodifiedText[0] =
262 static_cast<WebUChar>(gdk_keyval_to_unicode(event->keyval));
263
264 // If ctrl key is pressed down, then control character shall be input.
265 if (result.modifiers & WebInputEvent::ControlKey)
266 result.text[0] = getControlCharacter(
267 result.windowsKeyCode, result.modifiers & WebInputEvent::ShiftKey);
268 else
269 result.text[0] = result.unmodifiedText[0];
270
271 result.setKeyIdentifierFromWindowsKeyCode();
272
273 // FIXME: Do we need to set IsAutoRepeat or IsKeyPad?
274
275 return result;
276 }
277
278 WebKeyboardEvent WebInputEventFactory::keyboardEvent(wchar_t character, int state, double timeStampSeconds)
279 {
280 // keyboardEvent(const GdkEventKey*) depends on the GdkEventKey object and
281 // it is hard to use/ it from signal handlers which don't use GdkEventKey
282 // objects (e.g. GtkIMContext signal handlers.) For such handlers, this
283 // function creates a WebInputEvent::Char event without using a
284 // GdkEventKey object.
285 WebKeyboardEvent result;
286 result.type = WebKit::WebInputEvent::Char;
287 result.timeStampSeconds = timeStampSeconds;
288 result.modifiers = gdkStateToWebEventModifiers(state);
289 result.windowsKeyCode = character;
290 result.nativeKeyCode = character;
291 result.text[0] = character;
292 result.unmodifiedText[0] = character;
293
294 // According to MSDN:
295 // http://msdn.microsoft.com/en-us/library/ms646286(VS.85).aspx
296 // Key events with Alt modifier and F10 are system key events.
297 // We just emulate this behavior. It's necessary to prevent webkit from
298 // processing keypress event generated by alt-d, etc.
299 // F10 is not special on Linux, so don't treat it as system key.
300 if (result.modifiers & WebInputEvent::AltKey)
301 result.isSystemKey = true;
302
303 return result;
304 }
305
306 // WebMouseEvent --------------------------------------------------------------
307
308 WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventButton* event)
309 {
310 WebMouseEvent result;
311
312 result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
313
314 result.modifiers = gdkStateToWebEventModifiers(event->state);
315 result.x = static_cast<int>(event->x);
316 result.y = static_cast<int>(event->y);
317 result.windowX = result.x;
318 result.windowY = result.y;
319 result.globalX = static_cast<int>(event->x_root);
320 result.globalY = static_cast<int>(event->y_root);
321 result.clickCount = 0;
322
323 switch (event->type) {
324 case GDK_3BUTTON_PRESS:
325 ++result.clickCount;
326 // fallthrough
327 case GDK_2BUTTON_PRESS:
328 ++result.clickCount;
329 // fallthrough
330 case GDK_BUTTON_PRESS:
331 result.type = WebInputEvent::MouseDown;
332 ++result.clickCount;
333 break;
334 case GDK_BUTTON_RELEASE:
335 result.type = WebInputEvent::MouseUp;
336 break;
337
338 default:
339 ASSERT_NOT_REACHED();
340 };
341
342 result.button = WebMouseEvent::ButtonNone;
343 if (event->button == 1)
344 result.button = WebMouseEvent::ButtonLeft;
345 else if (event->button == 2)
346 result.button = WebMouseEvent::ButtonMiddle;
347 else if (event->button == 3)
348 result.button = WebMouseEvent::ButtonRight;
349
350 return result;
351 }
352
353 WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventMotion* event)
354 {
355 WebMouseEvent result;
356
357 result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
358 result.modifiers = gdkStateToWebEventModifiers(event->state);
359 result.x = static_cast<int>(event->x);
360 result.y = static_cast<int>(event->y);
361 result.windowX = result.x;
362 result.windowY = result.y;
363 result.globalX = static_cast<int>(event->x_root);
364 result.globalY = static_cast<int>(event->y_root);
365
366 switch (event->type) {
367 case GDK_MOTION_NOTIFY:
368 result.type = WebInputEvent::MouseMove;
369 break;
370 default:
371 ASSERT_NOT_REACHED();
372 }
373
374 result.button = WebMouseEvent::ButtonNone;
375 if (event->state & GDK_BUTTON1_MASK)
376 result.button = WebMouseEvent::ButtonLeft;
377 else if (event->state & GDK_BUTTON2_MASK)
378 result.button = WebMouseEvent::ButtonMiddle;
379 else if (event->state & GDK_BUTTON3_MASK)
380 result.button = WebMouseEvent::ButtonRight;
381
382 return result;
383 }
384
385 WebMouseEvent WebInputEventFactory::mouseEvent(const GdkEventCrossing* event)
386 {
387 WebMouseEvent result;
388
389 result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
390 result.modifiers = gdkStateToWebEventModifiers(event->state);
391 result.x = static_cast<int>(event->x);
392 result.y = static_cast<int>(event->y);
393 result.windowX = result.x;
394 result.windowY = result.y;
395 result.globalX = static_cast<int>(event->x_root);
396 result.globalY = static_cast<int>(event->y_root);
397
398 switch (event->type) {
399 case GDK_ENTER_NOTIFY:
400 case GDK_LEAVE_NOTIFY:
401 // Note that if we sent MouseEnter or MouseLeave to WebKit, it
402 // wouldn't work - they don't result in the proper JavaScript events.
403 // MouseMove does the right thing.
404 result.type = WebInputEvent::MouseMove;
405 break;
406 default:
407 ASSERT_NOT_REACHED();
408 }
409
410 result.button = WebMouseEvent::ButtonNone;
411 if (event->state & GDK_BUTTON1_MASK)
412 result.button = WebMouseEvent::ButtonLeft;
413 else if (event->state & GDK_BUTTON2_MASK)
414 result.button = WebMouseEvent::ButtonMiddle;
415 else if (event->state & GDK_BUTTON3_MASK)
416 result.button = WebMouseEvent::ButtonRight;
417
418 return result;
419 }
420
421 // WebMouseWheelEvent ---------------------------------------------------------
422
423 WebMouseWheelEvent WebInputEventFactory::mouseWheelEvent(const GdkEventScroll* event)
424 {
425 WebMouseWheelEvent result;
426
427 result.type = WebInputEvent::MouseWheel;
428 result.button = WebMouseEvent::ButtonNone;
429
430 result.timeStampSeconds = gdkEventTimeToWebEventTime(event->time);
431 result.modifiers = gdkStateToWebEventModifiers(event->state);
432 result.x = static_cast<int>(event->x);
433 result.y = static_cast<int>(event->y);
434 result.windowX = result.x;
435 result.windowY = result.y;
436 result.globalX = static_cast<int>(event->x_root);
437 result.globalY = static_cast<int>(event->y_root);
438
439 // How much should we scroll per mouse wheel event?
440 // - Windows uses 3 lines by default and obeys a system setting.
441 // - Mozilla has a pref that lets you either use the "system" number of lines
442 // to scroll, or lets the user override it.
443 // For the "system" number of lines, it appears they've hardcoded 3.
444 // See case NS_MOUSE_SCROLL in content/events/src/nsEventStateManager.cpp
445 // and InitMouseScrollEvent in widget/src/gtk2/nsCommonWidget.cpp .
446 // - Gtk makes the scroll amount a function of the size of the scroll bar,
447 // which is not available to us here.
448 // Instead, we pick a number that empirically matches Firefox's behavior.
449 static const float scrollbarPixelsPerTick = 160.0f / 3.0f;
450
451 switch (event->direction) {
452 case GDK_SCROLL_UP:
453 result.deltaY = scrollbarPixelsPerTick;
454 result.wheelTicksY = 1;
455 break;
456 case GDK_SCROLL_DOWN:
457 result.deltaY = -scrollbarPixelsPerTick;
458 result.wheelTicksY = -1;
459 break;
460 case GDK_SCROLL_LEFT:
461 result.deltaX = scrollbarPixelsPerTick;
462 result.wheelTicksX = -1; // Match Windows positive/negative orientation
463 break;
464 case GDK_SCROLL_RIGHT:
465 result.deltaX = -scrollbarPixelsPerTick;
466 result.wheelTicksX = 1;
467 break;
468 }
469
470 return result;
471 }
472
473 } // namespace WebKit
OLDNEW
« no previous file with comments | « webkit/api/src/gtk/WebFontInfo.cpp ('k') | webkit/api/src/gtk/WebScreenInfoFactory.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698