OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/chromeos/wm_overview_controller.h" | 5 #include "chrome/browser/chromeos/wm_overview_controller.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/linked_ptr.h" | 10 #include "base/linked_ptr.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 // remove it and just use the configure timer. The reason I'm not | 40 // remove it and just use the configure timer. The reason I'm not |
41 // doing that is that I have a hunch that we'll be needing to tune | 41 // doing that is that I have a hunch that we'll be needing to tune |
42 // things further, and this will be one of the knobs. | 42 // things further, and this will be one of the knobs. |
43 static const int kDelayTimeMs = 10; | 43 static const int kDelayTimeMs = 10; |
44 | 44 |
45 // The time between setting snapshots during the configuration pass, | 45 // The time between setting snapshots during the configuration pass, |
46 // so that the CPU has a chance to do something else (to keep overview | 46 // so that the CPU has a chance to do something else (to keep overview |
47 // mode responsive). | 47 // mode responsive). |
48 static const int kConfigureTimeMs = 10; | 48 static const int kConfigureTimeMs = 10; |
49 | 49 |
| 50 // This is the size of the web page when we lay it out for a snapshot. |
| 51 static const int kSnapshotWebPageWidth = 1024; |
| 52 static const int kSnapshotWebPageHeight = 1280; |
| 53 static const double kSnapshotWebPageRatio = |
| 54 static_cast<double>(kSnapshotWebPageWidth) / kSnapshotWebPageHeight; |
| 55 |
| 56 // This is the maximum percentage of the original browser client area |
| 57 // that a snapshot can take up. |
| 58 static const double kSnapshotMaxSizeRatio = 0.77; |
| 59 |
50 class BrowserListener : public TabStripModelObserver { | 60 class BrowserListener : public TabStripModelObserver { |
51 public: | 61 public: |
52 BrowserListener(Browser* browser, WmOverviewController* parent); | 62 BrowserListener(Browser* browser, WmOverviewController* parent); |
53 ~BrowserListener(); | 63 ~BrowserListener(); |
54 | 64 |
55 // Begin TabStripModelObserver methods | 65 // Begin TabStripModelObserver methods |
56 virtual void TabInsertedAt(TabContents* contents, | 66 virtual void TabInsertedAt(TabContents* contents, |
57 int index, | 67 int index, |
58 bool foreground); | 68 bool foreground); |
59 virtual void TabClosingAt(TabContents* contents, int index) {} | 69 virtual void TabClosingAt(TabContents* contents, int index) {} |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 void SelectTab(int index, uint32 timestamp); | 113 void SelectTab(int index, uint32 timestamp); |
104 | 114 |
105 // Shows any snapshots that are not visible. | 115 // Shows any snapshots that are not visible. |
106 void ShowSnapshots(); | 116 void ShowSnapshots(); |
107 | 117 |
108 // Returns the tab contents from the tab model for this child at index. | 118 // Returns the tab contents from the tab model for this child at index. |
109 TabContents* GetTabContentsAt(int index) const { | 119 TabContents* GetTabContentsAt(int index) const { |
110 return browser_->tabstrip_model()->GetTabContentsAt(index); | 120 return browser_->tabstrip_model()->GetTabContentsAt(index); |
111 } | 121 } |
112 private: | 122 private: |
| 123 // Calculate the size of a cell based on the browser window's size. |
| 124 gfx::Size CalculateCellSize(); |
113 | 125 |
114 // Configures a cell from the tab contents. | 126 // Configures a cell from the tab contents. |
115 void ConfigureCell(WmOverviewSnapshot* cell, TabContents* contents); | 127 void ConfigureCell(WmOverviewSnapshot* cell, TabContents* contents); |
116 | 128 |
117 // Configures a cell from the model. | 129 // Configures a cell from the model. |
118 void ConfigureCell(WmOverviewSnapshot* cell, int index) { | 130 void ConfigureCell(WmOverviewSnapshot* cell, int index) { |
119 ConfigureCell(cell, GetTabContentsAt(index)); | 131 ConfigureCell(cell, GetTabContentsAt(index)); |
120 } | 132 } |
121 | 133 |
122 // Inserts a new snapshot, initialized from the model, at the given | 134 // Inserts a new snapshot, initialized from the model, at the given |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
191 int from_index, | 203 int from_index, |
192 int to_index) { | 204 int to_index) { |
193 // Need to reorder tab in the snapshots list, and reset the window | 205 // Need to reorder tab in the snapshots list, and reset the window |
194 // type atom on the affected snapshots (the one moved, and all the | 206 // type atom on the affected snapshots (the one moved, and all the |
195 // ones after it), so that their indices are correct. | 207 // ones after it), so that their indices are correct. |
196 WmOverviewSnapshot* snapshot = snapshots_[from_index]; | 208 WmOverviewSnapshot* snapshot = snapshots_[from_index]; |
197 snapshots_.erase(snapshots_.begin() + from_index); | 209 snapshots_.erase(snapshots_.begin() + from_index); |
198 snapshots_.insert(snapshots_.begin() + to_index, snapshot); | 210 snapshots_.insert(snapshots_.begin() + to_index, snapshot); |
199 | 211 |
200 RenumberSnapshots(std::min(to_index, from_index)); | 212 RenumberSnapshots(std::min(to_index, from_index)); |
| 213 UpdateSelectedIndex(browser_->selected_index()); |
201 } | 214 } |
202 | 215 |
203 void BrowserListener::TabChangedAt( | 216 void BrowserListener::TabChangedAt( |
204 TabContents* contents, | 217 TabContents* contents, |
205 int index, | 218 int index, |
206 TabStripModelObserver::TabChangeType change_type) { | 219 TabStripModelObserver::TabChangeType change_type) { |
207 if (change_type != TabStripModelObserver::LOADING_ONLY && | 220 if (change_type != TabStripModelObserver::LOADING_ONLY && |
208 change_type != TabStripModelObserver::TITLE_NOT_LOADING) { | 221 change_type != TabStripModelObserver::TITLE_NOT_LOADING) { |
209 ReloadSnapshot(index); | 222 ReloadSnapshot(index); |
210 } | 223 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 ConfigureCell(cell, i); | 273 ConfigureCell(cell, i); |
261 return true; | 274 return true; |
262 } | 275 } |
263 } | 276 } |
264 return false; | 277 return false; |
265 } | 278 } |
266 | 279 |
267 void BrowserListener::RestoreOriginalSelectedTab() { | 280 void BrowserListener::RestoreOriginalSelectedTab() { |
268 if (original_selected_tab_ >= 0) { | 281 if (original_selected_tab_ >= 0) { |
269 browser_->SelectTabContentsAt(original_selected_tab_, false); | 282 browser_->SelectTabContentsAt(original_selected_tab_, false); |
| 283 UpdateSelectedIndex(browser_->selected_index()); |
270 } | 284 } |
271 } | 285 } |
272 | 286 |
273 void BrowserListener::ShowSnapshots() { | 287 void BrowserListener::ShowSnapshots() { |
274 for (SnapshotVector::size_type i = 0; i < snapshots_.size(); ++i) { | 288 for (SnapshotVector::size_type i = 0; i < snapshots_.size(); ++i) { |
275 WmOverviewSnapshot* snapshot = snapshots_[i]; | 289 WmOverviewSnapshot* snapshot = snapshots_[i]; |
276 if (!snapshot->IsVisible()) | 290 if (!snapshot->IsVisible()) |
277 snapshot->Show(); | 291 snapshot->Show(); |
278 } | 292 } |
279 } | 293 } |
280 | 294 |
281 void BrowserListener::SelectTab(int index, uint32 timestamp) { | 295 void BrowserListener::SelectTab(int index, uint32 timestamp) { |
282 uint32 old_value = select_tab_timestamp_; | 296 uint32 old_value = select_tab_timestamp_; |
283 select_tab_timestamp_ = timestamp; | 297 select_tab_timestamp_ = timestamp; |
284 browser_->SelectTabContentsAt(index, true); | 298 browser_->SelectTabContentsAt(index, true); |
285 select_tab_timestamp_ = old_value; | 299 select_tab_timestamp_ = old_value; |
286 } | 300 } |
287 | 301 |
| 302 gfx::Size BrowserListener::CalculateCellSize() { |
| 303 // Make the page size and the cell size a fixed size for overview |
| 304 // mode. The cell size is calculated based on the desired maximum |
| 305 // size on the screen, so it's related to the width and height of |
| 306 // the browser client area. In this way, when this snapshot gets |
| 307 // to the window manager, it will already have the correct size, |
| 308 // and will be scaled by 1.0, meaning that it won't be resampled |
| 309 // and will not be blurry. |
| 310 gfx::Rect bounds = static_cast<BrowserView*>(browser_->window())-> |
| 311 GetClientAreaBounds(); |
| 312 const gfx::Size max_size = gfx::Size( |
| 313 bounds.width() * kSnapshotMaxSizeRatio, |
| 314 bounds.height() * kSnapshotMaxSizeRatio) |
| 315 const double max_size_ratio = static_cast<double>(max_size.width()) / |
| 316 max_size.height(); |
| 317 gfx::Size cell_size; |
| 318 if (kSnapshotWebPageRatio > max_size_ratio) { |
| 319 const double scale_factor = |
| 320 static_cast<double>(max_size.width())/ kSnapshotWebPageWidth; |
| 321 cell_size = gfx::Size(max_size.width(), |
| 322 kSnapshotWebPageHeight * scale_factor + 0.5); |
| 323 } else { |
| 324 const double scale_factor = |
| 325 static_cast<double>(max_size.height())/ kSnapshotWebPageHeight; |
| 326 cell_size = gfx::Size(kSnapshotWebPageWidth * scale_factor + 0.5, |
| 327 max_size.height()); |
| 328 } |
| 329 return cell_size; |
| 330 } |
| 331 |
288 void BrowserListener::ConfigureCell(WmOverviewSnapshot* cell, | 332 void BrowserListener::ConfigureCell(WmOverviewSnapshot* cell, |
289 TabContents* contents) { | 333 TabContents* contents) { |
290 if (contents) { | 334 if (contents) { |
291 ThumbnailGenerator* generator = | 335 ThumbnailGenerator* generator = |
292 g_browser_process->GetThumbnailGenerator(); | 336 g_browser_process->GetThumbnailGenerator(); |
293 // TODO: Make sure that if the cell gets deleted before the | 337 // TODO: Make sure that if the cell gets deleted before the |
294 // callback is called that it sticks around until it gets | 338 // callback is called that it sticks around until it gets |
295 // called. (some kind of "in flight" list that uses linked_ptr | 339 // called. (some kind of "in flight" list that uses linked_ptr |
296 // to make sure they don't actually get deleted?) Also, make | 340 // to make sure they don't actually get deleted?) Also, make |
297 // sure that any request for a thumbnail eventually returns | 341 // sure that any request for a thumbnail eventually returns |
298 // (even if it has bogus data), so we don't leak orphaned cells, | 342 // (even if it has bogus data), so we don't leak orphaned cells, |
299 // which could happen if a tab is closed while it is being | 343 // which could happen if a tab is closed while it is being |
300 // rendered. | 344 // rendered. |
301 ThumbnailGenerator::ThumbnailReadyCallback* callback = | 345 ThumbnailGenerator::ThumbnailReadyCallback* callback = |
302 NewCallback(cell, &WmOverviewSnapshot::SetImage); | 346 NewCallback(cell, &WmOverviewSnapshot::SetImage); |
303 gfx::Size cell_size = cell->size(); | |
304 | 347 |
305 // Ask for the page size to be twice the requested size of the | |
306 // snapshot. | |
307 generator->AskForSnapshot(contents->render_view_host(), | 348 generator->AskForSnapshot(contents->render_view_host(), |
308 false, | 349 false, |
309 callback, | 350 callback, |
310 gfx::Size(cell_size.width() * 2, | 351 gfx::Size(kSnapshotWebPageWidth, |
311 cell_size.height() * 2), | 352 kSnapshotWebPageHeight), |
312 cell_size); | 353 CalculateCellSize()); |
313 } else { | 354 } else { |
314 // This happens because the contents haven't been loaded yet. | 355 // This happens because the contents haven't been loaded yet. |
315 | 356 |
316 // Make sure we set the snapshot image to something, otherwise | 357 // Make sure we set the snapshot image to something, otherwise |
317 // configured_snapshot remains false and | 358 // configured_snapshot remains false and |
318 // ConfigureNextUnconfiguredSnapshot would get stuck. | 359 // ConfigureNextUnconfiguredSnapshot would get stuck. |
319 cell->SetImage(SkBitmap()); | 360 cell->SetImage(SkBitmap()); |
320 } | 361 } |
321 } | 362 } |
322 | 363 |
323 void BrowserListener::InsertSnapshot(int index) { | 364 void BrowserListener::InsertSnapshot(int index) { |
324 WmOverviewSnapshot* snapshot = new WmOverviewSnapshot; | 365 WmOverviewSnapshot* snapshot = new WmOverviewSnapshot; |
325 gfx::Rect bounds = | 366 snapshot->Init(CalculateCellSize(), browser_, index); |
326 static_cast<BrowserView*>(browser_->window())->GetClientAreaBounds(); | |
327 gfx::Size size(bounds.width() / 2, bounds.height() / 2); | |
328 snapshot->Init(size, browser_, index); | |
329 snapshots_.insert(snapshots_.begin() + index, snapshot); | 367 snapshots_.insert(snapshots_.begin() + index, snapshot); |
330 snapshot->reload_snapshot(); | 368 snapshot->reload_snapshot(); |
331 controller_->StartDelayTimer(); | 369 controller_->StartDelayTimer(); |
332 } | 370 } |
333 | 371 |
334 // Removes the snapshot at index. | 372 // Removes the snapshot at index. |
335 void BrowserListener::ClearSnapshot(int index) { | 373 void BrowserListener::ClearSnapshot(int index) { |
336 snapshots_[index]->CloseNow(); | 374 snapshots_[index]->CloseNow(); |
337 snapshots_.erase(snapshots_.begin() + index); | 375 snapshots_.erase(snapshots_.begin() + index); |
338 } | 376 } |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
396 // sufficient to know when the first tab of a new browser has its | 434 // sufficient to know when the first tab of a new browser has its |
397 // dimensions set. The implementation of AddAllBrowsers avoids | 435 // dimensions set. The implementation of AddAllBrowsers avoids |
398 // doing anything to already-existing browsers, so it's not a huge | 436 // doing anything to already-existing browsers, so it's not a huge |
399 // problem, but still, it would be nice if there were a more | 437 // problem, but still, it would be nice if there were a more |
400 // appropriate (browser-level) notification. | 438 // appropriate (browser-level) notification. |
401 case NotificationType::TAB_CONTENTS_CONNECTED: | 439 case NotificationType::TAB_CONTENTS_CONNECTED: |
402 AddAllBrowsers(); | 440 AddAllBrowsers(); |
403 break; | 441 break; |
404 | 442 |
405 case NotificationType::THUMBNAIL_GENERATOR_SNAPSHOT_CHANGED: { | 443 case NotificationType::THUMBNAIL_GENERATOR_SNAPSHOT_CHANGED: { |
406 // Don't do any dynamic updating if we're not in overview mode. | 444 // It's OK to do this in active mode too -- nothing will happen |
407 if (layout_mode_ == OVERVIEW_MODE) { | 445 // except invalidation of the snapshot, because the delay timer |
408 RenderWidgetHost* renderer = Details<RenderViewHost>(details).ptr(); | 446 // won't start until we're in overview mode. |
409 SnapshotImageChanged(renderer); | 447 RenderWidgetHost* renderer = Details<RenderViewHost>(details).ptr(); |
410 } | 448 SnapshotImageChanged(renderer); |
411 break; | 449 break; |
412 } | 450 } |
413 default: | 451 default: |
414 // Do nothing. | 452 // Do nothing. |
415 break; | 453 break; |
416 } | 454 } |
417 } | 455 } |
418 | 456 |
419 void WmOverviewController::SnapshotImageChanged(RenderWidgetHost* renderer) { | 457 void WmOverviewController::SnapshotImageChanged(RenderWidgetHost* renderer) { |
420 // Find out which TabContents this renderer is attached to, and then | 458 // Find out which TabContents this renderer is attached to, and then |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 if (item.get() == NULL) { | 628 if (item.get() == NULL) { |
591 item = BrowserListenerVector::value_type( | 629 item = BrowserListenerVector::value_type( |
592 new BrowserListener(*iterator, this)); | 630 new BrowserListener(*iterator, this)); |
593 } | 631 } |
594 listeners_.push_back(item); | 632 listeners_.push_back(item); |
595 ++iterator; | 633 ++iterator; |
596 } | 634 } |
597 } | 635 } |
598 | 636 |
599 } // namespace chromeos | 637 } // namespace chromeos |
OLD | NEW |