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..855aa5d9ffc5ee5d4b5fb05de882b0b18a6d8254 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(); |
} |
@@ -1229,6 +1235,16 @@ 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; |
+ } |
+ |
+ // TODO(yzshen): is this correct? Nothing goes to the tool tip window? |
if (::IsWindow(tooltip_hwnd_)) { |
// Forward mouse events through to the tooltip window |
MSG msg; |
@@ -1292,10 +1308,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 +1498,45 @@ void RenderWidgetHostViewWin::OnAccessibilityNotifications( |
browser_accessibility_manager_->OnAccessibilityNotifications(params); |
} |
+bool RenderWidgetHostViewWin::LockMouse() { |
+ if (mouse_locked_) |
+ return true; |
+ |
+ mouse_locked_ = true; |
+ // TODO(yzshen): (1) Make sure it works with the current_cursor_. |
+ // (2) if not confined successful, we can tell once we receive |
+ // mouse leave message, does that help? |
+ // (3) ResetTooltip / EnsureTooltip, and make sure they work |
+ // consistently with other part of the code. |
+ |
+ // 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); |
+ |
+ 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 +1857,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); |
@@ -1827,6 +1911,7 @@ void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, |
// WM_LBUTTONDOWN. |
SetFocus(); |
} |
+ |
} |
void RenderWidgetHostViewWin::ShutdownHost() { |
@@ -1848,3 +1933,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); |
+} |
+ |