Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(646)

Side by Side Diff: chrome/browser/ui/views/ash/tab_scrubber.cc

Issue 11881042: highlight intermediate tabs (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make check for Gesture vs Scroll event for flings explicit Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/views/ash/tab_scrubber.h" 5 #include "chrome/browser/ui/views/ash/tab_scrubber.h"
6 6
7 #include "ash/shell.h" 7 #include "ash/shell.h"
8 #include "ash/wm/window_util.h" 8 #include "ash/wm/window_util.h"
9 #include "chrome/browser/ui/browser.h" 9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/browser_finder.h" 10 #include "chrome/browser/ui/browser_finder.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h" 11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/browser/ui/views/frame/browser_view.h" 12 #include "chrome/browser/ui/views/frame/browser_view.h"
13 #include "chrome/browser/ui/views/immersive_mode_controller.h"
13 #include "chrome/browser/ui/views/tabs/tab.h" 14 #include "chrome/browser/ui/views/tabs/tab.h"
14 #include "chrome/browser/ui/views/tabs/tab_strip.h" 15 #include "chrome/browser/ui/views/tabs/tab_strip.h"
15 #include "chrome/common/chrome_notification_types.h" 16 #include "chrome/common/chrome_notification_types.h"
17 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/notification_source.h" 18 #include "content/public/browser/notification_source.h"
17 #include "ui/aura/window.h" 19 #include "ui/aura/window.h"
18 #include "ui/base/events/event.h" 20 #include "ui/base/events/event.h"
19 #include "ui/base/events/event_utils.h" 21 #include "ui/base/events/event_utils.h"
22 #include "ui/views/controls/glow_hover_controller.h"
20 23
21 namespace { 24 namespace {
22 Tab* GetTabAt(TabStrip* tab_strip, gfx::Point point) { 25 const int64 kActivationDelayMS = 200;
23 for (int i = 0; i < tab_strip->tab_count(); ++i) { 26 const int64 kCancelImmersiveRevelDelayMS = 200;
24 Tab* tab = tab_strip->tab_at(i);
25 if (tab_strip->tab_at(i)->bounds().Contains(point))
26 return tab;
27 }
28 return NULL;
29 }
30
31 const int kInitialTabOffset = 10;
32 } 27 }
33 28
34 // static 29 // static
35 TabScrubber* TabScrubber::GetInstance() { 30 TabScrubber* TabScrubber::GetInstance() {
36 static TabScrubber* instance = NULL; 31 static TabScrubber* instance = NULL;
37 if (!instance) 32 if (!instance)
38 instance = new TabScrubber(); 33 instance = new TabScrubber();
39 return instance; 34 return instance;
40 } 35 }
41 36
42 TabScrubber::TabScrubber() 37 TabScrubber::TabScrubber()
43 : scrubbing_(false), 38 : scrubbing_(false),
44 browser_(NULL), 39 browser_(NULL),
45 scroll_x_(-1), 40 swipe_x_(-1),
46 scroll_y_(-1) { 41 swipe_y_(-1),
42 overridden_tab_(-1),
43 activate_timer_(true, false),
44 activation_delay_(base::TimeDelta::FromMilliseconds(kActivationDelayMS)),
45 should_cancel_immersive_reveal_(false),
46 cancel_immersive_reveal_timer_(true, false),
47 weak_ptr_factory_(this) {
47 ash::Shell::GetInstance()->AddPreTargetHandler(this); 48 ash::Shell::GetInstance()->AddPreTargetHandler(this);
sky 2013/01/22 18:05:01 Should this be removed at some point?
DaveMoore 2013/01/27 21:21:54 I thought the registrar takes care of that upon de
49 registrar_.Add(
50 this,
51 chrome::NOTIFICATION_BROWSER_CLOSING,
52 content::NotificationService::AllSources());
48 } 53 }
49 54
50 TabScrubber::~TabScrubber() { 55 TabScrubber::~TabScrubber() {
51 } 56 }
52 57
58 // static
59 const gfx::Point TabScrubber::GetStartPoint(
sky 2013/01/22 18:05:01 Make order match header.
DaveMoore 2013/01/27 21:21:54 Done.
60 TabStrip* tab_strip,
61 int index,
62 Direction direction) {
63 int initial_tab_offset = Tab::GetMiniWidth() / 2;
64 gfx::Rect tab_bounds = tab_strip->tab_at(index)->bounds();
sky 2013/01/22 18:05:01 If an animation is occurring bounds() is going to
DaveMoore 2013/01/27 21:21:54 Is there some way to get the right location then?
sky 2013/01/28 19:18:52 You can use ideal_bounds(index) to get the ideal b
65 float x = direction == LEFT ?
66 tab_bounds.x() + initial_tab_offset :
67 tab_bounds.right() - initial_tab_offset;
68 return gfx::Point(x, tab_bounds.CenterPoint().y());
69 }
70
53 void TabScrubber::OnScrollEvent(ui::ScrollEvent* event) { 71 void TabScrubber::OnScrollEvent(ui::ScrollEvent* event) {
54 if (event->type() == ui::ET_SCROLL_FLING_CANCEL) { 72 if (event->type() == ui::ET_SCROLL_FLING_CANCEL ||
55 if (scrubbing_) 73 event->type() == ui::ET_SCROLL_FLING_START) {
56 StopScrubbing(); 74 FinishScrub(true);
75 CancelImmersiveReveal();
57 return; 76 return;
58 } 77 }
59 78
60 if (event->finger_count() != 3 || 79 if (event->finger_count() != 3)
61 event->type() != ui::ET_SCROLL)
62 return; 80 return;
63 81
64 Browser* browser = GetActiveBrowser(); 82 Browser* browser = GetActiveBrowser();
65 if (!browser || (browser_ && browser != browser_)) { 83 if (!browser || (browser_ && browser != browser_)) {
66 if (scrubbing_) 84 FinishScrub(false);
67 StopScrubbing();
68 return; 85 return;
69 } 86 }
70 87
88 event->StopPropagation();
89 float x_offset = event->x_offset();
71 BrowserView* browser_view = 90 BrowserView* browser_view =
72 BrowserView::GetBrowserViewForNativeWindow( 91 BrowserView::GetBrowserViewForNativeWindow(
73 browser->window()->GetNativeWindow()); 92 browser->window()->GetNativeWindow());
74 TabStrip* tab_strip = browser_view->tabstrip(); 93 TabStrip* tab_strip = browser_view->tabstrip();
75 94
76 float x_offset = -event->x_offset(); 95 if (!ui::IsNaturalScrollEnabled())
96 x_offset = -x_offset;
97 int last_tab_index = overridden_tab_ == -1 ?
sky 2013/01/22 18:05:01 What happens if overrideen_tab_ is no longer a val
DaveMoore 2013/01/27 21:21:54 Added check above and abort if not valid. On 2013/
98 browser->tab_strip_model()->active_index() : overridden_tab_;
77 if (!scrubbing_) { 99 if (!scrubbing_) {
100 swipe_direction_ = (x_offset < 0) ? LEFT : RIGHT;
101 const gfx::Point start_point =
102 GetStartPoint(tab_strip,
103 browser->tab_strip_model()->active_index(),
104 swipe_direction_);
105 browser_ = browser;
78 scrubbing_ = true; 106 scrubbing_ = true;
79 browser_ = browser; 107
80 Tab* initial_tab = 108 swipe_x_ = start_point.x();
81 tab_strip->tab_at(browser_->tab_strip_model()->active_index()); 109 swipe_y_ = start_point.y();
82 scroll_x_ = initial_tab->x(); 110 ImmersiveModeController* immersive_controller =
83 scroll_x_ += (x_offset < 0) ? 111 browser_view->immersive_mode_controller();
84 kInitialTabOffset : initial_tab->width() - kInitialTabOffset; 112 if (cancel_immersive_reveal_timer_.IsRunning())
85 scroll_y_ = initial_tab->height() / 2; 113 cancel_immersive_reveal_timer_.Stop();
86 registrar_.Add( 114 if (immersive_controller->enabled() &&
87 this, 115 !immersive_controller->IsRevealed()) {
88 chrome::NOTIFICATION_BROWSER_CLOSING, 116 immersive_controller->MaybeStartReveal();
89 content::Source<Browser>(browser_)); 117 should_cancel_immersive_reveal_ = true;
118 }
119 } else if (overridden_tab_ == -1) {
120 Direction direction = (x_offset < 0) ? LEFT : RIGHT;
121 if (direction != swipe_direction_) {
122 const gfx::Point start_point =
123 GetStartPoint(tab_strip,
124 browser->tab_strip_model()->active_index(),
125 swipe_direction_);
126 swipe_x_ = start_point.x();
127 swipe_y_ = start_point.y();
128 swipe_direction_ = direction;
129 }
90 } 130 }
91 131
92 if (ui::IsNaturalScrollEnabled()) 132 swipe_x_ += x_offset;
93 scroll_x_ += event->x_offset();
94 else
95 scroll_x_ -= event->x_offset();
96 Tab* first_tab = tab_strip->tab_at(0); 133 Tab* first_tab = tab_strip->tab_at(0);
134 int first_tab_center = first_tab->bounds().CenterPoint().x();
97 Tab* last_tab = tab_strip->tab_at(tab_strip->tab_count() - 1); 135 Tab* last_tab = tab_strip->tab_at(tab_strip->tab_count() - 1);
98 if (scroll_x_ < first_tab->x()) 136 int last_tab_tab_center = last_tab->bounds().CenterPoint().x();
99 scroll_x_ = first_tab->x(); 137 if (swipe_x_ < first_tab_center)
100 if (scroll_x_ > last_tab->bounds().right()) 138 swipe_x_ = first_tab_center;
101 scroll_x_ = last_tab->bounds().right(); 139 if (swipe_x_ > last_tab_tab_center)
140 swipe_x_ = last_tab_tab_center;
102 141
103 gfx::Point tab_point(scroll_x_, scroll_y_); 142 Tab* initial_tab = tab_strip->tab_at(last_tab_index);
104 Tab* new_tab = GetTabAt(tab_strip, tab_point); 143 gfx::Point tab_point(swipe_x_, swipe_y_);
105 if (new_tab && !new_tab->IsActive()) { 144 views::View::ConvertPointToTarget(tab_strip, initial_tab, &tab_point);
106 int new_index = tab_strip->GetModelIndexOfTab(new_tab); 145 Tab* new_tab = tab_strip->GetTabAt(initial_tab, tab_point);
107 browser->tab_strip_model()->ActivateTabAt(new_index, true); 146 if (!new_tab)
147 return;
148
149 int new_index = tab_strip->GetModelIndexOfTab(new_tab);
150 if (new_index != overridden_tab_) {
151 if (activate_timer_.IsRunning()) {
152 activate_timer_.Reset();
153 } else {
154 activate_timer_.Start(FROM_HERE,
155 activation_delay_,
156 base::Bind(&TabScrubber::FinishScrub,
157 weak_ptr_factory_.GetWeakPtr(),
158 true));
159 }
108 } 160 }
109 161
110 event->StopPropagation(); 162 if (overridden_tab_ != new_index) {
163 if (overridden_tab_ != -1)
164 tab_strip->tab_at(overridden_tab_)->hover_controller()->HideImmediately();
165 if (new_index == browser->tab_strip_model()->active_index()) {
166 overridden_tab_ = -1;
167 } else {
168 overridden_tab_ = new_index;
169 new_tab->hover_controller()->Show(views::GlowHoverController::PRONOUNCED);
170 }
171 }
172 if (overridden_tab_ != -1) {
173 gfx::Point hover_point(swipe_x_, swipe_y_);
174 views::View::ConvertPointToTarget(tab_strip, new_tab, &hover_point);
175 new_tab->hover_controller()->SetLocation(hover_point);
176 }
177 }
178
179 void TabScrubber::FinishScrub(bool activate) {
180 if (activate_timer_.IsRunning())
181 activate_timer_.Stop();
182
183 if (browser_) {
184 BrowserView* browser_view =
185 BrowserView::GetBrowserViewForNativeWindow(
186 browser_->window()->GetNativeWindow());
187 if (activate && overridden_tab_ != -1) {
188 TabStrip* tab_strip = browser_view->tabstrip();
189 tab_strip->tab_at(overridden_tab_)->hover_controller()->HideImmediately();
190 browser_->tab_strip_model()->ActivateTabAt(overridden_tab_, true);
191 }
192 if (!cancel_immersive_reveal_timer_.IsRunning() &&
193 should_cancel_immersive_reveal_) {
194 cancel_immersive_reveal_timer_.Start(
195 FROM_HERE,
196 base::TimeDelta::FromMilliseconds(kCancelImmersiveRevelDelayMS),
197 base:: Bind(&TabScrubber::CancelImmersiveReveal,
198 weak_ptr_factory_.GetWeakPtr()));
199 }
200 }
201 swipe_x_ = -1;
202 swipe_y_ = -1;
203 scrubbing_ = false;
204 overridden_tab_ = -1;
205 }
206
207 void TabScrubber::CancelImmersiveReveal() {
208 if (cancel_immersive_reveal_timer_.IsRunning())
209 cancel_immersive_reveal_timer_.Stop();
210 if (browser_ && should_cancel_immersive_reveal_) {
sky 2013/01/22 18:05:01 What is browser_ changes between the time you star
DaveMoore 2013/01/27 21:21:54 There already was protection against this when bro
211 BrowserView* browser_view =
212 BrowserView::GetBrowserViewForNativeWindow(
213 browser_->window()->GetNativeWindow());
214 browser_view->immersive_mode_controller()->CancelReveal();
215 }
216 should_cancel_immersive_reveal_ = false;
111 } 217 }
112 218
113 void TabScrubber::Observe(int type, 219 void TabScrubber::Observe(int type,
114 const content::NotificationSource& source, 220 const content::NotificationSource& source,
115 const content::NotificationDetails& details) { 221 const content::NotificationDetails& details) {
116 DCHECK(type == chrome::NOTIFICATION_BROWSER_CLOSING && 222 if (content::Source<Browser>(source).ptr() == browser_)
117 content::Source<Browser>(source).ptr() == browser_); 223 FinishScrub(false);
118 StopScrubbing(); 224 browser_ = NULL;
119 } 225 }
120 226
121 Browser* TabScrubber::GetActiveBrowser() { 227 Browser* TabScrubber::GetActiveBrowser() {
122 aura::Window* active_window = ash::wm::GetActiveWindow(); 228 aura::Window* active_window = ash::wm::GetActiveWindow();
123 if (!active_window) 229 if (!active_window)
124 return NULL; 230 return NULL;
125 231
126 Browser* browser = chrome::FindBrowserWithWindow(active_window); 232 Browser* browser = chrome::FindBrowserWithWindow(active_window);
127 if (!browser || browser->type() != Browser::TYPE_TABBED) 233 if (!browser || browser->type() != Browser::TYPE_TABBED)
128 return NULL; 234 return NULL;
129 235
130 return browser; 236 return browser;
131 } 237 }
132
133 void TabScrubber::StopScrubbing() {
134 if (!scrubbing_)
135 return;
136
137 registrar_.Remove(
138 this,
139 chrome::NOTIFICATION_BROWSER_CLOSING,
140 content::Source<Browser>(browser_));
141 scrubbing_ = false;
142 browser_ = NULL;
143 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698