- add sources.
[platform/framework/web/crosswalk.git] / src / ui / events / win / events_win.cc
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <windowsx.h>
6
7 #include "ui/events/event_constants.h"
8
9 #include "base/logging.h"
10 #include "base/time/time.h"
11 #include "base/win/win_util.h"
12 #include "ui/events/event_utils.h"
13 #include "ui/events/keycodes/keyboard_code_conversion_win.h"
14 #include "ui/gfx/point.h"
15 #include "ui/gfx/win/dpi.h"
16
17 namespace ui {
18
19 namespace {
20
21 // From MSDN: "Mouse" events are flagged with 0xFF515700 if they come
22 // from a touch or stylus device.  In Vista or later, they are also flagged
23 // with 0x80 if they come from touch.
24 #define MOUSEEVENTF_FROMTOUCH (0xFF515700 | 0x80)
25
26 // Get the native mouse key state from the native event message type.
27 int GetNativeMouseKey(const base::NativeEvent& native_event) {
28   switch (native_event.message) {
29     case WM_LBUTTONDBLCLK:
30     case WM_LBUTTONDOWN:
31     case WM_LBUTTONUP:
32     case WM_NCLBUTTONDBLCLK:
33     case WM_NCLBUTTONDOWN:
34     case WM_NCLBUTTONUP:
35       return MK_LBUTTON;
36     case WM_MBUTTONDBLCLK:
37     case WM_MBUTTONDOWN:
38     case WM_MBUTTONUP:
39     case WM_NCMBUTTONDBLCLK:
40     case WM_NCMBUTTONDOWN:
41     case WM_NCMBUTTONUP:
42       return MK_MBUTTON;
43     case WM_RBUTTONDBLCLK:
44     case WM_RBUTTONDOWN:
45     case WM_RBUTTONUP:
46     case WM_NCRBUTTONDBLCLK:
47     case WM_NCRBUTTONDOWN:
48     case WM_NCRBUTTONUP:
49       return MK_RBUTTON;
50     case WM_NCXBUTTONDBLCLK:
51     case WM_NCXBUTTONDOWN:
52     case WM_NCXBUTTONUP:
53     case WM_XBUTTONDBLCLK:
54     case WM_XBUTTONDOWN:
55     case WM_XBUTTONUP:
56       return MK_XBUTTON1;
57   }
58   return 0;
59 }
60
61 bool IsButtonDown(const base::NativeEvent& native_event) {
62   return ((MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | MK_XBUTTON1 | MK_XBUTTON2) &
63           native_event.wParam) != 0;
64 }
65
66 bool IsClientMouseEvent(const base::NativeEvent& native_event) {
67   return native_event.message == WM_MOUSELEAVE ||
68          native_event.message == WM_MOUSEHOVER ||
69         (native_event.message >= WM_MOUSEFIRST &&
70          native_event.message <= WM_MOUSELAST);
71 }
72
73 bool IsNonClientMouseEvent(const base::NativeEvent& native_event) {
74   return native_event.message == WM_NCMOUSELEAVE ||
75          native_event.message == WM_NCMOUSEHOVER ||
76         (native_event.message >= WM_NCMOUSEMOVE &&
77          native_event.message <= WM_NCXBUTTONDBLCLK);
78 }
79
80 bool IsMouseWheelEvent(const base::NativeEvent& native_event) {
81   return native_event.message == WM_MOUSEWHEEL ||
82          native_event.message == WM_MOUSEHWHEEL;
83 }
84
85 bool IsKeyEvent(const base::NativeEvent& native_event) {
86   return native_event.message == WM_KEYDOWN ||
87          native_event.message == WM_SYSKEYDOWN ||
88          native_event.message == WM_CHAR ||
89          native_event.message == WM_KEYUP ||
90          native_event.message == WM_SYSKEYUP;
91 }
92
93 // Returns a mask corresponding to the set of pressed modifier keys.
94 // Checks the current global state and the state sent by client mouse messages.
95 int KeyStateFlagsFromNative(const base::NativeEvent& native_event) {
96   int flags = 0;
97   flags |= base::win::IsAltPressed() ? EF_ALT_DOWN : EF_NONE;
98   flags |= base::win::IsShiftPressed() ? EF_SHIFT_DOWN : EF_NONE;
99   flags |= base::win::IsCtrlPressed() ? EF_CONTROL_DOWN : EF_NONE;
100
101   // Check key messages for the extended key flag.
102   if (IsKeyEvent(native_event))
103     flags |= (HIWORD(native_event.lParam) & KF_EXTENDED) ? EF_EXTENDED : 0;
104
105   // Most client mouse messages include key state information.
106   if (IsClientMouseEvent(native_event)) {
107     int win_flags = GET_KEYSTATE_WPARAM(native_event.wParam);
108     flags |= (win_flags & MK_SHIFT) ? EF_SHIFT_DOWN : 0;
109     flags |= (win_flags & MK_CONTROL) ? EF_CONTROL_DOWN : 0;
110   }
111
112   return flags;
113 }
114
115 // Returns a mask corresponding to the set of pressed mouse buttons.
116 // This includes the button of the given message, even if it is being released.
117 int MouseStateFlagsFromNative(const base::NativeEvent& native_event) {
118   int win_flags = GetNativeMouseKey(native_event);
119
120   // Client mouse messages provide key states in their WPARAMs.
121   if (IsClientMouseEvent(native_event))
122     win_flags |= GET_KEYSTATE_WPARAM(native_event.wParam);
123
124   int flags = 0;
125   flags |= (win_flags & MK_LBUTTON) ? EF_LEFT_MOUSE_BUTTON : 0;
126   flags |= (win_flags & MK_MBUTTON) ? EF_MIDDLE_MOUSE_BUTTON : 0;
127   flags |= (win_flags & MK_RBUTTON) ? EF_RIGHT_MOUSE_BUTTON : 0;
128   flags |= IsNonClientMouseEvent(native_event) ? EF_IS_NON_CLIENT : 0;
129   return flags;
130 }
131
132 }  // namespace
133
134 void UpdateDeviceList() {
135   NOTIMPLEMENTED();
136 }
137
138 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
139   switch (native_event.message) {
140     case WM_KEYDOWN:
141     case WM_SYSKEYDOWN:
142     case WM_CHAR:
143       return ET_KEY_PRESSED;
144     case WM_KEYUP:
145     case WM_SYSKEYUP:
146       return ET_KEY_RELEASED;
147     case WM_LBUTTONDBLCLK:
148     case WM_LBUTTONDOWN:
149     case WM_MBUTTONDBLCLK:
150     case WM_MBUTTONDOWN:
151     case WM_NCLBUTTONDBLCLK:
152     case WM_NCLBUTTONDOWN:
153     case WM_NCMBUTTONDBLCLK:
154     case WM_NCMBUTTONDOWN:
155     case WM_NCRBUTTONDBLCLK:
156     case WM_NCRBUTTONDOWN:
157     case WM_NCXBUTTONDBLCLK:
158     case WM_NCXBUTTONDOWN:
159     case WM_RBUTTONDBLCLK:
160     case WM_RBUTTONDOWN:
161     case WM_XBUTTONDBLCLK:
162     case WM_XBUTTONDOWN:
163       return ET_MOUSE_PRESSED;
164     case WM_LBUTTONUP:
165     case WM_MBUTTONUP:
166     case WM_NCLBUTTONUP:
167     case WM_NCMBUTTONUP:
168     case WM_NCRBUTTONUP:
169     case WM_NCXBUTTONUP:
170     case WM_RBUTTONUP:
171     case WM_XBUTTONUP:
172       return ET_MOUSE_RELEASED;
173     case WM_MOUSEMOVE:
174       return IsButtonDown(native_event) ? ET_MOUSE_DRAGGED : ET_MOUSE_MOVED;
175     case WM_NCMOUSEMOVE:
176       return ET_MOUSE_MOVED;
177     case WM_MOUSEWHEEL:
178       return ET_MOUSEWHEEL;
179     case WM_MOUSELEAVE:
180     case WM_NCMOUSELEAVE:
181       return ET_MOUSE_EXITED;
182     default:
183       // We can't NOTREACHED() here, since this function can be called for any
184       // message.
185       break;
186   }
187   return ET_UNKNOWN;
188 }
189
190 int EventFlagsFromNative(const base::NativeEvent& native_event) {
191   int flags = KeyStateFlagsFromNative(native_event);
192   if (IsMouseEvent(native_event))
193     flags |= MouseStateFlagsFromNative(native_event);
194
195   return flags;
196 }
197
198 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
199   return base::TimeDelta::FromMilliseconds(native_event.time);
200 }
201
202 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
203   // Note: Wheel events are considered client, but their position is in screen
204   //       coordinates.
205   // Client message. The position is contained in the LPARAM.
206   if (IsClientMouseEvent(native_event) && !IsMouseWheelEvent(native_event))
207     return gfx::Point(native_event.lParam);
208   DCHECK(IsNonClientMouseEvent(native_event) ||
209          IsMouseWheelEvent(native_event));
210   // Non-client message. The position is contained in a POINTS structure in
211   // LPARAM, and is in screen coordinates so we have to convert to client.
212   POINT native_point = { GET_X_LPARAM(native_event.lParam),
213                          GET_Y_LPARAM(native_event.lParam) };
214   ScreenToClient(native_event.hwnd, &native_point);
215   gfx::Point location(native_point);
216   location = gfx::win::ScreenToDIPPoint(location);
217   return location;
218 }
219
220 gfx::Point EventSystemLocationFromNative(
221     const base::NativeEvent& native_event) {
222   // TODO(ben): Needs to always return screen position here. Returning normal
223   // origin for now since that's obviously wrong.
224   return gfx::Point(0, 0);
225 }
226
227 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
228   return KeyboardCodeForWindowsKeyCode(native_event.wParam);
229 }
230
231 bool IsMouseEvent(const base::NativeEvent& native_event) {
232   return IsClientMouseEvent(native_event) ||
233          IsNonClientMouseEvent(native_event);
234 }
235
236 int GetChangedMouseButtonFlagsFromNative(
237     const base::NativeEvent& native_event) {
238   switch (GetNativeMouseKey(native_event)) {
239     case MK_LBUTTON:
240       return EF_LEFT_MOUSE_BUTTON;
241     case MK_MBUTTON:
242       return EF_MIDDLE_MOUSE_BUTTON;
243     case MK_RBUTTON:
244       return EF_RIGHT_MOUSE_BUTTON;
245     // TODO: add support for MK_XBUTTON1.
246     default:
247       break;
248   }
249   return 0;
250 }
251
252 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
253   DCHECK(native_event.message == WM_MOUSEWHEEL);
254   return gfx::Vector2d(0, GET_WHEEL_DELTA_WPARAM(native_event.wParam));
255 }
256
257 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
258   NOTIMPLEMENTED();
259 }
260
261 int GetTouchId(const base::NativeEvent& xev) {
262   NOTIMPLEMENTED();
263   return 0;
264 }
265
266 float GetTouchRadiusX(const base::NativeEvent& native_event) {
267   NOTIMPLEMENTED();
268   return 1.0;
269 }
270
271 float GetTouchRadiusY(const base::NativeEvent& native_event) {
272   NOTIMPLEMENTED();
273   return 1.0;
274 }
275
276 float GetTouchAngle(const base::NativeEvent& native_event) {
277   NOTIMPLEMENTED();
278   return 0.0;
279 }
280
281 float GetTouchForce(const base::NativeEvent& native_event) {
282   NOTIMPLEMENTED();
283   return 0.0;
284 }
285
286 bool GetScrollOffsets(const base::NativeEvent& native_event,
287                       float* x_offset,
288                       float* y_offset,
289                       float* x_offset_ordinal,
290                       float* y_offset_ordinal,
291                       int* finger_count) {
292   // Not supported in Windows.
293   NOTIMPLEMENTED();
294   return false;
295 }
296
297 bool GetFlingData(const base::NativeEvent& native_event,
298                   float* vx,
299                   float* vy,
300                   float* vx_ordinal,
301                   float* vy_ordinal,
302                   bool* is_cancel) {
303   // Not supported in Windows.
304   NOTIMPLEMENTED();
305   return false;
306 }
307
308 bool GetGestureTimes(const base::NativeEvent& native_event,
309                      double* start_time,
310                      double* end_time) {
311   // Not supported in Windows.
312   *start_time = 0;
313   *end_time = 0;
314   return false;
315 }
316
317 void SetNaturalScroll(bool enabled) {
318   NOTIMPLEMENTED();
319 }
320
321 bool IsNaturalScrollEnabled() {
322   NOTIMPLEMENTED();
323   return false;
324 }
325
326 bool IsTouchpadEvent(const base::NativeEvent& event) {
327   NOTIMPLEMENTED();
328   return false;
329 }
330
331 bool IsNoopEvent(const base::NativeEvent& event) {
332   return event.message == WM_USER + 310;
333 }
334
335 base::NativeEvent CreateNoopEvent() {
336   MSG event = { NULL };
337   event.message = WM_USER + 310;
338   return event;
339 }
340
341 int GetModifiersFromACCEL(const ACCEL& accel) {
342   int modifiers = EF_NONE;
343   if (accel.fVirt & FSHIFT)
344     modifiers |= EF_SHIFT_DOWN;
345   if (accel.fVirt & FCONTROL)
346     modifiers |= EF_CONTROL_DOWN;
347   if (accel.fVirt & FALT)
348     modifiers |= EF_ALT_DOWN;
349   return modifiers;
350 }
351
352 int GetModifiersFromKeyState() {
353   int modifiers = EF_NONE;
354   if (base::win::IsShiftPressed())
355     modifiers |= EF_SHIFT_DOWN;
356   if (base::win::IsCtrlPressed())
357     modifiers |= EF_CONTROL_DOWN;
358   if (base::win::IsAltPressed())
359     modifiers |= EF_ALT_DOWN;
360   if (base::win::IsAltGrPressed())
361     modifiers |= EF_ALTGR_DOWN;
362   return modifiers;
363 }
364
365 // Windows emulates mouse messages for touch events.
366 bool IsMouseEventFromTouch(UINT message) {
367   return (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) &&
368       (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) ==
369       MOUSEEVENTF_FROMTOUCH;
370 }
371
372 }  // namespace ui