| OLD | NEW |
| (Empty) |
| 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 | |
| OLD | NEW |