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

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: 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 958 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 ime_input_.DestroyImeWindow(m_hWnd); 1228 ime_input_.DestroyImeWindow(m_hWnd);
1223 // Let WTL call ::DefWindowProc() and release its resources. 1229 // Let WTL call ::DefWindowProc() and release its resources.
1224 handled = FALSE; 1230 handled = FALSE;
1225 return 0; 1231 return 0;
1226 } 1232 }
1227 1233
1228 LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam, 1234 LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam,
1229 LPARAM lparam, BOOL& handled) { 1235 LPARAM lparam, BOOL& handled) {
1230 handled = TRUE; 1236 handled = TRUE;
1231 1237
1238 if (message == WM_MOUSELEAVE)
1239 ignore_mouse_movement_ = true;
1240
1241 if (mouse_locked_) {
1242 HandleLockedMouseEvent(message, wparam, lparam);
1243 MoveCursorToCenter();
1244 return 0;
1245 }
1246
1247 // TODO(yzshen): is this correct? Nothing goes to the tool tip window?
1232 if (::IsWindow(tooltip_hwnd_)) { 1248 if (::IsWindow(tooltip_hwnd_)) {
1233 // Forward mouse events through to the tooltip window 1249 // Forward mouse events through to the tooltip window
1234 MSG msg; 1250 MSG msg;
1235 msg.hwnd = m_hWnd; 1251 msg.hwnd = m_hWnd;
1236 msg.message = message; 1252 msg.message = message;
1237 msg.wParam = wparam; 1253 msg.wParam = wparam;
1238 msg.lParam = lparam; 1254 msg.lParam = lparam;
1239 SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL, 1255 SendMessage(tooltip_hwnd_, TTM_RELAYEVENT, NULL,
1240 reinterpret_cast<LPARAM>(&msg)); 1256 reinterpret_cast<LPARAM>(&msg));
1241 } 1257 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 1301
1286 ForwardMouseEventToRenderer(message, wparam, lparam); 1302 ForwardMouseEventToRenderer(message, wparam, lparam);
1287 return 0; 1303 return 0;
1288 } 1304 }
1289 1305
1290 LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam, 1306 LRESULT RenderWidgetHostViewWin::OnKeyEvent(UINT message, WPARAM wparam,
1291 LPARAM lparam, BOOL& handled) { 1307 LPARAM lparam, BOOL& handled) {
1292 handled = TRUE; 1308 handled = TRUE;
1293 1309
1294 // Force fullscreen windows to close on Escape. 1310 // Force fullscreen windows to close on Escape.
1295 if (is_fullscreen_ && (message == WM_KEYDOWN || message == WM_KEYUP) && 1311 if ((message == WM_KEYDOWN || message == WM_KEYUP) && wparam == VK_ESCAPE) {
1296 wparam == VK_ESCAPE) { 1312 if (mouse_locked_)
1297 SendMessage(WM_CANCELMODE); 1313 UnlockMouse();
1298 return 0; 1314 if (is_fullscreen_)
1315 SendMessage(WM_CANCELMODE);
1316 return 0;
1299 } 1317 }
1300 1318
1301 // If we are a pop-up, forward tab related messages to our parent HWND, so 1319 // 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 1320 // that we are dismissed appropriately and so that the focus advance in our
1303 // parent. 1321 // parent.
1304 // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the 1322 // TODO(jcampan): http://b/issue?id=1192881 Could be abstracted in the
1305 // FocusManager. 1323 // FocusManager.
1306 if (close_on_deactivate_ && 1324 if (close_on_deactivate_ &&
1307 (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) || 1325 (((message == WM_KEYDOWN || message == WM_KEYUP) && (wparam == VK_TAB)) ||
1308 (message == WM_CHAR && wparam == L'\t'))) { 1326 (message == WM_CHAR && wparam == L'\t'))) {
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 void RenderWidgetHostViewWin::OnAccessibilityNotifications( 1491 void RenderWidgetHostViewWin::OnAccessibilityNotifications(
1474 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) { 1492 const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params) {
1475 if (!browser_accessibility_manager_.get()) { 1493 if (!browser_accessibility_manager_.get()) {
1476 browser_accessibility_manager_.reset( 1494 browser_accessibility_manager_.reset(
1477 BrowserAccessibilityManager::CreateEmptyDocument( 1495 BrowserAccessibilityManager::CreateEmptyDocument(
1478 m_hWnd, static_cast<WebAccessibility::State>(0), this)); 1496 m_hWnd, static_cast<WebAccessibility::State>(0), this));
1479 } 1497 }
1480 browser_accessibility_manager_->OnAccessibilityNotifications(params); 1498 browser_accessibility_manager_->OnAccessibilityNotifications(params);
1481 } 1499 }
1482 1500
1501 bool RenderWidgetHostViewWin::LockMouse() {
1502 if (mouse_locked_)
1503 return true;
1504
1505 mouse_locked_ = true;
1506 // TODO(yzshen): (1) Make sure it works with the current_cursor_.
1507 // (2) if not confined successful, we can tell once we receive
1508 // mouse leave message, does that help?
1509 // (3) ResetTooltip / EnsureTooltip, and make sure they work
1510 // consistently with other part of the code.
1511
1512 // TODO(yzshen): Show an invisible cursor instead of using
1513 // ::ShowCursor(FALSE), so that MoveCursorToCenter() works with Remote
1514 // Desktop.
1515 ::ShowCursor(FALSE);
1516
1517 MoveCursorToCenter();
1518
1519 CRect rect;
1520 GetWindowRect(&rect);
1521 ::ClipCursor(&rect);
1522
1523 return true;
1524 }
1525
1526 void RenderWidgetHostViewWin::UnlockMouse() {
1527 if (!mouse_locked_)
1528 return;
1529
1530 mouse_locked_ = false;
1531
1532 ::ClipCursor(NULL);
1533 ::SetCursorPos(last_global_x_, last_global_y_);
1534 ::ShowCursor(TRUE);
1535
1536 if (render_widget_host_)
1537 render_widget_host_->LostMouseLock();
1538 }
1539
1483 void RenderWidgetHostViewWin::Observe(int type, 1540 void RenderWidgetHostViewWin::Observe(int type,
1484 const NotificationSource& source, 1541 const NotificationSource& source,
1485 const NotificationDetails& details) { 1542 const NotificationDetails& details) {
1486 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED); 1543 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
1487 1544
1488 // Get the RenderProcessHost that posted this notification, and exit 1545 // Get the RenderProcessHost that posted this notification, and exit
1489 // if it's not the one associated with this host view. 1546 // if it's not the one associated with this host view.
1490 RenderProcessHost* render_process_host = 1547 RenderProcessHost* render_process_host =
1491 Source<RenderProcessHost>(source).ptr(); 1548 Source<RenderProcessHost>(source).ptr();
1492 DCHECK(render_process_host); 1549 DCHECK(render_process_host);
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1793 1850
1794 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message, 1851 void RenderWidgetHostViewWin::ForwardMouseEventToRenderer(UINT message,
1795 WPARAM wparam, 1852 WPARAM wparam,
1796 LPARAM lparam) { 1853 LPARAM lparam) {
1797 if (!render_widget_host_) 1854 if (!render_widget_host_)
1798 return; 1855 return;
1799 1856
1800 WebMouseEvent event( 1857 WebMouseEvent event(
1801 WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam)); 1858 WebInputEventFactory::mouseEvent(m_hWnd, message, wparam, lparam));
1802 1859
1860 if (mouse_locked_) {
1861 CPoint center = GetClientCenter();
1862
1863 event.movementX = event.windowX - center.x;
1864 event.movementY = event.windowY - center.y;
1865 event.x = last_x_;
1866 event.y = last_y_;
1867 event.windowX = last_x_;
1868 event.windowY = last_y_;
1869 event.globalX = last_global_x_;
1870 event.globalY = last_global_y_;
1871 } else {
1872 if (ignore_mouse_movement_) {
1873 ignore_mouse_movement_ = false;
1874 event.movementX = 0;
1875 event.movementY = 0;
1876 } else {
1877 event.movementX = event.globalX - last_global_x_;
1878 event.movementY = event.globalY - last_global_y_;
1879 }
1880
1881 last_x_ = event.windowX;
1882 last_y_ = event.windowY;
1883 last_global_x_ = event.globalX;
1884 last_global_y_ = event.globalY;
1885 }
1886
1803 // Send the event to the renderer before changing mouse capture, so that the 1887 // Send the event to the renderer before changing mouse capture, so that the
1804 // capturelost event arrives after mouseup. 1888 // capturelost event arrives after mouseup.
1805 render_widget_host_->ForwardMouseEvent(event); 1889 render_widget_host_->ForwardMouseEvent(event);
1806 1890
1807 switch (event.type) { 1891 switch (event.type) {
1808 case WebInputEvent::MouseMove: 1892 case WebInputEvent::MouseMove:
1809 TrackMouseLeave(true); 1893 TrackMouseLeave(true);
1810 break; 1894 break;
1811 case WebInputEvent::MouseLeave: 1895 case WebInputEvent::MouseLeave:
1812 TrackMouseLeave(false); 1896 TrackMouseLeave(false);
1813 break; 1897 break;
1814 case WebInputEvent::MouseDown: 1898 case WebInputEvent::MouseDown:
1815 SetCapture(); 1899 SetCapture();
1816 break; 1900 break;
1817 case WebInputEvent::MouseUp: 1901 case WebInputEvent::MouseUp:
1818 if (GetCapture() == m_hWnd) 1902 if (GetCapture() == m_hWnd)
1819 ReleaseCapture(); 1903 ReleaseCapture();
1820 break; 1904 break;
1821 } 1905 }
1822 1906
1823 if (IsActivatable() && event.type == WebInputEvent::MouseDown) { 1907 if (IsActivatable() && event.type == WebInputEvent::MouseDown) {
1824 // This is a temporary workaround for bug 765011 to get focus when the 1908 // This is a temporary workaround for bug 765011 to get focus when the
1825 // mouse is clicked. This happens after the mouse down event is sent to 1909 // mouse is clicked. This happens after the mouse down event is sent to
1826 // the renderer because normally Windows does a WM_SETFOCUS after 1910 // the renderer because normally Windows does a WM_SETFOCUS after
1827 // WM_LBUTTONDOWN. 1911 // WM_LBUTTONDOWN.
1828 SetFocus(); 1912 SetFocus();
1829 } 1913 }
1914
1830 } 1915 }
1831 1916
1832 void RenderWidgetHostViewWin::ShutdownHost() { 1917 void RenderWidgetHostViewWin::ShutdownHost() {
1833 shutdown_factory_.RevokeAll(); 1918 shutdown_factory_.RevokeAll();
1834 if (render_widget_host_) 1919 if (render_widget_host_)
1835 render_widget_host_->Shutdown(); 1920 render_widget_host_->Shutdown();
1836 // Do not touch any members at this point, |this| has been deleted. 1921 // Do not touch any members at this point, |this| has been deleted.
1837 } 1922 }
1838 1923
1839 void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd, 1924 void RenderWidgetHostViewWin::DoPopupOrFullscreenInit(HWND parent_hwnd,
1840 const gfx::Rect& pos, 1925 const gfx::Rect& pos,
1841 DWORD ex_style) { 1926 DWORD ex_style) {
1842 parent_hwnd_ = parent_hwnd; 1927 parent_hwnd_ = parent_hwnd;
1843 Create(parent_hwnd_, NULL, NULL, WS_POPUP, ex_style); 1928 Create(parent_hwnd_, NULL, NULL, WS_POPUP, ex_style);
1844 MoveWindow(pos.x(), pos.y(), pos.width(), pos.height(), TRUE); 1929 MoveWindow(pos.x(), pos.y(), pos.width(), pos.height(), TRUE);
1845 // To show tooltip on popup window.(e.g. title in <select>) 1930 // To show tooltip on popup window.(e.g. title in <select>)
1846 // Popups default to showing, which means |DidBecomeSelected()| isn't invoked. 1931 // Popups default to showing, which means |DidBecomeSelected()| isn't invoked.
1847 // Ensure the tooltip is created otherwise tooltips are never shown. 1932 // Ensure the tooltip is created otherwise tooltips are never shown.
1848 EnsureTooltip(); 1933 EnsureTooltip();
1849 ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA); 1934 ShowWindow(IsActivatable() ? SW_SHOW : SW_SHOWNA);
1850 } 1935 }
1936
1937 CPoint RenderWidgetHostViewWin::GetClientCenter() const {
1938 CRect rect;
1939 GetClientRect(&rect);
1940 return rect.CenterPoint();
1941 }
1942
1943 void RenderWidgetHostViewWin::MoveCursorToCenter() const {
1944 CPoint center = GetClientCenter();
1945 ClientToScreen(&center);
1946 if (!::SetCursorPos(center.x, center.y))
1947 LOG_GETLASTERROR(WARNING) << "Failed to set cursor position.";
1948 }
1949
1950 void RenderWidgetHostViewWin::HandleLockedMouseEvent(UINT message,
1951 WPARAM wparam,
1952 LPARAM lparam) {
1953 DCHECK(mouse_locked_);
1954
1955 if (message == WM_MOUSEMOVE) {
1956 CPoint center = GetClientCenter();
1957 // Ignore WM_MOUSEMOVE messages generated by MoveCursorToCenter().
1958 if (LOWORD(lparam) == center.x && HIWORD(lparam) == center.y)
1959 return;
1960 }
1961
1962 ForwardMouseEventToRenderer(message, wparam, lparam);
1963 }
1964
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698