OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "config.h" | 5 #include "config.h" |
6 | 6 |
7 #include "webkit/glue/webinputevent.h" | 7 #include "webkit/glue/webinputevent.h" |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "webkit/glue/webinputevent_util.h" | 11 #include "webkit/glue/webinputevent_util.h" |
12 | 12 |
13 static const unsigned long kDefaultScrollLinesPerWheelDelta = 3; | 13 static const unsigned long kDefaultScrollLinesPerWheelDelta = 3; |
| 14 static const unsigned long kDefaultScrollCharsPerWheelDelta = 1; |
14 | 15 |
15 // WebMouseEvent -------------------------------------------------------------- | 16 // WebMouseEvent -------------------------------------------------------------- |
16 | 17 |
17 static LPARAM GetRelativeCursorPos(HWND hwnd) { | 18 static LPARAM GetRelativeCursorPos(HWND hwnd) { |
18 POINT pos = {-1, -1}; | 19 POINT pos = {-1, -1}; |
19 GetCursorPos(&pos); | 20 GetCursorPos(&pos); |
20 ScreenToClient(hwnd, &pos); | 21 ScreenToClient(hwnd, &pos); |
21 return MAKELPARAM(pos.x, pos.y); | 22 return MAKELPARAM(pos.x, pos.y); |
22 } | 23 } |
23 | 24 |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 // TODO(pkasting): http://b/1117926 Instead of using GetTickCount() here, we | 106 // TODO(pkasting): http://b/1117926 Instead of using GetTickCount() here, we |
106 // should use GetMessageTime() on the original Windows message in the browser | 107 // should use GetMessageTime() on the original Windows message in the browser |
107 // process, and pass that in the WebMouseEvent. | 108 // process, and pass that in the WebMouseEvent. |
108 timestamp_sec = GetTickCount() / 1000.0; | 109 timestamp_sec = GetTickCount() / 1000.0; |
109 | 110 |
110 layout_test_click_count = 0; | 111 layout_test_click_count = 0; |
111 } | 112 } |
112 | 113 |
113 // WebMouseWheelEvent --------------------------------------------------------- | 114 // WebMouseWheelEvent --------------------------------------------------------- |
114 | 115 |
115 WebMouseWheelEvent::WebMouseWheelEvent(HWND hwnd, UINT message, WPARAM wparam, | 116 WebMouseWheelEvent::WebMouseWheelEvent(HWND hwnd, |
116 LPARAM lparam) { | 117 UINT message, |
| 118 WPARAM wparam, |
| 119 LPARAM lparam) |
| 120 : scroll_by_page(false) { |
117 type = MOUSE_WHEEL; | 121 type = MOUSE_WHEEL; |
118 button = BUTTON_NONE; | 122 button = BUTTON_NONE; |
119 | 123 |
120 // Add a simple workaround to scroll multiples units per page. | 124 // Get key state, coordinates, and wheel delta from event. |
121 // The right fix needs to extend webkit's implementation of | |
122 // wheel events and that's not something we want to do at | |
123 // this time. See bug# 928509 | |
124 // TODO(joshia): Implement the right fix for bug# 928509 | |
125 const int kPageScroll = 10; // 10 times wheel scroll | |
126 | |
127 UINT key_state = GET_KEYSTATE_WPARAM(wparam); | |
128 int wheel_delta = static_cast<int>(GET_WHEEL_DELTA_WPARAM(wparam)); | |
129 | |
130 typedef SHORT (WINAPI *GetKeyStateFunction)(int key); | 125 typedef SHORT (WINAPI *GetKeyStateFunction)(int key); |
131 GetKeyStateFunction get_key_state = GetKeyState; | 126 GetKeyStateFunction get_key_state; |
132 | 127 UINT key_state; |
133 // Synthesize mousewheel event from a scroll event. | 128 float wheel_delta; |
134 // This is needed to simulate middle mouse scrolling in some | 129 bool horizontal_scroll = false; |
135 // laptops (Thinkpads) | 130 if ((message == WM_VSCROLL) || (message == WM_HSCROLL)) { |
136 if ((WM_VSCROLL == message) || (WM_HSCROLL == message)) { | 131 // Synthesize mousewheel event from a scroll event. This is needed to |
| 132 // simulate middle mouse scrolling in some laptops. Use GetAsyncKeyState |
| 133 // for key state since we are synthesizing the input event. |
| 134 get_key_state = GetAsyncKeyState; |
| 135 key_state = 0; |
| 136 if (get_key_state(VK_SHIFT)) |
| 137 key_state |= MK_SHIFT; |
| 138 if (get_key_state(VK_CONTROL)) |
| 139 key_state |= MK_CONTROL; |
137 | 140 |
138 POINT cursor_position = {0}; | 141 POINT cursor_position = {0}; |
139 GetCursorPos(&cursor_position); | 142 GetCursorPos(&cursor_position); |
140 | |
141 global_x = cursor_position.x; | 143 global_x = cursor_position.x; |
142 global_y = cursor_position.y; | 144 global_y = cursor_position.y; |
143 | 145 |
144 key_state = 0; | |
145 | |
146 // Since we are synthesizing the wheel event, we have to | |
147 // use GetAsyncKeyState | |
148 if (GetAsyncKeyState(VK_SHIFT)) | |
149 key_state |= MK_SHIFT; | |
150 | |
151 if (GetAsyncKeyState(VK_CONTROL)) | |
152 key_state |= MK_CONTROL; | |
153 | |
154 switch (LOWORD(wparam)) { | 146 switch (LOWORD(wparam)) { |
155 case SB_LINEUP: // == SB_LINELEFT | 147 case SB_LINEUP: // == SB_LINELEFT |
156 wheel_delta = WHEEL_DELTA; | 148 wheel_delta = WHEEL_DELTA; |
157 break; | 149 break; |
158 case SB_LINEDOWN: // == SB_LINERIGHT | 150 case SB_LINEDOWN: // == SB_LINERIGHT |
159 wheel_delta = -WHEEL_DELTA; | 151 wheel_delta = -WHEEL_DELTA; |
160 break; | 152 break; |
161 case SB_PAGEUP: | 153 case SB_PAGEUP: |
162 wheel_delta = kPageScroll * WHEEL_DELTA; | 154 wheel_delta = 1; |
| 155 scroll_by_page = true; |
163 break; | 156 break; |
164 case SB_PAGEDOWN: | 157 case SB_PAGEDOWN: |
165 wheel_delta = -kPageScroll * WHEEL_DELTA; | 158 wheel_delta = -1; |
| 159 scroll_by_page = true; |
166 break; | 160 break; |
167 // TODO(joshia): Handle SB_THUMBPOSITION and SB_THUMBTRACK | 161 default: // We don't supoprt SB_THUMBPOSITION or SB_THUMBTRACK here. |
168 // for compeleteness | 162 wheel_delta = 0; |
169 default: | |
170 break; | 163 break; |
171 } | 164 } |
172 | 165 |
173 // Touchpads (or trackpoints) send the following messages in scrolling | 166 if (message == WM_HSCROLL) { |
174 // horizontally. | 167 horizontal_scroll = true; |
175 // * Scrolling left | |
176 // message == WM_HSCROLL, wparam == SB_LINELEFT (== SB_LINEUP). | |
177 // * Scrolling right | |
178 // message == WM_HSCROLL, wparam == SB_LINERIGHT (== SB_LINEDOWN). | |
179 if (WM_HSCROLL == message) { | |
180 key_state |= MK_SHIFT; | |
181 wheel_delta = -wheel_delta; | 168 wheel_delta = -wheel_delta; |
182 } | 169 } |
183 | |
184 // Use GetAsyncKeyState for key state since we are synthesizing | |
185 // the input | |
186 get_key_state = GetAsyncKeyState; | |
187 } else { | 170 } else { |
188 // TODO(hbono): we should add a new variable which indicates scroll | 171 // Non-synthesized event; we can just read data off the event. |
189 // direction and remove this key_state hack. | 172 get_key_state = GetKeyState; |
190 if (WM_MOUSEHWHEEL == message) | 173 key_state = GET_KEYSTATE_WPARAM(wparam); |
191 key_state |= MK_SHIFT; | |
192 | 174 |
193 global_x = static_cast<short>(LOWORD(lparam)); | 175 global_x = static_cast<short>(LOWORD(lparam)); |
194 global_y = static_cast<short>(HIWORD(lparam)); | 176 global_y = static_cast<short>(HIWORD(lparam)); |
| 177 |
| 178 wheel_delta = static_cast<float>(GET_WHEEL_DELTA_WPARAM(wparam)); |
| 179 if (((message == WM_MOUSEHWHEEL) || (key_state & MK_SHIFT)) && |
| 180 (wheel_delta != 0)) |
| 181 horizontal_scroll = true; |
195 } | 182 } |
196 | 183 |
197 POINT client_point = { global_x, global_y }; | 184 // Set modifiers based on key state. |
198 ScreenToClient(hwnd, &client_point); | |
199 x = client_point.x; | |
200 y = client_point.y; | |
201 | |
202 // compute the scroll delta based on Raymond Chen's algorithm: | |
203 // http://blogs.msdn.com/oldnewthing/archive/2003/08/07/54615.aspx | |
204 | |
205 static int carryover = 0; | |
206 static HWND last_window = NULL; | |
207 | |
208 if (hwnd != last_window) { | |
209 last_window = hwnd; | |
210 carryover = 0; | |
211 } | |
212 | |
213 unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta; | |
214 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0); | |
215 | |
216 int delta_lines = 0; | |
217 if (scroll_lines == WHEEL_PAGESCROLL) { | |
218 scroll_lines = kPageScroll; | |
219 } | |
220 | |
221 if (scroll_lines == 0) { | |
222 carryover = 0; | |
223 } else { | |
224 const int delta = carryover + wheel_delta; | |
225 | |
226 // see how many lines we should scroll. relies on round-toward-zero. | |
227 delta_lines = delta * static_cast<int>(scroll_lines) / WHEEL_DELTA; | |
228 | |
229 // record the unused portion as the next carryover. | |
230 carryover = | |
231 delta - delta_lines * WHEEL_DELTA / static_cast<int>(scroll_lines); | |
232 } | |
233 | |
234 // Scroll horizontally if shift is held. WebKit's WebKit/win/WebView.cpp | |
235 // does the equivalent. | |
236 // TODO(jackson): Support WM_MOUSEHWHEEL = 0x020E event as well. | |
237 // (Need a mouse with horizontal scrolling capabilities to test it.) | |
238 if (key_state & MK_SHIFT) { | |
239 // Scrolling up should move left, scrolling down should move right | |
240 delta_x = -delta_lines; | |
241 delta_y = 0; | |
242 } else { | |
243 delta_x = 0; | |
244 delta_y = delta_lines; | |
245 } | |
246 | |
247 if (key_state & MK_SHIFT) | 185 if (key_state & MK_SHIFT) |
248 modifiers |= SHIFT_KEY; | 186 modifiers |= SHIFT_KEY; |
249 if (key_state & MK_CONTROL) | 187 if (key_state & MK_CONTROL) |
250 modifiers |= CTRL_KEY; | 188 modifiers |= CTRL_KEY; |
251 | |
252 // Get any additional key states needed | |
253 if (get_key_state(VK_MENU) & 0x8000) | 189 if (get_key_state(VK_MENU) & 0x8000) |
254 modifiers |= (ALT_KEY | META_KEY); | 190 modifiers |= (ALT_KEY | META_KEY); |
| 191 |
| 192 // Set coordinates by translating event coordinates from screen to client. |
| 193 POINT client_point = { global_x, global_y }; |
| 194 MapWindowPoints(NULL, hwnd, &client_point, 1); |
| 195 x = client_point.x; |
| 196 y = client_point.y; |
| 197 |
| 198 // Convert wheel delta amount to a number of lines/chars to scroll. |
| 199 float scroll_delta = wheel_delta / WHEEL_DELTA; |
| 200 if (horizontal_scroll) { |
| 201 unsigned long scroll_chars = kDefaultScrollCharsPerWheelDelta; |
| 202 SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scroll_chars, 0); |
| 203 scroll_delta *= static_cast<float>(scroll_chars); |
| 204 } else { |
| 205 unsigned long scroll_lines = kDefaultScrollLinesPerWheelDelta; |
| 206 SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scroll_lines, 0); |
| 207 if (scroll_lines == WHEEL_PAGESCROLL) |
| 208 scroll_by_page = true; |
| 209 if (!scroll_by_page) |
| 210 scroll_delta *= static_cast<float>(scroll_lines); |
| 211 } |
| 212 |
| 213 // Set scroll amount based on above calculations. |
| 214 if (horizontal_scroll) { |
| 215 // Scrolling up should move left, scrolling down should move right. This is |
| 216 // opposite Safari, but seems more consistent with vertical scrolling. |
| 217 delta_x = scroll_delta; |
| 218 delta_y = 0; |
| 219 } else { |
| 220 delta_x = 0; |
| 221 delta_y = scroll_delta; |
| 222 } |
255 } | 223 } |
256 | 224 |
257 // WebKeyboardEvent ----------------------------------------------------------- | 225 // WebKeyboardEvent ----------------------------------------------------------- |
258 | 226 |
259 bool IsKeyPad(WPARAM wparam, LPARAM lparam) { | 227 bool IsKeyPad(WPARAM wparam, LPARAM lparam) { |
260 bool keypad = false; | 228 bool keypad = false; |
261 switch (wparam) { | 229 switch (wparam) { |
262 case VK_RETURN: | 230 case VK_RETURN: |
263 keypad = (lparam >> 16) & KF_EXTENDED; | 231 keypad = (lparam >> 16) & KF_EXTENDED; |
264 break; | 232 break; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
356 modifiers |= CTRL_KEY; | 324 modifiers |= CTRL_KEY; |
357 if (GetKeyState(VK_MENU) & 0x8000) | 325 if (GetKeyState(VK_MENU) & 0x8000) |
358 modifiers |= (ALT_KEY | META_KEY); | 326 modifiers |= (ALT_KEY | META_KEY); |
359 | 327 |
360 if (LOWORD(lparam) > 1) | 328 if (LOWORD(lparam) > 1) |
361 modifiers |= IS_AUTO_REPEAT; | 329 modifiers |= IS_AUTO_REPEAT; |
362 if (IsKeyPad(wparam, lparam)) | 330 if (IsKeyPad(wparam, lparam)) |
363 modifiers |= IS_KEYPAD; | 331 modifiers |= IS_KEYPAD; |
364 } | 332 } |
365 | 333 |
OLD | NEW |