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 22d4f49432b802fd67d3f1ffbf826279730c28a6..77cace48767dac044fed0336de0e5f599ddd4306 100644 |
| --- a/content/browser/renderer_host/render_widget_host_view_win.cc |
| +++ b/content/browser/renderer_host/render_widget_host_view_win.cc |
| @@ -243,7 +243,12 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) |
| is_loading_(false), |
| overlay_color_(0), |
| text_input_type_(ui::TEXT_INPUT_TYPE_NONE), |
| - is_fullscreen_(false) { |
| + is_fullscreen_(false), |
| + last_x_(0), |
| + last_y_(0), |
| + last_global_x_(0), |
| + last_global_y_(0), |
| + ignore_mouse_movement_(true) { |
| render_widget_host_->SetView(this); |
| registrar_.Add(this, |
| content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| @@ -251,6 +256,7 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) |
| } |
| RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { |
| + UnlockMouse(); |
| ResetTooltip(); |
| } |
| @@ -1103,12 +1109,14 @@ LRESULT RenderWidgetHostViewWin::OnNotify(int w_param, NMHDR* header) { |
| tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, kTooltipMaxWidthPixels); |
| SetMsgHandled(TRUE); |
| break; |
| - } |
| + } |
| case TTN_POP: |
| tooltip_showing_ = false; |
| SetMsgHandled(TRUE); |
| break; |
| case TTN_SHOW: |
| + // Tooltip shouldn't be shown when the mouse is locked. |
| + DCHECK(!mouse_locked_); |
| tooltip_showing_ = true; |
| SetMsgHandled(TRUE); |
| break; |
| @@ -1229,6 +1237,15 @@ LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, |
| LPARAM lparam, BOOL& handled) { |
| handled = TRUE; |
| + if (message == WM_MOUSELEAVE) |
| + ignore_mouse_movement_ = true; |
| + |
| + if (mouse_locked_) { |
| + HandleLockedMouseEvent(message, wparam, lparam); |
| + MoveCursorToCenter(); |
| + return 0; |
| + } |
| + |
| if (::IsWindow(tooltip_hwnd_)) { |
| // Forward mouse events through to the tooltip window |
| MSG msg; |
| @@ -1292,10 +1309,12 @@ LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam, |
| handled = TRUE; |
| // Force fullscreen windows to close on Escape. |
| - if (is_fullscreen_ && (message == WM_KEYDOWN || message == WM_KEYUP) && |
| - wparam == VK_ESCAPE) { |
| - SendMessage(WM_CANCELMODE); |
| - return 0; |
| + if ((message == WM_KEYDOWN || message == WM_KEYUP) && wparam == VK_ESCAPE) { |
| + if (mouse_locked_) |
| + UnlockMouse(); |
| + if (is_fullscreen_) |
| + SendMessage(WM_CANCELMODE); |
| + return 0; |
| } |
| // If we are a pop-up, forward tab related messages to our parent HWND, so |
| @@ -1480,6 +1499,51 @@ void RenderWidgetHostViewWin::OnAccessibilityNotifications( |
| browser_accessibility_manager_->OnAccessibilityNotifications(params); |
| } |
| +bool RenderWidgetHostViewWin::LockMouse() { |
| + if (mouse_locked_) |
| + return true; |
| + |
| + mouse_locked_ = true; |
| + |
| + // Hide the tooltip window if it is currently visible. When the mouse is |
| + // locked, no mouse message is relayed to the tooltip window, so we don't need |
| + // to worry that it will reappear. |
| + if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) { |
| + ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0); |
| + // Sending a TTM_POP message doesn't seem to actually hide the tooltip |
| + // window, although we will receive a TTN_POP notification. As a result, |
| + // ShowWindow() is explicitly called to hide the window. |
| + ::ShowWindow(tooltip_hwnd_, SW_HIDE); |
| + } |
| + |
| + // TODO(yzshen): Show an invisible cursor instead of using |
| + // ::ShowCursor(FALSE), so that MoveCursorToCenter() works with Remote |
| + // Desktop. |
| + ::ShowCursor(FALSE); |
| + |
| + MoveCursorToCenter(); |
| + |
| + CRect rect; |
| + GetWindowRect(&rect); |
| + ::ClipCursor(&rect); |
|
brettw
2011/09/14 22:17:58
Is this the behavior we want? What if the window i
scheib
2011/09/14 22:24:50
On Linux I found that clipping the cursor was nece
yzshen1
2011/09/19 20:48:41
Vincent and I have discussed this issue before.
S
|
| + |
| + return true; |
| +} |
| + |
| +void RenderWidgetHostViewWin::UnlockMouse() { |
| + if (!mouse_locked_) |
| + return; |
| + |
| + mouse_locked_ = false; |
| + |
| + ::ClipCursor(NULL); |
| + ::SetCursorPos(last_global_x_, last_global_y_); |
| + ::ShowCursor(TRUE); |
| + |
| + if (render_widget_host_) |
| + render_widget_host_->LostMouseLock(); |
| +} |
| + |
| void RenderWidgetHostViewWin::Observe(int type, |
| const NotificationSource& source, |
| const NotificationDetails& details) { |
| @@ -1800,6 +1864,33 @@ void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, |
| WebMouseEvent event( |
| 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_x_; |
| + event.y = last_y_; |
| + event.windowX = last_x_; |
| + event.windowY = last_y_; |
| + event.globalX = last_global_x_; |
| + event.globalY = last_global_y_; |
| + } else { |
| + if (ignore_mouse_movement_) { |
| + ignore_mouse_movement_ = false; |
| + event.movementX = 0; |
| + event.movementY = 0; |
| + } else { |
| + event.movementX = event.globalX - last_global_x_; |
| + event.movementY = event.globalY - last_global_y_; |
| + } |
| + |
| + last_x_ = event.windowX; |
| + last_y_ = event.windowY; |
| + last_global_x_ = event.globalX; |
| + last_global_y_ = event.globalY; |
| + } |
| + |
| // Send the event to the renderer before changing mouse capture, so that the |
| // capturelost event arrives after mouseup. |
| render_widget_host_->ForwardMouseEvent(event); |
| @@ -1848,3 +1939,32 @@ void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd, |
| EnsureTooltip(); |
| ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA); |
| } |
| + |
| +CPoint RenderWidgetHostViewWin::GetClientCenter() const { |
| + CRect rect; |
| + GetClientRect(&rect); |
| + 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::HandleLockedMouseEvent(UINT message, |
| + WPARAM wparam, |
| + 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) |
| + return; |
| + } |
| + |
| + ForwardMouseEventToRenderer(message, wparam, lparam); |
| +} |
| + |