Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: content/browser/renderer_host/render_widget_host_view_win.cc

Issue 8791001: Fix mouse lock perf issue on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Changes in response to Brett's suggestion. Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/browser/renderer_host/render_widget_host_view_win.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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(&center); 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(&current_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
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 }
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_widget_host_view_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698