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

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

Issue 7863003: Mouse lock implementation, including the renderer side and the Windows version of the browser side. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove two tab chars. Created 9 years, 3 months 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
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 // Need a few defines from Win 7 headers for WM_GESTURE and 5 // Need a few defines from Win 7 headers for WM_GESTURE and
6 // ChangeWindowMessageFilterEx. 6 // ChangeWindowMessageFilterEx.
7 // TODO(jschuh): See crbug.com/92941 for longterm fix. 7 // TODO(jschuh): See crbug.com/92941 for longterm fix.
8 #include <windows.h> 8 #include <windows.h>
9 #if(WINVER < 0x0601) 9 #if(WINVER < 0x0601)
10 typedef struct tagCHANGEFILTERSTRUCT { 10 typedef struct tagCHANGEFILTERSTRUCT {
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 about_to_validate_and_paint_(false), 236 about_to_validate_and_paint_(false),
237 close_on_deactivate_(false), 237 close_on_deactivate_(false),
238 being_destroyed_(false), 238 being_destroyed_(false),
239 tooltip_hwnd_(NULL), 239 tooltip_hwnd_(NULL),
240 tooltip_showing_(false), 240 tooltip_showing_(false),
241 shutdown_factory_(this), 241 shutdown_factory_(this),
242 parent_hwnd_(NULL), 242 parent_hwnd_(NULL),
243 is_loading_(false), 243 is_loading_(false),
244 overlay_color_(0), 244 overlay_color_(0),
245 text_input_type_(ui::TEXT_INPUT_TYPE_NONE), 245 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
246 is_fullscreen_(false) { 246 is_fullscreen_(false),
247 last_x_(0),
248 last_y_(0),
249 last_global_x_(0),
250 last_global_y_(0),
251 ignore_mouse_movement_(true) {
247 render_widget_host_->SetView(this); 252 render_widget_host_->SetView(this);
248 registrar_.Add(this, 253 registrar_.Add(this,
249 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 254 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
250 NotificationService::AllSources()); 255 NotificationService::AllSources());
251 } 256 }
252 257
253 RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { 258 RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
259 UnlockMouse();
254 ResetTooltip(); 260 ResetTooltip();
255 } 261 }
256 262
257 void RenderWidgetHostViewWin::CreateWnd(HWND parent) { 263 void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
258 Create(parent); // ATL function to create the window. 264 Create(parent); // ATL function to create the window.
259 } 265 }
260 266
261 /////////////////////////////////////////////////////////////////////////////// 267 ///////////////////////////////////////////////////////////////////////////////
262 // RenderWidgetHostViewWin, RenderWidgetHostView implementation: 268 // RenderWidgetHostViewWin, RenderWidgetHostView implementation:
263 269
(...skipping 832 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 1102
1097 switch (header->code) { 1103 switch (header->code) {
1098 case TTN_GETDISPINFO: { 1104 case TTN_GETDISPINFO: {
1099 NMTTDISPINFOW* tooltip_info = reinterpret_cast<NMTTDISPINFOW*>(header); 1105 NMTTDISPINFOW* tooltip_info = reinterpret_cast<NMTTDISPINFOW*>(header);
1100 tooltip_info->szText[0] = L'\0'; 1106 tooltip_info->szText[0] = L'\0';
1101 tooltip_info->lpszText = const_cast<wchar_t*>(tooltip_text_.c_str()); 1107 tooltip_info->lpszText = const_cast<wchar_t*>(tooltip_text_.c_str());
1102 ::SendMessage( 1108 ::SendMessage(
1103 tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, kTooltipMaxWidthPixels); 1109 tooltip_hwnd_, TTM_SETMAXTIPWIDTH, 0, kTooltipMaxWidthPixels);
1104 SetMsgHandled(TRUE); 1110 SetMsgHandled(TRUE);
1105 break; 1111 break;
1106 } 1112 }
1107 case TTN_POP: 1113 case TTN_POP:
1108 tooltip_showing_ = false; 1114 tooltip_showing_ = false;
1109 SetMsgHandled(TRUE); 1115 SetMsgHandled(TRUE);
1110 break; 1116 break;
1111 case TTN_SHOW: 1117 case TTN_SHOW:
1118 // Tooltip shouldn't be shown when the mouse is locked.
1119 DCHECK(!mouse_locked_);
1112 tooltip_showing_ = true; 1120 tooltip_showing_ = true;
1113 SetMsgHandled(TRUE); 1121 SetMsgHandled(TRUE);
1114 break; 1122 break;
1115 } 1123 }
1116 return 0; 1124 return 0;
1117 } 1125 }
1118 1126
1119 LRESULT RenderWidgetHostViewWin::OnImeSetContext( 1127 LRESULT RenderWidgetHostViewWin::OnImeSetContext(
1120 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) { 1128 UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
1121 if (!render_widget_host_) 1129 if (!render_widget_host_)
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 ime_input_.DestroyImeWindow(m_hWnd); 1230 ime_input_.DestroyImeWindow(m_hWnd);
1223 // Let WTL call ::DefWindowProc() and release its resources. 1231 // Let WTL call ::DefWindowProc() and release its resources.
1224 handled = FALSE; 1232 handled = FALSE;
1225 return 0; 1233 return 0;
1226 } 1234 }
1227 1235
1228 LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, 1236 LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam,
1229 LPARAM lparam, BOOL& handled) { 1237 LPARAM lparam, BOOL& handled) {
1230 handled = TRUE; 1238 handled = TRUE;
1231 1239
1240 if (message == WM_MOUSELEAVE)
1241 ignore_mouse_movement_ = true;
1242
1243 if (mouse_locked_) {
1244 HandleLockedMouseEvent(message, wparam, lparam);
1245 MoveCursorToCenter();
1246 return 0;
1247 }
1248
1232 if (::IsWindow(tooltip_hwnd_)) { 1249 if (::IsWindow(tooltip_hwnd_)) {
1233 // Forward mouse events through to the tooltip window 1250 // Forward mouse events through to the tooltip window
1234 MSG msg; 1251 MSG msg;
1235 msg.hwnd = m_hWnd; 1252 msg.hwnd = m_hWnd;
1236 msg.message = message; 1253 msg.message = message;
1237 msg.wParam = wparam; 1254 msg.wParam = wparam;
1238 msg.lParam = lparam; 1255 msg.lParam = lparam;
1239 SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL, 1256 SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL,
1240 reinterpret_cast<LPARAM>(&msg)); 1257 reinterpret_cast<LPARAM>(&msg));
1241 } 1258 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 1302
1286 ForwardMouseEventToRenderer(message, wparam, lparam); 1303 ForwardMouseEventToRenderer(message, wparam, lparam);
1287 return 0; 1304 return 0;
1288 } 1305 }
1289 1306
1290 LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam, 1307 LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam,
1291 LPARAM lparam, BOOL& handled) { 1308 LPARAM lparam, BOOL& handled) {
1292 handled = TRUE; 1309 handled = TRUE;
1293 1310
1294 // Force fullscreen windows to close on Escape. 1311 // Force fullscreen windows to close on Escape.
1295 if (is_fullscreen_ && (message == WM_KEYDOWN || message == WM_KEYUP) && 1312 if ((message == WM_KEYDOWN || message == WM_KEYUP) && wparam == VK_ESCAPE) {
1296 wparam == VK_ESCAPE) { 1313 if (mouse_locked_)
1297 SendMessage(WM_CANCELMODE); 1314 UnlockMouse();
1298 return 0; 1315 if (is_fullscreen_)
1316 SendMessage(WM_CANCELMODE);
1317 return 0;
1299 } 1318 }
1300 1319
1301 // If we are a pop-up, forward tab related messages to our parent HWND, so 1320 // If we are a pop-up, forward tab related messages to our parent HWND, so
1302 // that we are dismissed appropriately and so that the focus advance in our 1321 // that we are dismissed appropriately and so that the focus advance in our
1303 // parent. 1322 // parent.
1304 // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the 1323 // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the
1305 // FocusManager. 1324 // FocusManager.
1306 if (close_on_deactivate_ && 1325 if (close_on_deactivate_ &&
1307 (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) || 1326 (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) ||
1308 (message == WM_CHAR && wparam == L'\t'))) { 1327 (message == WM_CHAR && wparam == L'\t'))) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 void RenderWidgetHostViewWin::OnAccessibilityNotifications( 1492 void RenderWidgetHostViewWin::OnAccessibilityNotifications(
1474 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) { 1493 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
1475 if (!browser_accessibility_manager_.get()) { 1494 if (!browser_accessibility_manager_.get()) {
1476 browser_accessibility_manager_.reset( 1495 browser_accessibility_manager_.reset(
1477 BrowserAccessibilityManager::CreateEmptyDocument( 1496 BrowserAccessibilityManager::CreateEmptyDocument(
1478 m_hWnd, static_cast<WebAccessibility::State>(0), this)); 1497 m_hWnd, static_cast<WebAccessibility::State>(0), this));
1479 } 1498 }
1480 browser_accessibility_manager_->OnAccessibilityNotifications(params); 1499 browser_accessibility_manager_->OnAccessibilityNotifications(params);
1481 } 1500 }
1482 1501
1502 bool RenderWidgetHostViewWin::LockMouse() {
1503 if (mouse_locked_)
1504 return true;
1505
1506 mouse_locked_ = true;
1507
1508 // Hide the tooltip window if it is currently visible. When the mouse is
1509 // locked, no mouse message is relayed to the tooltip window, so we don't need
1510 // to worry that it will reappear.
1511 if (::IsWindow(tooltip_hwnd_) && tooltip_showing_) {
1512 ::SendMessage(tooltip_hwnd_, TTM_POP, 0, 0);
1513 // Sending a TTM_POP message doesn't seem to actually hide the tooltip
1514 // window, although we will receive a TTN_POP notification. As a result,
1515 // ShowWindow() is explicitly called to hide the window.
1516 ::ShowWindow(tooltip_hwnd_, SW_HIDE);
1517 }
1518
1519 // TODO(yzshen): Show an invisible cursor instead of using
1520 // ::ShowCursor(FALSE), so that MoveCursorToCenter() works with Remote
1521 // Desktop.
1522 ::ShowCursor(FALSE);
1523
1524 MoveCursorToCenter();
1525
1526 CRect rect;
1527 GetWindowRect(&rect);
1528 ::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
1529
1530 return true;
1531 }
1532
1533 void RenderWidgetHostViewWin::UnlockMouse() {
1534 if (!mouse_locked_)
1535 return;
1536
1537 mouse_locked_ = false;
1538
1539 ::ClipCursor(NULL);
1540 ::SetCursorPos(last_global_x_, last_global_y_);
1541 ::ShowCursor(TRUE);
1542
1543 if (render_widget_host_)
1544 render_widget_host_->LostMouseLock();
1545 }
1546
1483 void RenderWidgetHostViewWin::Observe(int type, 1547 void RenderWidgetHostViewWin::Observe(int type,
1484 const NotificationSource& source, 1548 const NotificationSource& source,
1485 const NotificationDetails& details) { 1549 const NotificationDetails& details) {
1486 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); 1550 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
1487 1551
1488 // Get the RenderProcessHost that posted this notification, and exit 1552 // Get the RenderProcessHost that posted this notification, and exit
1489 // if it's not the one associated with this host view. 1553 // if it's not the one associated with this host view.
1490 RenderProcessHost* render_process_host = 1554 RenderProcessHost* render_process_host =
1491 Source<RenderProcessHost>(source).ptr(); 1555 Source<RenderProcessHost>(source).ptr();
1492 DCHECK(render_process_host); 1556 DCHECK(render_process_host);
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1793 1857
1794 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, 1858 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message,
1795 WPARAM wparam, 1859 WPARAM wparam,
1796 LPARAM lparam) { 1860 LPARAM lparam) {
1797 if (!render_widget_host_) 1861 if (!render_widget_host_)
1798 return; 1862 return;
1799 1863
1800 WebMouseEvent event( 1864 WebMouseEvent event(
1801 WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam)); 1865 WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam));
1802 1866
1867 if (mouse_locked_) {
1868 CPoint center = GetClientCenter();
1869
1870 event.movementX = event.windowX - center.x;
1871 event.movementY = event.windowY - center.y;
1872 event.x = last_x_;
1873 event.y = last_y_;
1874 event.windowX = last_x_;
1875 event.windowY = last_y_;
1876 event.globalX = last_global_x_;
1877 event.globalY = last_global_y_;
1878 } else {
1879 if (ignore_mouse_movement_) {
1880 ignore_mouse_movement_ = false;
1881 event.movementX = 0;
1882 event.movementY = 0;
1883 } else {
1884 event.movementX = event.globalX - last_global_x_;
1885 event.movementY = event.globalY - last_global_y_;
1886 }
1887
1888 last_x_ = event.windowX;
1889 last_y_ = event.windowY;
1890 last_global_x_ = event.globalX;
1891 last_global_y_ = event.globalY;
1892 }
1893
1803 // Send the event to the renderer before changing mouse capture, so that the 1894 // Send the event to the renderer before changing mouse capture, so that the
1804 // capturelost event arrives after mouseup. 1895 // capturelost event arrives after mouseup.
1805 render_widget_host_->ForwardMouseEvent(event); 1896 render_widget_host_->ForwardMouseEvent(event);
1806 1897
1807 switch (event.type) { 1898 switch (event.type) {
1808 case WebInputEvent::MouseMove: 1899 case WebInputEvent::MouseMove:
1809 TrackMouseLeave(true); 1900 TrackMouseLeave(true);
1810 break; 1901 break;
1811 case WebInputEvent::MouseLeave: 1902 case WebInputEvent::MouseLeave:
1812 TrackMouseLeave(false); 1903 TrackMouseLeave(false);
(...skipping 28 matching lines...) Expand all
1841 DWORD ex_style) { 1932 DWORD ex_style) {
1842 parent_hwnd_ = parent_hwnd; 1933 parent_hwnd_ = parent_hwnd;
1843 Create(parent_hwnd_, NULL, NULL, WS_POPUP, ex_style); 1934 Create(parent_hwnd_, NULL, NULL, WS_POPUP, ex_style);
1844 MoveWindow(pos.x(), pos.y(), pos.width(), pos.height(), TRUE); 1935 MoveWindow(pos.x(), pos.y(), pos.width(), pos.height(), TRUE);
1845 // To show tooltip on popup window.(e.g. title in <select>) 1936 // To show tooltip on popup window.(e.g. title in <select>)
1846 // Popups default to showing, which means |DidBecomeSelected()| isn't invoked. 1937 // Popups default to showing, which means |DidBecomeSelected()| isn't invoked.
1847 // Ensure the tooltip is created otherwise tooltips are never shown. 1938 // Ensure the tooltip is created otherwise tooltips are never shown.
1848 EnsureTooltip(); 1939 EnsureTooltip();
1849 ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA); 1940 ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
1850 } 1941 }
1942
1943 CPoint RenderWidgetHostViewWin::GetClientCenter() const {
1944 CRect rect;
1945 GetClientRect(&rect);
1946 return rect.CenterPoint();
1947 }
1948
1949 void RenderWidgetHostViewWin::MoveCursorToCenter() const {
1950 CPoint center = GetClientCenter();
1951 ClientToScreen(&center);
1952 if (!::SetCursorPos(center.x, center.y))
1953 LOG_GETLASTERROR(WARNING) << "Failed to set cursor position.";
1954 }
1955
1956 void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message,
1957 WPARAM wparam,
1958 LPARAM lparam) {
1959 DCHECK(mouse_locked_);
1960
1961 if (message == WM_MOUSEMOVE) {
1962 CPoint center = GetClientCenter();
1963 // Ignore WM_MOUSEMOVE messages generated by MoveCursorToCenter().
1964 if (LOWORD(lparam) == center.x && HIWORD(lparam) == center.y)
1965 return;
1966 }
1967
1968 ForwardMouseEventToRenderer(message, wparam, lparam);
1969 }
1970
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698