| 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() {
|
|
|