12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/ash/tab_scrubber.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h" 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/wm/window_util.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/metrics/histogram.h" 107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/browser_finder.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/frame/browser_view.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/views/tabs/tab_strip.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h" 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_source.h" 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/aura/window.h" 21d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h" 22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event_utils.h" 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "ui/events/gestures/gesture_configuration.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/glow_hover_controller.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kActivationDelayMS = 200; 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TabScrubber* TabScrubber::GetInstance() { 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static TabScrubber* instance = NULL; 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!instance) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) instance = new TabScrubber(); 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return instance; 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Point TabScrubber::GetStartPoint( 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStrip* tab_strip, 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index, 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabScrubber::Direction direction) { 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int initial_tab_offset = Tab::GetMiniWidth() / 2; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect tab_bounds = tab_strip->tab_at(index)->bounds(); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) float x = direction == LEFT ? 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_bounds.x() + initial_tab_offset : 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_bounds.right() - initial_tab_offset; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Point(x, tab_bounds.CenterPoint().y()); 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool TabScrubber::IsActivationPending() { 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return activate_timer_.IsRunning(); 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TabScrubber::TabScrubber() 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : scrubbing_(false), 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_(NULL), 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_(-1), 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_y_(-1), 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_direction_(LEFT), 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_(-1), 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activate_timer_(true, false), 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activation_delay_(kActivationDelayMS), 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) use_default_activation_delay_(true), 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_(this) { 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ash::Shell::GetInstance()->AddPreTargetHandler(this); 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) registrar_.Add( 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this, 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) chrome::NOTIFICATION_BROWSER_CLOSED, 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::NotificationService::AllSources()); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TabScrubber::~TabScrubber() { 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Note: The weak_ptr_factory_ should invalidate its weak pointers before 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // any other members are destroyed. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.InvalidateWeakPtrs(); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::OnScrollEvent(ui::ScrollEvent* event) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event->type() == ui::ET_SCROLL_FLING_CANCEL || 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->type() == ui::ET_SCROLL_FLING_START) { 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FinishScrub(true); 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) immersive_reveal_lock_.reset(); 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event->finger_count() != 3) 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = GetActiveBrowser(); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!browser || (scrubbing_ && browser_ && browser != browser_) || 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (highlighted_tab_ != -1 && 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ >= browser->tab_strip_model()->count())) { 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FinishScrub(false); 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserView* browser_view = 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserView::GetBrowserViewForNativeWindow( 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser->window()->GetNativeWindow()); 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStrip* tab_strip = browser_view->tabstrip(); 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (tab_strip->IsAnimating()) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FinishScrub(false); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // We are handling the event. 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->StopPropagation(); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) float x_offset = event->x_offset(); 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int last_tab_index = highlighted_tab_ == -1 ? 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser->tab_strip_model()->active_index() : highlighted_tab_; 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!scrubbing_) { 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_direction_ = (x_offset < 0) ? LEFT : RIGHT; 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Point start_point = 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetStartPoint(tab_strip, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser->tab_strip_model()->active_index(), 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_direction_); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_ = browser; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scrubbing_ = true; 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ = start_point.x(); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_y_ = start_point.y(); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ImmersiveModeController* immersive_controller = 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_view->immersive_mode_controller(); 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (immersive_controller->IsEnabled()) { 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) immersive_reveal_lock_.reset(immersive_controller->GetRevealedLock( 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ImmersiveModeController::ANIMATE_REVEAL_YES)); 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_strip->AddObserver(this); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (highlighted_tab_ == -1) { 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Direction direction = (x_offset < 0) ? LEFT : RIGHT; 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (direction != swipe_direction_) { 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Point start_point = 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetStartPoint(tab_strip, 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser->tab_strip_model()->active_index(), 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) direction); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ = start_point.x(); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_y_ = start_point.y(); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_direction_ = direction; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ += x_offset; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* first_tab = tab_strip->tab_at(0); 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int first_tab_center = first_tab->bounds().CenterPoint().x(); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* last_tab = tab_strip->tab_at(tab_strip->tab_count() - 1); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int last_tab_tab_center = last_tab->bounds().CenterPoint().x(); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (swipe_x_ < first_tab_center) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ = first_tab_center; 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (swipe_x_ > last_tab_tab_center) 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ = last_tab_tab_center; 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* initial_tab = tab_strip->tab_at(last_tab_index); 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Point tab_point(swipe_x_, swipe_y_); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View::ConvertPointToTarget(tab_strip, initial_tab, &tab_point); 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* new_tab = tab_strip->GetTabAt(initial_tab, tab_point); 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!new_tab) 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int new_index = tab_strip->GetModelIndexOfTab(new_tab); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ == -1 && 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_index == browser->tab_strip_model()->active_index()) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_index != highlighted_tab_) { 1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (activate_timer_.IsRunning()) { 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activate_timer_.Reset(); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int delay = use_default_activation_delay_ ? 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::GestureConfiguration::tab_scrub_activation_delay_in_ms() : 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activation_delay_; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delay >= 0) { 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activate_timer_.Start(FROM_HERE, 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta::FromMilliseconds(delay), 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&TabScrubber::FinishScrub, 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true)); 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ != -1) { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* tab = tab_strip->tab_at(highlighted_tab_); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->hover_controller()->HideImmediately(); 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_index == browser->tab_strip_model()->active_index()) { 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ = -1; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ = new_index; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_tab->hover_controller()->Show(views::GlowHoverController::PRONOUNCED); 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ != -1) { 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Point hover_point(swipe_x_, swipe_y_); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View::ConvertPointToTarget(tab_strip, new_tab, &hover_point); 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_tab->hover_controller()->SetLocation(hover_point); 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::Observe(int type, 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationSource& source, 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const content::NotificationDetails& details) { 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (content::Source<Browser>(source).ptr() == browser_) { 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activate_timer_.Stop(); 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ = -1; 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_y_ = -1; 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scrubbing_ = false; 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ = -1; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_ = NULL; 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::TabStripAddedTabAt(TabStrip* tab_strip, int index) { 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ == -1) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index < highlighted_tab_) 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++highlighted_tab_; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::TabStripMovedTab(TabStrip* tab_strip, 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int from_index, 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int to_index) { 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ == -1) 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (from_index == highlighted_tab_) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ = to_index; 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (from_index < highlighted_tab_&& highlighted_tab_<= to_index) 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --highlighted_tab_; 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else if (from_index > highlighted_tab_ && highlighted_tab_ >= to_index) 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++highlighted_tab_; 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::TabStripRemovedTabAt(TabStrip* tab_strip, int index) { 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ == -1) 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index == highlighted_tab_) { 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FinishScrub(false); 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (index < highlighted_tab_) 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --highlighted_tab_; 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::TabStripDeleted(TabStrip* tab_strip) { 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (highlighted_tab_ == -1) 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Browser* TabScrubber::GetActiveBrowser() { 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) aura::Window* active_window = ash::wm::GetActiveWindow(); 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!active_window) 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Browser* browser = chrome::FindBrowserWithWindow(active_window); 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!browser || browser->type() != Browser::TYPE_TABBED) 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return browser; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TabScrubber::FinishScrub(bool activate) { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) activate_timer_.Stop(); 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (browser_ && browser_->window()) { 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserView* browser_view = 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BrowserView::GetBrowserViewForNativeWindow( 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->window()->GetNativeWindow()); 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) TabStrip* tab_strip = browser_view->tabstrip(); 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (activate && highlighted_tab_ != -1) { 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Tab* tab = tab_strip->tab_at(highlighted_tab_); 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab->hover_controller()->HideImmediately(); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int distance = 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::abs( 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ - browser_->tab_strip_model()->active_index()); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.ScrubDistance", distance, 0, 20, 21); 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->ActivateTabAt(highlighted_tab_, true); 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) tab_strip->RemoveObserver(this); 2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_x_ = -1; 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) swipe_y_ = -1; 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scrubbing_ = false; 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) highlighted_tab_ = -1; 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 287