1/*
2 * Copyright (C) 2010 Apple Inc. All rights reserved.
3 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
4 * Copyright (C) 2011 Igalia S.L.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25 * THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "config.h"
29#include "WebEventFactory.h"
30
31#include "PlatformKeyboardEvent.h"
32#include "WindowsKeyboardCodes.h"
33
34#include <wtf/ASCIICType.h>
35
36using namespace WebCore;
37
38namespace WebKit {
39
40static inline GdkPoint positionForEvent(GdkEventAny* event)
41{
42 GdkPoint point;
43
44 switch (event->type) {
45 case GDK_MOTION_NOTIFY:
46 point.x = static_cast<int>(reinterpret_cast<GdkEventMotion *>(event)->x);
47 point.y = static_cast<int>(reinterpret_cast<GdkEventMotion *>(event)->y);
48 break;
49 case GDK_BUTTON_PRESS:
50 case GDK_2BUTTON_PRESS:
51 case GDK_3BUTTON_PRESS:
52 case GDK_BUTTON_RELEASE:
53 point.x = static_cast<int>(reinterpret_cast<GdkEventButton *>(event)->x);
54 point.y = static_cast<int>(reinterpret_cast<GdkEventButton *>(event)->y);
55 break;
56 case GDK_SCROLL:
57 point.x = static_cast<int>(reinterpret_cast<GdkEventScroll *>(event)->x);
58 point.y = static_cast<int>(reinterpret_cast<GdkEventScroll *>(event)->y);
59 break;
60 default :
61 ASSERT_NOT_REACHED();
62 }
63
64 return point;
65}
66
67static inline GdkPoint globalPositionForEvent(GdkEventAny* event)
68{
69 GdkPoint point;
70
71 switch (event->type) {
72 case GDK_MOTION_NOTIFY:
73 point.x = static_cast<int>(reinterpret_cast<GdkEventMotion *>(event)->x_root);
74 point.y = static_cast<int>(reinterpret_cast<GdkEventMotion *>(event)->y_root);
75 break;
76 case GDK_BUTTON_PRESS:
77 case GDK_2BUTTON_PRESS:
78 case GDK_3BUTTON_PRESS:
79 case GDK_BUTTON_RELEASE:
80 point.x = static_cast<int>(reinterpret_cast<GdkEventButton *>(event)->x_root);
81 point.y = static_cast<int>(reinterpret_cast<GdkEventButton *>(event)->y_root);
82 break;
83 case GDK_SCROLL:
84 point.x = static_cast<int>(reinterpret_cast<GdkEventScroll *>(event)->x_root);
85 point.y = static_cast<int>(reinterpret_cast<GdkEventScroll *>(event)->y_root);
86 break;
87 default :
88 ASSERT_NOT_REACHED();
89 }
90
91 return point;
92}
93
94static inline int clickCount(GdkEventAny* event)
95{
96 int sClickCount = 0;
97
98 switch (event->type) {
99 case GDK_BUTTON_PRESS:
100 sClickCount = 1;
101 break;
102 case GDK_2BUTTON_PRESS:
103 sClickCount = 2;
104 break;
105 case GDK_3BUTTON_PRESS:
106 sClickCount = 3;
107 break;
108 case GDK_MOTION_NOTIFY:
109 case GDK_BUTTON_RELEASE:
110 sClickCount = 0;
111 break;
112 default:
113 ASSERT_NOT_REACHED();
114 };
115
116 return sClickCount;
117}
118
119static inline WebEvent::Modifiers modifiersForEvent(guint state)
120{
121 unsigned modifiers = 0;
122
123 if (state & GDK_CONTROL_MASK)
124 modifiers |= WebEvent::ControlKey;
125 if (state & GDK_SHIFT_MASK)
126 modifiers |= WebEvent::ShiftKey;
127 if (state & GDK_MOD1_MASK)
128 modifiers |= WebEvent::AltKey;
129 if (state & GDK_META_MASK)
130 modifiers |= WebEvent::MetaKey;
131
132 return static_cast<WebEvent::Modifiers>(modifiers);
133}
134
135static inline WebMouseEvent::Button buttonForEvent(GdkEventAny *event)
136{
137 unsigned button = 0;
138 GdkEventMotion* motion;
139 GdkEventButton* bEvent;
140
141 switch (event->type) {
142 case GDK_MOTION_NOTIFY:
143 motion = (GdkEventMotion*) event;
144 button = WebMouseEvent::NoButton;
145 if (motion->state & GDK_BUTTON1_MASK)
146 button = WebMouseEvent::LeftButton;
147 else if (motion->state & GDK_BUTTON2_MASK)
148 button = WebMouseEvent::MiddleButton;
149 else if (motion->state & GDK_BUTTON3_MASK)
150 button = WebMouseEvent::RightButton;
151 break;
152 case GDK_BUTTON_PRESS:
153 case GDK_2BUTTON_PRESS:
154 case GDK_3BUTTON_PRESS:
155 case GDK_BUTTON_RELEASE:
156 bEvent = (GdkEventButton *)event;
157 if (bEvent->button == 1)
158 button = WebMouseEvent::LeftButton;
159 else if (bEvent->button == 2)
160 button = WebMouseEvent::MiddleButton;
161 else if (bEvent->button == 3)
162 button = WebMouseEvent::RightButton;
163 break;
164 default:
165 ASSERT_NOT_REACHED();
166 };
167
168 return static_cast<WebMouseEvent::Button>(button);
169}
170
171
172WebMouseEvent WebEventFactory::createWebMouseEvent(GdkEventAny *event)
173{
174 guint timestamp = 0;
175
176 WebEvent::Modifiers modifiers = static_cast<WebEvent::Modifiers>(0);
177 WebMouseEvent::Button button = buttonForEvent(event);
178
179 GdkPoint position = positionForEvent(event);
180 GdkPoint globalPosition = globalPositionForEvent((GdkEventAny *)event);
181 int clickcount = clickCount(event);
182
183 WebEvent::Type type = static_cast<WebEvent::Type>(0);
184
185 switch (event->type) {
186 case GDK_MOTION_NOTIFY:
187 type = WebEvent::MouseMove;
188 break;
189 case GDK_BUTTON_PRESS:
190 case GDK_2BUTTON_PRESS:
191 case GDK_3BUTTON_PRESS:
192 type = WebEvent::MouseDown;
193 break;
194 case GDK_BUTTON_RELEASE:
195 type = WebEvent::MouseUp;
196 break;
197 default :
198 ASSERT_NOT_REACHED();
199 }
200
201 WebCore::IntPoint eventPosition(position.x, position.y);
202 WebCore::IntPoint eventGlobalPosition(globalPosition.x, globalPosition.y);
203
204 return WebMouseEvent(type, button, eventPosition, eventGlobalPosition, 0, 0, 0, clickcount, modifiers, timestamp);
205}
206
207WebWheelEvent WebEventFactory::createWebWheelEvent(GdkEventScroll *event)
208{
209 WebWheelEvent::Granularity granularity = WebWheelEvent::ScrollByPixelWheelEvent;
210
211 double timestamp = event->time;
212
213 float deltaX = 0;
214 float deltaY = 0;
215 float wheelTicksX = 0;
216 float wheelTicksY = 0;
217 float scrollbarPixelsPerLine = 40;
218 float delta = 1;
219 GdkPoint position = positionForEvent((GdkEventAny *)event);
220 GdkPoint globalPosition = globalPositionForEvent((GdkEventAny *)event);
221 WebCore::IntPoint eventPosition(position.x, position.y);
222 WebCore::IntPoint eventGlobalPosition(globalPosition.x, globalPosition.y);
223 WebEvent::Modifiers modifiers = modifiersForEvent(event->state);
224
225 switch (event->direction) {
226 case GDK_SCROLL_UP:
227 deltaY = delta;
228 break;
229 case GDK_SCROLL_DOWN:
230 deltaY = -delta;
231 break;
232 case GDK_SCROLL_LEFT:
233 deltaX = delta;
234 break;
235 case GDK_SCROLL_RIGHT:
236 deltaX = -delta;
237 break;
238 }
239
240 wheelTicksX = deltaX;
241 wheelTicksY = deltaY;
242 deltaX *= scrollbarPixelsPerLine;
243 deltaY *= scrollbarPixelsPerLine;
244 WebCore::FloatSize eventDelta(deltaX, deltaY);
245 WebCore::FloatSize eventWheelTicks(wheelTicksX, wheelTicksY);
246
247 return WebWheelEvent(WebEvent::Wheel, eventPosition, eventGlobalPosition, eventDelta, eventWheelTicks, granularity, modifiers, timestamp);
248}
249
250
251static inline WebEvent::Modifiers modifiersForCurrentKeyState(guint state)
252{
253 unsigned modifiers = 0;
254
255 if (state & GDK_CONTROL_MASK)
256 modifiers |= WebEvent::ControlKey;
257 if ((state & GDK_SHIFT_MASK) || (state == GDK_KEY_3270_BackTab))
258 modifiers |= WebEvent::ShiftKey;
259 if (state & GDK_MOD1_MASK)
260 modifiers |= WebEvent::AltKey;
261 if (state & GDK_META_MASK)
262 modifiers |= WebEvent::MetaKey;
263
264 return static_cast<WebEvent::Modifiers>(modifiers);
265}
266
267WebKeyboardEvent WebEventFactory::createWebKeyboardEvent(GdkEventKey* event)
268{
269 WebEvent::Type type = (event->type == GDK_KEY_RELEASE) ? WebEvent::KeyUp : WebEvent::KeyDown;
270 String text = PlatformKeyboardEvent::singleCharacterString(event->keyval);
271 String unmodifiedText = PlatformKeyboardEvent::singleCharacterString(event->keyval);
272 String keyIdentifier = PlatformKeyboardEvent::keyIdentifierForGdkKeyCode(event->keyval);
273 int windowsVirtualKeyCode = PlatformKeyboardEvent::windowsKeyCodeForKeyEvent(event->keyval);
274 int nativeVirtualKeyCode = static_cast<int>(event->keyval);
275 int macCharCode = 0;
276 bool autoRepeat = false;
277 bool isKeypad = event->keyval >= GDK_KEY_KP_Space && event->keyval <= GDK_KEY_KP_9;
278 bool isSystemKey = false;
279 WebEvent::Modifiers modifiers = modifiersForCurrentKeyState(event->state);
280 double timestamp = event->time;
281
282 return WebKeyboardEvent(type, text, unmodifiedText, keyIdentifier, windowsVirtualKeyCode, nativeVirtualKeyCode, macCharCode, autoRepeat, isKeypad, isSystemKey, modifiers, timestamp);
283}
284
285} // namespace WebKit