Chromium Code Reviews| 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..3a7bfa994d86237f5c159653bb46a43c683b904b 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_win.cc |
| +++ b/content/browser/renderer_host/render_widget_host_view_win.cc |
| @@ -88,6 +88,11 @@ const int kIdCustom = 1; |
| // process a grace period to stop referencing it. |
| const int kDestroyCompositorHostWindowDelay = 10000; |
| +// In mouse lock mode, the cursor needs to be moved to the center of the view 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 |
| BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) { |
| @@ -334,6 +339,7 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) |
| overlay_color_(0), |
| text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
| is_fullscreen_(false), |
| + ignore_move_to_center_message_(false), |
| ignore_mouse_movement_(true), |
| composition_range_(ui::Range::InvalidRange()), |
| ignore_next_lbutton_message_at_same_location(false), |
| @@ -1404,7 +1410,7 @@ LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, |
| if (mouse_locked_) { |
| HandleLockedMouseEvent(message, wparam, lparam); |
| - MoveCursorToCenter(); |
| + MoveCursorToCenterIfNecessary(); |
| return 0; |
| } |
| @@ -1892,12 +1898,12 @@ 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(); |
| + last_locked_global_mouse_position_ = last_unlocked_global_mouse_position_; |
| + MoveCursorToCenterIfNecessary(); |
| CRect rect; |
| GetWindowRect(&rect); |
| @@ -1913,8 +1919,8 @@ void RenderWidgetHostViewWin::UnlockMouse() { |
| mouse_locked_ = false; |
| ::ClipCursor(NULL); |
| - ::SetCursorPos(last_global_mouse_position_.x(), |
| - last_global_mouse_position_.y()); |
| + ::SetCursorPos(last_unlocked_global_mouse_position_.x(), |
| + last_unlocked_global_mouse_position_.y()); |
| ::ShowCursor(TRUE); |
| if (render_widget_host_) |
| @@ -2296,28 +2302,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_locked_global_mouse_position_.x(); |
| + event.movementY = event.globalY - last_locked_global_mouse_position_.y(); |
| + last_locked_global_mouse_position_.SetPoint(event.globalX, event.globalY); |
| + |
| + event.x = last_unlocked_mouse_position_.x(); |
| + event.y = last_unlocked_mouse_position_.y(); |
| + event.windowX = last_unlocked_mouse_position_.x(); |
| + event.windowY = last_unlocked_mouse_position_.y(); |
| + event.globalX = last_unlocked_global_mouse_position_.x(); |
| + event.globalY = last_unlocked_global_mouse_position_.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_unlocked_global_mouse_position_.x(); |
| + event.movementY = |
| + event.globalY - last_unlocked_global_mouse_position_.y(); |
| } |
| - last_mouse_position_.SetPoint(event.windowX, event.windowY); |
| - last_global_mouse_position_.SetPoint(event.globalX, event.globalY); |
| + last_unlocked_mouse_position_.SetPoint(event.windowX, event.windowY); |
| + last_unlocked_global_mouse_position_.SetPoint(event.globalX, event.globalY); |
| } |
| // Send the event to the renderer before changing mouse capture, so that the |
| @@ -2375,11 +2383,26 @@ 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_locked_global_mouse_position_.x() < rect.left + border_x || |
| + last_locked_global_mouse_position_.x() > rect.right - border_x || |
| + last_locked_global_mouse_position_.y() < rect.top + border_y || |
| + last_locked_global_mouse_position_.y() > rect.bottom - border_y; |
| + |
| + if (should_move) { |
| + ignore_move_to_center_message_ = true; |
| + CPoint center = rect.CenterPoint(); |
| + if (!::SetCursorPos(center.x, center.y)) |
| + LOG_GETLASTERROR(WARNING) << "Failed to set cursor position."; |
| + } |
| } |
| void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, |
| @@ -2387,11 +2410,16 @@ void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message, |
| LPARAM lparam) { |
| DCHECK(mouse_locked_); |
| - if (message == WM_MOUSEMOVE) { |
| + if (message == WM_MOUSEMOVE && ignore_move_to_center_message_) { |
| CPoint center = GetClientCenter(); |
| - // Ignore WM_MOUSEMOVE messages generated by MoveCursorToCenter(). |
| - if (LOWORD(lparam) == center.x && HIWORD(lparam) == center.y) |
| + // Ignore WM_MOUSEMOVE messages generated by |
| + // MoveCursorToCenterIfNecessary(). |
| + if (LOWORD(lparam) == center.x && HIWORD(lparam) == center.y) { |
|
scheib
2011/12/03 04:13:01
Perhaps I'm being paranoid, but: consider caching
yzshen1
2011/12/05 01:16:42
I have also considered this scenario. But it won't
|
| + ignore_move_to_center_message_ = false; |
| + ClientToScreen(¢er); |
| + last_locked_global_mouse_position_.SetPoint(center.x, center.y); |
| return; |
| + } |
| } |
| ForwardMouseEventToRenderer(message, wparam, lparam); |