Chromium Code Reviews| Index: content/browser/renderer_host/render_widget_host_view_win.cc |
| =================================================================== |
| --- content/browser/renderer_host/render_widget_host_view_win.cc (revision 108760) |
| +++ content/browser/renderer_host/render_widget_host_view_win.cc (working copy) |
| @@ -8,11 +8,13 @@ |
| #include "base/command_line.h" |
| #include "base/i18n/rtl.h" |
| +#include "base/logging.h" |
| #include "base/metrics/histogram.h" |
| #include "base/process_util.h" |
| #include "base/threading/thread.h" |
| #include "base/win/scoped_comptr.h" |
| #include "base/win/scoped_gdi_object.h" |
| +#include "base/win/windows_version.h" |
| #include "base/win/win_util.h" |
| #include "base/win/windows_version.h" |
| #include "base/win/wrapped_window_proc.h" |
| @@ -879,19 +881,25 @@ |
| props_.push_back(ui::SetWindowSupportsRerouteMouseWheel(m_hWnd)); |
| if (base::win::GetVersion() >= base::win::VERSION_WIN7) { |
| - // Single finger panning is consistent with other windows applications. |
| - const DWORD gesture_allow = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | |
| - GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; |
| - const DWORD gesture_block = GC_PAN_WITH_GUTTER; |
| - GESTURECONFIG gc[] = { |
| - { GID_ZOOM, GC_ZOOM, 0 }, |
| - { GID_PAN, gesture_allow , gesture_block}, |
| - { GID_TWOFINGERTAP, GC_TWOFINGERTAP , 0}, |
| - { GID_PRESSANDTAP, GC_PRESSANDTAP , 0} |
| - }; |
| - if (!SetGestureConfig(m_hWnd, 0, arraysize(gc), gc, sizeof(GESTURECONFIG))) |
| - { |
| - NOTREACHED(); |
| + if (CommandLine::ForCurrentProcess()->HasSwitch( |
| + switches::kEnableTouchEvents)) { |
| + // Enable touch events rather than gestures. |
| + DCHECK(RegisterTouchWindow(m_hWnd, 0)); |
| + } else { |
| + // Single finger panning is consistent with other windows applications. |
| + const DWORD gesture_allow = GC_PAN_WITH_SINGLE_FINGER_VERTICALLY | |
| + GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY; |
| + const DWORD gesture_block = GC_PAN_WITH_GUTTER; |
| + GESTURECONFIG gc[] = { |
| + { GID_ZOOM, GC_ZOOM, 0 }, |
| + { GID_PAN, gesture_allow , gesture_block}, |
| + { GID_TWOFINGERTAP, GC_TWOFINGERTAP , 0}, |
| + { GID_PRESSANDTAP, GC_PRESSANDTAP , 0} |
| + }; |
| + if (!SetGestureConfig(m_hWnd, 0, arraysize(gc), gc, |
| + sizeof(GESTURECONFIG))) { |
| + NOTREACHED(); |
| + } |
| } |
| } |
| @@ -927,6 +935,8 @@ |
| props_.reset(); |
| + UnregisterTouchWindow(m_hWnd); |
| + |
| CleanupCompositorWindow(); |
| ResetTooltip(); |
| @@ -1102,6 +1112,7 @@ |
| render_widget_host_->GotFocus(); |
| render_widget_host_->SetActive(true); |
| } |
| + FinishTouchEvent(); |
| } |
| void RenderWidgetHostViewWin::OnKillFocus(HWND window) { |
| @@ -1109,6 +1120,7 @@ |
| render_widget_host_->SetActive(false); |
| render_widget_host_->Blur(); |
| } |
| + FinishTouchEvent(); |
| } |
| void RenderWidgetHostViewWin::OnCaptureChanged(HWND window) { |
| @@ -1570,6 +1582,174 @@ |
| return 0; |
| } |
| +void RenderWidgetHostViewWin::FinishTouchEvent() { |
|
ananta
2011/11/08 20:00:25
+1 for moving this inside a class and into a separ
|
| + if (touch_event_.touchesLength == 0) |
| + return; |
| + |
| + // Release all active touchpoints. |
| + for (unsigned int i = 0; i < touch_event_.touchesLength; ++i) { |
| + touch_event_.touches[i].state = WebKit::WebTouchPoint::StateReleased; |
| + touch_event_.changedTouches[i].state = |
| + WebKit::WebTouchPoint::StateReleased; |
| + } |
| + touch_event_.changedTouchesLength = touch_event_.touchesLength = 0; |
| + touch_event_.type = WebKit::WebInputEvent::TouchEnd; |
| + render_widget_host_->ForwardTouchEvent(touch_event_); |
| + touch_event_.touchesLength = 0; |
| +} |
| + |
| +WebKit::WebTouchPoint* RenderWidgetHostViewWin::AddTouchPoint( |
| + TOUCHINPUT* touch_input) { |
| + if (touch_event_.touchesLength >= WebKit::WebTouchEvent::touchesLengthCap) |
| + return NULL; |
| + WebKit::WebTouchPoint* point = |
| + &touch_event_.touches[touch_event_.touchesLength++]; |
| + point->state = WebKit::WebTouchPoint::StatePressed; |
| + point->id = touch_input->dwID; |
| + UpdateTouchPoint(point, touch_input); |
| + return point; |
| +} |
| + |
| +bool RenderWidgetHostViewWin::UpdateTouchPoint( |
| + WebKit::WebTouchPoint* touch_point, |
| + TOUCHINPUT* touch_input) { |
| + CPoint coordinates(TOUCH_COORD_TO_PIXEL(touch_input->x), |
| + TOUCH_COORD_TO_PIXEL(touch_input->y)); |
| + int radius_x = 0; |
| + int radius_y = 0; |
| + if (touch_input->dwMask & TOUCHINPUTMASKF_CONTACTAREA) { |
| + radius_x = TOUCH_COORD_TO_PIXEL(touch_input->cxContact); |
| + radius_y = TOUCH_COORD_TO_PIXEL(touch_input->cyContact); |
| + } |
| + |
| + // Detect and exclude stationary moves. |
| + if (touch_point->state == WebKit::WebTouchPoint::StateMoved && |
| + touch_point->screenPosition.x == coordinates.x && |
| + touch_point->screenPosition.y == coordinates.y && |
| + touch_point->radiusX == radius_x && |
| + touch_point->radiusY == radius_y) { |
| + touch_point->state = WebKit::WebTouchPoint::StateStationary; |
| + return true; |
| + } |
| + |
| + touch_point->screenPosition.x = coordinates.x; |
| + touch_point->screenPosition.y = coordinates.y; |
| + GetParent().ScreenToClient(&coordinates); |
| + touch_point->position.x = coordinates.x; |
| + touch_point->position.y = coordinates.y; |
| + touch_point->radiusX = radius_x; |
| + touch_point->radiusY = radius_y; |
| + touch_point->force = 1.0; |
| + touch_point->rotationAngle = 0; |
| + return false; |
| +} |
| + |
| +LRESULT RenderWidgetHostViewWin::OnTouchEvent(UINT message, WPARAM wparam, |
| + LPARAM lparam, BOOL& handled) { |
| + unsigned int touches_down = 0; |
| + unsigned int touches_up = 0; |
| + unsigned int touches_moved = 0; |
| + // TODO(jschuh): Add support for an arbitrary number of touchpoints. |
| + size_t points_count = std::min(static_cast<int>(LOWORD(wparam)), |
| + static_cast<int>(WebKit::WebTouchEvent::touchesLengthCap)); |
| + TOUCHINPUT points[WebKit::WebTouchEvent::touchesLengthCap]; |
| + |
| + if (points_count > WebKit::WebTouchEvent::touchesLengthCap) |
|
ananta
2011/11/08 20:00:25
The std::min statement above should ensure that th
|
| + points_count = WebKit::WebTouchEvent::touchesLengthCap; |
| + if (!points_count || !GetTouchInputInfo((HTOUCHINPUT)lparam, points_count, |
| + points, sizeof(TOUCHINPUT))) { |
| + return 0; |
| + } |
| + touch_event_.changedTouchesLength = 0; |
| + |
| + for (size_t i = 0; i < points_count; i++) { |
| + if (points[i].dwID == 0ul) |
| + continue; |
| + |
| + WebKit::WebTouchPoint* point = NULL; |
| + for (unsigned j = 0; j < touch_event_.touchesLength; ++j) { |
| + if (static_cast<DWORD>(touch_event_.touches[j].id) == points[i].dwID) { |
| + point = &touch_event_.touches[j]; |
| + break; |
| + } |
| + } |
| + |
| + // Use a move instead if we see a down on a point we already have. |
| + if (point && (points[i].dwFlags & 0x7) == TOUCHEVENTF_DOWN) |
|
ananta
2011/11/08 20:00:25
Can you add a define for the 0x7 mask?
|
| + points[i].dwFlags = (points[i].dwFlags & ~0x7) | TOUCHEVENTF_MOVE; |
| + |
| + switch (points[i].dwFlags & 0x7) { |
| + case TOUCHEVENTF_DOWN: { |
| + if (!(point = AddTouchPoint(&points[i]))) |
| + continue; |
| + ++touches_down; |
| + break; |
| + } |
| + |
| + case TOUCHEVENTF_UP: { |
| + if (!point) |
| + continue; |
| + point->state = WebKit::WebTouchPoint::StateReleased; |
| + UpdateTouchPoint(point, &points[i]); |
| + ++touches_up; |
| + break; |
| + } |
| + |
| + case TOUCHEVENTF_MOVE: { |
| + if (point) { |
| + point->state = WebKit::WebTouchPoint::StateMoved; |
| + // Don't update the message if the point didn't really move. |
| + if (UpdateTouchPoint(point, &points[i])) |
| + continue; |
| + ++touches_moved; |
| + } else { // Add a new point if we missed the TOUCHEVENTF_DOWN |
| + if (!(point = AddTouchPoint(&points[i]))) |
| + continue; |
| + ++touches_down; |
| + } |
| + break; |
| + } |
| + |
| + default: |
| + NOTREACHED(); |
| + continue; |
| + } |
| + touch_event_.changedTouches[touch_event_.changedTouchesLength++] = *point; |
| + } |
| + |
| + CloseTouchInputHandle((HTOUCHINPUT)lparam); |
| + |
| + // Set the event type based on what we've received. |
| + if (touches_down) |
| + touch_event_.type = WebKit::WebInputEvent::TouchStart; |
| + else if (touches_up) |
| + touch_event_.type = WebKit::WebInputEvent::TouchEnd; |
| + else if (touches_moved) |
| + touch_event_.type = WebKit::WebInputEvent::TouchMove; |
| + else |
| + touch_event_.type = WebKit::WebInputEvent::Undefined; |
| + |
| + // Forward the event only when there's a legitimate change. |
| + if (touch_event_.changedTouchesLength) |
| + render_widget_host_->ForwardTouchEvent(touch_event_); |
| + |
| + // Clean up released touches and reset everything else to staitonary. |
| + WebKit::WebTouchPoint* point = touch_event_.touches; |
| + WebKit::WebTouchPoint* end = |
| + &touch_event_.touches[touch_event_.touchesLength]; |
| + while (point < end) { |
| + if (point->state == WebKit::WebTouchPoint::StateReleased) { |
| + *point = *(--end); |
| + --touch_event_.touchesLength; |
| + } else { |
| + point->state = WebKit::WebTouchPoint::StateStationary; |
| + point++; |
| + } |
| + } |
| + |
| + return 0; |
| +} |
| + |
| LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message, |
| WPARAM wparam, |
| LPARAM lparam, |