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 "content/browser/renderer_host/render_widget_host_view_win.h" | 5 #include "content/browser/renderer_host/render_widget_host_view_win.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
81 const int kMaxTooltipLength = 1024; | 81 const int kMaxTooltipLength = 1024; |
82 | 82 |
83 // A custom MSAA object id used to determine if a screen reader is actively | 83 // A custom MSAA object id used to determine if a screen reader is actively |
84 // listening for MSAA events. | 84 // listening for MSAA events. |
85 const int kIdCustom = 1; | 85 const int kIdCustom = 1; |
86 | 86 |
87 // The delay before the compositor host window is destroyed. This gives the GPU | 87 // The delay before the compositor host window is destroyed. This gives the GPU |
88 // process a grace period to stop referencing it. | 88 // process a grace period to stop referencing it. |
89 const int kDestroyCompositorHostWindowDelay = 10000; | 89 const int kDestroyCompositorHostWindowDelay = 10000; |
90 | 90 |
| 91 // In mouse lock mode, we need to prevent the (invisible) cursor from hitting |
| 92 // the border of the view, in order to get valid movement information. However, |
| 93 // forcing the cursor back to the center of the view after each mouse move |
| 94 // doesn't work well. It reduces the frequency of useful WM_MOUSEMOVE messages |
| 95 // significantly. Therefore, we move the cursor to the center of the view only |
| 96 // if it approaches the border. |kMouseLockBorderPercentage| specifies the width |
| 97 // of the border area, in percentage of the corresponding dimension. |
| 98 const int kMouseLockBorderPercentage = 15; |
| 99 |
91 // A callback function for EnumThreadWindows to enumerate and dismiss | 100 // A callback function for EnumThreadWindows to enumerate and dismiss |
92 // any owned popop windows | 101 // any owned popup windows. |
93 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { | 102 BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { |
94 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg); | 103 const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg); |
95 | 104 |
96 if (::IsWindowVisible(window)) { | 105 if (::IsWindowVisible(window)) { |
97 const HWND owner = ::GetWindow(window, GW_OWNER); | 106 const HWND owner = ::GetWindow(window, GW_OWNER); |
98 if (toplevel_hwnd == owner) { | 107 if (toplevel_hwnd == owner) { |
99 ::PostMessage(window, WM_CANCELMODE, 0, 0); | 108 ::PostMessage(window, WM_CANCELMODE, 0, 0); |
100 } | 109 } |
101 } | 110 } |
102 | 111 |
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1397 last_pointer_down_location_ = 0; | 1406 last_pointer_down_location_ = 0; |
1398 if (last_location == lparam) | 1407 if (last_location == lparam) |
1399 return 0; | 1408 return 0; |
1400 } | 1409 } |
1401 | 1410 |
1402 if (message == WM_MOUSELEAVE) | 1411 if (message == WM_MOUSELEAVE) |
1403 ignore_mouse_movement_ = true; | 1412 ignore_mouse_movement_ = true; |
1404 | 1413 |
1405 if (mouse_locked_) { | 1414 if (mouse_locked_) { |
1406 HandleLockedMouseEvent(message, wparam, lparam); | 1415 HandleLockedMouseEvent(message, wparam, lparam); |
1407 MoveCursorToCenter(); | 1416 MoveCursorToCenterIfNecessary(); |
1408 return 0; | 1417 return 0; |
1409 } | 1418 } |
1410 | 1419 |
1411 if (::IsWindow(tooltip_hwnd_)) { | 1420 if (::IsWindow(tooltip_hwnd_)) { |
1412 // Forward mouse events through to the tooltip window | 1421 // Forward mouse events through to the tooltip window |
1413 MSG msg; | 1422 MSG msg; |
1414 msg.hwnd = m_hWnd; | 1423 msg.hwnd = m_hWnd; |
1415 msg.message = message; | 1424 msg.message = message; |
1416 msg.wParam = wparam; | 1425 msg.wParam = wparam; |
1417 msg.lParam = lparam; | 1426 msg.lParam = lparam; |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1885 // locked, no mouse message is relayed to the tooltip window, so we don't need | 1894 // locked, no mouse message is relayed to the tooltip window, so we don't need |
1886 // to worry that it will reappear. | 1895 // to worry that it will reappear. |
1887 if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) { | 1896 if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) { |
1888 ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); | 1897 ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
1889 // Sending a TTM_POP message doesn't seem to actually hide the tooltip | 1898 // Sending a TTM_POP message doesn't seem to actually hide the tooltip |
1890 // window, although we will receive a TTN_POP notification. As a result, | 1899 // window, although we will receive a TTN_POP notification. As a result, |
1891 // ShowWindow() is explicitly called to hide the window. | 1900 // ShowWindow() is explicitly called to hide the window. |
1892 ::ShowWindow(tooltip_hwnd_, SW_HIDE); | 1901 ::ShowWindow(tooltip_hwnd_, SW_HIDE); |
1893 } | 1902 } |
1894 | 1903 |
1895 // TODO(yzshen): Show an invisible cursor instead of using | 1904 // TODO(yzshen): ShowCursor(FALSE) causes SetCursorPos() to be ignored on |
1896 // ::ShowCursor(FALSE), so that MoveCursorToCenter() works with Remote | 1905 // Remote Desktop. |
1897 // Desktop. | |
1898 ::ShowCursor(FALSE); | 1906 ::ShowCursor(FALSE); |
1899 | 1907 |
1900 MoveCursorToCenter(); | 1908 move_to_center_request_.pending = false; |
| 1909 last_mouse_position_.locked_global = last_mouse_position_.unlocked_global; |
| 1910 MoveCursorToCenterIfNecessary(); |
1901 | 1911 |
1902 CRect rect; | 1912 CRect rect; |
1903 GetWindowRect(&rect); | 1913 GetWindowRect(&rect); |
1904 ::ClipCursor(&rect); | 1914 ::ClipCursor(&rect); |
1905 | 1915 |
1906 return true; | 1916 return true; |
1907 } | 1917 } |
1908 | 1918 |
1909 void RenderWidgetHostViewWin::UnlockMouse() { | 1919 void RenderWidgetHostViewWin::UnlockMouse() { |
1910 if (!mouse_locked_) | 1920 if (!mouse_locked_) |
1911 return; | 1921 return; |
1912 | 1922 |
1913 mouse_locked_ = false; | 1923 mouse_locked_ = false; |
1914 | 1924 |
1915 ::ClipCursor(NULL); | 1925 ::ClipCursor(NULL); |
1916 ::SetCursorPos(last_global_mouse_position_.x(), | 1926 ::SetCursorPos(last_mouse_position_.unlocked_global.x(), |
1917 last_global_mouse_position_.y()); | 1927 last_mouse_position_.unlocked_global.y()); |
1918 ::ShowCursor(TRUE); | 1928 ::ShowCursor(TRUE); |
1919 | 1929 |
1920 if (render_widget_host_) | 1930 if (render_widget_host_) |
1921 render_widget_host_->LostMouseLock(); | 1931 render_widget_host_->LostMouseLock(); |
1922 } | 1932 } |
1923 | 1933 |
1924 void RenderWidgetHostViewWin::Observe( | 1934 void RenderWidgetHostViewWin::Observe( |
1925 int type, | 1935 int type, |
1926 const content::NotificationSource& source, | 1936 const content::NotificationSource& source, |
1927 const content::NotificationDetails& details) { | 1937 const content::NotificationDetails& details) { |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2289 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, | 2299 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, |
2290 WPARAM wparam, | 2300 WPARAM wparam, |
2291 LPARAM lparam) { | 2301 LPARAM lparam) { |
2292 if (!render_widget_host_) | 2302 if (!render_widget_host_) |
2293 return; | 2303 return; |
2294 | 2304 |
2295 WebMouseEvent event( | 2305 WebMouseEvent event( |
2296 WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam)); | 2306 WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam)); |
2297 | 2307 |
2298 if (mouse_locked_) { | 2308 if (mouse_locked_) { |
2299 CPoint center = GetClientCenter(); | 2309 event.movementX = event.globalX - last_mouse_position_.locked_global.x(); |
| 2310 event.movementY = event.globalY - last_mouse_position_.locked_global.y(); |
| 2311 last_mouse_position_.locked_global.SetPoint(event.globalX, event.globalY); |
2300 | 2312 |
2301 event.movementX = event.windowX - center.x; | 2313 event.x = last_mouse_position_.unlocked.x(); |
2302 event.movementY = event.windowY - center.y; | 2314 event.y = last_mouse_position_.unlocked.y(); |
2303 event.x = last_mouse_position_.x(); | 2315 event.windowX = last_mouse_position_.unlocked.x(); |
2304 event.y = last_mouse_position_.y(); | 2316 event.windowY = last_mouse_position_.unlocked.y(); |
2305 event.windowX = last_mouse_position_.x(); | 2317 event.globalX = last_mouse_position_.unlocked_global.x(); |
2306 event.windowY = last_mouse_position_.y(); | 2318 event.globalY = last_mouse_position_.unlocked_global.y(); |
2307 event.globalX = last_global_mouse_position_.x(); | |
2308 event.globalY = last_global_mouse_position_.y(); | |
2309 } else { | 2319 } else { |
2310 if (ignore_mouse_movement_) { | 2320 if (ignore_mouse_movement_) { |
2311 ignore_mouse_movement_ = false; | 2321 ignore_mouse_movement_ = false; |
2312 event.movementX = 0; | 2322 event.movementX = 0; |
2313 event.movementY = 0; | 2323 event.movementY = 0; |
2314 } else { | 2324 } else { |
2315 event.movementX = event.globalX - last_global_mouse_position_.x(); | 2325 event.movementX = |
2316 event.movementY = event.globalY - last_global_mouse_position_.y(); | 2326 event.globalX - last_mouse_position_.unlocked_global.x(); |
| 2327 event.movementY = |
| 2328 event.globalY - last_mouse_position_.unlocked_global.y(); |
2317 } | 2329 } |
2318 | 2330 |
2319 last_mouse_position_.SetPoint(event.windowX, event.windowY); | 2331 last_mouse_position_.unlocked.SetPoint(event.windowX, event.windowY); |
2320 last_global_mouse_position_.SetPoint(event.globalX, event.globalY); | 2332 last_mouse_position_.unlocked_global.SetPoint(event.globalX, event.globalY); |
2321 } | 2333 } |
2322 | 2334 |
2323 // Send the event to the renderer before changing mouse capture, so that the | 2335 // Send the event to the renderer before changing mouse capture, so that the |
2324 // capturelost event arrives after mouseup. | 2336 // capturelost event arrives after mouseup. |
2325 render_widget_host_->ForwardMouseEvent(event); | 2337 render_widget_host_->ForwardMouseEvent(event); |
2326 | 2338 |
2327 switch (event.type) { | 2339 switch (event.type) { |
2328 case WebInputEvent::MouseMove: | 2340 case WebInputEvent::MouseMove: |
2329 TrackMouseLeave(true); | 2341 TrackMouseLeave(true); |
2330 break; | 2342 break; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2368 EnsureTooltip(); | 2380 EnsureTooltip(); |
2369 ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA); | 2381 ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA); |
2370 } | 2382 } |
2371 | 2383 |
2372 CPoint RenderWidgetHostViewWin::GetClientCenter() const { | 2384 CPoint RenderWidgetHostViewWin::GetClientCenter() const { |
2373 CRect rect; | 2385 CRect rect; |
2374 GetClientRect(&rect); | 2386 GetClientRect(&rect); |
2375 return rect.CenterPoint(); | 2387 return rect.CenterPoint(); |
2376 } | 2388 } |
2377 | 2389 |
2378 void RenderWidgetHostViewWin::MoveCursorToCenter() const { | 2390 void RenderWidgetHostViewWin::MoveCursorToCenterIfNecessary() { |
2379 CPoint center = GetClientCenter(); | 2391 DCHECK(mouse_locked_); |
2380 ClientToScreen(¢er); | 2392 |
2381 if (!::SetCursorPos(center.x, center.y)) | 2393 CRect rect; |
2382 LOG_GETLASTERROR(WARNING) << "Failed to set cursor position."; | 2394 GetWindowRect(&rect); |
| 2395 int border_x = rect.Width() * kMouseLockBorderPercentage / 100; |
| 2396 int border_y = rect.Height() * kMouseLockBorderPercentage / 100; |
| 2397 |
| 2398 bool should_move = |
| 2399 last_mouse_position_.locked_global.x() < rect.left + border_x || |
| 2400 last_mouse_position_.locked_global.x() > rect.right - border_x || |
| 2401 last_mouse_position_.locked_global.y() < rect.top + border_y || |
| 2402 last_mouse_position_.locked_global.y() > rect.bottom - border_y; |
| 2403 |
| 2404 if (should_move) { |
| 2405 move_to_center_request_.pending = true; |
| 2406 move_to_center_request_.target = rect.CenterPoint(); |
| 2407 if (!::SetCursorPos(move_to_center_request_.target.x(), |
| 2408 move_to_center_request_.target.y())) { |
| 2409 LOG_GETLASTERROR(WARNING) << "Failed to set cursor position."; |
| 2410 } |
| 2411 } |
2383 } | 2412 } |
2384 | 2413 |
2385 void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, | 2414 void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, |
2386 WPARAM wparam, | 2415 WPARAM wparam, |
2387 LPARAM lparam) { | 2416 LPARAM lparam) { |
2388 DCHECK(mouse_locked_); | 2417 DCHECK(mouse_locked_); |
2389 | 2418 |
2390 if (message == WM_MOUSEMOVE) { | 2419 if (message == WM_MOUSEMOVE && move_to_center_request_.pending) { |
2391 CPoint center = GetClientCenter(); | 2420 // Ignore WM_MOUSEMOVE messages generated by |
2392 // Ignore WM_MOUSEMOVE messages generated by MoveCursorToCenter(). | 2421 // MoveCursorToCenterIfNecessary(). |
2393 if (LOWORD(lparam) == center.x && HIWORD(lparam) == center.y) | 2422 CPoint current_position(LOWORD(lparam), HIWORD(lparam)); |
| 2423 ClientToScreen(¤t_position); |
| 2424 if (move_to_center_request_.target.x() == current_position.x && |
| 2425 move_to_center_request_.target.y() == current_position.y) { |
| 2426 move_to_center_request_.pending = false; |
| 2427 last_mouse_position_.locked_global = move_to_center_request_.target; |
2394 return; | 2428 return; |
| 2429 } |
2395 } | 2430 } |
2396 | 2431 |
2397 ForwardMouseEventToRenderer(message, wparam, lparam); | 2432 ForwardMouseEventToRenderer(message, wparam, lparam); |
2398 } | 2433 } |
2399 | 2434 |
2400 LRESULT RenderWidgetHostViewWin::OnDocumentFeed(RECONVERTSTRING* reconv) { | 2435 LRESULT RenderWidgetHostViewWin::OnDocumentFeed(RECONVERTSTRING* reconv) { |
2401 size_t target_offset; | 2436 size_t target_offset; |
2402 size_t target_length; | 2437 size_t target_length; |
2403 bool has_composition; | 2438 bool has_composition; |
2404 if (!composition_range_.is_empty()) { | 2439 if (!composition_range_.is_empty()) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2480 | 2515 |
2481 size_t offset = selection_range_.GetMin() - selection_text_offset_; | 2516 size_t offset = selection_range_.GetMin() - selection_text_offset_; |
2482 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), | 2517 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), |
2483 selection_text_.c_str() + offset, len * sizeof(WCHAR)); | 2518 selection_text_.c_str() + offset, len * sizeof(WCHAR)); |
2484 | 2519 |
2485 // According to Microsft API document, IMR_RECONVERTSTRING and | 2520 // According to Microsft API document, IMR_RECONVERTSTRING and |
2486 // IMR_DOCUMENTFEED should return reconv, but some applications return | 2521 // IMR_DOCUMENTFEED should return reconv, but some applications return |
2487 // need_size. | 2522 // need_size. |
2488 return reinterpret_cast<LRESULT>(reconv); | 2523 return reinterpret_cast<LRESULT>(reconv); |
2489 } | 2524 } |
OLD | NEW |