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.
7 #include "ui/events/event_constants.h"
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"
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)
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:
32 case WM_NCLBUTTONDBLCLK:
33 case WM_NCLBUTTONDOWN:
36 case WM_MBUTTONDBLCLK:
39 case WM_NCMBUTTONDBLCLK:
40 case WM_NCMBUTTONDOWN:
43 case WM_RBUTTONDBLCLK:
46 case WM_NCRBUTTONDBLCLK:
47 case WM_NCRBUTTONDOWN:
50 case WM_NCXBUTTONDBLCLK:
51 case WM_NCXBUTTONDOWN:
53 case WM_XBUTTONDBLCLK:
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;
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);
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);
80 bool IsMouseWheelEvent(const base::NativeEvent& native_event) {
81 return native_event.message == WM_MOUSEWHEEL ||
82 native_event.message == WM_MOUSEHWHEEL;
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;
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) {
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;
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;
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;
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);
120 // Client mouse messages provide key states in their WPARAMs.
121 if (IsClientMouseEvent(native_event))
122 win_flags |= GET_KEYSTATE_WPARAM(native_event.wParam);
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;
134 void UpdateDeviceList() {
138 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
139 switch (native_event.message) {
143 return ET_KEY_PRESSED;
146 return ET_KEY_RELEASED;
147 case WM_LBUTTONDBLCLK:
149 case WM_MBUTTONDBLCLK:
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:
161 case WM_XBUTTONDBLCLK:
163 return ET_MOUSE_PRESSED;
172 return ET_MOUSE_RELEASED;
174 return IsButtonDown(native_event) ? ET_MOUSE_DRAGGED : ET_MOUSE_MOVED;
176 return ET_MOUSE_MOVED;
178 return ET_MOUSEWHEEL;
180 case WM_NCMOUSELEAVE:
181 return ET_MOUSE_EXITED;
183 // We can't NOTREACHED() here, since this function can be called for any
190 int EventFlagsFromNative(const base::NativeEvent& native_event) {
191 int flags = KeyStateFlagsFromNative(native_event);
192 if (IsMouseEvent(native_event))
193 flags |= MouseStateFlagsFromNative(native_event);
198 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
199 return base::TimeDelta::FromMilliseconds(native_event.time);
202 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
203 // Note: Wheel events are considered client, but their position is in screen
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);
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);
227 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
228 return KeyboardCodeForWindowsKeyCode(native_event.wParam);
231 bool IsMouseEvent(const base::NativeEvent& native_event) {
232 return IsClientMouseEvent(native_event) ||
233 IsNonClientMouseEvent(native_event);
236 int GetChangedMouseButtonFlagsFromNative(
237 const base::NativeEvent& native_event) {
238 switch (GetNativeMouseKey(native_event)) {
240 return EF_LEFT_MOUSE_BUTTON;
242 return EF_MIDDLE_MOUSE_BUTTON;
244 return EF_RIGHT_MOUSE_BUTTON;
245 // TODO: add support for MK_XBUTTON1.
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));
257 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
261 int GetTouchId(const base::NativeEvent& xev) {
266 float GetTouchRadiusX(const base::NativeEvent& native_event) {
271 float GetTouchRadiusY(const base::NativeEvent& native_event) {
276 float GetTouchAngle(const base::NativeEvent& native_event) {
281 float GetTouchForce(const base::NativeEvent& native_event) {
286 bool GetScrollOffsets(const base::NativeEvent& native_event,
289 float* x_offset_ordinal,
290 float* y_offset_ordinal,
292 // Not supported in Windows.
297 bool GetFlingData(const base::NativeEvent& native_event,
303 // Not supported in Windows.
308 bool GetGestureTimes(const base::NativeEvent& native_event,
311 // Not supported in Windows.
317 void SetNaturalScroll(bool enabled) {
321 bool IsNaturalScrollEnabled() {
326 bool IsTouchpadEvent(const base::NativeEvent& event) {
331 bool IsNoopEvent(const base::NativeEvent& event) {
332 return event.message == WM_USER + 310;
335 base::NativeEvent CreateNoopEvent() {
336 MSG event = { NULL };
337 event.message = WM_USER + 310;
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;
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;
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;