Commit 11397833 authored by iyengar@google.com's avatar iyengar@google.com

Add support for touch based zoom gesture on Windows. This change also handles the WM_POINTERDOWN

and WM_POINTERUP messages to scroll the page if we touch the scrollbar.

BUG=none
TEST=Touch based zoom should work on Windows.
Review URL: http://codereview.chromium.org/8399009

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108232 0039d316-1c4b-4281-b951-d872f2087c98
parent e3c1326d
......@@ -32,6 +32,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/page_zoom.h"
#include "skia/ext/skia_utils_win.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCompositionUnderline.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
......@@ -201,8 +202,43 @@ LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
return ::DefWindowProc(window, message, wparam, lparam);
}
bool DecodeScrollGesture(WPARAM wParam,
LPARAM lParam,
bool DecodeZoomGesture(HWND hwnd, const GESTUREINFO& gi,
content::PageZoom* zoom,
POINT* zoom_center) {
static long start = 0;
static POINT zoom_first;
if (gi.dwFlags == GF_BEGIN) {
start = gi.ullArguments;
zoom_first.x = gi.ptsLocation.x;
zoom_first.y = gi.ptsLocation.y;
ScreenToClient(hwnd, &zoom_first);
return false;
}
if (gi.dwFlags == GF_END)
return false;
POINT zoom_second = {0};
zoom_second.x = gi.ptsLocation.x;
zoom_second.y = gi.ptsLocation.y;
ScreenToClient(hwnd, &zoom_second);
zoom_center->x = (zoom_first.x + zoom_second.x) / 2;
zoom_center->y = (zoom_first.y + zoom_second.y) / 2;
double zoom_factor =
static_cast<double>(gi.ullArguments)/static_cast<double>(start);
*zoom = zoom_factor >= 1 ? content::PAGE_ZOOM_IN :
content::PAGE_ZOOM_OUT;
start = gi.ullArguments;
zoom_first = zoom_second;
return true;
}
bool DecodeScrollGesture(const GESTUREINFO& gi,
POINT* start,
POINT* delta){
// Windows gestures are streams of messages with begin/end messages that
......@@ -211,16 +247,6 @@ bool DecodeScrollGesture(WPARAM wParam,
static POINT last_pt;
static POINT start_pt;
GESTUREINFO gi = {sizeof(GESTUREINFO)};
HGESTUREINFO gi_handle = reinterpret_cast<HGESTUREINFO>(lParam);
if (!::GetGestureInfo(gi_handle, &gi)) {
DWORD error = GetLastError();
NOTREACHED() << "Unable to get gesture info. Error : " << error;
}
if (gi.dwID != GID_PAN)
return false;
if (gi.dwFlags == GF_BEGIN) {
delta->x = 0;
delta->y = 0;
......@@ -233,32 +259,31 @@ bool DecodeScrollGesture(WPARAM wParam,
last_pt.x = gi.ptsLocation.x;
last_pt.y = gi.ptsLocation.y;
*start = start_pt;
::CloseGestureInfoHandle(gi_handle);
return true;
}
WebKit::WebMouseWheelEvent MakeFakeScrollWheelEvent(HWND hwnd,
POINT start,
POINT delta) {
WebKit::WebMouseWheelEvent result;
result.type = WebInputEvent::MouseWheel;
result.timeStampSeconds = ::GetMessageTime() / 1000.0;
result.button = WebMouseEvent::ButtonNone;
result.globalX = start.x;
result.globalY = start.y;
// Map to window coordinates.
POINT clientPoint = { result.globalX, result.globalY };
MapWindowPoints(0, hwnd, &clientPoint, 1);
result.x = clientPoint.x;
result.y = clientPoint.y;
result.windowX = result.x;
result.windowY = result.y;
// Note that we support diagonal scrolling.
result.deltaX = static_cast<float>(delta.x);
result.wheelTicksX = WHEEL_DELTA;
result.deltaY = static_cast<float>(delta.y);
result.wheelTicksY = WHEEL_DELTA;
return result;
WebKit::WebMouseWheelEvent result;
result.type = WebInputEvent::MouseWheel;
result.timeStampSeconds = ::GetMessageTime() / 1000.0;
result.button = WebMouseEvent::ButtonNone;
result.globalX = start.x;
result.globalY = start.y;
// Map to window coordinates.
POINT client_point = { result.globalX, result.globalY };
MapWindowPoints(0, hwnd, &client_point, 1);
result.x = client_point.x;
result.y = client_point.y;
result.windowX = result.x;
result.windowY = result.y;
// Note that we support diagonal scrolling.
result.deltaX = static_cast<float>(delta.x);
result.wheelTicksX = WHEEL_DELTA;
result.deltaY = static_cast<float>(delta.y);
result.wheelTicksY = WHEEL_DELTA;
return result;
}
} // namespace
......@@ -286,7 +311,9 @@ RenderWidgetHostViewWin::RenderWidgetHostViewWin(RenderWidgetHost* widget)
text_input_type_(ui::TEXT_INPUT_TYPE_NONE),
is_fullscreen_(false),
ignore_mouse_movement_(true),
composition_range_(ui::Range::InvalidRange()) {
composition_range_(ui::Range::InvalidRange()),
ignore_next_lbutton_message_at_same_location(false),
last_pointer_down_location_(0) {
render_widget_host_->SetView(this);
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
......@@ -299,7 +326,8 @@ RenderWidgetHostViewWin::~RenderWidgetHostViewWin() {
}
void RenderWidgetHostViewWin::CreateWnd(HWND parent) {
Create(parent); // ATL function to create the window.
// ATL function to create the window.
Create(parent);
}
///////////////////////////////////////////////////////////////////////////////
......@@ -1314,6 +1342,15 @@ LRESULT RenderWidgetHostViewWin::OnMouseEvent(UINT message, WPARAM wparam,
LPARAM lparam, BOOL& handled) {
handled = TRUE;
if (ignore_next_lbutton_message_at_same_location &&
message == WM_LBUTTONDOWN) {
ignore_next_lbutton_message_at_same_location = false;
LPARAM last_location = last_pointer_down_location_;
last_pointer_down_location_ = 0;
if (last_location == lparam)
return 0;
}
if (message == WM_MOUSELEAVE)
ignore_mouse_movement_ = true;
......@@ -1566,18 +1603,38 @@ LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT message,
}
LRESULT RenderWidgetHostViewWin::OnGestureEvent(
UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
// Right now we only decode scroll gestures and we forward to the page
// as scroll events.
POINT start;
POINT delta;
if (DecodeScrollGesture(wparam, lparam, &start, &delta)) {
handled = TRUE;
render_widget_host_->ForwardWheelEvent(
MakeFakeScrollWheelEvent(m_hWnd, start, delta));
} else {
handled = FALSE;
UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
handled = FALSE;
GESTUREINFO gi = {sizeof(GESTUREINFO)};
HGESTUREINFO gi_handle = reinterpret_cast<HGESTUREINFO>(lparam);
if (!::GetGestureInfo(gi_handle, &gi)) {
DWORD error = GetLastError();
NOTREACHED() << "Unable to get gesture info. Error : " << error;
return 0;
}
if (gi.dwID == GID_ZOOM) {
content::PageZoom zoom = content::PAGE_ZOOM_RESET;
POINT zoom_center = {0};
if (DecodeZoomGesture(m_hWnd, gi, &zoom, &zoom_center)) {
handled = TRUE;
Send(new ViewMsg_ZoomFactor(render_widget_host_->routing_id(),
zoom, zoom_center.x, zoom_center.y));
}
} else if (gi.dwID == GID_PAN) {
// Right now we only decode scroll gestures and we forward to the page
// as scroll events.
POINT start;
POINT delta;
if (DecodeScrollGesture(gi, &start, &delta)) {
handled = TRUE;
render_widget_host_->ForwardWheelEvent(
MakeFakeScrollWheelEvent(m_hWnd, start, delta));
}
}
::CloseGestureInfoHandle(gi_handle);
return 0;
}
......@@ -1862,6 +1919,27 @@ LRESULT RenderWidgetHostViewWin::OnParentNotify(UINT message, WPARAM wparam,
return 0;
}
LRESULT RenderWidgetHostViewWin::OnPointerMessage(
UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled) {
POINT point = {0};
point.x = GET_X_LPARAM(lparam);
point.y = GET_Y_LPARAM(lparam);
ScreenToClient(&point);
lparam = MAKELPARAM(point.x, point.y);
if (message == WM_POINTERDOWN) {
OnMouseEvent(WM_LBUTTONDOWN, MK_LBUTTON, lparam, handled);
ignore_next_lbutton_message_at_same_location = true;
last_pointer_down_location_ = lparam;
} else if (message == WM_POINTERUP) {
OnMouseEvent(WM_LBUTTONUP, MK_LBUTTON, lparam, handled);
}
handled = FALSE;
return 0;
}
void RenderWidgetHostViewWin::OnFinalMessage(HWND window) {
// When the render widget host is being destroyed, it ends up calling
// Destroy() which NULLs render_widget_host_.
......
......@@ -50,6 +50,21 @@ typedef CWinTraits<WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0>
CONTENT_EXPORT extern const wchar_t kRenderWidgetHostHWNDClass[];
// TODO(ananta)
// This should be removed once we have the new windows SDK which defines these
// messages.
#if !defined(WM_POINTERUPDATE)
#define WM_POINTERUPDATE 0x0245
#endif // WM_POINTERUPDATE
#if !defined(WM_POINTERDOWN)
#define WM_POINTERDOWN 0x0246
#endif // WM_POINTERDOWN
#if !defined(WM_POINTERUP)
#define WM_POINTERUP 0x0247
#endif // WM_POINTERUP
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewWin
//
......@@ -130,6 +145,8 @@ class RenderWidgetHostViewWin
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
MESSAGE_HANDLER(WM_GETOBJECT, OnGetObject)
MESSAGE_HANDLER(WM_PARENTNOTIFY, OnParentNotify)
MESSAGE_HANDLER(WM_POINTERDOWN, OnPointerMessage)
MESSAGE_HANDLER(WM_POINTERUP, OnPointerMessage)
MESSAGE_HANDLER(WM_GESTURE, OnGestureEvent)
END_MSG_MAP()
......@@ -244,6 +261,10 @@ class RenderWidgetHostViewWin
LRESULT OnParentNotify(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled);
// Handle the new pointer messages
LRESULT OnPointerMessage(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled);
// Handle high-level touch events.
LRESULT OnGestureEvent(UINT message, WPARAM wparam, LPARAM lparam,
BOOL& handled);
......@@ -420,6 +441,14 @@ class RenderWidgetHostViewWin
ui::Range composition_range_;
// Set to true if the next lbutton down message is to be ignored. Set by the
// WM_POINTERXX handler. We do this to ensure that we don't send out
// duplicate lbutton down messages to the renderer.
bool ignore_next_lbutton_message_at_same_location;
// The location of the last WM_POINTERDOWN message. We ignore the subsequent
// lbutton down only if the locations match.
LPARAM last_pointer_down_location_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewWin);
};
......
......@@ -921,6 +921,12 @@ IPC_MESSAGE_ROUTED1(ViewMsg_Zoom,
IPC_MESSAGE_ROUTED1(ViewMsg_SetZoomLevel,
double /* zoom_level */)
// Zooms the page by the factor defined in the renderer.
IPC_MESSAGE_ROUTED3(ViewMsg_ZoomFactor,
content::PageZoom,
int /* zoom center_x */,
int /* zoom center_y */)
// Set the zoom level for a particular url that the renderer is in the
// process of loading. This will be stored, to be used if the load commits
// and ignored otherwise.
......
......@@ -271,6 +271,8 @@ static const int kMaximumNumberOfUnacknowledgedPopups = 25;
static const float kScalingIncrement = 0.1f;
static const float kScalingIncrementForGesture = 0.01f;
static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
WebVector<WebURL> urls;
ds->redirectChain(urls);
......@@ -599,6 +601,7 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck)
IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevel, OnSetZoomLevel)
IPC_MESSAGE_HANDLER(ViewMsg_ZoomFactor, OnZoomFactor)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
OnSetZoomLevelForLoadingURL)
IPC_MESSAGE_HANDLER(ViewMsg_ExitFullscreen, OnExitFullscreen)
......@@ -3553,17 +3556,36 @@ void RenderViewImpl::OnZoom(content::PageZoom zoom) {
}
webview()->setZoomLevel(false, zoom_level);
#else
ZoomFactorHelper(function, 0, 0, kScalingIncrement);
#endif
zoomLevelChanged();
}
void RenderViewImpl::OnZoomFactor(content::PageZoom zoom,
int zoom_center_x, int zoom_center_y) {
ZoomFactorHelper(zoom, zoom_center_x, zoom_center_y,
kScalingIncrementForGesture);
}
void RenderViewImpl::ZoomFactorHelper(content::PageZoom zoom,
int zoom_center_x,
int zoom_center_y,
float scaling_increment) {
if (!webview()) // Not sure if this can happen, but no harm in being safe.
return;
double old_page_scale_factor = webview()->pageScaleFactor();
double page_scale_factor;
if (zoom == content::PAGE_ZOOM_RESET) {
page_scale_factor = 1.0;
} else {
page_scale_factor = old_page_scale_factor +
(zoom > 0 ? kScalingIncrement : -kScalingIncrement);
(zoom > 0 ? scaling_increment : -scaling_increment);
}
if (page_scale_factor > 0) {
webview()->scalePage(page_scale_factor,
WebPoint(zoom_center_x, zoom_center_y));
}
webview()->scalePage(page_scale_factor, WebPoint(0, 0));
#endif
zoomLevelChanged();
}
void RenderViewImpl::OnSetZoomLevel(double zoom_level) {
......
......@@ -860,6 +860,9 @@ class RenderViewImpl : public RenderWidget,
void OnSelectPopupMenuItem(int selected_index);
#endif
void OnZoom(content::PageZoom zoom);
void OnZoomFactor(content::PageZoom zoom, int zoom_center_x,
int zoom_center_y);
void OnEnableViewSourceMode();
void OnJavaBridgeInit(const IPC::ChannelHandle& channel_handle);
......@@ -868,6 +871,8 @@ class RenderViewImpl : public RenderWidget,
// and put it in the same position in the .cc file.
// Misc private functions ----------------------------------------------------
void ZoomFactorHelper(content::PageZoom zoom, int zoom_center_x,
int zoom_center_y, float scaling_increment);
void AltErrorPageFinished(WebKit::WebFrame* frame,
const WebKit::WebURLError& original_error,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment