OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 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 "aura/event.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "ui/base/keycodes/keyboard_code_conversion_win.h" | |
9 | |
10 namespace aura { | |
11 | |
12 namespace { | |
13 | |
14 bool IsClientMouseEvent(const NativeEvent& native_event) { | |
15 return native_event.message == WM_MOUSELEAVE || | |
16 native_event.message == WM_MOUSEHOVER || | |
17 (native_event.message >= WM_MOUSEFIRST && | |
18 native_event.message <= WM_MOUSELAST); | |
19 } | |
20 | |
21 bool IsNonClientMouseEvent(const NativeEvent& native_event) { | |
22 return native_event.message == WM_NCMOUSELEAVE || | |
23 native_event.message == WM_NCMOUSEHOVER || | |
24 (native_event.message >= WM_NCMOUSEMOVE && | |
25 native_event.message <= WM_NCXBUTTONDBLCLK); | |
26 } | |
27 | |
28 // Returns a mask corresponding to the set of modifier keys that are currently | |
29 // pressed. Windows key messages don't come with control key state as parameters | |
30 // as with mouse messages, so we need to explicitly ask for these states. | |
31 int GetKeyStateFlags() { | |
32 int flags = 0; | |
33 flags |= (GetKeyState(VK_MENU) & 0x80)? ui::EF_ALT_DOWN : 0; | |
34 flags |= (GetKeyState(VK_SHIFT) & 0x80)? ui::EF_SHIFT_DOWN : 0; | |
35 flags |= (GetKeyState(VK_CONTROL) & 0x80)? ui::EF_CONTROL_DOWN : 0; | |
36 return flags; | |
37 } | |
38 | |
39 bool IsButtonDown(NativeEvent native_event) { | |
40 return (native_event.wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | | |
41 MK_XBUTTON1 | MK_XBUTTON2)) != 0; | |
42 } | |
43 | |
44 // Convert windows message identifiers to Event types. | |
45 ui::EventType EventTypeFromNative(NativeEvent native_event) { | |
46 switch (native_event.message) { | |
47 case WM_KEYDOWN: | |
48 case WM_SYSKEYDOWN: | |
49 case WM_CHAR: | |
50 return ui::ET_KEY_PRESSED; | |
51 case WM_KEYUP: | |
52 case WM_SYSKEYUP: | |
53 return ui::ET_KEY_RELEASED; | |
54 case WM_LBUTTONDBLCLK: | |
55 case WM_LBUTTONDOWN: | |
56 case WM_MBUTTONDBLCLK: | |
57 case WM_MBUTTONDOWN: | |
58 case WM_NCLBUTTONDBLCLK: | |
59 case WM_NCLBUTTONDOWN: | |
60 case WM_NCMBUTTONDBLCLK: | |
61 case WM_NCMBUTTONDOWN: | |
62 case WM_NCRBUTTONDBLCLK: | |
63 case WM_NCRBUTTONDOWN: | |
64 case WM_NCXBUTTONDBLCLK: | |
65 case WM_NCXBUTTONDOWN: | |
66 case WM_RBUTTONDBLCLK: | |
67 case WM_RBUTTONDOWN: | |
68 case WM_XBUTTONDBLCLK: | |
69 case WM_XBUTTONDOWN: | |
70 return ui::ET_MOUSE_PRESSED; | |
71 case WM_LBUTTONUP: | |
72 case WM_MBUTTONUP: | |
73 case WM_NCLBUTTONUP: | |
74 case WM_NCMBUTTONUP: | |
75 case WM_NCRBUTTONUP: | |
76 case WM_NCXBUTTONUP: | |
77 case WM_RBUTTONUP: | |
78 case WM_XBUTTONUP: | |
79 return ui::ET_MOUSE_RELEASED; | |
80 case WM_MOUSEMOVE: | |
81 return IsButtonDown(native_event) ? ui::ET_MOUSE_DRAGGED : | |
82 ui::ET_MOUSE_MOVED; | |
83 case WM_NCMOUSEMOVE: | |
84 return ui::ET_MOUSE_MOVED; | |
85 case WM_MOUSEWHEEL: | |
86 return ui::ET_MOUSEWHEEL; | |
87 case WM_MOUSELEAVE: | |
88 case WM_NCMOUSELEAVE: | |
89 return ui::ET_MOUSE_EXITED; | |
90 default: | |
91 NOTREACHED(); | |
92 } | |
93 return ui::ET_UNKNOWN; | |
94 } | |
95 | |
96 // Get views::Event flags from a native Windows message | |
97 int EventFlagsFromNative(NativeEvent native_event) { | |
98 int flags = 0; | |
99 | |
100 // TODO(msw): ORing the pressed/released button into the flags is _wrong_. | |
101 // It makes it impossible to tell which button was modified when multiple | |
102 // buttons are/were held down. We need to instead put the modified button into | |
103 // a separate member on the MouseEvent, then audit all consumers of | |
104 // MouseEvents to fix them to use the resulting values correctly. | |
105 switch (native_event.message) { | |
106 case WM_LBUTTONDBLCLK: | |
107 case WM_LBUTTONDOWN: | |
108 case WM_LBUTTONUP: | |
109 case WM_NCLBUTTONDBLCLK: | |
110 case WM_NCLBUTTONDOWN: | |
111 case WM_NCLBUTTONUP: | |
112 native_event.wParam |= MK_LBUTTON; | |
113 break; | |
114 case WM_MBUTTONDBLCLK: | |
115 case WM_MBUTTONDOWN: | |
116 case WM_MBUTTONUP: | |
117 case WM_NCMBUTTONDBLCLK: | |
118 case WM_NCMBUTTONDOWN: | |
119 case WM_NCMBUTTONUP: | |
120 native_event.wParam |= MK_MBUTTON; | |
121 break; | |
122 case WM_RBUTTONDBLCLK: | |
123 case WM_RBUTTONDOWN: | |
124 case WM_RBUTTONUP: | |
125 case WM_NCRBUTTONDBLCLK: | |
126 case WM_NCRBUTTONDOWN: | |
127 case WM_NCRBUTTONUP: | |
128 native_event.wParam |= MK_RBUTTON; | |
129 break; | |
130 case WM_NCXBUTTONDBLCLK: | |
131 case WM_NCXBUTTONDOWN: | |
132 case WM_NCXBUTTONUP: | |
133 case WM_XBUTTONDBLCLK: | |
134 case WM_XBUTTONDOWN: | |
135 case WM_XBUTTONUP: | |
136 native_event.wParam |= MK_XBUTTON1; | |
137 break; | |
138 } | |
139 | |
140 // Check if the event occurred in the non-client area. | |
141 if (IsNonClientMouseEvent(native_event)) | |
142 flags |= ui::EF_IS_NON_CLIENT; | |
143 | |
144 // Check for double click events. | |
145 switch (native_event.message) { | |
146 case WM_NCLBUTTONDBLCLK: | |
147 case WM_NCMBUTTONDBLCLK: | |
148 case WM_NCRBUTTONDBLCLK: | |
149 case WM_NCXBUTTONDBLCLK: | |
150 case WM_LBUTTONDBLCLK: | |
151 case WM_MBUTTONDBLCLK: | |
152 case WM_RBUTTONDBLCLK: | |
153 case WM_XBUTTONDBLCLK: | |
154 flags |= ui::EF_IS_DOUBLE_CLICK; | |
155 break; | |
156 } | |
157 | |
158 // For non-client mouse message, the WPARAM value represents the hit test | |
159 // result, instead of the key state. | |
160 switch (native_event.message) { | |
161 case WM_NCLBUTTONDOWN: | |
162 case WM_NCLBUTTONUP: | |
163 flags |= ui::EF_LEFT_BUTTON_DOWN; | |
164 break; | |
165 case WM_NCMBUTTONDOWN: | |
166 case WM_NCMBUTTONUP: | |
167 flags |= ui::EF_MIDDLE_BUTTON_DOWN; | |
168 break; | |
169 case WM_NCRBUTTONDOWN: | |
170 case WM_NCRBUTTONUP: | |
171 flags |= ui::EF_RIGHT_BUTTON_DOWN; | |
172 break; | |
173 default: { | |
174 UINT win_flags = GET_KEYSTATE_WPARAM(native_event.wParam); | |
175 flags |= (win_flags & MK_CONTROL) ? ui::EF_CONTROL_DOWN : 0; | |
176 flags |= (win_flags & MK_SHIFT) ? ui::EF_SHIFT_DOWN : 0; | |
177 flags |= (GetKeyState(VK_MENU) < 0) ? ui::EF_ALT_DOWN : 0; | |
178 flags |= (win_flags & MK_LBUTTON) ? ui::EF_LEFT_BUTTON_DOWN : 0; | |
179 flags |= (win_flags & MK_MBUTTON) ? ui::EF_MIDDLE_BUTTON_DOWN : 0; | |
180 flags |= (win_flags & MK_RBUTTON) ? ui::EF_RIGHT_BUTTON_DOWN : 0; | |
181 break; | |
182 } | |
183 } | |
184 | |
185 return flags; | |
186 } | |
187 | |
188 } // namespace | |
189 | |
190 void Event::Init() { | |
191 ZeroMemory(&native_event_, sizeof(native_event_)); | |
192 } | |
193 | |
194 void Event::InitWithNativeEvent(NativeEvent native_event) { | |
195 native_event_ = native_event; | |
196 } | |
197 | |
198 LocatedEvent::LocatedEvent(NativeEvent native_event) | |
199 : Event(native_event, EventTypeFromNative(native_event), | |
200 EventFlagsFromNative(native_event)), | |
201 location_(native_event.pt.x, native_event.pt.y) { | |
202 } | |
203 | |
204 MouseEvent::MouseEvent(NativeEvent native_event) | |
205 : LocatedEvent(native_event) { | |
206 if (IsNonClientMouseEvent(native_event)) { | |
207 // Non-client message. The position is contained in a POINTS structure in | |
208 // LPARAM, and is in screen coordinates so we have to convert to client. | |
209 POINT native_point = location_.ToPOINT(); | |
210 ScreenToClient(native_event.hwnd, &native_point); | |
211 location_ = gfx::Point(native_point); | |
212 } | |
213 } | |
214 | |
215 KeyEvent::KeyEvent(NativeEvent native_event) | |
216 : Event(native_event, | |
217 EventTypeFromNative(native_event), | |
218 GetKeyStateFlags()), | |
219 key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)) { | |
220 } | |
221 | |
222 } // namespace aura | |
OLD | NEW |