OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "views/events/event.h" | 5 #include "views/events/event.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "ui/base/keycodes/keyboard_code_conversion_win.h" | 10 #include "ui/base/keycodes/keyboard_code_conversion_win.h" |
| 11 #include "ui/base/win/event_util.h" |
11 | 12 |
12 namespace views { | 13 namespace views { |
13 | 14 |
14 namespace { | |
15 | |
16 // Returns a mask corresponding to the set of modifier keys that are currently | |
17 // pressed. Windows key messages don't come with control key state as parameters | |
18 // as with mouse messages, so we need to explicitly ask for these states. | |
19 int GetKeyStateFlags() { | |
20 int flags = 0; | |
21 flags |= (GetKeyState(VK_MENU) & 0x80)? ui::EF_ALT_DOWN : 0; | |
22 flags |= (GetKeyState(VK_SHIFT) & 0x80)? ui::EF_SHIFT_DOWN : 0; | |
23 flags |= (GetKeyState(VK_CONTROL) & 0x80)? ui::EF_CONTROL_DOWN : 0; | |
24 return flags; | |
25 } | |
26 | |
27 bool IsButtonDown(NativeEvent native_event) { | |
28 return (native_event.wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON | | |
29 MK_XBUTTON1 | MK_XBUTTON2)) != 0; | |
30 } | |
31 | |
32 // Convert windows message identifiers to Event types. | |
33 ui::EventType EventTypeFromNative(NativeEvent native_event) { | |
34 switch (native_event.message) { | |
35 case WM_KEYDOWN: | |
36 case WM_SYSKEYDOWN: | |
37 case WM_CHAR: | |
38 return ui::ET_KEY_PRESSED; | |
39 case WM_KEYUP: | |
40 case WM_SYSKEYUP: | |
41 return ui::ET_KEY_RELEASED; | |
42 case WM_LBUTTONDBLCLK: | |
43 case WM_LBUTTONDOWN: | |
44 case WM_MBUTTONDBLCLK: | |
45 case WM_MBUTTONDOWN: | |
46 case WM_NCLBUTTONDBLCLK: | |
47 case WM_NCLBUTTONDOWN: | |
48 case WM_NCMBUTTONDBLCLK: | |
49 case WM_NCMBUTTONDOWN: | |
50 case WM_NCRBUTTONDBLCLK: | |
51 case WM_NCRBUTTONDOWN: | |
52 case WM_NCXBUTTONDBLCLK: | |
53 case WM_NCXBUTTONDOWN: | |
54 case WM_RBUTTONDBLCLK: | |
55 case WM_RBUTTONDOWN: | |
56 case WM_XBUTTONDBLCLK: | |
57 case WM_XBUTTONDOWN: | |
58 return ui::ET_MOUSE_PRESSED; | |
59 case WM_LBUTTONUP: | |
60 case WM_MBUTTONUP: | |
61 case WM_NCLBUTTONUP: | |
62 case WM_NCMBUTTONUP: | |
63 case WM_NCRBUTTONUP: | |
64 case WM_NCXBUTTONUP: | |
65 case WM_RBUTTONUP: | |
66 case WM_XBUTTONUP: | |
67 return ui::ET_MOUSE_RELEASED; | |
68 case WM_MOUSEMOVE: | |
69 return IsButtonDown(native_event) ? ui::ET_MOUSE_DRAGGED : | |
70 ui::ET_MOUSE_MOVED; | |
71 case WM_NCMOUSEMOVE: | |
72 return ui::ET_MOUSE_MOVED; | |
73 case WM_MOUSEWHEEL: | |
74 return ui::ET_MOUSEWHEEL; | |
75 case WM_MOUSELEAVE: | |
76 case WM_NCMOUSELEAVE: | |
77 return ui::ET_MOUSE_EXITED; | |
78 default: | |
79 NOTREACHED(); | |
80 } | |
81 return ui::ET_UNKNOWN; | |
82 } | |
83 | |
84 // Get views::Event flags from a native Windows message | |
85 int EventFlagsFromNative(NativeEvent native_event) { | |
86 int flags = 0; | |
87 | |
88 // TODO(msw): ORing the pressed/released button into the flags is _wrong_. | |
89 // It makes it impossible to tell which button was modified when multiple | |
90 // buttons are/were held down. We need to instead put the modified button into | |
91 // a separate member on the MouseEvent, then audit all consumers of | |
92 // MouseEvents to fix them to use the resulting values correctly. | |
93 switch (native_event.message) { | |
94 case WM_LBUTTONDBLCLK: | |
95 case WM_LBUTTONDOWN: | |
96 case WM_LBUTTONUP: | |
97 case WM_NCLBUTTONDBLCLK: | |
98 case WM_NCLBUTTONDOWN: | |
99 case WM_NCLBUTTONUP: | |
100 native_event.wParam |= MK_LBUTTON; | |
101 break; | |
102 case WM_MBUTTONDBLCLK: | |
103 case WM_MBUTTONDOWN: | |
104 case WM_MBUTTONUP: | |
105 case WM_NCMBUTTONDBLCLK: | |
106 case WM_NCMBUTTONDOWN: | |
107 case WM_NCMBUTTONUP: | |
108 native_event.wParam |= MK_MBUTTON; | |
109 break; | |
110 case WM_RBUTTONDBLCLK: | |
111 case WM_RBUTTONDOWN: | |
112 case WM_RBUTTONUP: | |
113 case WM_NCRBUTTONDBLCLK: | |
114 case WM_NCRBUTTONDOWN: | |
115 case WM_NCRBUTTONUP: | |
116 native_event.wParam |= MK_RBUTTON; | |
117 break; | |
118 case WM_NCXBUTTONDBLCLK: | |
119 case WM_NCXBUTTONDOWN: | |
120 case WM_NCXBUTTONUP: | |
121 case WM_XBUTTONDBLCLK: | |
122 case WM_XBUTTONDOWN: | |
123 case WM_XBUTTONUP: | |
124 native_event.wParam |= MK_XBUTTON1; | |
125 break; | |
126 } | |
127 | |
128 // Check if the event occurred in the non-client area. | |
129 if (IsNonClientMouseEvent(native_event)) | |
130 flags |= ui::EF_IS_NON_CLIENT; | |
131 | |
132 // Check for double click events. | |
133 switch (native_event.message) { | |
134 case WM_NCLBUTTONDBLCLK: | |
135 case WM_NCMBUTTONDBLCLK: | |
136 case WM_NCRBUTTONDBLCLK: | |
137 case WM_NCXBUTTONDBLCLK: | |
138 case WM_LBUTTONDBLCLK: | |
139 case WM_MBUTTONDBLCLK: | |
140 case WM_RBUTTONDBLCLK: | |
141 case WM_XBUTTONDBLCLK: | |
142 flags |= ui::EF_IS_DOUBLE_CLICK; | |
143 break; | |
144 } | |
145 | |
146 // For non-client mouse message, the WPARAM value represents the hit test | |
147 // result, instead of the key state. | |
148 switch (native_event.message) { | |
149 case WM_NCLBUTTONDOWN: | |
150 case WM_NCLBUTTONUP: | |
151 flags |= ui::EF_LEFT_BUTTON_DOWN; | |
152 break; | |
153 case WM_NCMBUTTONDOWN: | |
154 case WM_NCMBUTTONUP: | |
155 flags |= ui::EF_MIDDLE_BUTTON_DOWN; | |
156 break; | |
157 case WM_NCRBUTTONDOWN: | |
158 case WM_NCRBUTTONUP: | |
159 flags |= ui::EF_RIGHT_BUTTON_DOWN; | |
160 break; | |
161 default: { | |
162 UINT win_flags = GET_KEYSTATE_WPARAM(native_event.wParam); | |
163 flags |= (win_flags & MK_CONTROL) ? ui::EF_CONTROL_DOWN : 0; | |
164 flags |= (win_flags & MK_SHIFT) ? ui::EF_SHIFT_DOWN : 0; | |
165 flags |= (GetKeyState(VK_MENU) < 0) ? ui::EF_ALT_DOWN : 0; | |
166 flags |= (win_flags & MK_LBUTTON) ? ui::EF_LEFT_BUTTON_DOWN : 0; | |
167 flags |= (win_flags & MK_MBUTTON) ? ui::EF_MIDDLE_BUTTON_DOWN : 0; | |
168 flags |= (win_flags & MK_RBUTTON) ? ui::EF_RIGHT_BUTTON_DOWN : 0; | |
169 break; | |
170 } | |
171 } | |
172 | |
173 return flags; | |
174 } | |
175 | |
176 } // namespace | |
177 | |
178 bool IsClientMouseEvent(const views::NativeEvent& native_event) { | |
179 return native_event.message == WM_MOUSELEAVE || | |
180 native_event.message == WM_MOUSEHOVER || | |
181 (native_event.message >= WM_MOUSEFIRST && | |
182 native_event.message <= WM_MOUSELAST); | |
183 } | |
184 | |
185 bool IsNonClientMouseEvent(const views::NativeEvent& native_event) { | |
186 return native_event.message == WM_NCMOUSELEAVE || | |
187 native_event.message == WM_NCMOUSEHOVER || | |
188 (native_event.message >= WM_NCMOUSEMOVE && | |
189 native_event.message <= WM_NCXBUTTONDBLCLK); | |
190 } | |
191 | |
192 //////////////////////////////////////////////////////////////////////////////// | |
193 // Event, public: | |
194 | |
195 int Event::GetWindowsFlags() const { | |
196 // TODO: need support for x1/x2. | |
197 int result = 0; | |
198 result |= (flags_ & ui::EF_SHIFT_DOWN) ? MK_SHIFT : 0; | |
199 result |= (flags_ & ui::EF_CONTROL_DOWN) ? MK_CONTROL : 0; | |
200 result |= (flags_ & ui::EF_LEFT_BUTTON_DOWN) ? MK_LBUTTON : 0; | |
201 result |= (flags_ & ui::EF_MIDDLE_BUTTON_DOWN) ? MK_MBUTTON : 0; | |
202 result |= (flags_ & ui::EF_RIGHT_BUTTON_DOWN) ? MK_RBUTTON : 0; | |
203 return result; | |
204 } | |
205 | |
206 //////////////////////////////////////////////////////////////////////////////// | 15 //////////////////////////////////////////////////////////////////////////////// |
207 // Event, private: | 16 // Event, private: |
208 | 17 |
209 void Event::Init() { | 18 void Event::Init() { |
210 ZeroMemory(&native_event_, sizeof(native_event_)); | 19 ZeroMemory(&native_event_, sizeof(native_event_)); |
211 native_event_2_ = NULL; | 20 native_event_2_ = NULL; |
212 } | 21 } |
213 | 22 |
214 void Event::InitWithNativeEvent(NativeEvent native_event) { | 23 void Event::InitWithNativeEvent(NativeEvent native_event) { |
215 native_event_ = native_event; | 24 native_event_ = native_event; |
216 // TODO(beng): remove once we rid views of Gtk/Gdk. | 25 // TODO(beng): remove once we rid views of Gtk/Gdk. |
217 native_event_2_ = NULL; | 26 native_event_2_ = NULL; |
218 } | 27 } |
219 | 28 |
220 void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, | 29 void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, |
221 FromNativeEvent2) { | 30 FromNativeEvent2) { |
222 // No one should ever call this on Windows. | 31 // No one should ever call this on Windows. |
223 // TODO(beng): remove once we rid views of Gtk/Gdk. | 32 // TODO(beng): remove once we rid views of Gtk/Gdk. |
224 NOTREACHED(); | 33 NOTREACHED(); |
225 native_event_2_ = NULL; | 34 native_event_2_ = NULL; |
226 } | 35 } |
227 | 36 |
228 //////////////////////////////////////////////////////////////////////////////// | 37 //////////////////////////////////////////////////////////////////////////////// |
229 // LocatedEvent, protected: | 38 // LocatedEvent, protected: |
230 | 39 |
231 LocatedEvent::LocatedEvent(NativeEvent native_event) | 40 LocatedEvent::LocatedEvent(NativeEvent native_event) |
232 : Event(native_event, EventTypeFromNative(native_event), | 41 : Event(native_event, ui::EventTypeFromNative(native_event), |
233 EventFlagsFromNative(native_event)), | 42 ui::EventFlagsFromNative(native_event)), |
234 location_(native_event.pt.x, native_event.pt.y) { | 43 location_(ui::EventLocationFromNative(native_event)) { |
235 } | 44 } |
236 | 45 |
237 LocatedEvent::LocatedEvent(NativeEvent2 native_event_2, | 46 LocatedEvent::LocatedEvent(NativeEvent2 native_event_2, |
238 FromNativeEvent2 from_native) | 47 FromNativeEvent2 from_native) |
239 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { | 48 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { |
240 // No one should ever call this on Windows. | 49 // No one should ever call this on Windows. |
241 // TODO(msw): remove once we rid views of Gtk/Gdk. | 50 // TODO(msw): remove once we rid views of Gtk/Gdk. |
242 NOTREACHED(); | 51 NOTREACHED(); |
243 } | 52 } |
244 | 53 |
245 //////////////////////////////////////////////////////////////////////////////// | 54 //////////////////////////////////////////////////////////////////////////////// |
246 // KeyEvent, public: | 55 // KeyEvent, public: |
247 | 56 |
248 KeyEvent::KeyEvent(NativeEvent native_event) | 57 KeyEvent::KeyEvent(NativeEvent native_event) |
249 : Event(native_event, | 58 : Event(native_event, |
250 EventTypeFromNative(native_event), | 59 ui::EventTypeFromNative(native_event), |
251 GetKeyStateFlags()), | 60 ui::EventFlagsFromNative(native_event)), |
252 key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)), | 61 key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)), |
253 character_(0), | 62 character_(0), |
254 unmodified_character_(0) { | 63 unmodified_character_(0) { |
255 } | 64 } |
256 | 65 |
257 KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) | 66 KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) |
258 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { | 67 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { |
259 // No one should ever call this on Windows. | 68 // No one should ever call this on Windows. |
260 // TODO(beng): remove once we rid views of Gtk/Gdk. | 69 // TODO(beng): remove once we rid views of Gtk/Gdk. |
261 NOTREACHED(); | 70 NOTREACHED(); |
(...skipping 12 matching lines...) Expand all Loading... |
274 // Looks like there is no way to get unmodified character on Windows. | 83 // Looks like there is no way to get unmodified character on Windows. |
275 return (native_event().message == WM_CHAR) ? key_code_ : | 84 return (native_event().message == WM_CHAR) ? key_code_ : |
276 GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); | 85 GetCharacterFromKeyCode(key_code_, flags() & ui::EF_SHIFT_DOWN); |
277 } | 86 } |
278 | 87 |
279 //////////////////////////////////////////////////////////////////////////////// | 88 //////////////////////////////////////////////////////////////////////////////// |
280 // MouseEvent, public: | 89 // MouseEvent, public: |
281 | 90 |
282 MouseEvent::MouseEvent(NativeEvent native_event) | 91 MouseEvent::MouseEvent(NativeEvent native_event) |
283 : LocatedEvent(native_event) { | 92 : LocatedEvent(native_event) { |
284 if (IsNonClientMouseEvent(native_event)) { | |
285 // Non-client message. The position is contained in a POINTS structure in | |
286 // LPARAM, and is in screen coordinates so we have to convert to client. | |
287 POINT native_point = location_.ToPOINT(); | |
288 ScreenToClient(native_event.hwnd, &native_point); | |
289 location_ = gfx::Point(native_point); | |
290 } | |
291 } | 93 } |
292 | 94 |
293 MouseEvent::MouseEvent(NativeEvent2 native_event_2, | 95 MouseEvent::MouseEvent(NativeEvent2 native_event_2, |
294 FromNativeEvent2 from_native) | 96 FromNativeEvent2 from_native) |
295 : LocatedEvent(native_event_2, from_native) { | 97 : LocatedEvent(native_event_2, from_native) { |
296 // No one should ever call this on Windows. | 98 // No one should ever call this on Windows. |
297 // TODO(msw): remove once we rid views of Gtk/Gdk. | 99 // TODO(msw): remove once we rid views of Gtk/Gdk. |
298 NOTREACHED(); | 100 NOTREACHED(); |
299 } | 101 } |
300 | 102 |
301 //////////////////////////////////////////////////////////////////////////////// | 103 //////////////////////////////////////////////////////////////////////////////// |
302 // MouseWheelEvent, public: | 104 // MouseWheelEvent, public: |
303 | 105 |
304 MouseWheelEvent::MouseWheelEvent(NativeEvent native_event) | 106 MouseWheelEvent::MouseWheelEvent(NativeEvent native_event) |
305 : MouseEvent(native_event), | 107 : MouseEvent(native_event), |
306 offset_(GET_WHEEL_DELTA_WPARAM(native_event.wParam)) { | 108 offset_(ui::GetMouseWheelOffset(native_event)) { |
307 } | 109 } |
308 | 110 |
309 MouseWheelEvent::MouseWheelEvent(NativeEvent2 native_event_2, | 111 MouseWheelEvent::MouseWheelEvent(NativeEvent2 native_event_2, |
310 FromNativeEvent2 from_native) | 112 FromNativeEvent2 from_native) |
311 : MouseEvent(native_event_2, from_native) { | 113 : MouseEvent(native_event_2, from_native) { |
312 // No one should ever call this on Windows. | 114 // No one should ever call this on Windows. |
313 // TODO(msw): remove once we rid views of Gtk/Gdk. | 115 // TODO(msw): remove once we rid views of Gtk/Gdk. |
314 NOTREACHED(); | 116 NOTREACHED(); |
315 } | 117 } |
316 | 118 |
317 } // namespace views | 119 } // namespace views |
OLD | NEW |