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

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

Issue 8341125: Forward Windows touch messages to the renderer (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 1 month 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 #include "content/browser/renderer_host/render_widget_host_view_win.h" 5 #include "content/browser/renderer_host/render_widget_host_view_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/command_line.h" 9 #include "base/command_line.h"
10 #include "base/i18n/rtl.h" 10 #include "base/i18n/rtl.h"
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 result.windowX = result.x; 283 result.windowX = result.x;
284 result.windowY = result.y; 284 result.windowY = result.y;
285 // Note that we support diagonal scrolling. 285 // Note that we support diagonal scrolling.
286 result.deltaX = static_cast<float>(delta.x); 286 result.deltaX = static_cast<float>(delta.x);
287 result.wheelTicksX = WHEEL_DELTA; 287 result.wheelTicksX = WHEEL_DELTA;
288 result.deltaY = static_cast<float>(delta.y); 288 result.deltaY = static_cast<float>(delta.y);
289 result.wheelTicksY = WHEEL_DELTA; 289 result.wheelTicksY = WHEEL_DELTA;
290 return result; 290 return result;
291 } 291 }
292 292
293 static const int kTouchMask = 0x7;
294
295 inline int GetTouchType(const TOUCHINPUT& point) {
296 return point.dwFlags & kTouchMask;
297 }
298
299 inline void SetTouchType(TOUCHINPUT* point, int type) {
300 point->dwFlags = (point->dwFlags & kTouchMask) | type;
301 }
302
293 } // namespace 303 } // namespace
294 304
295 /////////////////////////////////////////////////////////////////////////////// 305 ///////////////////////////////////////////////////////////////////////////////
296 // RenderWidgetHostViewWin, public: 306 // RenderWidgetHostViewWin, public:
297 307
298 RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget) 308 RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
299 : render_widget_host_(widget), 309 : render_widget_host_(widget),
300 compositor_host_window_(NULL), 310 compositor_host_window_(NULL),
301 hide_compositor_window_at_next_paint_(false), 311 hide_compositor_window_at_next_paint_(false),
302 track_mouse_leave_(false), 312 track_mouse_leave_(false),
303 ime_notification_(false), 313 ime_notification_(false),
304 capture_enter_key_(false), 314 capture_enter_key_(false),
305 is_hidden_(false), 315 is_hidden_(false),
306 about_to_validate_and_paint_(false), 316 about_to_validate_and_paint_(false),
307 close_on_deactivate_(false), 317 close_on_deactivate_(false),
308 being_destroyed_(false), 318 being_destroyed_(false),
309 tooltip_hwnd_(NULL), 319 tooltip_hwnd_(NULL),
310 tooltip_showing_(false), 320 tooltip_showing_(false),
311 shutdown_factory_(this), 321 shutdown_factory_(this),
312 parent_hwnd_(NULL), 322 parent_hwnd_(NULL),
313 is_loading_(false), 323 is_loading_(false),
314 overlay_color_(0), 324 overlay_color_(0),
315 text_input_type_(ui::TEXT_INPUT_TYPE_NONE), 325 text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
316 is_fullscreen_(false), 326 is_fullscreen_(false),
317 ignore_mouse_movement_(true), 327 ignore_mouse_movement_(true),
318 composition_range_(ui::Range::InvalidRange()), 328 composition_range_(ui::Range::InvalidRange()),
319 ignore_next_lbutton_message_at_same_location(false), 329 ignore_next_lbutton_message_at_same_location(false),
320 last_pointer_down_location_(0) { 330 last_pointer_down_location_(0),
331 touch_state_(this) {
321 render_widget_host_->SetView(this); 332 render_widget_host_->SetView(this);
322 registrar_.Add(this, 333 registrar_.Add(this,
323 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, 334 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
324 content::NotificationService::AllBrowserContextsAndSources()); 335 content::NotificationService::AllBrowserContextsAndSources());
325 } 336 }
326 337
327 RenderWidgetHostViewWin::~RenderWidgetHostViewWin() { 338 RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
328 UnlockMouse(); 339 UnlockMouse();
329 ResetTooltip(); 340 ResetTooltip();
330 } 341 }
(...skipping 541 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 883
873 LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) { 884 LRESULT RenderWidgetHostViewWin::OnCreate(CREATESTRUCT* create_struct) {
874 // Call the WM_INPUTLANGCHANGE message handler to initialize the input locale 885 // Call the WM_INPUTLANGCHANGE message handler to initialize the input locale
875 // of a browser process. 886 // of a browser process.
876 OnInputLangChange(0, 0); 887 OnInputLangChange(0, 0);
877 // Marks that window as supporting mouse-wheel messages rerouting so it is 888 // Marks that window as supporting mouse-wheel messages rerouting so it is
878 // scrolled when under the mouse pointer even if inactive. 889 // scrolled when under the mouse pointer even if inactive.
879 props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(m_hWnd)); 890 props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(m_hWnd));
880 891
881 if (base::win::GetVersion() >= base::win::VERSION_WIN7) { 892 if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
882 // Single finger panning is consistent with other windows applications. 893 // Use gestures if touch event switch isn't present or registration fails.
883 const DWORD gesture_allow = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | 894 if (!CommandLine::ForCurrentProcess()->HasSwitch(
884 GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; 895 switches::kEnableTouchEvents) ||
885 const DWORD gesture_block = GC_PAN_WITH_GUTTER; 896 !RegisterTouchWindow(m_hWnd, 0)) {
886 GESTURECONFIG gc[] = { 897 // Single finger panning is consistent with other windows applications.
887 { GID_ZOOM, GC_ZOOM, 0 }, 898 const DWORD gesture_allow = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY |
888 { GID_PAN, gesture_allow , gesture_block}, 899 GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY;
889 { GID_TWOFINGERTAP, GC_TWOFINGERTAP , 0}, 900 const DWORD gesture_block = GC_PAN_WITH_GUTTER;
890 { GID_PRESSANDTAP, GC_PRESSANDTAP , 0} 901 GESTURECONFIG gc[] = {
891 }; 902 { GID_ZOOM, GC_ZOOM, 0 },
892 if (!SetGestureConfig(m_hWnd, 0, arraysize(gc), gc, sizeof(GESTURECONFIG))) 903 { GID_PAN, gesture_allow , gesture_block},
893 { 904 { GID_TWOFINGERTAP, GC_TWOFINGERTAP , 0},
894 NOTREACHED(); 905 { GID_PRESSANDTAP, GC_PRESSANDTAP , 0}
906 };
907 if (!SetGestureConfig(m_hWnd, 0, arraysize(gc), gc,
908 sizeof(GESTURECONFIG))) {
909 NOTREACHED();
910 }
895 } 911 }
896 } 912 }
897 913
898 return 0; 914 return 0;
899 } 915 }
900 916
901 void RenderWidgetHostViewWin::OnActivate(UINT action, BOOL minimized, 917 void RenderWidgetHostViewWin::OnActivate(UINT action, BOOL minimized,
902 HWND window) { 918 HWND window) {
903 // If the container is a popup, clicking elsewhere on screen should close the 919 // If the container is a popup, clicking elsewhere on screen should close the
904 // popup. 920 // popup.
(...skipping 15 matching lines...) Expand all
920 // handler for NPP_DestroyStream relies on. 936 // handler for NPP_DestroyStream relies on.
921 // 937 //
922 // The fix is to detach plugin windows from web contents when it is going 938 // The fix is to detach plugin windows from web contents when it is going
923 // away. This will prevent the plugin windows from getting destroyed 939 // away. This will prevent the plugin windows from getting destroyed
924 // automatically. The detached plugin windows will get cleaned up in proper 940 // automatically. The detached plugin windows will get cleaned up in proper
925 // sequence as part of the usual cleanup when the plugin instance goes away. 941 // sequence as part of the usual cleanup when the plugin instance goes away.
926 EnumChildWindows(m_hWnd, DetachPluginWindowsCallback, NULL); 942 EnumChildWindows(m_hWnd, DetachPluginWindowsCallback, NULL);
927 943
928 props_.reset(); 944 props_.reset();
929 945
946 if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
947 IsTouchWindow(m_hWnd, NULL)) {
948 UnregisterTouchWindow(m_hWnd);
949 }
950
930 CleanupCompositorWindow(); 951 CleanupCompositorWindow();
931 952
932 ResetTooltip(); 953 ResetTooltip();
933 TrackMouseLeave(false); 954 TrackMouseLeave(false);
934 } 955 }
935 956
936 void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) { 957 void RenderWidgetHostViewWin::OnPaint(HDC unused_dc) {
937 if (!render_widget_host_) 958 if (!render_widget_host_)
938 return; 959 return;
939 960
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 return 0; 1116 return 0;
1096 } 1117 }
1097 1118
1098 void RenderWidgetHostViewWin::OnSetFocus(HWND window) { 1119 void RenderWidgetHostViewWin::OnSetFocus(HWND window) {
1099 if (browser_accessibility_manager_.get()) 1120 if (browser_accessibility_manager_.get())
1100 browser_accessibility_manager_->GotFocus(); 1121 browser_accessibility_manager_->GotFocus();
1101 if (render_widget_host_) { 1122 if (render_widget_host_) {
1102 render_widget_host_->GotFocus(); 1123 render_widget_host_->GotFocus();
1103 render_widget_host_->SetActive(true); 1124 render_widget_host_->SetActive(true);
1104 } 1125 }
1126 if (touch_state_.ReleaseTouchPoints())
1127 render_widget_host_->ForwardTouchEvent(touch_state_.touch_event());
1105 } 1128 }
1106 1129
1107 void RenderWidgetHostViewWin::OnKillFocus(HWND window) { 1130 void RenderWidgetHostViewWin::OnKillFocus(HWND window) {
1108 if (render_widget_host_) { 1131 if (render_widget_host_) {
1109 render_widget_host_->SetActive(false); 1132 render_widget_host_->SetActive(false);
1110 render_widget_host_->Blur(); 1133 render_widget_host_->Blur();
1111 } 1134 }
1135 if (touch_state_.ReleaseTouchPoints())
1136 render_widget_host_->ForwardTouchEvent(touch_state_.touch_event());
1112 } 1137 }
1113 1138
1114 void RenderWidgetHostViewWin::OnCaptureChanged(HWND window) { 1139 void RenderWidgetHostViewWin::OnCaptureChanged(HWND window) {
1115 if (render_widget_host_) 1140 if (render_widget_host_)
1116 render_widget_host_->LostCapture(); 1141 render_widget_host_->LostCapture();
1117 } 1142 }
1118 1143
1119 void RenderWidgetHostViewWin::OnCancelMode() { 1144 void RenderWidgetHostViewWin::OnCancelMode() {
1120 if (render_widget_host_) 1145 if (render_widget_host_)
1121 render_widget_host_->LostCapture(); 1146 render_widget_host_->LostCapture();
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 1588
1564 if (!handled_by_TabContents && render_widget_host_) { 1589 if (!handled_by_TabContents && render_widget_host_) {
1565 render_widget_host_->ForwardWheelEvent( 1590 render_widget_host_->ForwardWheelEvent(
1566 WebInputEventFactory::mouseWheelEvent(m_hWnd, message, wparam, 1591 WebInputEventFactory::mouseWheelEvent(m_hWnd, message, wparam,
1567 lparam)); 1592 lparam));
1568 } 1593 }
1569 handled = TRUE; 1594 handled = TRUE;
1570 return 0; 1595 return 0;
1571 } 1596 }
1572 1597
1598 RenderWidgetHostViewWin::WebTouchState::WebTouchState(const CWindowImpl* window)
1599 : window_(window) { }
1600
1601 size_t RenderWidgetHostViewWin::WebTouchState::UpdateTouchPoints(
1602 TOUCHINPUT* points, size_t count) {
1603 // First we reset all touch event state. This involves removing any released
1604 // touchpoints and marking the rest as stationary. After that we go through
1605 // and alter/add any touchpoints (from the touch input buffer) that we can
1606 // coalesce into a single message. The return value is the number of consumed
1607 // input message.
1608 WebKit::WebTouchPoint* point = touch_event_.touches;
1609 WebKit::WebTouchPoint* end = point + touch_event_.touchesLength;
1610 while (point < end) {
1611 if (point->state == WebKit::WebTouchPoint::StateReleased) {
1612 *point = *(--end);
1613 --touch_event_.touchesLength;
1614 } else {
1615 point->state = WebKit::WebTouchPoint::StateStationary;
1616 point++;
1617 }
1618 }
1619 touch_event_.changedTouchesLength = 0;
1620
1621 // Consume all events of the same type and add them to the changed list.
1622 int last_type = 0;
1623 for (size_t i = 0; i < count; ++i) {
1624 if (points[i].dwID == 0ul)
1625 continue;
1626
1627 WebKit::WebTouchPoint* point = NULL;
1628 for (unsigned j = 0; j < touch_event_.touchesLength; ++j) {
1629 if (static_cast<DWORD>(touch_event_.touches[j].id) == points[i].dwID) {
1630 point = &touch_event_.touches[j];
1631 break;
1632 }
1633 }
1634
1635 // Use a move instead if we see a down on a point we already have.
1636 int type = GetTouchType(points[i]);
1637 if (point && type == TOUCHEVENTF_DOWN)
1638 SetTouchType(&points[i], TOUCHEVENTF_MOVE);
1639
1640 // Stop processing when the event type changes.
1641 if (touch_event_.changedTouchesLength && type != last_type)
1642 return i;
1643
1644 last_type = type;
1645 switch (type) {
1646 case TOUCHEVENTF_DOWN: {
1647 if (!(point = AddTouchPoint(&points[i])))
1648 continue;
1649 touch_event_.type = WebKit::WebInputEvent::TouchStart;
1650 break;
1651 }
1652
1653 case TOUCHEVENTF_UP: {
1654 if (!point) // Just throw away a stray up.
1655 continue;
1656 point->state = WebKit::WebTouchPoint::StateReleased;
1657 UpdateTouchPoint(point, &points[i]);
1658 touch_event_.type = WebKit::WebInputEvent::TouchEnd;
1659 break;
1660 }
1661
1662 case TOUCHEVENTF_MOVE: {
1663 if (point) {
1664 point->state = WebKit::WebTouchPoint::StateMoved;
1665 // Don't update the message if the point didn't really move.
1666 if (UpdateTouchPoint(point, &points[i]))
1667 continue;
1668 touch_event_.type = WebKit::WebInputEvent::TouchMove;
1669 } else if (touch_event_.changedTouchesLength) {
1670 // Can't add a point if we're already handling move events.
1671 return i;
1672 } else {
1673 // Treat a move with no existing point as a down.
1674 if (!(point = AddTouchPoint(&points[i])))
1675 continue;
1676 last_type = TOUCHEVENTF_DOWN;
1677 SetTouchType(&points[i], TOUCHEVENTF_DOWN);
1678 touch_event_.type = WebKit::WebInputEvent::TouchStart;
1679 }
1680 break;
1681 }
1682
1683 default:
1684 NOTREACHED();
1685 continue;
1686 }
1687 touch_event_.changedTouches[touch_event_.changedTouchesLength++] = *point;
1688 }
1689
1690 return count;
1691 }
1692
1693 bool RenderWidgetHostViewWin::WebTouchState::ReleaseTouchPoints() {
1694 if (touch_event_.touchesLength == 0)
1695 return false;
1696 // Mark every active touchpoint as released.
1697 touch_event_.type = WebKit::WebInputEvent::TouchEnd;
1698 touch_event_.changedTouchesLength = touch_event_.touchesLength;
1699 for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) {
1700 touch_event_.touches[i].state = WebKit::WebTouchPoint::StateReleased;
1701 touch_event_.changedTouches[i].state =
1702 WebKit::WebTouchPoint::StateReleased;
1703 }
1704
1705 return true;
1706 }
1707
1708 WebKit::WebTouchPoint* RenderWidgetHostViewWin::WebTouchState::AddTouchPoint(
1709 TOUCHINPUT* touch_input) {
1710 if (touch_event_.touchesLength >= WebKit::WebTouchEvent::touchesLengthCap)
1711 return NULL;
1712 WebKit::WebTouchPoint* point =
1713 &touch_event_.touches[touch_event_.touchesLength++];
1714 point->state = WebKit::WebTouchPoint::StatePressed;
1715 point->id = touch_input->dwID;
1716 UpdateTouchPoint(point, touch_input);
1717 return point;
1718 }
1719
1720 bool RenderWidgetHostViewWin::WebTouchState::UpdateTouchPoint(
1721 WebKit::WebTouchPoint* touch_point,
1722 TOUCHINPUT* touch_input) {
1723 CPoint coordinates(TOUCH_COORD_TO_PIXEL(touch_input->x),
1724 TOUCH_COORD_TO_PIXEL(touch_input->y));
1725 int radius_x = 1;
1726 int radius_y = 1;
1727 if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) {
1728 radius_x = TOUCH_COORD_TO_PIXEL(touch_input->cxContact);
1729 radius_y = TOUCH_COORD_TO_PIXEL(touch_input->cyContact);
1730 }
1731
1732 // Detect and exclude stationary moves.
1733 if (GetTouchType(*touch_input) == TOUCHEVENTF_MOVE &&
1734 touch_point->screenPosition.x == coordinates.x &&
1735 touch_point->screenPosition.y == coordinates.y &&
1736 touch_point->radiusX == radius_x &&
1737 touch_point->radiusY == radius_y) {
1738 touch_point->state = WebKit::WebTouchPoint::StateStationary;
1739 return true;
1740 }
1741
1742 touch_point->screenPosition.x = coordinates.x;
1743 touch_point->screenPosition.y = coordinates.y;
1744 window_->GetParent().ScreenToClient(&coordinates);
1745 touch_point->position.x = coordinates.x;
1746 touch_point->position.y = coordinates.y;
1747 touch_point->radiusX = radius_x;
1748 touch_point->radiusY = radius_y;
1749 touch_point->force = 0;
1750 touch_point->rotationAngle = 0;
1751 return false;
1752 }
1753
1754 LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam,
1755 LPARAM lparam, BOOL& handled) {
1756 // TODO(jschuh): Add support for an arbitrary number of touchpoints.
1757 size_t total = std::min(static_cast<int>(LOWORD(wparam)),
1758 static_cast<int>(WebKit::WebTouchEvent::touchesLengthCap));
1759 TOUCHINPUT points[WebKit::WebTouchEvent::touchesLengthCap];
1760
1761 if (!total || !GetTouchInputInfo((HTOUCHINPUT)lparam, total,
1762 points, sizeof(TOUCHINPUT))) {
1763 return 0;
1764 }
1765
1766 for (size_t start = 0; start < total;) {
1767 start += touch_state_.UpdateTouchPoints(points + start, total - start);
1768 if (touch_state_.is_changed())
1769 render_widget_host_->ForwardTouchEvent(touch_state_.touch_event());
1770 }
1771
1772 CloseTouchInputHandle((HTOUCHINPUT)lparam);
1773
1774 return 0;
1775 }
1776
1573 LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message, 1777 LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message,
1574 WPARAM wparam, 1778 WPARAM wparam,
1575 LPARAM lparam, 1779 LPARAM lparam,
1576 BOOL& handled) { 1780 BOOL& handled) {
1577 if (!render_widget_host_) 1781 if (!render_widget_host_)
1578 return MA_NOACTIVATE; 1782 return MA_NOACTIVATE;
1579 1783
1580 if (!IsActivatable()) 1784 if (!IsActivatable())
1581 return MA_NOACTIVATE; 1785 return MA_NOACTIVATE;
1582 1786
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
2225 2429
2226 size_t offset = selection_range_.GetMin() - selection_text_offset_; 2430 size_t offset = selection_range_.GetMin() - selection_text_offset_;
2227 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING), 2431 memcpy(reinterpret_cast<char*>(reconv) + sizeof(RECONVERTSTRING),
2228 selection_text_.c_str() + offset, len * sizeof(WCHAR)); 2432 selection_text_.c_str() + offset, len * sizeof(WCHAR));
2229 2433
2230 // According to Microsft API document, IMR_RECONVERTSTRING and 2434 // According to Microsft API document, IMR_RECONVERTSTRING and
2231 // IMR_DOCUMENTFEED should return reconv, but some applications return 2435 // IMR_DOCUMENTFEED should return reconv, but some applications return
2232 // need_size. 2436 // need_size.
2233 return reinterpret_cast<LRESULT>(reconv); 2437 return reinterpret_cast<LRESULT>(reconv);
2234 } 2438 }
OLDNEW
« no previous file with comments | « content/browser/renderer_host/render_widget_host_view_win.h ('k') | content/public/common/content_switches.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698