172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/wm_overview_controller.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <algorithm>
8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector>
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/linked_ptr.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/browser_process.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/wm_ipc.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/chromeos/wm_overview_favicon.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/wm_overview_snapshot.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/chromeos/wm_overview_title.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/tab_contents/thumbnail_generator.h"
173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/tabs/tab_strip_model.h"
184a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch#include "chrome/browser/ui/browser.h"
1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/ui/views/frame/browser_view.h"
21dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_view_host.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host.h"
23dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/renderer_host/render_widget_host_view.h"
24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents_view.h"
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/common/notification_service.h"
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/root_view.h"
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/widget/widget_gtk.h"
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "views/window/window.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::vector;
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if !defined(OS_CHROMEOS)
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#error This file is only meant to be compiled for ChromeOS
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace chromeos {
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
39201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// Use this timer to delay consecutive snapshots during the updating process.
40201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// We will start the timer upon successfully retrieving a new snapshot, or if
41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// for some reason the current snapshot is still pending (while Chrome is
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch// still loading the page.)
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kDelayTimeMs = 10;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is the size of the web page when we lay it out for a snapshot.
46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kSnapshotWebPageWidth = 1024;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kSnapshotWebPageHeight = 1280;
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const double kSnapshotWebPageRatio =
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    static_cast<double>(kSnapshotWebPageWidth) / kSnapshotWebPageHeight;
50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is the maximum percentage of the original browser client area
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// that a snapshot can take up.
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const double kSnapshotMaxSizeRatio = 0.77;
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is the height of the title in pixels.
56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kTitleHeight = 32;
57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The number of additional padding pixels to remove from the title width.
59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const int kFaviconPadding = 5;
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass BrowserListener : public TabStripModelObserver {
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserListener(Browser* browser, WmOverviewController* parent);
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~BrowserListener();
65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Begin TabStripModelObserver methods
67201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabInsertedAt(TabContentsWrapper* contents,
68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             int index,
69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             bool foreground);
70731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  virtual void TabClosingAt(TabStripModel* tab_strip_model,
71201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                            TabContentsWrapper* contents,
72731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick                            int index) {}
73201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabDetachedAt(TabContentsWrapper* contents, int index);
74201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabMoved(TabContentsWrapper* contents,
75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int from_index,
76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                        int to_index);
77201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabChangedAt(TabContentsWrapper* contents, int index,
78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            TabStripModelObserver::TabChangeType change_type);
79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void TabStripEmpty();
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  virtual void TabDeselected(TabContentsWrapper* contents) {}
81201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  virtual void TabSelectedAt(TabContentsWrapper* old_contents,
82201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                             TabContentsWrapper* new_contents,
83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             int index,
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             bool user_gesture);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // End TabStripModelObserver methods
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the number of tabs in this child.
88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int count() const { return browser_->tabstrip_model()->count(); }
89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the browser that this child gets its data from.
91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* browser() const { return browser_; }
92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Removes all the snapshots and re-populates them from the browser.
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RecreateSnapshots();
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Mark the given snapshot as dirty, and start the delay timer.
97201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void MarkSnapshotAsDirty(int index);
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Updates the selected index and tab count on the toplevel window.
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void UpdateSelectedIndex(int index);
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
102201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Update the first "dirty" snapshot, which is ordered after (excluding)
103201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // the snapshot whose index is given by |start_from|; When |start_from| is
104201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // -1, search start at the begining of the list.
105201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Return the index of the snapshot which is actually updated; -1 if there
106201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // are no more tab contents (after |start_from|) to configure on this
107201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // listener.
108201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int ConfigureNextUnconfiguredSnapshot(int start_from);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Saves the currently selected tab.
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  void SaveCurrentTab() { original_selected_tab_ = browser_->active_index(); }
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reverts the selected browser tab to the tab that was selected
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // when This BrowserListener was created, or the last time
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // SaveCurrentTab was called.
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RestoreOriginalSelectedTab();
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Selects the tab at the given index.
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void SelectTab(int index, uint32 timestamp);
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Shows any snapshots that are not visible.
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ShowSnapshots();
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
124201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Callback for |AskForSnapshot|, start delay timer for next round.
125201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  void OnSnapshotReady(const SkBitmap& sk_bitmap);
126201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Returns the tab contents from the tab model for this child at index.
128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* GetTabContentsAt(int index) const  {
129201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return browser_->tabstrip_model()->GetTabContentsAt(index)->tab_contents();
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
131201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Calculate the size of a cell based on the browser window's size.
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size CalculateCellSize();
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Configures a cell from the tab contents.
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ConfigureCell(WmOverviewSnapshot* cell, TabContents* contents);
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Configures a cell from the model.
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ConfigureCell(WmOverviewSnapshot* cell, int index) {
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ConfigureCell(cell, GetTabContentsAt(index));
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Inserts a new snapshot, initialized from the model, at the given
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // index, and renumbers any following snapshots.
146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void InsertSnapshot(int index);
147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Removes the snapshot at index.
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void ClearSnapshot(int index);
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Renumbers the index atom in the snapshots starting at the given
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // index.
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  void RenumberSnapshots(int start_index);
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* browser_;  // Not owned
156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WmOverviewController* controller_;  // Not owned
157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
158201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Which renderer host we are working on.
159201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  RenderWidgetHost* current_renderer_host_; // Not owned
160201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Widgets containing snapshot images for this browser.  Note that
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // these are all subclasses of WidgetGtk, and they are all added to
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // parents, so they will be deleted by the parents when they are
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // closed.
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  struct SnapshotNode {
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WmOverviewSnapshot* snapshot;  // Not owned
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WmOverviewTitle* title;  // Not owned
168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    WmOverviewFavicon* favicon;  // Not owned
169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  };
170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  typedef std::vector<SnapshotNode> SnapshotVector;
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SnapshotVector snapshots_;
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Non-zero if we are currently setting the tab from within SelectTab.
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is used to make sure we use the right timestamp when sending
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // property changes that originated from the window manager.
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  uint32 select_tab_timestamp_;
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The tab selected the last time SaveCurrentTab is called.
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int original_selected_tab_;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DISALLOW_COPY_AND_ASSIGN(BrowserListener);
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserListener::BrowserListener(Browser* browser,
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 WmOverviewController* controller)
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : browser_(browser),
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      controller_(controller),
188201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      current_renderer_host_(NULL),
189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      select_tab_timestamp_(0),
190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      original_selected_tab_(-1) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(browser_);
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CHECK(controller_);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_->tabstrip_model()->AddObserver(this);
195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This browser didn't already exist, and so we haven't been
197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // watching it for tab insertions, so we need to create the
198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // snapshots associated with it.
199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RecreateSnapshots();
200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
202c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserListener::~BrowserListener() {
203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  browser_->tabstrip_model()->RemoveObserver(this);
204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
206201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserListener::TabInsertedAt(TabContentsWrapper* contents,
207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    int index,
208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    bool foreground) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  InsertSnapshot(index);
210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RenumberSnapshots(index);
211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UpdateSelectedIndex(browser_->active_index());
212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
214201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserListener::TabDetachedAt(TabContentsWrapper* contents, int index) {
215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ClearSnapshot(index);
216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UpdateSelectedIndex(browser_->active_index());
217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RenumberSnapshots(index);
218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
220201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserListener::TabMoved(TabContentsWrapper* contents,
221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               int from_index,
222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                               int to_index) {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Need to reorder tab in the snapshots list, and reset the window
224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // type atom on the affected snapshots (the one moved, and all the
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // ones after it), so that their indices are correct.
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SnapshotNode node = snapshots_[from_index];
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_.erase(snapshots_.begin() + from_index);
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_.insert(snapshots_.begin() + to_index, node);
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RenumberSnapshots(std::min(to_index, from_index));
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  UpdateSelectedIndex(browser_->active_index());
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::TabChangedAt(
235201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    TabContentsWrapper* contents,
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    int index,
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    TabStripModelObserver::TabChangeType change_type) {
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (change_type != TabStripModelObserver::LOADING_ONLY) {
239201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    snapshots_[index].title->SetTitle(contents->tab_contents()->GetTitle());
240201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    snapshots_[index].title->SetUrl(contents->tab_contents()->GetURL());
241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    snapshots_[index].favicon->SetFavicon(
242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        contents->tab_contents()->GetFavicon());
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (change_type != TabStripModelObserver::TITLE_NOT_LOADING)
244201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      MarkSnapshotAsDirty(index);
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::TabStripEmpty() {
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_.clear();
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
252201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserListener::TabSelectedAt(TabContentsWrapper* old_contents,
253201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch                                    TabContentsWrapper* new_contents,
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    int index,
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    bool user_gesture) {
256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (old_contents == new_contents)
257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  UpdateSelectedIndex(index);
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
262201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserListener::MarkSnapshotAsDirty(int index) {
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_[index].snapshot->reload_snapshot();
264201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  controller_->UpdateSnapshots();
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::RecreateSnapshots() {
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_.clear();
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (int i = 0; i < count(); ++i)
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    InsertSnapshot(i);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  RenumberSnapshots(0);
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::UpdateSelectedIndex(int index) {
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  WmIpcWindowType type = WmIpc::instance()->GetWindowType(
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      GTK_WIDGET(browser_->window()->GetNativeHandle()), NULL);
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make sure we only operate on toplevel windows.
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (type == WM_IPC_WINDOW_CHROME_TOPLEVEL) {
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    std::vector<int> params;
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params.push_back(browser_->tab_count());
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params.push_back(index);
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    params.push_back(select_tab_timestamp_ ? select_tab_timestamp_ :
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     gtk_get_current_event_time());
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WmIpc::instance()->SetWindowType(
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        GTK_WIDGET(browser_->window()->GetNativeHandle()),
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        WM_IPC_WINDOW_CHROME_TOPLEVEL,
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        &params);
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
293201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochint BrowserListener::ConfigureNextUnconfiguredSnapshot(int start_from) {
294201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (SnapshotVector::size_type i = start_from + 1;
295201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      i < snapshots_.size(); ++i) {
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    WmOverviewSnapshot* cell = snapshots_[i].snapshot;
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!cell->configured_snapshot()) {
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ConfigureCell(cell, i);
299201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return i;
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
302201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  return -1;
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::RestoreOriginalSelectedTab() {
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (original_selected_tab_ >= 0) {
307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    browser_->ActivateTabAt(original_selected_tab_, false);
308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UpdateSelectedIndex(browser_->active_index());
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::ShowSnapshots() {
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (SnapshotVector::size_type i = 0; i < snapshots_.size(); ++i) {
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const SnapshotNode& node = snapshots_[i];
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!node.snapshot->IsVisible())
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      node.snapshot->Show();
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (!snapshots_[i].title->IsVisible())
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      node.title->Show();
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!snapshots_[i].favicon->IsVisible())
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      node.favicon->Show();
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::SelectTab(int index, uint32 timestamp) {
325513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // Ignore requests to switch to non-existent tabs (the window manager gets
326513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // notified asynchronously about the number of tabs in each window, so there's
327513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  // no guarantee that the messages that it sends us will make sense).
328513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (index < 0 || index >= browser_->tab_count())
329513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return;
330513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  uint32 old_value = select_tab_timestamp_;
332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  select_tab_timestamp_ = timestamp;
333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  browser_->ActivateTabAt(index, true);
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  select_tab_timestamp_ = old_value;
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochgfx::Size BrowserListener::CalculateCellSize() {
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make the page size and the cell size a fixed size for overview
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // mode.  The cell size is calculated based on the desired maximum
340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // size on the screen, so it's related to the width and height of
341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the browser client area.  In this way, when this snapshot gets
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // to the window manager, it will already have the correct size,
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and will be scaled by 1.0, meaning that it won't be resampled
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // and will not be blurry.
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Rect bounds = static_cast<BrowserView*>(browser_->window())->
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                     GetClientAreaBounds();
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const gfx::Size max_size = gfx::Size(
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bounds.width() * kSnapshotMaxSizeRatio,
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      bounds.height() * kSnapshotMaxSizeRatio);
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  const double max_size_ratio = static_cast<double>(max_size.width()) /
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                max_size.height();
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size cell_size;
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (kSnapshotWebPageRatio > max_size_ratio) {
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const double scale_factor =
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        static_cast<double>(max_size.width())/ kSnapshotWebPageWidth;
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cell_size = gfx::Size(max_size.width(),
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          kSnapshotWebPageHeight * scale_factor + 0.5);
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    const double scale_factor =
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        static_cast<double>(max_size.height())/ kSnapshotWebPageHeight;
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cell_size = gfx::Size(kSnapshotWebPageWidth * scale_factor + 0.5,
362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          max_size.height());
363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return cell_size;
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid BrowserListener::OnSnapshotReady(const SkBitmap& sk_bitmap) {
368201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  for (int i = 0; i < count(); i++) {
369201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    RenderWidgetHostView* view =
370201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        GetTabContentsAt(i)->GetRenderWidgetHostView();
371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (view && view->GetRenderWidgetHost() == current_renderer_host_) {
372201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      snapshots_[i].snapshot->SetImage(sk_bitmap);
373201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      current_renderer_host_ = NULL;
374201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
375201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      // Start timer for next round of snapshot updating.
376201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      controller_->StartDelayTimer();
377201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      return;
378201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
379201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
380201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DCHECK(current_renderer_host_ == NULL);
381201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch}
382201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::ConfigureCell(WmOverviewSnapshot* cell,
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                    TabContents* contents) {
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (contents) {
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ThumbnailGenerator* generator =
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        g_browser_process->GetThumbnailGenerator();
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // TODO: Make sure that if the cell gets deleted before the
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // callback is called that it sticks around until it gets
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // called.  (some kind of "in flight" list that uses linked_ptr
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to make sure they don't actually get deleted?)  Also, make
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // sure that any request for a thumbnail eventually returns
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // (even if it has bogus data), so we don't leak orphaned cells,
394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // which could happen if a tab is closed while it is being
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // rendered.
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ThumbnailGenerator::ThumbnailReadyCallback* callback =
397201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        NewCallback(this, &BrowserListener::OnSnapshotReady);
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
399201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    current_renderer_host_ = contents->render_view_host();
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    generator->AskForSnapshot(contents->render_view_host(),
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              false,
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              callback,
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              gfx::Size(kSnapshotWebPageWidth,
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                        kSnapshotWebPageHeight),
405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                              CalculateCellSize());
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This happens because the contents haven't been loaded yet.
408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Make sure we set the snapshot image to something, otherwise
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // configured_snapshot remains false and
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // ConfigureNextUnconfiguredSnapshot would get stuck.
412201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    current_renderer_host_ = NULL;
413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    cell->SetImage(SkBitmap());
414201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    cell->reload_snapshot();
415201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    controller_->StartDelayTimer();
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::InsertSnapshot(int index) {
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SnapshotNode node;
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  node.snapshot = new WmOverviewSnapshot;
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gfx::Size cell_size = CalculateCellSize();
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  node.snapshot->Init(cell_size, browser_, index);
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  node.favicon = new WmOverviewFavicon;
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  node.favicon->Init(node.snapshot);
427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  node.favicon->SetFavicon(browser_->GetTabContentsAt(index)->GetFavicon());
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  node.title = new WmOverviewTitle;
430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  node.title->Init(gfx::Size(std::max(0, cell_size.width() -
431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      WmOverviewFavicon::kIconSize -
432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                      kFaviconPadding),
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                             kTitleHeight), node.snapshot);
434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  node.title->SetTitle(browser_->GetTabContentsAt(index)->GetTitle());
435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_.insert(snapshots_.begin() + index, node);
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  node.snapshot->reload_snapshot();
438201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  controller_->UpdateSnapshots();
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Removes the snapshot at index.
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::ClearSnapshot(int index) {
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_[index].snapshot->CloseNow();
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_[index].title->CloseNow();
445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  snapshots_[index].favicon->CloseNow();
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  snapshots_.erase(snapshots_.begin() + index);
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BrowserListener::RenumberSnapshots(int start_index) {
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (SnapshotVector::size_type i = start_index; i < snapshots_.size(); ++i) {
451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (snapshots_[i].snapshot->index() != static_cast<int>(i))
452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      snapshots_[i].snapshot->UpdateIndex(browser_, i);
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch///////////////////////////////////
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WmOverviewController methods
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static
46021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenWmOverviewController* WmOverviewController::GetInstance() {
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  static WmOverviewController* instance = NULL;
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!instance) {
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    instance = Singleton<WmOverviewController>::get();
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return instance;
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
468c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWmOverviewController::WmOverviewController()
469201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    : layout_mode_(ACTIVE_MODE),
470201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      updating_snapshots_(false),
471201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      browser_listener_index_(0),
472201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      tab_contents_index_(-1) {
473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  AddAllBrowsers();
474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (registrar_.IsEmpty()) {
476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Make sure we get notifications for when the tab contents are
477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // connected, so we know when a new browser has been created.
478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    registrar_.Add(this,
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationType::TAB_CONTENTS_CONNECTED,
480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationService::AllSources());
481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Ask for notification when the snapshot source image has changed
483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // and needs to be refreshed.
484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    registrar_.Add(this,
485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationType::THUMBNAIL_GENERATOR_SNAPSHOT_CHANGED,
486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                   NotificationService::AllSources());
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::AddObserver(this);
49021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  WmMessageListener::GetInstance()->AddObserver(this);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWmOverviewController::~WmOverviewController() {
49421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  WmMessageListener::GetInstance()->RemoveObserver(this);
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::RemoveObserver(this);
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  listeners_.clear();
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::Observe(NotificationType type,
500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   const NotificationSource& source,
501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                   const NotificationDetails& details) {
502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (type.value) {
503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Now that the tab contents are ready, we create the listeners
504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // and snapshots for any new browsers out there.  This actually
505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // results in us traversing the list of browsers more often than
506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // necessary (whenever a tab is connected, as opposed to only when
507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // a new browser is created), but other notifications aren't
508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // sufficient to know when the first tab of a new browser has its
509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // dimensions set.  The implementation of AddAllBrowsers avoids
510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // doing anything to already-existing browsers, so it's not a huge
511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // problem, but still, it would be nice if there were a more
512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // appropriate (browser-level) notification.
513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::TAB_CONTENTS_CONNECTED:
514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      AddAllBrowsers();
515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case NotificationType::THUMBNAIL_GENERATOR_SNAPSHOT_CHANGED: {
518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // It's OK to do this in active mode too -- nothing will happen
519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // except invalidation of the snapshot, because the delay timer
520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // won't start until we're in overview mode.
521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RenderWidgetHost* renderer = Details<RenderViewHost>(details).ptr();
522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SnapshotImageChanged(renderer);
523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
525c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Do nothing.
527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::SnapshotImageChanged(RenderWidgetHost* renderer) {
532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Find out which TabContents this renderer is attached to, and then
533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // invalidate the associated snapshot so it'll update.
534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserListenerVector::iterator iter = listeners_.begin();
535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iter != listeners_.end()) {
536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (int i = 0; i < (*iter)->count(); i++) {
537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      RenderWidgetHostView* view =
538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          (*iter)->GetTabContentsAt(i)->GetRenderWidgetHostView();
539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (view && view->GetRenderWidgetHost() == renderer) {
540201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        (*iter)->MarkSnapshotAsDirty(i);
541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return;
542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ++iter;
545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
546201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  DLOG(ERROR) << "SnapshotImageChanged, but we do not know which it is?";
547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
549731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid WmOverviewController::OnBrowserRemoved(const Browser* browser) {
550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserListenerVector::iterator i = listeners_.begin();
551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != listeners_.end(); ++i) {
552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((*i)->browser() == browser) {
553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      listeners_.erase(i);
554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
559c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBrowserView* GetBrowserViewForGdkWindow(GdkWindow* gdk_window) {
560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gpointer data = NULL;
561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  gdk_window_get_user_data(gdk_window, &data);
562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  GtkWidget* widget = reinterpret_cast<GtkWidget*>(data);
563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (widget) {
564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    GtkWindow* gtk_window = GTK_WINDOW(widget);
565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return BrowserView::GetBrowserViewForNativeWindow(gtk_window);
566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return NULL;
568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::ProcessWmMessage(const WmIpc::Message& message,
572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                            GdkWindow* window) {
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (message.type()) {
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WM_IPC_MESSAGE_CHROME_NOTIFY_LAYOUT_MODE: {
575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      layout_mode_ = message.param(0) == 0 ? ACTIVE_MODE : OVERVIEW_MODE;
576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if (layout_mode_ == ACTIVE_MODE || BrowserList::size() == 0) {
577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        Hide(message.param(1) != 0);
578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      } else {
579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        Show();
580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case WM_IPC_MESSAGE_CHROME_NOTIFY_TAB_SELECT: {
584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      BrowserView* browser_window = GetBrowserViewForGdkWindow(window);
585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // Find out which listener this goes to, and send it there.
586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      for (BrowserListenerVector::iterator i = listeners_.begin();
587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch           i != listeners_.end(); ++i) {
588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        if ((*i)->browser()->window() == browser_window) {
589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // param(0): index of the tab to select.
590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          // param(1): timestamp of the event.
591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          (*i)->SelectTab(message.param(0), message.param(1));
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          break;
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        }
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      break;
599c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
601c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::StartDelayTimer() {
603201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // We're rate limiting the number of times we can reconfigure the
604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // snapshots.  If we were to restart the delay timer, it could
605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // result in a very long delay until they get configured if tabs
606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // keep changing.
607201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  updating_snapshots_ = false;
608201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (layout_mode_ == OVERVIEW_MODE) {
609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    delay_timer_.Start(
610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        base::TimeDelta::FromMilliseconds(kDelayTimeMs), this,
611201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        &WmOverviewController::UpdateSnapshots);
612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::RestoreTabSelections() {
616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserListenerVector::iterator i = listeners_.begin();
617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != listeners_.end(); ++i) {
618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    (*i)->RestoreOriginalSelectedTab();
619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
620c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::SaveTabSelections() {
623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserListenerVector::iterator i = listeners_.begin();
624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != listeners_.end(); ++i) {
625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    (*i)->SaveCurrentTab();
626c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::Show() {
630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SaveTabSelections();
631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  for (BrowserListenerVector::iterator i = listeners_.begin();
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch       i != listeners_.end(); ++i) {
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    (*i)->ShowSnapshots();
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
636201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
637201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // TODO(jiesun): Make the focused tab as the start point.
638201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  browser_listener_index_ = 0;
639201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  tab_contents_index_ = -1;
640201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  UpdateSnapshots();
641c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
642c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
643c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::Hide(bool cancelled) {
644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  delay_timer_.Stop();
645201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  updating_snapshots_ = false;
646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (cancelled) {
647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    RestoreTabSelections();
648c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
651201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid WmOverviewController::UpdateSnapshots() {
652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
653201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Only updating snapshots during overview mode.
654201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (layout_mode_ != OVERVIEW_MODE)
655201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
656201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
657201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Only reloading snapshots when not already started.
658201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (updating_snapshots_ || delay_timer_.IsRunning())
659201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
660201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
661201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Only update one snapshot in round-robin mode.
662201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // Start delay timer after each update unless all snapshots had been updated.
663201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (!listeners_.size())
664201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    return;
665201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
666201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  if (int(listeners_.size()) <= browser_listener_index_) {
667201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    DLOG(INFO) << "Browser listener(s) have disappeared since last update";
668201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    browser_listener_index_ = 0;
669201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    tab_contents_index_ = -1;
670201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  } else {
671201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    BrowserListener* listener = listeners_[browser_listener_index_].get();
672201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (listener->count() <= tab_contents_index_) {
673201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      DLOG(INFO) << "Tab content(s) have disappeared since last update";
674201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      tab_contents_index_ = -1;
675201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
676201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  }
677201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
678201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int browser_listener_index = browser_listener_index_;
679201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  int tab_contents_index = tab_contents_index_;
680201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
681201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  bool loop_back = false;
682201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  while (1) {
683201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    BrowserListener* listener = listeners_[browser_listener_index].get();
684201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    tab_contents_index =
685201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch        listener->ConfigureNextUnconfiguredSnapshot(tab_contents_index);
686201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (tab_contents_index >= 0) {
687201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      updating_snapshots_ = true;  // Prevent future parallel updates.
688201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      browser_listener_index_ = browser_listener_index;
689201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      tab_contents_index_ = tab_contents_index;
690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return;
691201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    }
692201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
693201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    // Found next one;
69421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    browser_listener_index++;
695201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    browser_listener_index = browser_listener_index % listeners_.size();
696201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    tab_contents_index = -1;
697201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
698201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    if (loop_back)
699201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch      break;
700201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch    loop_back = browser_listener_index == browser_listener_index_;
701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
702201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
703201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  // All snapshots have been fully updated.
704201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch  updating_snapshots_ = false;
705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WmOverviewController::AddAllBrowsers() {
708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Make a copy so the old ones aren't deleted yet.
709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserListenerVector old_listeners;
710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  listeners_.swap(old_listeners);
712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Iterator through the browser list, adding all the browsers in the
714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // new order.  If they were in the old list of listeners, just copy
715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // that linked pointer, instead of making a new listener, so that we
716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // can avoid lots of spurious destroy/create messages.
717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  BrowserList::const_iterator iterator = BrowserList::begin();
718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  while (iterator != BrowserList::end()) {
719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // Don't add a browser to the list if that type of browser doesn't
720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // have snapshots in overview mode.
721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if ((*iterator)->type() != Browser::TYPE_NORMAL &&
72221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        (*iterator)->type() != Browser::TYPE_APP) {
723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      ++iterator;
724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      continue;
725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    BrowserListenerVector::value_type item(
728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        BrowserListenerVector::value_type(NULL));
729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    for (BrowserListenerVector::iterator old_iter = old_listeners.begin();
730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch         old_iter != old_listeners.end(); ++old_iter) {
731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      if ((*old_iter)->browser() == *iterator) {
732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        item = *old_iter;
733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // This browser isn't tracked by any listener, so create it.
738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (item.get() == NULL) {
739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      item = BrowserListenerVector::value_type(
740c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          new BrowserListener(*iterator, this));
741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    listeners_.push_back(item);
743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    ++iterator;
744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace chromeos
748