Index: content/browser/renderer_host/render_widget_host_view_win.cc |
diff --git a/content/browser/renderer_host/render_widget_host_view_win.cc b/content/browser/renderer_host/render_widget_host_view_win.cc |
index be206c3eb4fc80f1fbb830c9c9444f9d7626a5a0..8353a4a2440e2ee97721e99f90730d87b28c9a15 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_win.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_win.cc |
@@ -88,8 +88,17 @@ const int kIdCustom = 1; |
// process a grace period to stop referencing it. |
const int kDestroyCompositorHostWindowDelay = 10000; |
+// In mouse lock mode, we need to prevent the (invisible) cursor from hitting |
+// the border of the view, in order to get valid movement information. However, |
+// forcing the cursor back to the center of the view after each mouse move |
+// doesn't work well. It reduces the frequency of useful WM_MOUSEMOVE messages |
+// significantly. Therefore, we move the cursor to the center of the view only |
+// if it approaches the border. |kMouseLockBorderPercentage| specifies the width |
+// of the border area, in percentage of the corresponding dimension. |
+const int kMouseLockBorderPercentage = 15; |
+ |
// A callback function for EnumThreadWindows to enumerate and dismiss |
-// any owned popop windows |
+// any owned popup windows. |
BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { |
const HWND toplevel_hwnd = reinterpret_cast<HWND>(arg); |
@@ -1404,7 +1413,7 @@ LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, |
if (mouse_locked_) { |
HandleLockedMouseEvent(message, wparam, lparam); |
- MoveCursorToCenter(); |
+ MoveCursorToCenterIfNecessary(); |
return 0; |
} |
@@ -1892,12 +1901,13 @@ bool RenderWidgetHostViewWin::LockMouse() { |
::ShowWindow(tooltip_hwnd_, SW_HIDE); |
} |
- // TODO(yzshen): Show an invisible cursor instead of using |
- // ::ShowCursor(FALSE), so that MoveCursorToCenter() works with Remote |
- // Desktop. |
+ // TODO(yzshen): ShowCursor(FALSE) causes SetCursorPos() to be ignored on |
+ // Remote Desktop. |
::ShowCursor(FALSE); |
- MoveCursorToCenter(); |
+ move_to_center_request_.pending = false; |
+ last_mouse_position_.locked_global = last_mouse_position_.unlocked_global; |
+ MoveCursorToCenterIfNecessary(); |
CRect rect; |
GetWindowRect(&rect); |
@@ -1913,8 +1923,8 @@ void RenderWidgetHostViewWin::UnlockMouse() { |
mouse_locked_ = false; |
::ClipCursor(NULL); |
- ::SetCursorPos(last_global_mouse_position_.x(), |
- last_global_mouse_position_.y()); |
+ ::SetCursorPos(last_mouse_position_.unlocked_global.x(), |
+ last_mouse_position_.unlocked_global.y()); |
::ShowCursor(TRUE); |
if (render_widget_host_) |
@@ -2296,28 +2306,30 @@ void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, |
WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam)); |
if (mouse_locked_) { |
- CPoint center = GetClientCenter(); |
- |
- event.movementX = event.windowX - center.x; |
- event.movementY = event.windowY - center.y; |
- event.x = last_mouse_position_.x(); |
- event.y = last_mouse_position_.y(); |
- event.windowX = last_mouse_position_.x(); |
- event.windowY = last_mouse_position_.y(); |
- event.globalX = last_global_mouse_position_.x(); |
- event.globalY = last_global_mouse_position_.y(); |
+ event.movementX = event.globalX - last_mouse_position_.locked_global.x(); |
+ event.movementY = event.globalY - last_mouse_position_.locked_global.y(); |
+ last_mouse_position_.locked_global.SetPoint(event.globalX, event.globalY); |
+ |
+ event.x = last_mouse_position_.unlocked.x(); |
+ event.y = last_mouse_position_.unlocked.y(); |
+ event.windowX = last_mouse_position_.unlocked.x(); |
+ event.windowY = last_mouse_position_.unlocked.y(); |
+ event.globalX = last_mouse_position_.unlocked_global.x(); |
+ event.globalY = last_mouse_position_.unlocked_global.y(); |
} else { |
if (ignore_mouse_movement_) { |
ignore_mouse_movement_ = false; |
event.movementX = 0; |
event.movementY = 0; |
} else { |
- event.movementX = event.globalX - last_global_mouse_position_.x(); |
- event.movementY = event.globalY - last_global_mouse_position_.y(); |
+ event.movementX = |
+ event.globalX - last_mouse_position_.unlocked_global.x(); |
+ event.movementY = |
+ event.globalY - last_mouse_position_.unlocked_global.y(); |
} |
- last_mouse_position_.SetPoint(event.windowX, event.windowY); |
- last_global_mouse_position_.SetPoint(event.globalX, event.globalY); |
+ last_mouse_position_.unlocked.SetPoint(event.windowX, event.windowY); |
+ last_mouse_position_.unlocked_global.SetPoint(event.globalX, event.globalY); |
} |
// Send the event to the renderer before changing mouse capture, so that the |
@@ -2375,11 +2387,28 @@ CPoint RenderWidgetHostViewWin::GetClientCenter() const { |
return rect.CenterPoint(); |
} |
-void RenderWidgetHostViewWin::MoveCursorToCenter() const { |
- CPoint center = GetClientCenter(); |
- ClientToScreen(¢er); |
- if (!::SetCursorPos(center.x, center.y)) |
- LOG_GETLASTERROR(WARNING) << "Failed to set cursor position."; |
+void RenderWidgetHostViewWin::MoveCursorToCenterIfNecessary() { |
+ DCHECK(mouse_locked_); |
+ |
+ CRect rect; |
+ GetWindowRect(&rect); |
+ int border_x = rect.Width() * kMouseLockBorderPercentage / 100; |
+ int border_y = rect.Height() * kMouseLockBorderPercentage / 100; |
+ |
+ bool should_move = |
+ last_mouse_position_.locked_global.x() < rect.left + border_x || |
+ last_mouse_position_.locked_global.x() > rect.right - border_x || |
+ last_mouse_position_.locked_global.y() < rect.top + border_y || |
+ last_mouse_position_.locked_global.y() > rect.bottom - border_y; |
+ |
+ if (should_move) { |
+ move_to_center_request_.pending = true; |
+ move_to_center_request_.target = rect.CenterPoint(); |
+ if (!::SetCursorPos(move_to_center_request_.target.x(), |
+ move_to_center_request_.target.y())) { |
+ LOG_GETLASTERROR(WARNING) << "Failed to set cursor position."; |
+ } |
+ } |
} |
void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, |
@@ -2387,11 +2416,17 @@ void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, |
LPARAM lparam) { |
DCHECK(mouse_locked_); |
- if (message == WM_MOUSEMOVE) { |
- CPoint center = GetClientCenter(); |
- // Ignore WM_MOUSEMOVE messages generated by MoveCursorToCenter(). |
- if (LOWORD(lparam) == center.x && HIWORD(lparam) == center.y) |
+ if (message == WM_MOUSEMOVE && move_to_center_request_.pending) { |
+ // Ignore WM_MOUSEMOVE messages generated by |
+ // MoveCursorToCenterIfNecessary(). |
+ CPoint current_position(LOWORD(lparam), HIWORD(lparam)); |
+ ClientToScreen(¤t_position); |
+ if (move_to_center_request_.target.x() == current_position.x && |
+ move_to_center_request_.target.y() == current_position.y) { |
+ move_to_center_request_.pending = false; |
+ last_mouse_position_.locked_global = move_to_center_request_.target; |
return; |
+ } |
} |
ForwardMouseEventToRenderer(message, wparam, lparam); |