| Index: chrome/browser/ui/views/tabs/tab_strip.cc | 
| diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc | 
| index ca534a13b30b2d4ba8a10c52620ce3a782b72e03..effca95055c413ea016e978ddac04e8e33201322 100644 | 
| --- a/chrome/browser/ui/views/tabs/tab_strip.cc | 
| +++ b/chrome/browser/ui/views/tabs/tab_strip.cc | 
| @@ -267,16 +267,17 @@ class ResetDraggingStateDelegate | 
| DISALLOW_COPY_AND_ASSIGN(ResetDraggingStateDelegate); | 
| }; | 
|  | 
| -// If |dest| contains the point |point_in_source| the event handler from |dest| | 
| +// If |dest| contains the rect |rect_in_source| the event handler from |dest| | 
| // is returned. Otherwise NULL is returned. | 
| -views::View* ConvertPointToViewAndGetEventHandler( | 
| +views::View* ConvertRectToViewAndGetEventHandler( | 
| views::View* source, | 
| views::View* dest, | 
| -    const gfx::Point& point_in_source) { | 
| -  gfx::Point dest_point(point_in_source); | 
| -  views::View::ConvertPointToTarget(source, dest, &dest_point); | 
| -  return dest->HitTestPoint(dest_point) ? | 
| -      dest->GetEventHandlerForPoint(dest_point) : NULL; | 
| +    const gfx::Rect& rect_in_source, | 
| +    views::View::EventType type) { | 
| +  gfx::Rect dest_rect(rect_in_source); | 
| +  views::View::ConvertRectToTarget(source, dest, &dest_rect); | 
| +  return dest->HitTestRect(dest_rect) ? | 
| +      dest->GetEventHandler(dest_rect, type) : NULL; | 
| } | 
|  | 
| }  // namespace | 
| @@ -298,6 +299,10 @@ class NewTabButton : public views::ImageButton { | 
| background_offset_ = offset; | 
| } | 
|  | 
| +  View* GetEventHandler(const gfx::Rect& rect, EventType type) OVERRIDE { | 
| +    return View::GetEventHandler(rect, type); | 
| +  } | 
| + | 
| protected: | 
| // Overridden from views::View: | 
| virtual bool HasHitTestMask() const OVERRIDE; | 
| @@ -1342,11 +1347,43 @@ void TabStrip::GetAccessibleState(ui::AccessibleViewState* state) { | 
| state->role = ui::AccessibilityTypes::ROLE_PAGETABLIST; | 
| } | 
|  | 
| -views::View* TabStrip::GetEventHandlerForPoint(const gfx::Point& point) { | 
| +double CoverageProportion(const gfx::Rect& rect_one, | 
| +                          const gfx::Rect& rect_two) { | 
| +  gfx::Rect intersection = rect_one.Intersect(rect_two); | 
| +  double rect_one_area = rect_one.size().GetArea(); | 
| +  double rect_two_area = rect_two.size().GetArea(); | 
| +  double intersection_area = intersection.size().GetArea(); | 
| +  if ((rect_one_area <= 0) || (rect_two_area <= 0)) | 
| +    return 0.0; | 
| +  if (rect_one_area > rect_two_area) | 
| +    return intersection_area / rect_two_area; | 
| +  else | 
| +    return intersection_area / rect_one_area; | 
| +} | 
| + | 
| +views::View* TabStrip::GetEventHandler(const gfx::Rect& rect, | 
| +                                       EventType type) { | 
| +#if defined(OS_WIN) | 
| +  if (ui::IsMouseEventFromTouch(WM_MOUSEMOVE) && | 
| +      (type == EVENT_HANDLER_TYPE_MOUSE)) { | 
| +    // This MOUSE event was actually generated from a touch. | 
| +    // Views doesn't currently enable Windows OS touch. | 
| +    int touch_size = 24; | 
| +    return GetEventHandler(gfx::Rect(rect.x()-touch_size, rect.y()-touch_size, | 
| +                           touch_size*2, touch_size*2), | 
| +                           EVENT_HANDLER_TYPE_TOUCH); | 
| +  } | 
| +#endif | 
| + | 
| +  View* closest_view = NULL; | 
| +  View* closest_untouched_view = NULL; | 
| +  double max_proportion = 0; | 
| +  int closest_distance = INT_MAX; | 
| + | 
| if (!touch_layout_.get()) { | 
| // Return any view that isn't a Tab or this TabStrip immediately. We don't | 
| // want to interfere. | 
| -    views::View* v = View::GetEventHandlerForPoint(point); | 
| +    views::View* v = View::GetEventHandler(rect, type); | 
| if (v && v != this && v->GetClassName() != Tab::kViewClassName) | 
| return v; | 
|  | 
| @@ -1356,21 +1393,24 @@ views::View* TabStrip::GetEventHandlerForPoint(const gfx::Point& point) { | 
| // left-adjacent Tab, so we look ahead for it as we walk. | 
| for (int i = 0; i < tab_count(); ++i) { | 
| Tab* next_tab = i < (tab_count() - 1) ? tab_at(i + 1) : NULL; | 
| -      if (next_tab && next_tab->IsActive() && IsPointInTab(next_tab, point)) | 
| +      if (next_tab && next_tab->IsActive() && IsRectInTab(next_tab, rect)) | 
| return next_tab; | 
| -      if (IsPointInTab(tab_at(i), point)) | 
| +      if (IsRectInTab(tab_at(i), rect)) | 
| return tab_at(i); | 
| } | 
| } else { | 
| +    // Test for new tab button.... | 
| if (newtab_button_->visible()) { | 
| views::View* view = | 
| -          ConvertPointToViewAndGetEventHandler(this, newtab_button_, point); | 
| +          ConvertRectToViewAndGetEventHandler( | 
| +              this, newtab_button_, rect, type); | 
| if (view) | 
| return view; | 
| } | 
| -    Tab* tab = FindTabForEvent(point); | 
| +    // Otherwise, check for other tabs.... | 
| +    Tab* tab = FindTabForEvent(rect); | 
| if (tab) | 
| -      return ConvertPointToViewAndGetEventHandler(this, tab, point); | 
| +      return ConvertRectToViewAndGetEventHandler(this, tab, rect, type); | 
| } | 
| return this; | 
| } | 
| @@ -2452,6 +2492,13 @@ bool TabStrip::IsPointInTab(Tab* tab, | 
| return tab->HitTestPoint(point_in_tab_coords); | 
| } | 
|  | 
| +bool TabStrip::IsRectInTab(Tab* tab, | 
| +                           const gfx::Rect& rect_in_tabstrip_coords) { | 
| +  gfx::Rect rect_in_tab_coords(rect_in_tabstrip_coords); | 
| +  View::ConvertRectToTarget(this, tab, &rect_in_tab_coords); | 
| +  return tab->HitTestRect(rect_in_tab_coords); | 
| +} | 
| + | 
| int TabStrip::GetStartXForNormalTabs() const { | 
| int mini_tab_count = GetMiniTabCount(); | 
| if (mini_tab_count == 0) | 
| @@ -2460,6 +2507,20 @@ int TabStrip::GetStartXForNormalTabs() const { | 
| kMiniToNonMiniGap; | 
| } | 
|  | 
| +Tab* TabStrip::FindTabForEvent(const gfx::Rect& rect) { | 
| +  DCHECK(touch_layout_.get()); | 
| +  int active_tab_index = touch_layout_->active_index(); | 
| +  Tab* tab = NULL; | 
| +  if (active_tab_index != -1) { | 
| +    tab = FindTabForEventFrom(rect, active_tab_index, -1); | 
| +    if (!tab) | 
| +      tab = FindTabForEventFrom(rect, active_tab_index + 1, 1); | 
| +  } else if (tab_count()) { | 
| +    tab = FindTabForEventFrom(rect, 0, 1); | 
| +  } | 
| +  return tab; | 
| +} | 
| + | 
| Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { | 
| DCHECK(touch_layout_.get()); | 
| int active_tab_index = touch_layout_->active_index(); | 
| @@ -2474,6 +2535,19 @@ Tab* TabStrip::FindTabForEvent(const gfx::Point& point) { | 
| return tab; | 
| } | 
|  | 
| +Tab* TabStrip::FindTabForEventFrom(const gfx::Rect& rect, | 
| +                                   int start, | 
| +                                   int delta) { | 
| +  // |start| equals tab_count() when there are only pinned tabs. | 
| +  if (start == tab_count()) | 
| +    start += delta; | 
| +  for (int i = start; i >= 0 && i < tab_count(); i += delta) { | 
| +    if (IsRectInTab(tab_at(i), rect)) | 
| +      return tab_at(i); | 
| +  } | 
| +  return NULL; | 
| +} | 
| + | 
| Tab* TabStrip::FindTabForEventFrom(const gfx::Point& point, | 
| int start, | 
| int delta) { | 
|  |