diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-01 21:06:29 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-07-01 21:06:29 +0000 |
commit | 4dab725746e1cea9430833de820d27999b5f0c43 (patch) | |
tree | 1a5e815ee568f4c5ca1db6116ca01ed55142ec20 | |
parent | 59470077c6e1b77fdb11aec535958b1fdd8e623a (diff) | |
download | chromium_src-4dab725746e1cea9430833de820d27999b5f0c43.zip chromium_src-4dab725746e1cea9430833de820d27999b5f0c43.tar.gz chromium_src-4dab725746e1cea9430833de820d27999b5f0c43.tar.bz2 |
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
8 files changed, 153 insertions, 25 deletions
diff --git a/chrome/browser/views/tabs/dragged_tab_controller.h b/chrome/browser/views/tabs/dragged_tab_controller.h index 5330b8a..11c88a6 100644 --- a/chrome/browser/views/tabs/dragged_tab_controller.h +++ b/chrome/browser/views/tabs/dragged_tab_controller.h @@ -68,6 +68,12 @@ class DraggedTabController : public TabContentsDelegate, // Returns true if the specified Tab matches the Tab being dragged. bool IsDragSourceTab(Tab* tab) const; + + + TabContents* dragged_contents() { return dragged_contents_; } + + + private: class DockDisplayer; friend class DockDisplayer; diff --git a/chrome/browser/views/tabs/tab_overview_controller.cc b/chrome/browser/views/tabs/tab_overview_controller.cc index eeb8347..c2f245b 100644 --- a/chrome/browser/views/tabs/tab_overview_controller.cc +++ b/chrome/browser/views/tabs/tab_overview_controller.cc @@ -11,6 +11,7 @@ #include "chrome/browser/tab_contents/thumbnail_generator.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_drag_controller.h" #include "chrome/browser/views/tabs/tab_overview_grid.h" #include "chrome/browser/views/tabs/tab_overview_types.h" #include "chrome/browser/window_sizer.h" @@ -85,21 +86,38 @@ void TabOverviewController::SetBrowser(Browser* browser, browser_ = browser; if (browser_) model()->AddObserver(this); + + show_thumbnails_ = false; + StartDelayTimer(); + gfx::Rect host_bounds = CalculateHostBounds(); if (moved_offscreen_ && model() && model()->count()) { // Need to reset the bounds if we were offscreen. host_->SetBounds(host_bounds); moved_offscreen_ = false; + } else if (!model() && shown_) { + MoveOffscreen(); } + if (!moved_offscreen_) + container_->SchedulePaint(); + RecreateCells(); container_->set_arrow_center(horizontal_center_ - host_bounds.x()); + + if (!moved_offscreen_) + container_->SchedulePaint(); } TabStripModel* TabOverviewController::model() const { 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() { if (host_->IsVisible()) return; @@ -107,9 +125,9 @@ void TabOverviewController::Show() { shown_ = true; DCHECK(model()); // The model needs to be set before showing. host_->Show(); - delay_timer_.Start( - base::TimeDelta::FromMilliseconds(350), this, - &TabOverviewController::StartConfiguring); + + show_thumbnails_ = false; + StartDelayTimer(); } void TabOverviewController::ConfigureCell(TabOverviewCell* cell, @@ -321,6 +339,7 @@ gfx::Rect TabOverviewController::CalculateHostBounds() { void TabOverviewController::StartConfiguring() { show_thumbnails_ = true; + configure_timer_.Stop(); configure_timer_.Start( base::TimeDelta::FromMilliseconds(10), this, &TabOverviewController::ConfigureNextUnconfiguredCell); @@ -336,3 +355,11 @@ void TabOverviewController::ConfigureNextUnconfiguredCell() { } configure_timer_.Stop(); } + +void TabOverviewController::StartDelayTimer() { + configure_timer_.Stop(); + delay_timer_.Stop(); + delay_timer_.Start( + base::TimeDelta::FromMilliseconds(350), this, + &TabOverviewController::StartConfiguring); +} diff --git a/chrome/browser/views/tabs/tab_overview_controller.h b/chrome/browser/views/tabs/tab_overview_controller.h index 15b13f5..ce5f0f7 100644 --- a/chrome/browser/views/tabs/tab_overview_controller.h +++ b/chrome/browser/views/tabs/tab_overview_controller.h @@ -54,6 +54,9 @@ class TabOverviewController : public TabStripModelObserver { // offscren if the user detaches the last tab in the tab strip. 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. void Show(); @@ -126,6 +129,9 @@ class TabOverviewController : public TabStripModelObserver { // it. If all the thumnbails have been set configure_timer_ is stopped. void ConfigureNextUnconfiguredCell(); + // Starts the delay timer. + void StartDelayTimer(); + // The widget showing the view. views::Widget* host_; diff --git a/chrome/browser/views/tabs/tab_overview_drag_controller.cc b/chrome/browser/views/tabs/tab_overview_drag_controller.cc index b6740cc..da2df5c 100644 --- a/chrome/browser/views/tabs/tab_overview_drag_controller.cc +++ b/chrome/browser/views/tabs/tab_overview_drag_controller.cc @@ -7,6 +7,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/browser_window.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/tabs/tab_strip_model.h" #include "chrome/browser/tab_contents/tab_contents.h" @@ -32,14 +33,16 @@ TabOverviewDragController::TabOverviewDragController( y_offset_(0), dragging_(false), modifying_model_(false), - detached_window_(NULL) { + detached_window_(NULL), + hidden_browser_(NULL), + mouse_over_mini_window_(false) { } TabOverviewDragController::~TabOverviewDragController() { if (dragging_) controller_->DragEnded(); if (original_index_ != -1) - RevertDrag(); + RevertDrag(false); } 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. controller_->SelectTab(index); + + if (controller_->browser()) { + browser_window_size_ = + controller_->browser()->window()->GetNormalBounds().size(); + } + return true; } @@ -95,7 +104,12 @@ void TabOverviewDragController::CommitDrag(const gfx::Point& location) { Drag(location); 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_ ) { // We haven't started dragging. Tell the controller to focus the browser. controller_->FocusBrowser(); @@ -109,25 +123,32 @@ void TabOverviewDragController::CommitDrag(const gfx::Point& location) { original_index_ = -1; } -void TabOverviewDragController::RevertDrag() { +void TabOverviewDragController::RevertDrag(bool tab_destroyed) { if (original_index_ == -1) return; modifying_model_ = true; if (detached_tab_) { // Tab is currently detached, add it back to the original tab strip. - original_model_->InsertTabContentsAt(original_index_, - detached_tab_, true, false); + if (!tab_destroyed) { + original_model_->InsertTabContentsAt(original_index_, + detached_tab_, true, false); + } SetDetachedContents(NULL); detached_window_->Close(); 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 // original. TabContents* contents = model()->DetachTabContentsAt(current_index_); original_model_->InsertTabContentsAt(original_index_, contents, true, false); - } else if (current_index_ != original_index_) { + } else if (current_index_ != original_index_ && !tab_destroyed) { original_model_->MoveTabContentsAt(current_index_, original_index_, true); } modifying_model_ = false; @@ -149,7 +170,7 @@ void TabOverviewDragController::Observe(NotificationType type, const NotificationDetails& details) { DCHECK(type == NotificationType::TAB_CONTENTS_DESTROYED); DCHECK(Source<TabContents>(source).ptr() == detached_tab_); - RevertDrag(); + RevertDrag(true); } void TabOverviewDragController::OpenURLFromTab( @@ -326,6 +347,9 @@ void TabOverviewDragController::Detach(const gfx::Point& location) { // to empty out the tabstrip as otherwise they may trigger Chrome to // exit. controller_->MoveOffscreen(); + hidden_browser_ = controller_->browser(); + gtk_widget_hide(GTK_WIDGET(static_cast<BrowserWindowGtk*>( + hidden_browser_->window())->GetNativeHandle())); } modifying_model_ = true; model()->DetachTabContentsAt(current_index_); @@ -336,13 +360,12 @@ void TabOverviewDragController::DropTab(const gfx::Point& location) { TabContents* contents = detached_tab_; SetDetachedContents(NULL); - gfx::Rect browser_rect = controller_->browser()->window()->GetNormalBounds(); gfx::Point screen_loc(location); grid()->ConvertPointToScreen(grid(), &screen_loc); - gfx::Rect window_bounds( - screen_loc, gfx::Size(browser_rect.width(), browser_rect.height())); - Browser* new_browser = model()->delegate()->CreateNewStripWithContents( - contents, window_bounds, DockInfo()); + gfx::Rect window_bounds(screen_loc, browser_window_size_); + Browser* new_browser = + original_model_->delegate()->CreateNewStripWithContents( + contents, window_bounds, DockInfo()); new_browser->window()->Show(); detached_window_->Close(); @@ -357,6 +380,15 @@ void TabOverviewDragController::MoveDetachedWindow( detached_window_->SetBounds( gfx::Rect(screen_loc, 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( @@ -364,7 +396,7 @@ views::Widget* TabOverviewDragController::CreateDetachedWindow( TabContents* tab_contents) { // TODO: wrap the cell in another view that provides a background. views::WidgetGtk* widget = - new views::WidgetGtk(views::WidgetGtk::TYPE_POPUP); + new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW); widget->MakeTransparent(); gfx::Point screen_loc = location; screen_loc.Offset(-x_offset_, -y_offset_); diff --git a/chrome/browser/views/tabs/tab_overview_drag_controller.h b/chrome/browser/views/tabs/tab_overview_drag_controller.h index 7bf5298..4a8a2a0 100644 --- a/chrome/browser/views/tabs/tab_overview_drag_controller.h +++ b/chrome/browser/views/tabs/tab_overview_drag_controller.h @@ -10,6 +10,7 @@ #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/notification_registrar.h" +class Browser; class TabOverviewController; class TabOverviewGrid; class TabStripModel; @@ -40,18 +41,24 @@ class TabOverviewDragController : public TabContentsDelegate, explicit TabOverviewDragController(TabOverviewController* controller); ~TabOverviewDragController(); - // Invoked to prepare the TabOverviewDragController for a drag. Returns true - // if over a cell, false if the mouse isn't over a valid location. + // Sets whether the mouse is over a mini-window. + 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); // Invoked as the user drags the mouse. 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); - // Invoked to rever the drag. - void RevertDrag(); + // Reverts the drag. Use true if the revert is the result of the tab being + // destroyed. + void RevertDrag(bool tab_destroyed); bool modifying_model() const { return modifying_model_; } TabOverviewGrid* grid() const; @@ -151,6 +158,19 @@ class TabOverviewDragController : public TabContentsDelegate, // around; this is that 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); }; diff --git a/chrome/browser/views/tabs/tab_overview_grid.cc b/chrome/browser/views/tabs/tab_overview_grid.cc index faa151b..35bd116 100644 --- a/chrome/browser/views/tabs/tab_overview_grid.cc +++ b/chrome/browser/views/tabs/tab_overview_grid.cc @@ -24,6 +24,10 @@ TabOverviewCell* TabOverviewGrid::GetTabOverviewCellAt(int index) { return static_cast<TabOverviewCell*>(GetChildViewAt(index)); } +TabOverviewDragController* TabOverviewGrid::drag_controller() const { + return drag_controller_.get(); +} + void TabOverviewGrid::CancelDrag() { drag_controller_.reset(NULL); } @@ -65,7 +69,7 @@ void TabOverviewGrid::OnMouseReleased(const views::MouseEvent& event, return; if (canceled) - drag_controller_->RevertDrag(); + drag_controller_->RevertDrag(false); else drag_controller_->CommitDrag(event.location()); drag_controller_.reset(NULL); diff --git a/chrome/browser/views/tabs/tab_overview_grid.h b/chrome/browser/views/tabs/tab_overview_grid.h index afb4aba..52cf27f 100644 --- a/chrome/browser/views/tabs/tab_overview_grid.h +++ b/chrome/browser/views/tabs/tab_overview_grid.h @@ -27,6 +27,10 @@ class TabOverviewGrid : public Grid { // Returns the TabOverviewCell at the specified 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. void CancelDrag(); diff --git a/chrome/browser/views/tabs/tab_overview_message_listener.cc b/chrome/browser/views/tabs/tab_overview_message_listener.cc index 1014574..85d6607 100644 --- a/chrome/browser/views/tabs/tab_overview_message_listener.cc +++ b/chrome/browser/views/tabs/tab_overview_message_listener.cc @@ -62,14 +62,43 @@ void TabOverviewMessageListener::ProcessMessage( case TabOverviewTypes::Message::CHROME_NOTIFY_LAYOUT_MODE: { if (message.param(0) == 0) { new_browser_window_.reset(NULL); + controller_.reset(NULL); } else if (BrowserList::size() > 0) { Browser* browser = *BrowserList::begin(); + controller_.reset(new TabOverviewController( + browser->window()->GetNormalBounds().origin())); new_browser_window_.reset( new NewBrowserWindowWidget(browser->profile())); } 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: break; } @@ -86,5 +115,5 @@ void TabOverviewMessageListener::ShowOverview(Browser* browser, } void TabOverviewMessageListener::HideOverview() { - controller_.reset(NULL); + controller_->SetBrowser(NULL, -1); } |