Commit 104432df authored by aburago@chromium.org's avatar aburago@chromium.org

Fix handling of minimized panel count

Increments and decrements of minimized panel count in the docking strip would not balance out in certain scenarios, e.g.: 
- if you add a panel that is already minimized (the count was incremented before the panel is added, sometimes causing a DCHECK to fire) 
- if you minimize a panel that is in "temporary layout" 
- if a panel's expansion state is changed when it is not in the docked strip (that is very hard to guard against, since a panel can jump into the overflow strip as a side effect of many operations) 

Changed the handling of minimized panel count to be more bullet-proof; added a test 

BUG=113682
TEST=PanelOverflowBrowserTest::AddMinimizedTillOverflow()

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@126966 0039d316-1c4b-4281-b951-d872f2087c98
parent b53e3fd1
...@@ -180,6 +180,7 @@ void DockedPanelStrip::InsertExistingPanelAtKnownPosition(Panel* panel) { ...@@ -180,6 +180,7 @@ void DockedPanelStrip::InsertExistingPanelAtKnownPosition(Panel* panel) {
if (x > (*iter)->GetBounds().x()) if (x > (*iter)->GetBounds().x())
break; break;
panels_.insert(iter, panel); panels_.insert(iter, panel);
UpdateMinimizedPanelCount();
// This will automatically update all affected panels due to the insertion. // This will automatically update all affected panels due to the insertion.
if (iter != panels_.end()) if (iter != panels_.end())
...@@ -195,7 +196,6 @@ void DockedPanelStrip::InsertExistingPanelAtDefaultPosition( ...@@ -195,7 +196,6 @@ void DockedPanelStrip::InsertExistingPanelAtDefaultPosition(
int width = restored_size.width(); int width = restored_size.width();
int x = FitPanelWithWidth(width); int x = FitPanelWithWidth(width);
if (update_bounds) { if (update_bounds) {
Panel::ExpansionState expansion_state_to_restore; Panel::ExpansionState expansion_state_to_restore;
if (panel->expansion_state() == Panel::EXPANDED) { if (panel->expansion_state() == Panel::EXPANDED) {
...@@ -208,7 +208,6 @@ void DockedPanelStrip::InsertExistingPanelAtDefaultPosition( ...@@ -208,7 +208,6 @@ void DockedPanelStrip::InsertExistingPanelAtDefaultPosition(
expansion_state_to_restore = Panel::MINIMIZED; expansion_state_to_restore = Panel::MINIMIZED;
height = Panel::kMinimizedPanelHeight; height = Panel::kMinimizedPanelHeight;
} }
IncrementMinimizedPanels();
} }
int y = int y =
GetBottomPositionForExpansionState(expansion_state_to_restore) - height; GetBottomPositionForExpansionState(expansion_state_to_restore) - height;
...@@ -221,6 +220,7 @@ void DockedPanelStrip::InsertExistingPanelAtDefaultPosition( ...@@ -221,6 +220,7 @@ void DockedPanelStrip::InsertExistingPanelAtDefaultPosition(
} }
panels_.push_back(panel); panels_.push_back(panel);
UpdateMinimizedPanelCount();
} }
int DockedPanelStrip::GetMaxPanelWidth() const { int DockedPanelStrip::GetMaxPanelWidth() const {
...@@ -244,9 +244,6 @@ void DockedPanelStrip::RemovePanel(Panel* panel) { ...@@ -244,9 +244,6 @@ void DockedPanelStrip::RemovePanel(Panel* panel) {
DCHECK_EQ(this, panel->panel_strip()); DCHECK_EQ(this, panel->panel_strip());
panel->SetPanelStrip(NULL); panel->SetPanelStrip(NULL);
if (panel->expansion_state() != Panel::EXPANDED)
DecrementMinimizedPanels();
if (panel->has_temporary_layout()) { if (panel->has_temporary_layout()) {
panels_in_temporary_layout_.erase(panel); panels_in_temporary_layout_.erase(panel);
return; return;
...@@ -287,6 +284,9 @@ void DockedPanelStrip::RemovePanel(Panel* panel) { ...@@ -287,6 +284,9 @@ void DockedPanelStrip::RemovePanel(Panel* panel) {
RefreshLayout(); RefreshLayout();
} }
if (panel->expansion_state() != Panel::EXPANDED)
UpdateMinimizedPanelCount();
} }
bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const { bool DockedPanelStrip::CanShowPanelAsActive(const Panel* panel) const {
...@@ -447,26 +447,23 @@ void DockedPanelStrip::EndDraggingPanelWithinStrip(Panel* panel, bool aborted) { ...@@ -447,26 +447,23 @@ void DockedPanelStrip::EndDraggingPanelWithinStrip(Panel* panel, bool aborted) {
void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) { void DockedPanelStrip::OnPanelExpansionStateChanged(Panel* panel) {
gfx::Size size = panel->restored_size(); gfx::Size size = panel->restored_size();
Panel::ExpansionState expansion_state = panel->expansion_state(); Panel::ExpansionState expansion_state = panel->expansion_state();
Panel::ExpansionState old_state = panel->old_expansion_state();
switch (expansion_state) { switch (expansion_state) {
case Panel::EXPANDED: case Panel::EXPANDED:
if (old_state == Panel::TITLE_ONLY || old_state == Panel::MINIMIZED)
DecrementMinimizedPanels();
break; break;
case Panel::TITLE_ONLY: case Panel::TITLE_ONLY:
size.set_height(panel->TitleOnlyHeight()); size.set_height(panel->TitleOnlyHeight());
if (old_state == Panel::EXPANDED)
IncrementMinimizedPanels();
break; break;
case Panel::MINIMIZED: case Panel::MINIMIZED:
size.set_height(Panel::kMinimizedPanelHeight); size.set_height(Panel::kMinimizedPanelHeight);
if (old_state == Panel::EXPANDED)
IncrementMinimizedPanels();
break; break;
default: default:
NOTREACHED(); NOTREACHED();
break; break;
} }
UpdateMinimizedPanelCount();
int bottom = GetBottomPositionForExpansionState(expansion_state); int bottom = GetBottomPositionForExpansionState(expansion_state);
gfx::Rect bounds = panel->GetBounds(); gfx::Rect bounds = panel->GetBounds();
...@@ -517,18 +514,21 @@ bool DockedPanelStrip::IsPanelMinimized(const Panel* panel) const { ...@@ -517,18 +514,21 @@ bool DockedPanelStrip::IsPanelMinimized(const Panel* panel) const {
return panel->expansion_state() != Panel::EXPANDED; return panel->expansion_state() != Panel::EXPANDED;
} }
void DockedPanelStrip::IncrementMinimizedPanels() { void DockedPanelStrip::UpdateMinimizedPanelCount() {
minimized_panel_count_++; int prev_minimized_panel_count = minimized_panel_count_;
if (minimized_panel_count_ == 1) minimized_panel_count_ = 0;
panel_manager_->mouse_watcher()->AddObserver(this); for (Panels::const_iterator panel_iter = panels_.begin();
DCHECK_LE(minimized_panel_count_, num_panels()); panel_iter != panels_.end(); ++panel_iter) {
} if ((*panel_iter)->expansion_state() != Panel::EXPANDED)
minimized_panel_count_++;
}
void DockedPanelStrip::DecrementMinimizedPanels() { if (prev_minimized_panel_count == 0 && minimized_panel_count_ > 0)
minimized_panel_count_--; panel_manager_->mouse_watcher()->AddObserver(this);
DCHECK_GE(minimized_panel_count_, 0); else if (prev_minimized_panel_count > 0 && minimized_panel_count_ == 0)
if (minimized_panel_count_ == 0)
panel_manager_->mouse_watcher()->RemoveObserver(this); panel_manager_->mouse_watcher()->RemoveObserver(this);
DCHECK_LE(minimized_panel_count_, num_panels());
} }
void DockedPanelStrip::ResizePanelWindow( void DockedPanelStrip::ResizePanelWindow(
......
...@@ -107,6 +107,8 @@ class DockedPanelStrip : public PanelStrip, ...@@ -107,6 +107,8 @@ class DockedPanelStrip : public PanelStrip,
int num_temporary_layout_panels() const { int num_temporary_layout_panels() const {
return panels_in_temporary_layout_.size(); return panels_in_temporary_layout_.size();
} }
int minimized_panel_count() const {return minimized_panel_count_; }
#endif #endif
private: private:
...@@ -135,8 +137,7 @@ class DockedPanelStrip : public PanelStrip, ...@@ -135,8 +137,7 @@ class DockedPanelStrip : public PanelStrip,
void InsertExistingPanelAtDefaultPosition(Panel* panel, bool refresh_bounds); void InsertExistingPanelAtDefaultPosition(Panel* panel, bool refresh_bounds);
// Keep track of the minimized panels to control mouse watching. // Keep track of the minimized panels to control mouse watching.
void IncrementMinimizedPanels(); void UpdateMinimizedPanelCount();
void DecrementMinimizedPanels();
// Help functions to drag the given panel. // Help functions to drag the given panel.
void DragLeft(Panel* dragging_panel); void DragLeft(Panel* dragging_panel);
......
...@@ -52,8 +52,7 @@ Panel::Panel(Browser* browser, const gfx::Size& requested_size) ...@@ -52,8 +52,7 @@ Panel::Panel(Browser* browser, const gfx::Size& requested_size)
auto_resizable_(false), auto_resizable_(false),
always_on_top_(false), always_on_top_(false),
in_preview_mode_(false), in_preview_mode_(false),
expansion_state_(EXPANDED), expansion_state_(EXPANDED) {
old_expansion_state_(EXPANDED) {
} }
Panel::~Panel() { Panel::~Panel() {
...@@ -178,7 +177,6 @@ void Panel::SetPanelStrip(PanelStrip* new_strip) { ...@@ -178,7 +177,6 @@ void Panel::SetPanelStrip(PanelStrip* new_strip) {
void Panel::SetExpansionState(ExpansionState new_state) { void Panel::SetExpansionState(ExpansionState new_state) {
if (expansion_state_ == new_state) if (expansion_state_ == new_state)
return; return;
old_expansion_state_ = expansion_state_;
expansion_state_ = new_state; expansion_state_ = new_state;
manager()->OnPanelExpansionStateChanged(this); manager()->OnPanelExpansionStateChanged(this);
......
...@@ -226,7 +226,6 @@ class Panel : public BrowserWindow, ...@@ -226,7 +226,6 @@ class Panel : public BrowserWindow,
void SetPanelStrip(PanelStrip* new_strip); void SetPanelStrip(PanelStrip* new_strip);
ExpansionState expansion_state() const { return expansion_state_; } ExpansionState expansion_state() const { return expansion_state_; }
ExpansionState old_expansion_state() const { return old_expansion_state_; }
const gfx::Size& min_size() const { return min_size_; } const gfx::Size& min_size() const { return min_size_; }
const gfx::Size& max_size() const { return max_size_; } const gfx::Size& max_size() const { return max_size_; }
bool auto_resizable() const { return auto_resizable_; } bool auto_resizable() const { return auto_resizable_; }
...@@ -336,7 +335,6 @@ class Panel : public BrowserWindow, ...@@ -336,7 +335,6 @@ class Panel : public BrowserWindow,
NativePanel* native_panel_; // Weak, owns us. NativePanel* native_panel_; // Weak, owns us.
ExpansionState expansion_state_; ExpansionState expansion_state_;
ExpansionState old_expansion_state_;
content::NotificationRegistrar registrar_; content::NotificationRegistrar registrar_;
......
...@@ -169,17 +169,33 @@ void PanelManager::EndDragging(bool cancelled) { ...@@ -169,17 +169,33 @@ void PanelManager::EndDragging(bool cancelled) {
} }
void PanelManager::OnPanelExpansionStateChanged(Panel* panel) { void PanelManager::OnPanelExpansionStateChanged(Panel* panel) {
docked_strip_->OnPanelExpansionStateChanged(panel); // For panels outside of the docked strip changing state is a no-op.
// But since this method may be called for panels in other strips
// we need to check this condition.
if (panel->panel_strip() == docked_strip_.get())
docked_strip_->OnPanelExpansionStateChanged(panel);
} }
void PanelManager::OnWindowAutoResized(Panel* panel, void PanelManager::OnWindowAutoResized(Panel* panel,
const gfx::Size& preferred_window_size) { const gfx::Size& preferred_window_size) {
DCHECK(auto_sizing_enabled_); DCHECK(auto_sizing_enabled_);
docked_strip_->ResizePanelWindow(panel, preferred_window_size); // Even though overflow panels are always minimized, we need
// to keep track of their size to put them back into the
// docked strip when they fit. So the docked panel strip manages
// the size of panels for the overflow strip as well.
if (panel->panel_strip() == overflow_strip_.get())
docked_strip_->ResizePanelWindow(panel, preferred_window_size);
else
panel->panel_strip()->ResizePanelWindow(panel, preferred_window_size);
} }
void PanelManager::ResizePanel(Panel* panel, const gfx::Size& new_size) { void PanelManager::ResizePanel(Panel* panel, const gfx::Size& new_size) {
docked_strip_->ResizePanelWindow(panel, new_size); // See the comment in OnWindowAutoResized()
if (panel->panel_strip() == overflow_strip_.get())
docked_strip_->ResizePanelWindow(panel, new_size);
else
panel->panel_strip()->ResizePanelWindow(panel, new_size);
panel->SetAutoResizable(false); panel->SetAutoResizable(false);
} }
......
...@@ -354,6 +354,46 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, ...@@ -354,6 +354,46 @@ IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest,
PanelManager::GetInstance()->CloseAll(); PanelManager::GetInstance()->CloseAll();
} }
IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, AddMinimizedTillOverflow) {
PanelManager* panel_manager = PanelManager::GetInstance();
DockedPanelStrip* docked_strip = panel_manager->docked_strip();
OverflowPanelStrip* overflow_strip = panel_manager->overflow_strip();
EXPECT_EQ(0, panel_manager->num_panels());
EXPECT_EQ(0, docked_strip->num_panels());
EXPECT_EQ(0, overflow_strip->num_panels());
CreatePanelParams params("Test", gfx::Rect(0, 0, 100, 100), SHOW_AS_INACTIVE);
// We want our panels to be uninitialized at the beginning so that
// we test minimizing panels in temp layout and its effect on
// the minimized panel count.
params.wait_for_fully_created = false;
unsigned int num_panels_to_add = 10;
unsigned int num_panels = 0;
for (; num_panels < num_panels_to_add; ++num_panels) {
Panel* panel = CreatePanelWithParams(params);
panel->SetExpansionState(Panel::MINIMIZED);
panel->panel_strip()->RemovePanel(panel);
EXPECT_EQ(NULL, panel->panel_strip());
panel->set_has_temporary_layout(false);
docked_strip->AddPanel(panel, PanelStrip::DEFAULT_POSITION);
EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
EXPECT_EQ(false, panel->has_temporary_layout());
}
EXPECT_EQ(num_panels_to_add, num_panels);
EXPECT_EQ(0, docked_strip->num_temporary_layout_panels());
EXPECT_EQ(num_panels, static_cast<unsigned int>
(docked_strip->minimized_panel_count() +
overflow_strip->num_panels()));
PanelManager::GetInstance()->CloseAll();
}
IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest, IN_PROC_BROWSER_TEST_F(PanelOverflowBrowserTest,
CreatePanelOnDelayedOverflow) { CreatePanelOnDelayedOverflow) {
// Create 2 big panels. // Create 2 big panels.
......
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