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

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: Disable tests for win7_aura Created 7 years, 10 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
37 // static
38 gfx::Point TabScrubber::GetStartPoint(
39 TabStrip* tab_strip,
40 int index,
41 TabScrubber::Direction direction) {
42 int initial_tab_offset = Tab::GetMiniWidth() / 2;
43 gfx::Rect tab_bounds = tab_strip->tab_at(index)->bounds();
44 float x = direction == LEFT ?
45 tab_bounds.x() + initial_tab_offset :
46 tab_bounds.right() - initial_tab_offset;
47 return gfx::Point(x, tab_bounds.CenterPoint().y());
48 }
49
50 bool TabScrubber::IsActivationPending() {
51 return activate_timer_.IsRunning();
52 }
53
42 TabScrubber::TabScrubber() 54 TabScrubber::TabScrubber()
43 : scrubbing_(false), 55 : scrubbing_(false),
44 browser_(NULL), 56 browser_(NULL),
45 scroll_x_(-1), 57 swipe_x_(-1),
46 scroll_y_(-1) { 58 swipe_y_(-1),
59 swipe_direction_(LEFT),
60 highlighted_tab_(-1),
61 activate_timer_(true, false),
62 activation_delay_(base::TimeDelta::FromMilliseconds(kActivationDelayMS)),
63 should_cancel_immersive_reveal_(false),
64 cancel_immersive_reveal_timer_(true, false),
65 weak_ptr_factory_(this) {
47 ash::Shell::GetInstance()->AddPreTargetHandler(this); 66 ash::Shell::GetInstance()->AddPreTargetHandler(this);
67 registrar_.Add(
68 this,
69 chrome::NOTIFICATION_BROWSER_CLOSING,
70 content::NotificationService::AllSources());
48 } 71 }
49 72
50 TabScrubber::~TabScrubber() { 73 TabScrubber::~TabScrubber() {
74 // Note: The weak_ptr_factory_ should invalidate its weak pointers before
75 // any other members are destroyed.
76 weak_ptr_factory_.InvalidateWeakPtrs();
51 } 77 }
52 78
53 void TabScrubber::OnScrollEvent(ui::ScrollEvent* event) { 79 void TabScrubber::OnScrollEvent(ui::ScrollEvent* event) {
54 if (event->type() == ui::ET_SCROLL_FLING_CANCEL) { 80 if (event->type() == ui::ET_SCROLL_FLING_CANCEL ||
55 if (scrubbing_) 81 event->type() == ui::ET_SCROLL_FLING_START) {
56 StopScrubbing(); 82 FinishScrub(true);
83 CancelImmersiveReveal();
57 return; 84 return;
58 } 85 }
59 86
60 if (event->finger_count() != 3 || 87 if (event->finger_count() != 3)
61 event->type() != ui::ET_SCROLL)
62 return; 88 return;
63 89
64 Browser* browser = GetActiveBrowser(); 90 Browser* browser = GetActiveBrowser();
65 if (!browser || (browser_ && browser != browser_)) { 91 if (!browser || (scrubbing_ && browser_ && browser != browser_) ||
66 if (scrubbing_) 92 (highlighted_tab_ != -1 &&
67 StopScrubbing(); 93 highlighted_tab_ >= browser->tab_strip_model()->count())) {
94 FinishScrub(false);
68 return; 95 return;
69 } 96 }
70 97
71 BrowserView* browser_view = 98 BrowserView* browser_view =
72 BrowserView::GetBrowserViewForNativeWindow( 99 BrowserView::GetBrowserViewForNativeWindow(
73 browser->window()->GetNativeWindow()); 100 browser->window()->GetNativeWindow());
74 TabStrip* tab_strip = browser_view->tabstrip(); 101 TabStrip* tab_strip = browser_view->tabstrip();
75 102
76 float x_offset = -event->x_offset(); 103 if (tab_strip->IsAnimating()) {
77 if (!scrubbing_) { 104 FinishScrub(false);
78 scrubbing_ = true; 105 return;
79 browser_ = browser;
80 Tab* initial_tab =
81 tab_strip->tab_at(browser_->tab_strip_model()->active_index());
82 scroll_x_ = initial_tab->x();
83 scroll_x_ += (x_offset < 0) ?
84 kInitialTabOffset : initial_tab->width() - kInitialTabOffset;
85 scroll_y_ = initial_tab->height() / 2;
86 registrar_.Add(
87 this,
88 chrome::NOTIFICATION_BROWSER_CLOSING,
89 content::Source<Browser>(browser_));
90 } 106 }
91 107
92 if (ui::IsNaturalScrollEnabled()) 108 // We are handling the event.
93 scroll_x_ += event->x_offset(); 109 event->StopPropagation();
94 else
95 scroll_x_ -= event->x_offset();
96 Tab* first_tab = tab_strip->tab_at(0);
97 Tab* last_tab = tab_strip->tab_at(tab_strip->tab_count() - 1);
98 if (scroll_x_ < first_tab->x())
99 scroll_x_ = first_tab->x();
100 if (scroll_x_ > last_tab->bounds().right())
101 scroll_x_ = last_tab->bounds().right();
102 110
103 gfx::Point tab_point(scroll_x_, scroll_y_); 111 float x_offset = event->x_offset();
104 Tab* new_tab = GetTabAt(tab_strip, tab_point); 112 if (!ui::IsNaturalScrollEnabled())
105 if (new_tab && !new_tab->IsActive()) { 113 x_offset = -x_offset;
106 int new_index = tab_strip->GetModelIndexOfTab(new_tab); 114 int last_tab_index = highlighted_tab_ == -1 ?
107 browser->tab_strip_model()->ActivateTabAt(new_index, true); 115 browser->tab_strip_model()->active_index() : highlighted_tab_;
116 if (!scrubbing_) {
117 swipe_direction_ = (x_offset < 0) ? LEFT : RIGHT;
118 const gfx::Point start_point =
119 GetStartPoint(tab_strip,
120 browser->tab_strip_model()->active_index(),
121 swipe_direction_);
122 browser_ = browser;
123 scrubbing_ = true;
124
125 swipe_x_ = start_point.x();
126 swipe_y_ = start_point.y();
127 ImmersiveModeController* immersive_controller =
128 browser_view->immersive_mode_controller();
129 CancelImmersiveReveal();
130 if (immersive_controller->enabled() &&
131 !immersive_controller->IsRevealed()) {
132 immersive_controller->MaybeStartReveal();
133 should_cancel_immersive_reveal_ = true;
134 }
135 tab_strip->AddObserver(this);
136 } else if (highlighted_tab_ == -1) {
137 Direction direction = (x_offset < 0) ? LEFT : RIGHT;
138 if (direction != swipe_direction_) {
139 const gfx::Point start_point =
140 GetStartPoint(tab_strip,
141 browser->tab_strip_model()->active_index(),
142 direction);
143 swipe_x_ = start_point.x();
144 swipe_y_ = start_point.y();
145 swipe_direction_ = direction;
146 }
108 } 147 }
109 148
110 event->StopPropagation(); 149 swipe_x_ += x_offset;
150 Tab* first_tab = tab_strip->tab_at(0);
151 int first_tab_center = first_tab->bounds().CenterPoint().x();
152 Tab* last_tab = tab_strip->tab_at(tab_strip->tab_count() - 1);
153 int last_tab_tab_center = last_tab->bounds().CenterPoint().x();
154 if (swipe_x_ < first_tab_center)
155 swipe_x_ = first_tab_center;
156 if (swipe_x_ > last_tab_tab_center)
157 swipe_x_ = last_tab_tab_center;
158
159 Tab* initial_tab = tab_strip->tab_at(last_tab_index);
160 gfx::Point tab_point(swipe_x_, swipe_y_);
161 views::View::ConvertPointToTarget(tab_strip, initial_tab, &tab_point);
162 Tab* new_tab = tab_strip->GetTabAt(initial_tab, tab_point);
163 if (!new_tab)
164 return;
165
166 int new_index = tab_strip->GetModelIndexOfTab(new_tab);
167 if (new_index != highlighted_tab_) {
168 if (activate_timer_.IsRunning()) {
169 activate_timer_.Reset();
170 } else {
171 activate_timer_.Start(FROM_HERE,
172 activation_delay_,
173 base::Bind(&TabScrubber::FinishScrub,
174 weak_ptr_factory_.GetWeakPtr(),
175 true));
176 }
177 if (highlighted_tab_ != -1) {
178 Tab* tab = tab_strip->tab_at(highlighted_tab_);
179 tab->hover_controller()->HideImmediately();
180 }
181 if (new_index == browser->tab_strip_model()->active_index()) {
182 highlighted_tab_ = -1;
183 } else {
184 highlighted_tab_ = new_index;
185 new_tab->hover_controller()->Show(views::GlowHoverController::PRONOUNCED);
186 }
187 }
188 if (highlighted_tab_ != -1) {
189 gfx::Point hover_point(swipe_x_, swipe_y_);
190 views::View::ConvertPointToTarget(tab_strip, new_tab, &hover_point);
191 new_tab->hover_controller()->SetLocation(hover_point);
192 }
111 } 193 }
112 194
113 void TabScrubber::Observe(int type, 195 void TabScrubber::Observe(int type,
114 const content::NotificationSource& source, 196 const content::NotificationSource& source,
115 const content::NotificationDetails& details) { 197 const content::NotificationDetails& details) {
116 DCHECK(type == chrome::NOTIFICATION_BROWSER_CLOSING && 198 if (content::Source<Browser>(source).ptr() == browser_)
117 content::Source<Browser>(source).ptr() == browser_); 199 FinishScrub(false);
118 StopScrubbing(); 200 browser_ = NULL;
201 }
202
203 void TabScrubber::TabStripAddedTabAt(TabStrip* tab_strip, int index) {
204 if (highlighted_tab_ == -1)
205 return;
206
207 if (index < highlighted_tab_)
208 ++highlighted_tab_;
209 }
210
211 void TabScrubber::TabStripMovedTab(TabStrip* tab_strip,
212 int from_index,
213 int to_index) {
214 if (highlighted_tab_ == -1)
215 return;
216
217 if (from_index == highlighted_tab_)
218 highlighted_tab_ = to_index;
219 else if (from_index < highlighted_tab_&& highlighted_tab_<= to_index)
220 --highlighted_tab_;
221 else if (from_index > highlighted_tab_ && highlighted_tab_ >= to_index)
222 ++highlighted_tab_;
223 }
224
225 void TabScrubber::TabStripRemovedTabAt(TabStrip* tab_strip, int index) {
226 if (highlighted_tab_ == -1)
227 return;
228 if (index == highlighted_tab_) {
229 FinishScrub(false);
230 return;
231 }
232 if (index < highlighted_tab_)
233 --highlighted_tab_;
234 }
235
236 void TabScrubber::TabStripDeleted(TabStrip* tab_strip) {
237 if (highlighted_tab_ == -1)
238 return;
119 } 239 }
120 240
121 Browser* TabScrubber::GetActiveBrowser() { 241 Browser* TabScrubber::GetActiveBrowser() {
122 aura::Window* active_window = ash::wm::GetActiveWindow(); 242 aura::Window* active_window = ash::wm::GetActiveWindow();
123 if (!active_window) 243 if (!active_window)
124 return NULL; 244 return NULL;
125 245
126 Browser* browser = chrome::FindBrowserWithWindow(active_window); 246 Browser* browser = chrome::FindBrowserWithWindow(active_window);
127 if (!browser || browser->type() != Browser::TYPE_TABBED) 247 if (!browser || browser->type() != Browser::TYPE_TABBED)
128 return NULL; 248 return NULL;
129 249
130 return browser; 250 return browser;
131 } 251 }
132 252
133 void TabScrubber::StopScrubbing() { 253 void TabScrubber::FinishScrub(bool activate) {
134 if (!scrubbing_) 254 activate_timer_.Stop();
135 return;
136 255
137 registrar_.Remove( 256 if (browser_) {
138 this, 257 BrowserView* browser_view =
139 chrome::NOTIFICATION_BROWSER_CLOSING, 258 BrowserView::GetBrowserViewForNativeWindow(
140 content::Source<Browser>(browser_)); 259 browser_->window()->GetNativeWindow());
260 TabStrip* tab_strip = browser_view->tabstrip();
261 if (activate && highlighted_tab_ != -1) {
262 Tab* tab = tab_strip->tab_at(highlighted_tab_);
263 tab->hover_controller()->HideImmediately();
264 browser_->tab_strip_model()->ActivateTabAt(highlighted_tab_, true);
265 }
266 tab_strip->RemoveObserver(this);
267 if (!cancel_immersive_reveal_timer_.IsRunning() &&
268 should_cancel_immersive_reveal_) {
269 cancel_immersive_reveal_timer_.Start(
270 FROM_HERE,
271 base::TimeDelta::FromMilliseconds(kCancelImmersiveRevelDelayMS),
272 base:: Bind(&TabScrubber::CancelImmersiveReveal,
273 weak_ptr_factory_.GetWeakPtr()));
274 }
275 }
276 swipe_x_ = -1;
277 swipe_y_ = -1;
141 scrubbing_ = false; 278 scrubbing_ = false;
142 browser_ = NULL; 279 highlighted_tab_ = -1;
143 } 280 }
281
282 void TabScrubber::CancelImmersiveReveal() {
283 cancel_immersive_reveal_timer_.Stop();
284 if (browser_ && should_cancel_immersive_reveal_) {
285 BrowserView* browser_view =
286 BrowserView::GetBrowserViewForNativeWindow(
287 browser_->window()->GetNativeWindow());
288 browser_view->immersive_mode_controller()->CancelReveal();
289 }
290 should_cancel_immersive_reveal_ = false;
291 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/ash/tab_scrubber.h ('k') | chrome/browser/ui/views/ash/tab_scrubber_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698