Add ICU message format support
[chromium-blink-merge.git] / ui / events / win / events_win.cc
blob81d290b9bf9a3bec43fc3a48d7dd51ab12d7d904
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.
5 #include <windowsx.h>
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/geometry/point.h"
15 #include "ui/gfx/win/dpi.h"
17 namespace ui {
19 namespace {
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:
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;
58 return 0;
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 IsMouseEvent(const base::NativeEvent& native_event) {
81 return IsClientMouseEvent(native_event) ||
82 IsNonClientMouseEvent(native_event);
85 bool IsMouseWheelEvent(const base::NativeEvent& native_event) {
86 return native_event.message == WM_MOUSEWHEEL ||
87 native_event.message == WM_MOUSEHWHEEL;
90 bool IsKeyEvent(const base::NativeEvent& native_event) {
91 return native_event.message == WM_KEYDOWN ||
92 native_event.message == WM_SYSKEYDOWN ||
93 native_event.message == WM_CHAR ||
94 native_event.message == WM_KEYUP ||
95 native_event.message == WM_SYSKEYUP;
98 bool IsScrollEvent(const base::NativeEvent& native_event) {
99 return native_event.message == WM_VSCROLL ||
100 native_event.message == WM_HSCROLL;
103 // Returns a mask corresponding to the set of pressed modifier keys.
104 // Checks the current global state and the state sent by client mouse messages.
105 int KeyStateFlagsFromNative(const base::NativeEvent& native_event) {
106 int flags = 0;
107 flags |= base::win::IsAltPressed() ? EF_ALT_DOWN : EF_NONE;
108 flags |= base::win::IsShiftPressed() ? EF_SHIFT_DOWN : EF_NONE;
109 flags |= base::win::IsCtrlPressed() ? EF_CONTROL_DOWN : EF_NONE;
111 // Check key messages for the extended key flag.
112 if (IsKeyEvent(native_event))
113 flags |= (HIWORD(native_event.lParam) & KF_EXTENDED) ? EF_EXTENDED : 0;
115 // Most client mouse messages include key state information.
116 if (IsClientMouseEvent(native_event)) {
117 int win_flags = GET_KEYSTATE_WPARAM(native_event.wParam);
118 flags |= (win_flags & MK_SHIFT) ? EF_SHIFT_DOWN : 0;
119 flags |= (win_flags & MK_CONTROL) ? EF_CONTROL_DOWN : 0;
122 return flags;
125 // Returns a mask corresponding to the set of pressed mouse buttons.
126 // This includes the button of the given message, even if it is being released.
127 int MouseStateFlagsFromNative(const base::NativeEvent& native_event) {
128 int win_flags = GetNativeMouseKey(native_event);
130 // Client mouse messages provide key states in their WPARAMs.
131 if (IsClientMouseEvent(native_event))
132 win_flags |= GET_KEYSTATE_WPARAM(native_event.wParam);
134 int flags = 0;
135 flags |= (win_flags & MK_LBUTTON) ? EF_LEFT_MOUSE_BUTTON : 0;
136 flags |= (win_flags & MK_MBUTTON) ? EF_MIDDLE_MOUSE_BUTTON : 0;
137 flags |= (win_flags & MK_RBUTTON) ? EF_RIGHT_MOUSE_BUTTON : 0;
138 flags |= IsNonClientMouseEvent(native_event) ? EF_IS_NON_CLIENT : 0;
139 return flags;
142 } // namespace
144 void UpdateDeviceList() {
145 NOTIMPLEMENTED();
148 EventType EventTypeFromNative(const base::NativeEvent& native_event) {
149 switch (native_event.message) {
150 case WM_KEYDOWN:
151 case WM_SYSKEYDOWN:
152 case WM_CHAR:
153 return ET_KEY_PRESSED;
154 // The WM_DEADCHAR message is posted to the window with the keyboard focus
155 // when a WM_KEYUP message is translated. This happens for special keyboard
156 // sequences.
157 case WM_DEADCHAR:
158 case WM_KEYUP:
159 // The WM_SYSDEADCHAR message is posted to a window with keyboard focus
160 // when the WM_SYSKEYDOWN message is translated by the TranslateMessage
161 // function. It specifies the character code of the system dead key.
162 case WM_SYSDEADCHAR:
163 case WM_SYSKEYUP:
164 return ET_KEY_RELEASED;
165 case WM_LBUTTONDBLCLK:
166 case WM_LBUTTONDOWN:
167 case WM_MBUTTONDBLCLK:
168 case WM_MBUTTONDOWN:
169 case WM_NCLBUTTONDBLCLK:
170 case WM_NCLBUTTONDOWN:
171 case WM_NCMBUTTONDBLCLK:
172 case WM_NCMBUTTONDOWN:
173 case WM_NCRBUTTONDBLCLK:
174 case WM_NCRBUTTONDOWN:
175 case WM_NCXBUTTONDBLCLK:
176 case WM_NCXBUTTONDOWN:
177 case WM_RBUTTONDBLCLK:
178 case WM_RBUTTONDOWN:
179 case WM_XBUTTONDBLCLK:
180 case WM_XBUTTONDOWN:
181 return ET_MOUSE_PRESSED;
182 case WM_LBUTTONUP:
183 case WM_MBUTTONUP:
184 case WM_NCLBUTTONUP:
185 case WM_NCMBUTTONUP:
186 case WM_NCRBUTTONUP:
187 case WM_NCXBUTTONUP:
188 case WM_RBUTTONUP:
189 case WM_XBUTTONUP:
190 return ET_MOUSE_RELEASED;
191 case WM_MOUSEMOVE:
192 return IsButtonDown(native_event) ? ET_MOUSE_DRAGGED : ET_MOUSE_MOVED;
193 case WM_NCMOUSEMOVE:
194 return ET_MOUSE_MOVED;
195 case WM_MOUSEWHEEL:
196 case WM_MOUSEHWHEEL:
197 return ET_MOUSEWHEEL;
198 case WM_MOUSELEAVE:
199 case WM_NCMOUSELEAVE:
200 return ET_MOUSE_EXITED;
201 case WM_VSCROLL:
202 case WM_HSCROLL:
203 return ET_SCROLL;
204 default:
205 // We can't NOTREACHED() here, since this function can be called for any
206 // message.
207 break;
209 return ET_UNKNOWN;
212 int EventFlagsFromNative(const base::NativeEvent& native_event) {
213 int flags = KeyStateFlagsFromNative(native_event);
214 if (IsMouseEvent(native_event))
215 flags |= MouseStateFlagsFromNative(native_event);
217 return flags;
220 base::TimeDelta EventTimeFromNative(const base::NativeEvent& native_event) {
221 return base::TimeDelta::FromMilliseconds(native_event.time);
224 gfx::Point EventLocationFromNative(const base::NativeEvent& native_event) {
225 POINT native_point;
226 if ((native_event.message == WM_MOUSELEAVE ||
227 native_event.message == WM_NCMOUSELEAVE) ||
228 IsScrollEvent(native_event)) {
229 // These events have no coordinates. For sanity with rest of events grab
230 // coordinates from the OS.
231 ::GetCursorPos(&native_point);
232 } else if (IsClientMouseEvent(native_event) &&
233 !IsMouseWheelEvent(native_event)) {
234 // Note: Wheel events are considered client, but their position is in screen
235 // coordinates.
236 // Client message. The position is contained in the LPARAM.
237 return gfx::Point(native_event.lParam);
238 } else {
239 DCHECK(IsNonClientMouseEvent(native_event) ||
240 IsMouseWheelEvent(native_event) || IsScrollEvent(native_event));
241 // Non-client message. The position is contained in a POINTS structure in
242 // LPARAM, and is in screen coordinates so we have to convert to client.
243 native_point.x = GET_X_LPARAM(native_event.lParam);
244 native_point.y = GET_Y_LPARAM(native_event.lParam);
246 ScreenToClient(native_event.hwnd, &native_point);
247 return gfx::Point(native_point);
250 gfx::Point EventSystemLocationFromNative(
251 const base::NativeEvent& native_event) {
252 POINT global_point = { static_cast<short>(LOWORD(native_event.lParam)),
253 static_cast<short>(HIWORD(native_event.lParam)) };
254 ClientToScreen(native_event.hwnd, &global_point);
255 return gfx::Point(global_point);
258 KeyboardCode KeyboardCodeFromNative(const base::NativeEvent& native_event) {
259 return KeyboardCodeForWindowsKeyCode(static_cast<WORD>(native_event.wParam));
262 DomCode CodeFromNative(const base::NativeEvent& native_event) {
263 const uint16 scan_code = GetScanCodeFromLParam(native_event.lParam);
264 return CodeForWindowsScanCode(scan_code);
267 uint32 PlatformKeycodeFromNative(const base::NativeEvent& native_event) {
268 return static_cast<uint32>(native_event.wParam);
271 bool IsCharFromNative(const base::NativeEvent& native_event) {
272 return native_event.message == WM_CHAR;
275 int GetChangedMouseButtonFlagsFromNative(
276 const base::NativeEvent& native_event) {
277 switch (GetNativeMouseKey(native_event)) {
278 case MK_LBUTTON:
279 return EF_LEFT_MOUSE_BUTTON;
280 case MK_MBUTTON:
281 return EF_MIDDLE_MOUSE_BUTTON;
282 case MK_RBUTTON:
283 return EF_RIGHT_MOUSE_BUTTON;
284 // TODO: add support for MK_XBUTTON1.
285 default:
286 break;
288 return 0;
291 gfx::Vector2d GetMouseWheelOffset(const base::NativeEvent& native_event) {
292 DCHECK(native_event.message == WM_MOUSEWHEEL ||
293 native_event.message == WM_MOUSEHWHEEL);
294 if (native_event.message == WM_MOUSEWHEEL)
295 return gfx::Vector2d(0, GET_WHEEL_DELTA_WPARAM(native_event.wParam));
296 return gfx::Vector2d(GET_WHEEL_DELTA_WPARAM(native_event.wParam), 0);
299 base::NativeEvent CopyNativeEvent(const base::NativeEvent& event) {
300 return event;
303 void ReleaseCopiedNativeEvent(const base::NativeEvent& event) {
306 void ClearTouchIdIfReleased(const base::NativeEvent& xev) {
307 NOTIMPLEMENTED();
310 int GetTouchId(const base::NativeEvent& xev) {
311 NOTIMPLEMENTED();
312 return 0;
315 float GetTouchRadiusX(const base::NativeEvent& native_event) {
316 NOTIMPLEMENTED();
317 return 1.0;
320 float GetTouchRadiusY(const base::NativeEvent& native_event) {
321 NOTIMPLEMENTED();
322 return 1.0;
325 float GetTouchAngle(const base::NativeEvent& native_event) {
326 NOTIMPLEMENTED();
327 return 0.0;
330 float GetTouchForce(const base::NativeEvent& native_event) {
331 NOTIMPLEMENTED();
332 return 0.0;
335 bool GetScrollOffsets(const base::NativeEvent& native_event,
336 float* x_offset,
337 float* y_offset,
338 float* x_offset_ordinal,
339 float* y_offset_ordinal,
340 int* finger_count) {
341 // TODO(ananta)
342 // Support retrieving the scroll offsets from the scroll event.
343 if (native_event.message == WM_VSCROLL || native_event.message == WM_HSCROLL)
344 return true;
345 return false;
348 bool GetFlingData(const base::NativeEvent& native_event,
349 float* vx,
350 float* vy,
351 float* vx_ordinal,
352 float* vy_ordinal,
353 bool* is_cancel) {
354 // Not supported in Windows.
355 NOTIMPLEMENTED();
356 return false;
359 int GetModifiersFromACCEL(const ACCEL& accel) {
360 int modifiers = EF_NONE;
361 if (accel.fVirt & FSHIFT)
362 modifiers |= EF_SHIFT_DOWN;
363 if (accel.fVirt & FCONTROL)
364 modifiers |= EF_CONTROL_DOWN;
365 if (accel.fVirt & FALT)
366 modifiers |= EF_ALT_DOWN;
367 return modifiers;
370 int GetModifiersFromKeyState() {
371 int modifiers = EF_NONE;
372 if (base::win::IsShiftPressed())
373 modifiers |= EF_SHIFT_DOWN;
374 if (base::win::IsCtrlPressed())
375 modifiers |= EF_CONTROL_DOWN;
376 if (base::win::IsAltPressed())
377 modifiers |= EF_ALT_DOWN;
378 if (base::win::IsAltGrPressed())
379 modifiers |= EF_ALTGR_DOWN;
380 return modifiers;
383 // Windows emulates mouse messages for touch events.
384 bool IsMouseEventFromTouch(UINT message) {
385 return (message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST) &&
386 (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) ==
387 MOUSEEVENTF_FROMTOUCH;
390 // Conversion scan_code and LParam each other.
391 // uint16 scan_code:
392 // ui/events/keycodes/dom/keycode_converter_data.inc
393 // 0 - 15bits: represetns the scan code.
394 // 28 - 30 bits (0xE000): represents whether this is an extended key or not.
396 // LPARAM lParam:
397 // http://msdn.microsoft.com/en-us/library/windows/desktop/ms644984.aspx
398 // 16 - 23bits: represetns the scan code.
399 // 24bit (0x0100): represents whether this is an extended key or not.
400 uint16 GetScanCodeFromLParam(LPARAM l_param) {
401 uint16 scan_code = ((l_param >> 16) & 0x00FF);
402 if (l_param & (1 << 24))
403 scan_code |= 0xE000;
404 return scan_code;
407 LPARAM GetLParamFromScanCode(uint16 scan_code) {
408 LPARAM l_param = static_cast<LPARAM>(scan_code & 0x00FF) << 16;
409 if ((scan_code & 0xE000) == 0xE000)
410 l_param |= (1 << 24);
411 return l_param;
414 } // namespace ui