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 | 11 |
12 namespace views { | 12 namespace views { |
13 | 13 |
14 namespace { | 14 namespace { |
15 | 15 |
16 // Returns a mask corresponding to the set of modifier keys that are currently | 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 | 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. | 18 // as with mouse messages, so we need to explicitly ask for these states. |
19 int GetKeyStateFlags() { | 19 int GetKeyStateFlags() { |
20 int flags = 0; | 20 int flags = 0; |
21 if (GetKeyState(VK_MENU) & 0x80) | 21 flags |= (GetKeyState(VK_MENU) & 0x80)? ui::EF_ALT_DOWN : 0; |
22 flags |= ui::EF_ALT_DOWN; | 22 flags |= (GetKeyState(VK_SHIFT) & 0x80)? ui::EF_SHIFT_DOWN : 0; |
23 if (GetKeyState(VK_SHIFT) & 0x80) | 23 flags |= (GetKeyState(VK_CONTROL) & 0x80)? ui::EF_CONTROL_DOWN : 0; |
24 flags |= ui::EF_SHIFT_DOWN; | |
25 if (GetKeyState(VK_CONTROL) & 0x80) | |
26 flags |= ui::EF_CONTROL_DOWN; | |
27 return flags; | 24 return flags; |
28 } | 25 } |
29 | 26 |
30 // Convert windows message identifiers to Event types. | 27 // Convert windows message identifiers to Event types. |
31 ui::EventType EventTypeFromNative(NativeEvent native_event) { | 28 ui::EventType EventTypeFromNative(NativeEvent native_event) { |
32 switch (native_event.message) { | 29 switch (native_event.message) { |
33 case WM_KEYDOWN: | 30 case WM_KEYDOWN: |
34 case WM_SYSKEYDOWN: | 31 case WM_SYSKEYDOWN: |
35 case WM_CHAR: | 32 case WM_CHAR: |
36 return ui::ET_KEY_PRESSED; | 33 return ui::ET_KEY_PRESSED; |
(...skipping 27 matching lines...) Expand all Loading... |
64 return ui::ET_MOUSEWHEEL; | 61 return ui::ET_MOUSEWHEEL; |
65 case WM_MOUSELEAVE: | 62 case WM_MOUSELEAVE: |
66 case WM_NCMOUSELEAVE: | 63 case WM_NCMOUSELEAVE: |
67 return ui::ET_MOUSE_EXITED; | 64 return ui::ET_MOUSE_EXITED; |
68 default: | 65 default: |
69 NOTREACHED(); | 66 NOTREACHED(); |
70 } | 67 } |
71 return ui::ET_UNKNOWN; | 68 return ui::ET_UNKNOWN; |
72 } | 69 } |
73 | 70 |
74 int GetFlagsFromNative(NativeEvent native_event) { | 71 bool IsClientMouseEvent(NativeEvent native_event) { |
75 // Allow other applicable messages as necessary. | 72 return native_event.message == WM_MOUSELEAVE || |
76 DCHECK(native_event.message == WM_MOUSEWHEEL); | 73 native_event.message == WM_MOUSEHOVER || |
77 return Event::ConvertWindowsFlags(GET_KEYSTATE_WPARAM(native_event.wParam)); | 74 (native_event.message >= WM_MOUSEFIRST && |
| 75 native_event.message <= WM_MOUSELAST); |
| 76 } |
| 77 |
| 78 bool IsNonClientMouseEvent(NativeEvent native_event) { |
| 79 return native_event.message == WM_NCMOUSELEAVE || |
| 80 native_event.message == WM_NCMOUSEHOVER || |
| 81 (native_event.message >= WM_NCMOUSEMOVE && |
| 82 native_event.message <= WM_NCXBUTTONDBLCLK); |
| 83 } |
| 84 |
| 85 // Get views::Event flags from a native Windows message |
| 86 int EventFlagsFromNative(NativeEvent native_event) { |
| 87 int flags = 0; |
| 88 |
| 89 // TODO(msw): ORing the pressed/released button into the flags is _wrong_. |
| 90 // It makes it impossible to tell which button was modified when multiple |
| 91 // buttons are/were held down. We need to instead put the modified button into |
| 92 // a separate member on the MouseEvent, then audit all consumers of |
| 93 // MouseEvents to fix them to use the resulting values correctly. |
| 94 switch (native_event.message) { |
| 95 case WM_LBUTTONDBLCLK: |
| 96 case WM_LBUTTONDOWN: |
| 97 case WM_LBUTTONUP: |
| 98 case WM_NCLBUTTONDBLCLK: |
| 99 case WM_NCLBUTTONDOWN: |
| 100 case WM_NCLBUTTONUP: |
| 101 native_event.wParam |= MK_LBUTTON; |
| 102 break; |
| 103 case WM_MBUTTONDBLCLK: |
| 104 case WM_MBUTTONDOWN: |
| 105 case WM_MBUTTONUP: |
| 106 case WM_NCMBUTTONDBLCLK: |
| 107 case WM_NCMBUTTONDOWN: |
| 108 case WM_NCMBUTTONUP: |
| 109 native_event.wParam |= MK_MBUTTON; |
| 110 break; |
| 111 case WM_RBUTTONDBLCLK: |
| 112 case WM_RBUTTONDOWN: |
| 113 case WM_RBUTTONUP: |
| 114 case WM_NCRBUTTONDBLCLK: |
| 115 case WM_NCRBUTTONDOWN: |
| 116 case WM_NCRBUTTONUP: |
| 117 native_event.wParam |= MK_RBUTTON; |
| 118 break; |
| 119 } |
| 120 |
| 121 // Check if the event occurred in the non-client area. |
| 122 if (IsNonClientMouseEvent(native_event)) |
| 123 flags |= ui::EF_IS_NON_CLIENT; |
| 124 |
| 125 // Check for double click events. |
| 126 switch (native_event.message) { |
| 127 case WM_NCLBUTTONDBLCLK: |
| 128 case WM_NCMBUTTONDBLCLK: |
| 129 case WM_NCRBUTTONDBLCLK: |
| 130 case WM_LBUTTONDBLCLK: |
| 131 case WM_MBUTTONDBLCLK: |
| 132 case WM_RBUTTONDBLCLK: |
| 133 flags |= ui::EF_IS_DOUBLE_CLICK; |
| 134 break; |
| 135 } |
| 136 |
| 137 UINT win_flags = GET_KEYSTATE_WPARAM(native_event.wParam); |
| 138 flags |= (win_flags & MK_CONTROL) ? ui::EF_CONTROL_DOWN : 0; |
| 139 flags |= (win_flags & MK_SHIFT) ? ui::EF_SHIFT_DOWN : 0; |
| 140 flags |= (GetKeyState(VK_MENU) < 0) ? ui::EF_ALT_DOWN : 0; |
| 141 flags |= (win_flags & MK_LBUTTON) ? ui::EF_LEFT_BUTTON_DOWN : 0; |
| 142 flags |= (win_flags & MK_MBUTTON) ? ui::EF_MIDDLE_BUTTON_DOWN : 0; |
| 143 flags |= (win_flags & MK_RBUTTON) ? ui::EF_RIGHT_BUTTON_DOWN : 0; |
| 144 |
| 145 return flags; |
78 } | 146 } |
79 | 147 |
80 } // namespace | 148 } // namespace |
81 | 149 |
82 //////////////////////////////////////////////////////////////////////////////// | 150 //////////////////////////////////////////////////////////////////////////////// |
83 // Event, public: | 151 // Event, public: |
84 | 152 |
85 int Event::GetWindowsFlags() const { | 153 int Event::GetWindowsFlags() const { |
86 // TODO: need support for x1/x2. | 154 // TODO: need support for x1/x2. |
87 int result = 0; | 155 int result = 0; |
88 result |= (flags_ & ui::EF_SHIFT_DOWN) ? MK_SHIFT : 0; | 156 result |= (flags_ & ui::EF_SHIFT_DOWN) ? MK_SHIFT : 0; |
89 result |= (flags_ & ui::EF_CONTROL_DOWN) ? MK_CONTROL : 0; | 157 result |= (flags_ & ui::EF_CONTROL_DOWN) ? MK_CONTROL : 0; |
90 result |= (flags_ & ui::EF_LEFT_BUTTON_DOWN) ? MK_LBUTTON : 0; | 158 result |= (flags_ & ui::EF_LEFT_BUTTON_DOWN) ? MK_LBUTTON : 0; |
91 result |= (flags_ & ui::EF_MIDDLE_BUTTON_DOWN) ? MK_MBUTTON : 0; | 159 result |= (flags_ & ui::EF_MIDDLE_BUTTON_DOWN) ? MK_MBUTTON : 0; |
92 result |= (flags_ & ui::EF_RIGHT_BUTTON_DOWN) ? MK_RBUTTON : 0; | 160 result |= (flags_ & ui::EF_RIGHT_BUTTON_DOWN) ? MK_RBUTTON : 0; |
93 return result; | 161 return result; |
94 } | 162 } |
95 | 163 |
96 //static | |
97 int Event::ConvertWindowsFlags(UINT win_flags) { | |
98 int r = 0; | |
99 if (win_flags & MK_CONTROL) | |
100 r |= ui::EF_CONTROL_DOWN; | |
101 if (win_flags & MK_SHIFT) | |
102 r |= ui::EF_SHIFT_DOWN; | |
103 if (GetKeyState(VK_MENU) < 0) | |
104 r |= ui::EF_ALT_DOWN; | |
105 if (win_flags & MK_LBUTTON) | |
106 r |= ui::EF_LEFT_BUTTON_DOWN; | |
107 if (win_flags & MK_MBUTTON) | |
108 r |= ui::EF_MIDDLE_BUTTON_DOWN; | |
109 if (win_flags & MK_RBUTTON) | |
110 r |= ui::EF_RIGHT_BUTTON_DOWN; | |
111 return r; | |
112 } | |
113 | |
114 //////////////////////////////////////////////////////////////////////////////// | 164 //////////////////////////////////////////////////////////////////////////////// |
115 // Event, private: | 165 // Event, private: |
116 | 166 |
117 void Event::Init() { | 167 void Event::Init() { |
118 ZeroMemory(&native_event_, sizeof(native_event_)); | 168 ZeroMemory(&native_event_, sizeof(native_event_)); |
119 native_event_2_ = NULL; | 169 native_event_2_ = NULL; |
120 } | 170 } |
121 | 171 |
122 void Event::InitWithNativeEvent(NativeEvent native_event) { | 172 void Event::InitWithNativeEvent(NativeEvent native_event) { |
123 native_event_ = native_event; | 173 native_event_ = native_event; |
124 // TODO(beng): remove once we rid views of Gtk/Gdk. | 174 // TODO(beng): remove once we rid views of Gtk/Gdk. |
125 native_event_2_ = NULL; | 175 native_event_2_ = NULL; |
126 } | 176 } |
127 | 177 |
128 void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, | 178 void Event::InitWithNativeEvent2(NativeEvent2 native_event_2, |
129 FromNativeEvent2) { | 179 FromNativeEvent2) { |
130 // No one should ever call this on Windows. | 180 // No one should ever call this on Windows. |
131 // TODO(beng): remove once we rid views of Gtk/Gdk. | 181 // TODO(beng): remove once we rid views of Gtk/Gdk. |
132 NOTREACHED(); | 182 NOTREACHED(); |
133 native_event_2_ = NULL; | 183 native_event_2_ = NULL; |
134 } | 184 } |
135 | 185 |
136 //////////////////////////////////////////////////////////////////////////////// | 186 //////////////////////////////////////////////////////////////////////////////// |
137 // LocatedEvent, protected: | 187 // LocatedEvent, protected: |
138 | 188 |
139 LocatedEvent::LocatedEvent(NativeEvent native_event) | 189 LocatedEvent::LocatedEvent(NativeEvent native_event) |
140 : Event(native_event, EventTypeFromNative(native_event), | 190 : Event(native_event, EventTypeFromNative(native_event), |
141 GetFlagsFromNative(native_event)), | 191 EventFlagsFromNative(native_event)), |
142 location_(native_event.pt.x, native_event.pt.y) { | 192 location_(native_event.pt.x, native_event.pt.y) { |
143 } | 193 } |
144 | 194 |
145 LocatedEvent::LocatedEvent(NativeEvent2 native_event_2, | 195 LocatedEvent::LocatedEvent(NativeEvent2 native_event_2, |
146 FromNativeEvent2 from_native) | 196 FromNativeEvent2 from_native) |
147 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { | 197 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { |
148 // No one should ever call this on Windows. | 198 // No one should ever call this on Windows. |
149 // TODO(msw): remove once we rid views of Gtk/Gdk. | 199 // TODO(msw): remove once we rid views of Gtk/Gdk. |
150 NOTREACHED(); | 200 NOTREACHED(); |
151 } | 201 } |
152 | 202 |
153 //////////////////////////////////////////////////////////////////////////////// | 203 //////////////////////////////////////////////////////////////////////////////// |
154 // KeyEvent, public: | 204 // KeyEvent, public: |
155 | 205 |
156 KeyEvent::KeyEvent(NativeEvent native_event) | 206 KeyEvent::KeyEvent(NativeEvent native_event) |
157 : Event(native_event, | 207 : Event(native_event, |
158 EventTypeFromNative(native_event), | 208 EventTypeFromNative(native_event), |
159 GetKeyStateFlags()), | 209 GetKeyStateFlags()), |
160 key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)) { | 210 key_code_(ui::KeyboardCodeForWindowsKeyCode(native_event.wParam)) { |
161 } | 211 } |
162 | 212 |
163 KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) | 213 KeyEvent::KeyEvent(NativeEvent2 native_event_2, FromNativeEvent2 from_native) |
164 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { | 214 : Event(native_event_2, ui::ET_UNKNOWN, 0, from_native) { |
165 // No one should ever call this on Windows. | 215 // No one should ever call this on Windows. |
166 // TODO(beng): remove once we rid views of Gtk/Gdk. | 216 // TODO(beng): remove once we rid views of Gtk/Gdk. |
167 NOTREACHED(); | 217 NOTREACHED(); |
168 } | 218 } |
169 | 219 |
170 //////////////////////////////////////////////////////////////////////////////// | 220 //////////////////////////////////////////////////////////////////////////////// |
| 221 // MouseEvent, public: |
| 222 |
| 223 MouseEvent::MouseEvent(NativeEvent native_event) |
| 224 : LocatedEvent(native_event) { |
| 225 if (IsNonClientMouseEvent(native_event)) { |
| 226 // Non-client message. The position is contained in a POINTS structure in |
| 227 // LPARAM, and is in screen coordinates so we have to convert to client. |
| 228 POINT native_point = location_.ToPOINT(); |
| 229 ScreenToClient(native_event.hwnd, &native_point); |
| 230 location_ = gfx::Point(native_point); |
| 231 } |
| 232 } |
| 233 |
| 234 MouseEvent::MouseEvent(NativeEvent2 native_event_2, |
| 235 FromNativeEvent2 from_native) |
| 236 : LocatedEvent(native_event_2, from_native) { |
| 237 // No one should ever call this on Windows. |
| 238 // TODO(msw): remove once we rid views of Gtk/Gdk. |
| 239 NOTREACHED(); |
| 240 } |
| 241 |
| 242 //////////////////////////////////////////////////////////////////////////////// |
171 // MouseWheelEvent, public: | 243 // MouseWheelEvent, public: |
172 | 244 |
173 MouseWheelEvent::MouseWheelEvent(NativeEvent native_event) | 245 MouseWheelEvent::MouseWheelEvent(NativeEvent native_event) |
174 : LocatedEvent(native_event), | 246 : MouseEvent(native_event), |
175 offset_(GET_WHEEL_DELTA_WPARAM(native_event.wParam)) { | 247 offset_(GET_WHEEL_DELTA_WPARAM(native_event.wParam)) { |
176 } | 248 } |
177 | 249 |
178 MouseWheelEvent::MouseWheelEvent(NativeEvent2 native_event_2, | 250 MouseWheelEvent::MouseWheelEvent(NativeEvent2 native_event_2, |
179 FromNativeEvent2 from_native) | 251 FromNativeEvent2 from_native) |
180 : LocatedEvent(native_event_2, from_native) { | 252 : MouseEvent(native_event_2, from_native) { |
181 // No one should ever call this on Windows. | 253 // No one should ever call this on Windows. |
182 // TODO(msw): remove once we rid views of Gtk/Gdk. | 254 // TODO(msw): remove once we rid views of Gtk/Gdk. |
183 NOTREACHED(); | 255 NOTREACHED(); |
184 } | 256 } |
185 | 257 |
186 } // namespace views | 258 } // namespace views |
OLD | NEW |