Index: chrome/browser/ui/panels/panel_manager.cc |
=================================================================== |
--- chrome/browser/ui/panels/panel_manager.cc (revision 98834) |
+++ chrome/browser/ui/panels/panel_manager.cc (working copy) |
@@ -8,6 +8,7 @@ |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop.h" |
#include "chrome/browser/ui/browser.h" |
#include "chrome/browser/ui/window_sizer.h" |
@@ -28,26 +29,29 @@ |
const double kPanelMaxWidthFactor = 1.0; |
const double kPanelMaxHeightFactor = 0.5; |
+// Occasionally some system, like Windows, might not bring up or down the bottom |
+// bar when the mouse enters or leaves the bottom screen area. This is the |
+// maximum time we will wait for the bottom bar visibility change notification. |
+// After the time expires, we bring up/down the titlebars as planned. |
+const int kMaxMillisecondsWaitForBottomBarVisibilityChange = 1000; |
+ |
// Single instance of PanelManager. |
-scoped_ptr<PanelManager> panel_instance; |
+scoped_refptr<PanelManager> panel_instance; |
} // namespace |
// static |
PanelManager* PanelManager::GetInstance() { |
- if (!panel_instance.get()) { |
- panel_instance.reset(new PanelManager()); |
- } |
+ if (!panel_instance.get()) |
+ panel_instance = new PanelManager(); |
return panel_instance.get(); |
} |
PanelManager::PanelManager() |
- : max_width_(0), |
- max_height_(0), |
- min_x_(0), |
- current_x_(0), |
- bottom_edge_y_(0), |
- dragging_panel_index_(kInvalidPanelIndex), |
- dragging_panel_original_x_(0) { |
+ : dragging_panel_index_(kInvalidPanelIndex), |
+ dragging_panel_original_x_(0), |
+ delayed_titlebar_action_(NO_ACTION), |
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { |
+ auto_hiding_desktop_bar_ = AutoHidingDesktopBar::Create(this); |
OnDisplayChanged(); |
} |
@@ -67,13 +71,10 @@ |
return; |
work_area_ = work_area; |
- min_x_ = work_area.x(); |
- current_x_ = work_area.right(); |
- bottom_edge_y_ = work_area.bottom(); |
- max_width_ = static_cast<int>(work_area.width() * kPanelMaxWidthFactor); |
- max_height_ = static_cast<int>(work_area.height() * kPanelMaxHeightFactor); |
+ auto_hiding_desktop_bar_->UpdateWorkArea(work_area_); |
+ AdjustWorkAreaForAutoHidingDesktopBars(); |
- Rearrange(panels_.begin()); |
+ Rearrange(panels_.begin(), adjusted_work_area_.right()); |
} |
void PanelManager::FindAndClosePanelOnOverflow(const Extension* extension) { |
@@ -97,20 +98,55 @@ |
} |
Panel* PanelManager::CreatePanel(Browser* browser) { |
+ // Adjust the width and height to fit into our constraint. |
+ int width = browser->override_bounds().width(); |
+ int height = browser->override_bounds().height(); |
+ |
+ if (width == 0 && height == 0) { |
+ width = kPanelDefaultWidthPixels; |
+ height = kPanelDefaultHeightPixels; |
+ } |
+ |
+ int max_panel_width = |
+ static_cast<int>(adjusted_work_area_.width() * kPanelMaxWidthFactor); |
+ int max_panel_height = |
+ static_cast<int>(adjusted_work_area_.height() * kPanelMaxHeightFactor); |
+ |
+ if (width < kPanelMinWidthPixels) |
+ width = kPanelMinWidthPixels; |
+ else if (width > max_panel_width) |
+ width = max_panel_width; |
+ |
+ if (height < kPanelMinHeightPixels) |
+ height = kPanelMinHeightPixels; |
+ else if (height > max_panel_height) |
+ height = max_panel_height; |
+ |
+ // Compute the origin. Ensure that it falls within the adjusted work area by |
+ // closing other panels if needed. |
+ int y = adjusted_work_area_.bottom() - height; |
+ |
const Extension* extension = NULL; |
- gfx::Rect bounds = browser->override_bounds(); |
- while (!ComputeBoundsForNextPanel(&bounds, true)) { |
+ int x; |
+ while ((x = GetRightMostAvaialblePosition() - width) < |
+ adjusted_work_area_.x() ) { |
if (!extension) |
extension = Panel::GetExtension(browser); |
FindAndClosePanelOnOverflow(extension); |
} |
- Panel* panel = new Panel(browser, bounds); |
+ // Now create the panel with the computed bounds. |
+ Panel* panel = new Panel(browser, gfx::Rect(x, y, width, height)); |
panels_.push_back(panel); |
return panel; |
} |
+int PanelManager::GetRightMostAvaialblePosition() const { |
+ return panels_.empty() ? adjusted_work_area_.right() : |
+ (panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing); |
+} |
+ |
void PanelManager::Remove(Panel* panel) { |
// If we're in the process of dragging, delay the removal. |
if (dragging_panel_index_ != kInvalidPanelIndex) { |
@@ -133,8 +169,7 @@ |
return; |
gfx::Rect bounds = (*iter)->GetBounds(); |
- current_x_ = bounds.x() + bounds.width(); |
- Rearrange(panels_.erase(iter)); |
+ Rearrange(panels_.erase(iter), bounds.right()); |
} |
void PanelManager::StartDragging(Panel* panel) { |
@@ -268,8 +303,16 @@ |
DelayedRemove(); |
} |
-bool PanelManager::ShouldBringUpTitlebarForAllMinimizedPanels( |
- int mouse_x, int mouse_y) const { |
+bool PanelManager::ShouldBringUpTitlebars(int mouse_x, int mouse_y) const { |
+ // We should always bring up the titlebar if the mouse is over the |
+ // visible auto-hiding bottom bar. |
+ if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM) && |
+ auto_hiding_desktop_bar_->GetVisibility( |
+ AutoHidingDesktopBar::ALIGN_BOTTOM) == |
+ AutoHidingDesktopBar::VISIBLE && |
+ mouse_y >= adjusted_work_area_.bottom()) |
+ return true; |
+ |
for (Panels::const_iterator iter = panels_.begin(); |
iter != panels_.end(); ++iter) { |
if ((*iter)->ShouldBringUpTitlebar(mouse_x, mouse_y)) |
@@ -278,7 +321,45 @@ |
return false; |
} |
-void PanelManager::BringUpOrDownTitlebarForAllMinimizedPanels(bool bring_up) { |
+void PanelManager::BringUpOrDownTitlebars(bool bring_up) { |
+ // If the auto-hiding bottom bar exists, delay the action until the bottom |
+ // bar is fully visible or hidden. We do not want both bottom bar and panel |
+ // titlebar to move at the same time but with different speeds. |
+ if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM)) { |
+ AutoHidingDesktopBar::Visibility visibility = auto_hiding_desktop_bar_-> |
+ GetVisibility(AutoHidingDesktopBar::ALIGN_BOTTOM); |
+ if (visibility != (bring_up ? AutoHidingDesktopBar::VISIBLE |
+ : AutoHidingDesktopBar::HIDDEN)) { |
+ // OnAutoHidingDesktopBarVisibilityChanged will handle this. |
+ delayed_titlebar_action_ = bring_up ? BRING_UP : BRING_DOWN; |
+ |
+ // Occasionally some system, like Windows, might not bring up or down the |
+ // bottom bar when the mouse enters or leaves the bottom screen area. |
+ // Thus, we schedule a delayed task to do the work if we do not receive |
+ // the bottom bar visibility change notification within a certain period |
+ // of time. |
+ MessageLoop::current()->PostDelayedTask( |
+ FROM_HERE, |
+ method_factory_.NewRunnableMethod( |
+ &PanelManager::DelayedBringUpOrDownTitlebarsCheck), |
+ kMaxMillisecondsWaitForBottomBarVisibilityChange); |
+ |
+ return; |
+ } |
+ } |
+ |
+ DoBringUpOrDownTitlebars(bring_up); |
+} |
+ |
+void PanelManager::DelayedBringUpOrDownTitlebarsCheck() { |
+ if (delayed_titlebar_action_ == NO_ACTION) |
+ return; |
+ |
+ DoBringUpOrDownTitlebars(delayed_titlebar_action_ == BRING_UP); |
+ delayed_titlebar_action_ = NO_ACTION; |
+} |
+ |
+void PanelManager::DoBringUpOrDownTitlebars(bool bring_up) { |
for (Panels::const_iterator iter = panels_.begin(); |
iter != panels_.end(); ++iter) { |
Panel* panel = *iter; |
@@ -297,51 +378,78 @@ |
} |
} |
-void PanelManager::Rearrange(Panels::iterator iter_to_start) { |
- if (iter_to_start == panels_.end()) |
- return; |
+void PanelManager::AdjustWorkAreaForAutoHidingDesktopBars() { |
+ // Note that we do not care about the desktop bar aligned to the top edge |
+ // since panels could not reach so high due to size constraint. |
+ adjusted_work_area_ = work_area_; |
+ if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM)) { |
+ int space = auto_hiding_desktop_bar_->GetThickness( |
+ AutoHidingDesktopBar::ALIGN_BOTTOM); |
+ adjusted_work_area_.set_height(adjusted_work_area_.height() - space); |
+ } |
+ if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_LEFT)) { |
+ int space = auto_hiding_desktop_bar_->GetThickness( |
+ AutoHidingDesktopBar::ALIGN_LEFT); |
+ adjusted_work_area_.set_x(adjusted_work_area_.x() + space); |
+ adjusted_work_area_.set_width(adjusted_work_area_.width() - space); |
+ } |
+ if (auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_RIGHT)) { |
+ int space = auto_hiding_desktop_bar_->GetThickness( |
+ AutoHidingDesktopBar::ALIGN_RIGHT); |
+ adjusted_work_area_.set_width(adjusted_work_area_.width() - space); |
+ } |
+} |
- for (Panels::iterator iter = iter_to_start; iter != panels_.end(); ++iter) { |
- gfx::Rect new_bounds((*iter)->GetBounds()); |
- ComputeBoundsForNextPanel(&new_bounds, false); |
- if (new_bounds != (*iter)->GetBounds()) |
- (*iter)->SetPanelBounds(new_bounds); |
+int PanelManager::GetBottomPositionForExpansionState( |
+ Panel::ExpansionState expansion_state) const { |
+ // If there is an auto-hiding desktop bar aligned to the bottom edge, we need |
+ // to move the minimize panel down to the bottom edge. |
+ int bottom = adjusted_work_area_.bottom(); |
+ if (expansion_state == Panel::MINIMIZED && |
+ auto_hiding_desktop_bar_->IsEnabled(AutoHidingDesktopBar::ALIGN_BOTTOM)) { |
+ bottom += auto_hiding_desktop_bar_->GetThickness( |
+ AutoHidingDesktopBar::ALIGN_BOTTOM); |
} |
+ return bottom; |
} |
-bool PanelManager::ComputeBoundsForNextPanel(gfx::Rect* bounds, |
- bool allow_size_change) { |
- int width = bounds->width(); |
- int height = bounds->height(); |
+void PanelManager::OnAutoHidingDesktopBarThicknessChanged() { |
+ AdjustWorkAreaForAutoHidingDesktopBars(); |
+ Rearrange(panels_.begin(), adjusted_work_area_.right()); |
+} |
- // Update the width and/or height to fit into our constraint. |
- if (allow_size_change) { |
- if (width == 0 && height == 0) { |
- width = kPanelDefaultWidthPixels; |
- height = kPanelDefaultHeightPixels; |
- } |
+void PanelManager::OnAutoHidingDesktopBarVisibilityChanged( |
+ AutoHidingDesktopBar::Alignment alignment, |
+ AutoHidingDesktopBar::Visibility visibility) { |
+ if (delayed_titlebar_action_ == NO_ACTION) |
+ return; |
- if (width < kPanelMinWidthPixels) |
- width = kPanelMinWidthPixels; |
- else if (width > max_width_) |
- width = max_width_; |
+ AutoHidingDesktopBar::Visibility expected_visibility = |
+ delayed_titlebar_action_ == BRING_UP ? AutoHidingDesktopBar::VISIBLE |
+ : AutoHidingDesktopBar::HIDDEN; |
+ if (visibility != expected_visibility) |
+ return; |
- if (height < kPanelMinHeightPixels) |
- height = kPanelMinHeightPixels; |
- else if (height > max_height_) |
- height = max_height_; |
- } |
+ DoBringUpOrDownTitlebars(delayed_titlebar_action_ == BRING_UP); |
+ delayed_titlebar_action_ = NO_ACTION; |
+} |
- int x = current_x_ - width; |
- int y = bottom_edge_y_ - height; |
+void PanelManager::Rearrange(Panels::iterator iter_to_start, |
+ int rightmost_position) { |
+ if (iter_to_start == panels_.end()) |
+ return; |
- if (x < min_x_) |
- return false; |
+ for (Panels::iterator iter = iter_to_start; iter != panels_.end(); ++iter) { |
+ Panel* panel = *iter; |
- current_x_ -= width + kPanelsHorizontalSpacing; |
+ gfx::Rect new_bounds(panel->GetBounds()); |
+ new_bounds.set_x(rightmost_position - new_bounds.width()); |
+ new_bounds.set_y(adjusted_work_area_.bottom() - new_bounds.height()); |
+ if (new_bounds != panel->GetBounds()) |
+ panel->SetPanelBounds(new_bounds); |
- bounds->SetRect(x, y, width, height); |
- return true; |
+ rightmost_position = new_bounds.x() - kPanelsHorizontalSpacing; |
+ } |
} |
void PanelManager::RemoveAll() { |