Commit 4dab7257 authored by sky@chromium.org's avatar sky@chromium.org

Improves tab overview.

BUG=none
TEST=none

Review URL: http://codereview.chromium.org/151169

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@19761 0039d316-1c4b-4281-b951-d872f2087c98
parent 59470077
...@@ -68,6 +68,12 @@ class DraggedTabController : public TabContentsDelegate, ...@@ -68,6 +68,12 @@ class DraggedTabController : public TabContentsDelegate,
// Returns true if the specified Tab matches the Tab being dragged. // Returns true if the specified Tab matches the Tab being dragged.
bool IsDragSourceTab(Tab* tab) const; bool IsDragSourceTab(Tab* tab) const;
TabContents* dragged_contents() { return dragged_contents_; }
private: private:
class DockDisplayer; class DockDisplayer;
friend class DockDisplayer; friend class DockDisplayer;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "chrome/browser/tab_contents/thumbnail_generator.h" #include "chrome/browser/tab_contents/thumbnail_generator.h"
#include "chrome/browser/views/tabs/tab_overview_cell.h" #include "chrome/browser/views/tabs/tab_overview_cell.h"
#include "chrome/browser/views/tabs/tab_overview_container.h" #include "chrome/browser/views/tabs/tab_overview_container.h"
#include "chrome/browser/views/tabs/tab_overview_drag_controller.h"
#include "chrome/browser/views/tabs/tab_overview_grid.h" #include "chrome/browser/views/tabs/tab_overview_grid.h"
#include "chrome/browser/views/tabs/tab_overview_types.h" #include "chrome/browser/views/tabs/tab_overview_types.h"
#include "chrome/browser/window_sizer.h" #include "chrome/browser/window_sizer.h"
...@@ -85,21 +86,38 @@ void TabOverviewController::SetBrowser(Browser* browser, ...@@ -85,21 +86,38 @@ void TabOverviewController::SetBrowser(Browser* browser,
browser_ = browser; browser_ = browser;
if (browser_) if (browser_)
model()->AddObserver(this); model()->AddObserver(this);
show_thumbnails_ = false;
StartDelayTimer();
gfx::Rect host_bounds = CalculateHostBounds(); gfx::Rect host_bounds = CalculateHostBounds();
if (moved_offscreen_ && model() && model()->count()) { if (moved_offscreen_ && model() && model()->count()) {
// Need to reset the bounds if we were offscreen. // Need to reset the bounds if we were offscreen.
host_->SetBounds(host_bounds); host_->SetBounds(host_bounds);
moved_offscreen_ = false; moved_offscreen_ = false;
} else if (!model() && shown_) {
MoveOffscreen();
} }
if (!moved_offscreen_)
container_->SchedulePaint();
RecreateCells(); RecreateCells();
container_->set_arrow_center(horizontal_center_ - host_bounds.x()); container_->set_arrow_center(horizontal_center_ - host_bounds.x());
if (!moved_offscreen_)
container_->SchedulePaint();
} }
TabStripModel* TabOverviewController::model() const { TabStripModel* TabOverviewController::model() const {
return browser_ ? browser_->tabstrip_model() : NULL; return browser_ ? browser_->tabstrip_model() : NULL;
} }
void TabOverviewController::SetMouseOverMiniWindow(bool over_mini_window) {
if (grid_->drag_controller())
grid_->drag_controller()->set_mouse_over_mini_window(over_mini_window);
}
void TabOverviewController::Show() { void TabOverviewController::Show() {
if (host_->IsVisible()) if (host_->IsVisible())
return; return;
...@@ -107,9 +125,9 @@ void TabOverviewController::Show() { ...@@ -107,9 +125,9 @@ void TabOverviewController::Show() {
shown_ = true; shown_ = true;
DCHECK(model()); // The model needs to be set before showing. DCHECK(model()); // The model needs to be set before showing.
host_->Show(); host_->Show();
delay_timer_.Start(
base::TimeDelta::FromMilliseconds(350), this, show_thumbnails_ = false;
&TabOverviewController::StartConfiguring); StartDelayTimer();
} }
void TabOverviewController::ConfigureCell(TabOverviewCell* cell, void TabOverviewController::ConfigureCell(TabOverviewCell* cell,
...@@ -321,6 +339,7 @@ gfx::Rect TabOverviewController::CalculateHostBounds() { ...@@ -321,6 +339,7 @@ gfx::Rect TabOverviewController::CalculateHostBounds() {
void TabOverviewController::StartConfiguring() { void TabOverviewController::StartConfiguring() {
show_thumbnails_ = true; show_thumbnails_ = true;
configure_timer_.Stop();
configure_timer_.Start( configure_timer_.Start(
base::TimeDelta::FromMilliseconds(10), this, base::TimeDelta::FromMilliseconds(10), this,
&TabOverviewController::ConfigureNextUnconfiguredCell); &TabOverviewController::ConfigureNextUnconfiguredCell);
...@@ -336,3 +355,11 @@ void TabOverviewController::ConfigureNextUnconfiguredCell() { ...@@ -336,3 +355,11 @@ void TabOverviewController::ConfigureNextUnconfiguredCell() {
} }
configure_timer_.Stop(); configure_timer_.Stop();
} }
void TabOverviewController::StartDelayTimer() {
configure_timer_.Stop();
delay_timer_.Stop();
delay_timer_.Start(
base::TimeDelta::FromMilliseconds(350), this,
&TabOverviewController::StartConfiguring);
}
...@@ -54,6 +54,9 @@ class TabOverviewController : public TabStripModelObserver { ...@@ -54,6 +54,9 @@ class TabOverviewController : public TabStripModelObserver {
// offscren if the user detaches the last tab in the tab strip. // offscren if the user detaches the last tab in the tab strip.
bool moved_offscreen() const { return moved_offscreen_; } bool moved_offscreen() const { return moved_offscreen_; }
// Sets whether the mouse is over a mini-window.
void SetMouseOverMiniWindow(bool over_mini_window);
// Shows the grid. // Shows the grid.
void Show(); void Show();
...@@ -126,6 +129,9 @@ class TabOverviewController : public TabStripModelObserver { ...@@ -126,6 +129,9 @@ class TabOverviewController : public TabStripModelObserver {
// it. If all the thumnbails have been set configure_timer_ is stopped. // it. If all the thumnbails have been set configure_timer_ is stopped.
void ConfigureNextUnconfiguredCell(); void ConfigureNextUnconfiguredCell();
// Starts the delay timer.
void StartDelayTimer();
// The widget showing the view. // The widget showing the view.
views::Widget* host_; views::Widget* host_;
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "chrome/browser/browser.h" #include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h" #include "chrome/browser/browser_window.h"
#include "chrome/browser/dock_info.h" #include "chrome/browser/dock_info.h"
#include "chrome/browser/gtk/browser_window_gtk.h"
#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tab_contents/tab_contents.h"
...@@ -32,14 +33,16 @@ TabOverviewDragController::TabOverviewDragController( ...@@ -32,14 +33,16 @@ TabOverviewDragController::TabOverviewDragController(
y_offset_(0), y_offset_(0),
dragging_(false), dragging_(false),
modifying_model_(false), modifying_model_(false),
detached_window_(NULL) { detached_window_(NULL),
hidden_browser_(NULL),
mouse_over_mini_window_(false) {
} }
TabOverviewDragController::~TabOverviewDragController() { TabOverviewDragController::~TabOverviewDragController() {
if (dragging_) if (dragging_)
controller_->DragEnded(); controller_->DragEnded();
if (original_index_ != -1) if (original_index_ != -1)
RevertDrag(); RevertDrag(false);
} }
bool TabOverviewDragController::Configure(const gfx::Point& location) { bool TabOverviewDragController::Configure(const gfx::Point& location) {
...@@ -70,6 +73,12 @@ bool TabOverviewDragController::Configure(const gfx::Point& location) { ...@@ -70,6 +73,12 @@ bool TabOverviewDragController::Configure(const gfx::Point& location) {
// Ask the controller to select the cell. // Ask the controller to select the cell.
controller_->SelectTab(index); controller_->SelectTab(index);
if (controller_->browser()) {
browser_window_size_ =
controller_->browser()->window()->GetNormalBounds().size();
}
return true; return true;
} }
...@@ -95,7 +104,12 @@ void TabOverviewDragController::CommitDrag(const gfx::Point& location) { ...@@ -95,7 +104,12 @@ void TabOverviewDragController::CommitDrag(const gfx::Point& location) {
Drag(location); Drag(location);
if (detached_tab_) { if (detached_tab_) {
DropTab(location); if (mouse_over_mini_window_) {
// Dragged over a mini window, add as the last tab to the browser.
Attach(model()->count());
} else {
DropTab(location);
}
} else if (!dragging_ ) { } else if (!dragging_ ) {
// We haven't started dragging. Tell the controller to focus the browser. // We haven't started dragging. Tell the controller to focus the browser.
controller_->FocusBrowser(); controller_->FocusBrowser();
...@@ -109,25 +123,32 @@ void TabOverviewDragController::CommitDrag(const gfx::Point& location) { ...@@ -109,25 +123,32 @@ void TabOverviewDragController::CommitDrag(const gfx::Point& location) {
original_index_ = -1; original_index_ = -1;
} }
void TabOverviewDragController::RevertDrag() { void TabOverviewDragController::RevertDrag(bool tab_destroyed) {
if (original_index_ == -1) if (original_index_ == -1)
return; return;
modifying_model_ = true; modifying_model_ = true;
if (detached_tab_) { if (detached_tab_) {
// Tab is currently detached, add it back to the original tab strip. // Tab is currently detached, add it back to the original tab strip.
original_model_->InsertTabContentsAt(original_index_, if (!tab_destroyed) {
detached_tab_, true, false); original_model_->InsertTabContentsAt(original_index_,
detached_tab_, true, false);
}
SetDetachedContents(NULL); SetDetachedContents(NULL);
detached_window_->Close(); detached_window_->Close();
detached_window_ = NULL; detached_window_ = NULL;
} else if (original_model_ != model()) {
if (hidden_browser_) {
gtk_widget_show(GTK_WIDGET(static_cast<BrowserWindowGtk*>(
hidden_browser_->window())->GetNativeHandle()));
}
} else if (original_model_ != model() && !tab_destroyed) {
// The tab was added to a different tab strip. Move it back to the // The tab was added to a different tab strip. Move it back to the
// original. // original.
TabContents* contents = model()->DetachTabContentsAt(current_index_); TabContents* contents = model()->DetachTabContentsAt(current_index_);
original_model_->InsertTabContentsAt(original_index_, contents, true, original_model_->InsertTabContentsAt(original_index_, contents, true,
false); false);
} else if (current_index_ != original_index_) { } else if (current_index_ != original_index_ && !tab_destroyed) {
original_model_->MoveTabContentsAt(current_index_, original_index_, true); original_model_->MoveTabContentsAt(current_index_, original_index_, true);
} }
modifying_model_ = false; modifying_model_ = false;
...@@ -149,7 +170,7 @@ void TabOverviewDragController::Observe(NotificationType type, ...@@ -149,7 +170,7 @@ void TabOverviewDragController::Observe(NotificationType type,
const NotificationDetails& details) { const NotificationDetails& details) {
DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED);
DCHECK(Source<TabContents>(source).ptr() == detached_tab_); DCHECK(Source<TabContents>(source).ptr() == detached_tab_);
RevertDrag(); RevertDrag(true);
} }
void TabOverviewDragController::OpenURLFromTab( void TabOverviewDragController::OpenURLFromTab(
...@@ -326,6 +347,9 @@ void TabOverviewDragController::Detach(const gfx::Point& location) { ...@@ -326,6 +347,9 @@ void TabOverviewDragController::Detach(const gfx::Point& location) {
// to empty out the tabstrip as otherwise they may trigger Chrome to // to empty out the tabstrip as otherwise they may trigger Chrome to
// exit. // exit.
controller_->MoveOffscreen(); controller_->MoveOffscreen();
hidden_browser_ = controller_->browser();
gtk_widget_hide(GTK_WIDGET(static_cast<BrowserWindowGtk*>(
hidden_browser_->window())->GetNativeHandle()));
} }
modifying_model_ = true; modifying_model_ = true;
model()->DetachTabContentsAt(current_index_); model()->DetachTabContentsAt(current_index_);
...@@ -336,13 +360,12 @@ void TabOverviewDragController::DropTab(const gfx::Point& location) { ...@@ -336,13 +360,12 @@ void TabOverviewDragController::DropTab(const gfx::Point& location) {
TabContents* contents = detached_tab_; TabContents* contents = detached_tab_;
SetDetachedContents(NULL); SetDetachedContents(NULL);
gfx::Rect browser_rect = controller_->browser()->window()->GetNormalBounds();
gfx::Point screen_loc(location); gfx::Point screen_loc(location);
grid()->ConvertPointToScreen(grid(), &screen_loc); grid()->ConvertPointToScreen(grid(), &screen_loc);
gfx::Rect window_bounds( gfx::Rect window_bounds(screen_loc, browser_window_size_);
screen_loc, gfx::Size(browser_rect.width(), browser_rect.height())); Browser* new_browser =
Browser* new_browser = model()->delegate()->CreateNewStripWithContents( original_model_->delegate()->CreateNewStripWithContents(
contents, window_bounds, DockInfo()); contents, window_bounds, DockInfo());
new_browser->window()->Show(); new_browser->window()->Show();
detached_window_->Close(); detached_window_->Close();
...@@ -357,6 +380,15 @@ void TabOverviewDragController::MoveDetachedWindow( ...@@ -357,6 +380,15 @@ void TabOverviewDragController::MoveDetachedWindow(
detached_window_->SetBounds( detached_window_->SetBounds(
gfx::Rect(screen_loc, gfx::Rect(screen_loc,
detached_window_->GetRootView()->GetPreferredSize())); detached_window_->GetRootView()->GetPreferredSize()));
// Notify the wm of the move.
TabOverviewTypes::Message message;
message.set_type(TabOverviewTypes::Message::WM_MOVE_FLOATING_TAB);
message.set_param(0, x11_util::GetX11WindowFromGtkWidget(
detached_window_->GetNativeView()));
message.set_param(1, screen_loc.x() + x_offset_);
message.set_param(2, screen_loc.y() + y_offset_);
TabOverviewTypes::instance()->SendMessage(message);
} }
views::Widget* TabOverviewDragController::CreateDetachedWindow( views::Widget* TabOverviewDragController::CreateDetachedWindow(
...@@ -364,7 +396,7 @@ views::Widget* TabOverviewDragController::CreateDetachedWindow( ...@@ -364,7 +396,7 @@ views::Widget* TabOverviewDragController::CreateDetachedWindow(
TabContents* tab_contents) { TabContents* tab_contents) {
// TODO: wrap the cell in another view that provides a background. // TODO: wrap the cell in another view that provides a background.
views::WidgetGtk* widget = views::WidgetGtk* widget =
new views::WidgetGtk(views::WidgetGtk::TYPE_POPUP); new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
widget->MakeTransparent(); widget->MakeTransparent();
gfx::Point screen_loc = location; gfx::Point screen_loc = location;
screen_loc.Offset(-x_offset_, -y_offset_); screen_loc.Offset(-x_offset_, -y_offset_);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/common/notification_registrar.h" #include "chrome/common/notification_registrar.h"
class Browser;
class TabOverviewController; class TabOverviewController;
class TabOverviewGrid; class TabOverviewGrid;
class TabStripModel; class TabStripModel;
...@@ -40,18 +41,24 @@ class TabOverviewDragController : public TabContentsDelegate, ...@@ -40,18 +41,24 @@ class TabOverviewDragController : public TabContentsDelegate,
explicit TabOverviewDragController(TabOverviewController* controller); explicit TabOverviewDragController(TabOverviewController* controller);
~TabOverviewDragController(); ~TabOverviewDragController();
// Invoked to prepare the TabOverviewDragController for a drag. Returns true // Sets whether the mouse is over a mini-window.
// if over a cell, false if the mouse isn't over a valid location. void set_mouse_over_mini_window(bool over_mini_window) {
mouse_over_mini_window_ = over_mini_window;
}
// Prepares the TabOverviewDragController for a drag. Returns true if over a
// cell, false if the mouse isn't over a valid location.
bool Configure(const gfx::Point& location); bool Configure(const gfx::Point& location);
// Invoked as the user drags the mouse. // Invoked as the user drags the mouse.
void Drag(const gfx::Point& location); void Drag(const gfx::Point& location);
// Invoked to commit the drag, typically when the user pressed enter. // Commits the drag, typically when the user releases the mouse.
void CommitDrag(const gfx::Point& location); void CommitDrag(const gfx::Point& location);
// Invoked to rever the drag. // Reverts the drag. Use true if the revert is the result of the tab being
void RevertDrag(); // destroyed.
void RevertDrag(bool tab_destroyed);
bool modifying_model() const { return modifying_model_; } bool modifying_model() const { return modifying_model_; }
TabOverviewGrid* grid() const; TabOverviewGrid* grid() const;
...@@ -151,6 +158,19 @@ class TabOverviewDragController : public TabContentsDelegate, ...@@ -151,6 +158,19 @@ class TabOverviewDragController : public TabContentsDelegate,
// around; this is that window. // around; this is that window.
views::Widget* detached_window_; views::Widget* detached_window_;
// When a tab is detached from a browser with a single tab we hide the
// browser. If this is non-null it means a single tab has been detached
// and this is the browser it was detached from.
Browser* hidden_browser_;
// Whether the mouse is over a mini window.
bool mouse_over_mini_window_;
// Size of the browser window. Cached in case browser() becomes NULL (as
// happens when the user drags over a region that shouldn't show the tab
// overview).
gfx::Size browser_window_size_;
DISALLOW_COPY_AND_ASSIGN(TabOverviewDragController); DISALLOW_COPY_AND_ASSIGN(TabOverviewDragController);
}; };
......
...@@ -24,6 +24,10 @@ TabOverviewCell* TabOverviewGrid::GetTabOverviewCellAt(int index) { ...@@ -24,6 +24,10 @@ TabOverviewCell* TabOverviewGrid::GetTabOverviewCellAt(int index) {
return static_cast<TabOverviewCell*>(GetChildViewAt(index)); return static_cast<TabOverviewCell*>(GetChildViewAt(index));
} }
TabOverviewDragController* TabOverviewGrid::drag_controller() const {
return drag_controller_.get();
}
void TabOverviewGrid::CancelDrag() { void TabOverviewGrid::CancelDrag() {
drag_controller_.reset(NULL); drag_controller_.reset(NULL);
} }
...@@ -65,7 +69,7 @@ void TabOverviewGrid::OnMouseReleased(const views::MouseEvent& event, ...@@ -65,7 +69,7 @@ void TabOverviewGrid::OnMouseReleased(const views::MouseEvent& event,
return; return;
if (canceled) if (canceled)
drag_controller_->RevertDrag(); drag_controller_->RevertDrag(false);
else else
drag_controller_->CommitDrag(event.location()); drag_controller_->CommitDrag(event.location());
drag_controller_.reset(NULL); drag_controller_.reset(NULL);
......
...@@ -27,6 +27,10 @@ class TabOverviewGrid : public Grid { ...@@ -27,6 +27,10 @@ class TabOverviewGrid : public Grid {
// Returns the TabOverviewCell at the specified index. // Returns the TabOverviewCell at the specified index.
TabOverviewCell* GetTabOverviewCellAt(int index); TabOverviewCell* GetTabOverviewCellAt(int index);
// Returns the TabOverviewDragController. This is NULL if a drag is not
// underway.
TabOverviewDragController* drag_controller() const;
// Cancels the drag. Does nothing if a drag is not underway. // Cancels the drag. Does nothing if a drag is not underway.
void CancelDrag(); void CancelDrag();
......
...@@ -62,14 +62,43 @@ void TabOverviewMessageListener::ProcessMessage( ...@@ -62,14 +62,43 @@ void TabOverviewMessageListener::ProcessMessage(
case TabOverviewTypes::Message::CHROME_NOTIFY_LAYOUT_MODE: { case TabOverviewTypes::Message::CHROME_NOTIFY_LAYOUT_MODE: {
if (message.param(0) == 0) { if (message.param(0) == 0) {
new_browser_window_.reset(NULL); new_browser_window_.reset(NULL);
controller_.reset(NULL);
} else if (BrowserList::size() > 0) { } else if (BrowserList::size() > 0) {
Browser* browser = *BrowserList::begin(); Browser* browser = *BrowserList::begin();
controller_.reset(new TabOverviewController(
browser->window()->GetNormalBounds().origin()));
new_browser_window_.reset( new_browser_window_.reset(
new NewBrowserWindowWidget(browser->profile())); new NewBrowserWindowWidget(browser->profile()));
} }
break; break;
} }
case TabOverviewTypes::Message::CHROME_NOTIFY_FLOATING_TAB_OVER_TOPLEVEL: {
if (!controller_.get())
return;
bool over_mini_window = message.param(1) == 1;
controller_->SetMouseOverMiniWindow(over_mini_window);
if (!over_mini_window)
return;
// Not over a mini-window, make sure the controller is showing the
// contents of the browser the mouse is over.
BrowserWindowGtk* browser_window =
BrowserWindowGtk::GetBrowserWindowForNativeWindow(
BrowserWindowGtk::GetBrowserWindowForXID(message.param(0)));
if (!browser_window)
return;
if (controller_->browser()->window() == browser_window)
return;
TabOverviewTypes::Message select_message;
select_message.set_type(TabOverviewTypes::Message::WM_MOVE_FLOATING_TAB);
select_message.set_param(0, message.param(1));
TabOverviewTypes::instance()->SendMessage(select_message);
}
default: default:
break; break;
} }
...@@ -86,5 +115,5 @@ void TabOverviewMessageListener::ShowOverview(Browser* browser, ...@@ -86,5 +115,5 @@ void TabOverviewMessageListener::ShowOverview(Browser* browser,
} }
void TabOverviewMessageListener::HideOverview() { void TabOverviewMessageListener::HideOverview() {
controller_.reset(NULL); controller_->SetBrowser(NULL, -1);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment