Index: chrome/browser/renderer_host/render_widget_host_view_gtk.cc |
diff --git a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc |
index 179fbbdd3b8e0dead41b5c55c3e2bf8cf761a26c..03c0afbc08af70851ec71ae0c41323e21129bcd7 100644 |
--- a/chrome/browser/renderer_host/render_widget_host_view_gtk.cc |
+++ b/chrome/browser/renderer_host/render_widget_host_view_gtk.cc |
@@ -48,7 +48,14 @@ static const int kMaxWindowHeight = 4000; |
static const char* kRenderWidgetHostViewKey = "__RENDER_WIDGET_HOST_VIEW__"; |
#if defined(OS_CHROMEOS) |
-static const float kDefaultVertScrollDelta = 20.0; |
+// TODO(davemoore) Under Chromeos we are increasing the rate that the trackpad |
+// generates events to get better precisions. Eventually we will coordinate the |
+// driver and this setting to ensure they match. |
+static const float kDefaultScrollPixelsPerTick = 20; |
+#else |
+// See WebInputEventFactor.cpp for a reason for this being the default |
+// scroll size for linux. |
+static const float kDefaultScrollPixelsPerTick = 160.0f / 3.0f; |
#endif |
using WebKit::WebInputEventFactory; |
@@ -310,27 +317,73 @@ class RenderWidgetHostViewGtkWidget { |
return true; |
} |
-#if defined(OS_CHROMEOS) |
// Allow the vertical scroll delta to be overridden from the command line. |
// This will allow us to test more easily to discover the amount |
// (either hard coded or computed) that's best. |
- static float GetVertScrollDelta() { |
- static float vert_scroll_delta = -1; |
- if (vert_scroll_delta < 0) { |
- vert_scroll_delta = kDefaultVertScrollDelta; |
+ static float GetScrollPixelsPerTick() { |
+ static float scroll_pixels = -1; |
+ if (scroll_pixels < 0) { |
+ scroll_pixels = kDefaultScrollPixelsPerTick; |
CommandLine* command_line = CommandLine::ForCurrentProcess(); |
- std::string vert_scroll_option = |
- command_line->GetSwitchValueASCII(switches::kVertScrollDelta); |
- if (!vert_scroll_option.empty()) { |
+ std::string scroll_pixels_option = |
+ command_line->GetSwitchValueASCII(switches::kScrollPixels); |
+ if (!scroll_pixels_option.empty()) { |
double v; |
- if (StringToDouble(vert_scroll_option, &v)) |
- vert_scroll_delta = static_cast<float>(v); |
+ if (StringToDouble(scroll_pixels_option, &v)) |
+ scroll_pixels = static_cast<float>(v); |
} |
- DCHECK_GT(vert_scroll_delta, 0); |
+ DCHECK_GT(scroll_pixels, 0); |
} |
- return vert_scroll_delta; |
+ return scroll_pixels; |
+ } |
+ |
+ // Return the net up / down (or left / right) distance represented by events |
+ // in the events will be removed from the queue. We only look at the top of |
+ // queue...any other type of event will cause us not to look farther. |
+ // If there is a change to the set of modifier keys or scroll axis |
+ // in the events we will stop looking as well. |
+ static int GetPendingScrollDelta(bool vert, guint current_event_state) { |
+ int num_clicks = 0; |
+ GdkEvent* event; |
+ bool event_coalesced = true; |
+ while ((event = gdk_event_get()) && event_coalesced) { |
+ event_coalesced = false; |
+ if (event->type == GDK_SCROLL) { |
+ GdkEventScroll scroll = event->scroll; |
+ if (scroll.state & GDK_SHIFT_MASK) { |
+ if (scroll.direction == GDK_SCROLL_UP) |
+ scroll.direction = GDK_SCROLL_LEFT; |
+ else if (scroll.direction == GDK_SCROLL_DOWN) |
+ scroll.direction = GDK_SCROLL_RIGHT; |
+ } |
+ if (vert) { |
+ if (scroll.direction == GDK_SCROLL_UP || |
+ scroll.direction == GDK_SCROLL_DOWN) { |
+ if (scroll.state == current_event_state) { |
+ num_clicks += (scroll.direction == GDK_SCROLL_UP ? 1 : -1); |
+ gdk_event_free(event); |
+ event_coalesced = true; |
+ } |
+ } |
+ } else { |
+ if (scroll.direction == GDK_SCROLL_RIGHT || |
+ scroll.direction == GDK_SCROLL_LEFT) { |
+ if (scroll.state == current_event_state) { |
+ num_clicks += (scroll.direction == GDK_SCROLL_RIGHT ? 1 : -1); |
+ gdk_event_free(event); |
+ event_coalesced = true; |
+ } |
+ } |
+ } |
+ } |
+ } |
+ // If we have an event left we put it back on the queue. |
+ if (event) { |
+ gdk_event_put(event); |
+ gdk_event_free(event); |
+ } |
+ return num_clicks * GetScrollPixelsPerTick(); |
} |
-#endif |
static gboolean MouseScrollEvent(GtkWidget* widget, GdkEventScroll* event, |
RenderWidgetHostViewGtk* host_view) { |
@@ -345,20 +398,22 @@ class RenderWidgetHostViewGtkWidget { |
} |
WebMouseWheelEvent web_event = WebInputEventFactory::mouseWheelEvent(event); |
-#if defined (OS_CHROMEOS) |
- // Under ChromeOS we know that the wheel is a touchpad. The driver for this |
- // can generate events very quickly. We configure it to generate more |
- // events and scroll by a smaller amount on each, to give us better |
- // precision. This is only configured for vertical scrolling, and |
- // doesn't apply if we are using the shift modifier to cause a horizontal |
- // scroll. |
- if (!(event->state & GDK_SHIFT_MASK)) { |
+ // We peek ahead at the top of the queue to look for additional pending |
+ // scroll events. |
+ if (event->direction == GDK_SCROLL_UP || |
+ event->direction == GDK_SCROLL_DOWN) { |
if (event->direction == GDK_SCROLL_UP) |
- web_event.deltaY = GetVertScrollDelta(); |
+ web_event.deltaY = GetScrollPixelsPerTick(); |
+ else |
+ web_event.deltaY = -GetScrollPixelsPerTick(); |
+ web_event.deltaY += GetPendingScrollDelta(true, event->state); |
+ } else { |
+ if (event->direction == GDK_SCROLL_RIGHT) |
+ web_event.deltaX = GetScrollPixelsPerTick(); |
else |
- web_event.deltaY = -GetVertScrollDelta(); |
+ web_event.deltaX = -GetScrollPixelsPerTick(); |
+ web_event.deltaX += GetPendingScrollDelta(false, event->state); |
} |
-#endif // OS_CHROMEOS |
host_view->GetRenderWidgetHost()->ForwardWheelEvent(web_event); |
return FALSE; |
} |