summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-30 23:59:12 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-30 23:59:12 +0000
commit714fe56f1a80a4844f3c1c9fa44c791179863e24 (patch)
tree67b28398d7210584d6def2f2858d3932d7750133
parentd88bf0abc08d368fd615a645bd0125ee6ab4f7c2 (diff)
downloadchromium_src-714fe56f1a80a4844f3c1c9fa44c791179863e24.zip
chromium_src-714fe56f1a80a4844f3c1c9fa44c791179863e24.tar.gz
chromium_src-714fe56f1a80a4844f3c1c9fa44c791179863e24.tar.bz2
Support auto-hide taskbar for panels on Windows.
BUG=none TEST=browser test Review URL: http://codereview.chromium.org/7646003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@98898 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar.h72
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar_chromeos.cc56
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar_cocoa.mm61
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar_gtk.cc61
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc194
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar_win.h66
-rw-r--r--chrome/browser/ui/panels/auto_hiding_desktop_bar_win_unittest.cc67
-rw-r--r--chrome/browser/ui/panels/base_panel_browser_test.cc241
-rw-r--r--chrome/browser/ui/panels/base_panel_browser_test.h76
-rw-r--r--chrome/browser/ui/panels/panel_browser_view.cc6
-rw-r--r--chrome/browser/ui/panels/panel_browser_view_browsertest.cc233
-rw-r--r--chrome/browser/ui/panels/panel_browsertest.cc115
-rw-r--r--chrome/browser/ui/panels/panel_manager.cc226
-rw-r--r--chrome/browser/ui/panels/panel_manager.h103
-rw-r--r--chrome/browser/ui/panels/panel_mouse_watcher_win.cc15
-rw-r--r--chrome/chrome_browser.gypi6
-rw-r--r--chrome/chrome_tests.gypi3
-rw-r--r--views/widget/monitor_win.cc12
-rw-r--r--views/widget/monitor_win.h6
-rw-r--r--views/widget/native_widget_win.cc22
20 files changed, 1331 insertions, 310 deletions
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar.h b/chrome/browser/ui/panels/auto_hiding_desktop_bar.h
new file mode 100644
index 0000000..d910a15
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_PANELS_AUTO_HIDING_DESKTOP_BAR_H_
+#define CHROME_BROWSER_UI_PANELS_AUTO_HIDING_DESKTOP_BAR_H_
+#pragma once
+
+#include "base/memory/ref_counted.h"
+
+namespace gfx {
+class Rect;
+}
+
+// Encapsulates the logic to deal with always-on-top auto-hiding desktop bars,
+// like Windows taskbar or MacOSX dock.
+// Note that the ref count is needed by using PostTask in the implementation of
+// MockAutoHidingDesktopBar that derives from AutoHidingDesktopBar.
+class AutoHidingDesktopBar : public base::RefCounted<AutoHidingDesktopBar> {
+ public:
+ // Indicates which screen edge the desktop bar is aligned to.
+ // We do not care about the desktop aligned to the top screen edge.
+ enum Alignment {
+ ALIGN_BOTTOM = 0,
+ ALIGN_LEFT = 1,
+ ALIGN_RIGHT = 2
+ };
+
+ enum Visibility {
+ VISIBLE,
+ ANIMATING,
+ HIDDEN
+ };
+
+ // Observer can listen to various events regarding the desktop bar changes.
+ class Observer {
+ public:
+ // Called when any of the desktop bars get their thickness changed.
+ // Note that if an auto-hiding desktop bar is moved from one edge
+ // to another edge, it will cause thickness changes to both edges.
+ virtual void OnAutoHidingDesktopBarThicknessChanged() = 0;
+
+ // Called when an auto-hiding desktop bar has its visibility changed.
+ virtual void OnAutoHidingDesktopBarVisibilityChanged(
+ Alignment alignment, Visibility visibility) = 0;
+ };
+
+ static AutoHidingDesktopBar* Create(Observer* observer);
+
+ virtual ~AutoHidingDesktopBar() { }
+
+ // This should be called each time when the work area is changed. We only
+ // care about the desktop bars that sit on the screen that hosts the specified
+ // work area.
+ virtual void UpdateWorkArea(const gfx::Rect& work_area) = 0;
+
+ // Returns true if there is a desktop bar that is aligned to the specified
+ // screen edge and set to auto-hide.
+ virtual bool IsEnabled(Alignment alignment) = 0;
+
+ // Returns the thickness of the desktop bar that is aligned to the specified
+ // screen edge, when it is visible. When the desktop bar is aligned to bottom
+ // edge, this is the height of the bar. If the desktop bar is aligned to
+ // left or right edge, this is the width of the bar.
+ virtual int GetThickness(Alignment alignment) const = 0;
+
+ // Returns the visibility state of the desktop bar that is aligned to the
+ // specified screen edge.
+ virtual Visibility GetVisibility(Alignment alignment) const = 0;
+};
+
+#endif // CHROME_BROWSER_UI_PANELS_AUTO_HIDING_DESKTOP_BAR_H_
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar_chromeos.cc b/chrome/browser/ui/panels/auto_hiding_desktop_bar_chromeos.cc
new file mode 100644
index 0000000..60a8daa
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar_chromeos.cc
@@ -0,0 +1,56 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
+
+#include "base/compiler_specific.h"
+
+namespace {
+
+class AutoHidingDesktopBarChromeOS : public AutoHidingDesktopBar {
+ public:
+ explicit AutoHidingDesktopBarChromeOS(Observer* observer);
+ virtual ~AutoHidingDesktopBarChromeOS() { }
+
+ // Overridden from AutoHidingDesktopBar:
+ virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE;
+ virtual bool IsEnabled(Alignment alignment) OVERRIDE;
+ virtual int GetThickness(Alignment alignment) const OVERRIDE;
+ virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE;
+
+ private:
+ Observer* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoHidingDesktopBarChromeOS);
+};
+
+AutoHidingDesktopBarChromeOS::AutoHidingDesktopBarChromeOS(Observer* observer)
+ : observer_(observer) {
+}
+
+void AutoHidingDesktopBarChromeOS::UpdateWorkArea(const gfx::Rect& work_area) {
+}
+
+bool AutoHidingDesktopBarChromeOS::IsEnabled(
+ AutoHidingDesktopBar::Alignment alignment) {
+ // No taskbar exists on ChromeOS.
+ return false;
+}
+
+int AutoHidingDesktopBarChromeOS::GetThickness(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ return 0;
+}
+
+AutoHidingDesktopBar::Visibility AutoHidingDesktopBarChromeOS::GetVisibility(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ return AutoHidingDesktopBar::HIDDEN;
+}
+
+} // namespace
+
+// static
+AutoHidingDesktopBar* AutoHidingDesktopBar::Create(Observer* observer) {
+ return new AutoHidingDesktopBarChromeOS(observer);
+}
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar_cocoa.mm b/chrome/browser/ui/panels/auto_hiding_desktop_bar_cocoa.mm
new file mode 100644
index 0000000..45d404a
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar_cocoa.mm
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+
+namespace {
+
+class AutoHidingDesktopBarCocoa : public AutoHidingDesktopBar {
+ public:
+ explicit AutoHidingDesktopBarCocoa(Observer* observer);
+ virtual ~AutoHidingDesktopBarCocoa() { }
+
+ // Overridden from AutoHidingDesktopBar:
+ virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE;
+ virtual bool IsEnabled(Alignment alignment) OVERRIDE;
+ virtual int GetThickness(Alignment alignment) const OVERRIDE;
+ virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE;
+
+ private:
+ Observer* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoHidingDesktopBarCocoa);
+};
+
+AutoHidingDesktopBarCocoa::AutoHidingDesktopBarCocoa(Observer* observer)
+ : observer_(observer) {
+ DCHECK(observer);
+}
+
+void AutoHidingDesktopBarCocoa::UpdateWorkArea(const gfx::Rect& work_area) {
+ NOTIMPLEMENTED();
+}
+
+bool AutoHidingDesktopBarCocoa::IsEnabled(
+ AutoHidingDesktopBar::Alignment alignment) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+int AutoHidingDesktopBarCocoa::GetThickness(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+AutoHidingDesktopBar::Visibility AutoHidingDesktopBarCocoa::GetVisibility(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ NOTIMPLEMENTED();
+ return AutoHidingDesktopBar::HIDDEN;
+}
+
+} // namespace
+
+// static
+AutoHidingDesktopBar* AutoHidingDesktopBar::Create(Observer* observer) {
+ return new AutoHidingDesktopBarCocoa(observer);
+}
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar_gtk.cc b/chrome/browser/ui/panels/auto_hiding_desktop_bar_gtk.cc
new file mode 100644
index 0000000..e0e12d1
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar_gtk.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+
+namespace {
+
+class AutoHidingDesktopBarGtk : public AutoHidingDesktopBar {
+ public:
+ explicit AutoHidingDesktopBarGtk(Observer* observer);
+ virtual ~AutoHidingDesktopBarGtk() { }
+
+ // Overridden from AutoHidingDesktopBar:
+ virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE;
+ virtual bool IsEnabled(Alignment alignment) OVERRIDE;
+ virtual int GetThickness(Alignment alignment) const OVERRIDE;
+ virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE;
+
+ private:
+ Observer* observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoHidingDesktopBarGtk);
+};
+
+AutoHidingDesktopBarGtk::AutoHidingDesktopBarGtk(Observer* observer)
+ : observer_(observer) {
+ DCHECK(observer);
+}
+
+void AutoHidingDesktopBarGtk::UpdateWorkArea(const gfx::Rect& work_area) {
+ NOTIMPLEMENTED();
+}
+
+bool AutoHidingDesktopBarGtk::IsEnabled(
+ AutoHidingDesktopBar::Alignment alignment) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+int AutoHidingDesktopBarGtk::GetThickness(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+AutoHidingDesktopBar::Visibility AutoHidingDesktopBarGtk::GetVisibility(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ NOTIMPLEMENTED();
+ return AutoHidingDesktopBar::HIDDEN;
+}
+
+} // namespace
+
+// static
+AutoHidingDesktopBar* AutoHidingDesktopBar::Create(Observer* observer) {
+ return new AutoHidingDesktopBarGtk(observer);
+}
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc b/chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc
new file mode 100644
index 0000000..944c6b1
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar_win.cc
@@ -0,0 +1,194 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar_win.h"
+
+#include <shellapi.h>
+
+#include "base/logging.h"
+#include "views/widget/monitor_win.h"
+
+namespace {
+// The thickness of the area of an auto-hiding taskbar that is still visible
+// when the taskbar becomes hidden.
+const int kHiddenAutoHideTaskbarThickness = 2;
+
+// The polling interval to check auto-hiding taskbars.
+const int kCheckTaskbarPollingIntervalMs = 500;
+} // namespace
+
+AutoHidingDesktopBarWin::AutoHidingDesktopBarWin(Observer* observer)
+ : observer_(observer) {
+ DCHECK(observer);
+ memset(taskbars_, 0, sizeof(taskbars_));
+}
+
+AutoHidingDesktopBarWin::~AutoHidingDesktopBarWin() {
+}
+
+void AutoHidingDesktopBarWin::UpdateWorkArea(const gfx::Rect& work_area) {
+ if (work_area_ == work_area)
+ return;
+ work_area_ = work_area;
+
+ RECT rect = work_area_.ToRECT();
+ monitor_ = ::MonitorFromRect(&rect, MONITOR_DEFAULTTOPRIMARY);
+ DCHECK(monitor_);
+
+ bool taskbar_exists = CheckTaskbars(false);
+
+ // If no auto-hiding taskbar exists, we do not need to start the polling
+ // timer. If a taskbar is then set to auto-hiding, UpdateWorkArea will be
+ // called due to the work area change.
+ if (taskbar_exists) {
+ if (!polling_timer_.IsRunning()) {
+ polling_timer_.Start(
+ base::TimeDelta::FromMilliseconds(kCheckTaskbarPollingIntervalMs),
+ this,
+ &AutoHidingDesktopBarWin::OnPollingTimer);
+ }
+ } else {
+ if (polling_timer_.IsRunning())
+ polling_timer_.Stop();
+ }
+}
+
+bool AutoHidingDesktopBarWin::IsEnabled(
+ AutoHidingDesktopBar::Alignment alignment) {
+ CheckTaskbars(false);
+ return taskbars_[static_cast<int>(alignment)].window != NULL;
+}
+
+int AutoHidingDesktopBarWin::GetThickness(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ return GetThicknessFromBounds(alignment, GetBounds(alignment));
+}
+
+AutoHidingDesktopBar::Visibility AutoHidingDesktopBarWin::GetVisibility(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ return GetVisibilityFromBounds(alignment, GetBounds(alignment));
+}
+
+gfx::Rect AutoHidingDesktopBarWin::GetBounds(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ HWND taskbar_window = taskbars_[static_cast<int>(alignment)].window;
+ if (!taskbar_window)
+ return gfx::Rect();
+
+ RECT rect;
+ if (!::GetWindowRect(taskbar_window, &rect))
+ return gfx::Rect();
+ return gfx::Rect(rect);
+}
+
+int AutoHidingDesktopBarWin::GetThicknessFromBounds(
+ AutoHidingDesktopBar::Alignment alignment,
+ const gfx::Rect& taskbar_bounds) const {
+ switch (alignment) {
+ case AutoHidingDesktopBar::ALIGN_BOTTOM:
+ return taskbar_bounds.height();
+ case AutoHidingDesktopBar::ALIGN_LEFT:
+ case AutoHidingDesktopBar::ALIGN_RIGHT:
+ return taskbar_bounds.width();
+ default:
+ NOTREACHED();
+ return 0;
+ }
+}
+
+AutoHidingDesktopBar::Visibility
+AutoHidingDesktopBarWin::GetVisibilityFromBounds(
+ AutoHidingDesktopBar::Alignment alignment,
+ const gfx::Rect& taskbar_bounds) const {
+ switch (alignment) {
+ case AutoHidingDesktopBar::ALIGN_BOTTOM:
+ if (taskbar_bounds.bottom() <= work_area_.bottom())
+ return VISIBLE;
+ else if (taskbar_bounds.y() >=
+ work_area_.bottom() - kHiddenAutoHideTaskbarThickness)
+ return HIDDEN;
+ else
+ return ANIMATING;
+
+ case AutoHidingDesktopBar::ALIGN_LEFT:
+ if (taskbar_bounds.x() >= work_area_.x())
+ return VISIBLE;
+ else if (taskbar_bounds.right() <=
+ work_area_.x() + kHiddenAutoHideTaskbarThickness)
+ return HIDDEN;
+ else
+ return ANIMATING;
+
+ case AutoHidingDesktopBar::ALIGN_RIGHT:
+ if (taskbar_bounds.right() <= work_area_.right())
+ return VISIBLE;
+ else if (taskbar_bounds.x() >=
+ work_area_.right() - kHiddenAutoHideTaskbarThickness)
+ return HIDDEN;
+ else
+ return ANIMATING;
+
+ default:
+ NOTREACHED();
+ return VISIBLE;
+ }
+}
+
+void AutoHidingDesktopBarWin::OnPollingTimer() {
+ CheckTaskbars(true);
+}
+
+bool AutoHidingDesktopBarWin::CheckTaskbars(bool notify_observer) {
+ bool taskbar_exists = false;
+ UINT edges[] = { ABE_BOTTOM, ABE_LEFT, ABE_RIGHT };
+ for (size_t i = 0; i < kMaxTaskbars; ++i) {
+ taskbars_[i].window =
+ views::GetTopmostAutoHideTaskbarForEdge(edges[i], monitor_);
+ if (taskbars_[i].window)
+ taskbar_exists = true;
+ }
+ if (!taskbar_exists) {
+ for (size_t i = 0; i < kMaxTaskbars; ++i) {
+ taskbars_[i].thickness = 0;
+ taskbars_[i].visibility = AutoHidingDesktopBar::HIDDEN;
+ }
+ return false;
+ }
+
+ bool thickness_changed = false;
+ for (size_t i = 0; i < kMaxTaskbars; ++i) {
+ AutoHidingDesktopBar::Alignment alignment = static_cast<Alignment>(i);
+
+ gfx::Rect bounds = GetBounds(alignment);
+
+ // Check the thickness change.
+ int thickness = GetThicknessFromBounds(alignment, bounds);
+ if (thickness != taskbars_[i].thickness) {
+ taskbars_[i].thickness = thickness;
+ thickness_changed = true;
+ }
+
+ // Check and notify the visibility change.
+ AutoHidingDesktopBar::Visibility visibility =
+ GetVisibilityFromBounds(alignment, bounds);
+ if (visibility != taskbars_[i].visibility) {
+ taskbars_[i].visibility = visibility;
+ if (notify_observer) {
+ observer_->OnAutoHidingDesktopBarVisibilityChanged(alignment,
+ visibility);
+ }
+ }
+ }
+
+ // Notify the thickness change if needed.
+ if (thickness_changed && notify_observer)
+ observer_->OnAutoHidingDesktopBarThicknessChanged();
+
+ return true;
+}
+
+// static
+AutoHidingDesktopBar* AutoHidingDesktopBar::Create(Observer* observer) {
+ return new AutoHidingDesktopBarWin(observer);
+}
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar_win.h b/chrome/browser/ui/panels/auto_hiding_desktop_bar_win.h
new file mode 100644
index 0000000..5bc1206
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar_win.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_PANELS_AUTO_HIDING_DESKTOP_BAR_WIN_H_
+#define CHROME_BROWSER_UI_PANELS_AUTO_HIDING_DESKTOP_BAR_WIN_H_
+#pragma once
+
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
+
+#include <windows.h>
+#include "base/compiler_specific.h"
+#include "base/timer.h"
+#include "ui/gfx/rect.h"
+
+class AutoHidingDesktopBarWin : public AutoHidingDesktopBar {
+ public:
+ explicit AutoHidingDesktopBarWin(Observer* observer);
+ virtual ~AutoHidingDesktopBarWin();
+
+ // Overridden from AutoHidingDesktopBar:
+ virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE;
+ virtual bool IsEnabled(Alignment alignment) OVERRIDE;
+ virtual int GetThickness(Alignment alignment) const OVERRIDE;
+ virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE;
+
+#ifdef UNIT_TEST
+ void set_work_area(const gfx::Rect& work_area) {
+ work_area_ = work_area;
+ }
+#endif
+
+ private:
+ friend class AutoHidingDesktopBarWinTest;
+
+ struct Taskbar {
+ HWND window;
+ AutoHidingDesktopBar::Visibility visibility;
+ int thickness;
+ };
+
+ // Callback to perform periodic check for taskbar changes.
+ void OnPollingTimer();
+
+ // Returns true if there is at least one auto-hiding taskbar found.
+ bool CheckTaskbars(bool notify_observer);
+
+ gfx::Rect GetBounds(Alignment alignment) const;
+ int GetThicknessFromBounds(
+ Alignment alignment, const gfx::Rect& taskbar_bounds) const;
+ Visibility GetVisibilityFromBounds(
+ Alignment alignment, const gfx::Rect& taskbar_bounds) const;
+
+ // Maximum number of taskbars we're interested in: bottom, left, and right.
+ static const int kMaxTaskbars = 3;
+
+ Observer* observer_;
+ gfx::Rect work_area_;
+ HMONITOR monitor_;
+ Taskbar taskbars_[kMaxTaskbars];
+ base::RepeatingTimer<AutoHidingDesktopBarWin> polling_timer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutoHidingDesktopBarWin);
+};
+
+#endif // CHROME_BROWSER_UI_PANELS_AUTO_HIDING_DESKTOP_BAR_WIN_H_
diff --git a/chrome/browser/ui/panels/auto_hiding_desktop_bar_win_unittest.cc b/chrome/browser/ui/panels/auto_hiding_desktop_bar_win_unittest.cc
new file mode 100644
index 0000000..0a3ca3f
--- /dev/null
+++ b/chrome/browser/ui/panels/auto_hiding_desktop_bar_win_unittest.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar_win.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+
+class AutoHidingDesktopBarWinTest : public testing::Test,
+ public AutoHidingDesktopBar::Observer {
+ protected:
+ // Overridden from AutoHidingDesktopBar::Observer:
+ virtual void OnAutoHidingDesktopBarThicknessChanged() OVERRIDE {
+ }
+
+ virtual void OnAutoHidingDesktopBarVisibilityChanged(
+ AutoHidingDesktopBar::Alignment alignment,
+ AutoHidingDesktopBar::Visibility visibility) OVERRIDE {
+ }
+
+ void TestGetVisibilityFromBounds() {
+ scoped_refptr<AutoHidingDesktopBarWin> bar =
+ new AutoHidingDesktopBarWin(this);
+ bar->set_work_area(gfx::Rect(0, 0, 800, 600));
+
+ AutoHidingDesktopBar::Visibility visibility;
+
+ // Tests for bottom bar.
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, gfx::Rect(0, 560, 800, 40));
+ EXPECT_EQ(AutoHidingDesktopBar::VISIBLE, visibility);
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, gfx::Rect(0, 598, 800, 40));
+ EXPECT_EQ(AutoHidingDesktopBar::HIDDEN, visibility);
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, gfx::Rect(0, 580, 800, 40));
+ EXPECT_EQ(AutoHidingDesktopBar::ANIMATING, visibility);
+
+ // Tests for right bar.
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_RIGHT, gfx::Rect(760, 0, 40, 600));
+ EXPECT_EQ(AutoHidingDesktopBar::VISIBLE, visibility);
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_RIGHT, gfx::Rect(798, 0, 40, 600));
+ EXPECT_EQ(AutoHidingDesktopBar::HIDDEN, visibility);
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_RIGHT, gfx::Rect(780, 0, 40, 600));
+ EXPECT_EQ(AutoHidingDesktopBar::ANIMATING, visibility);
+
+ // Tests for left bar.
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_LEFT, gfx::Rect(0, 0, 40, 600));
+ EXPECT_EQ(AutoHidingDesktopBar::VISIBLE, visibility);
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_LEFT, gfx::Rect(-38, 0, 40, 600));
+ EXPECT_EQ(AutoHidingDesktopBar::HIDDEN, visibility);
+ visibility = bar->GetVisibilityFromBounds(
+ AutoHidingDesktopBar::ALIGN_LEFT, gfx::Rect(-15, 0, 40, 600));
+ EXPECT_EQ(AutoHidingDesktopBar::ANIMATING, visibility);
+ }
+};
+
+TEST_F(AutoHidingDesktopBarWinTest, GetVisibilityFromBounds) {
+ TestGetVisibilityFromBounds();
+}
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.cc b/chrome/browser/ui/panels/base_panel_browser_test.cc
new file mode 100644
index 0000000..b0a4c05
--- /dev/null
+++ b/chrome/browser/ui/panels/base_panel_browser_test.cc
@@ -0,0 +1,241 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/panels/base_panel_browser_test.h"
+
+#include "base/command_line.h"
+#include "base/mac/scoped_nsautorelease_pool.h"
+#include "base/message_loop.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
+#include "chrome/common/chrome_switches.h"
+#include "content/browser/tab_contents/test_tab_contents.h"
+
+#if defined(OS_MACOSX)
+#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
+#endif
+
+namespace {
+
+const int kTestingWorkAreaWidth = 800;
+const int kTestingWorkAreaHeight = 600;
+const int kDefaultAutoHidingDesktopBarThickness = 40;
+const int kDefaultPanelWidth = 150;
+const int kDefaultPanelHeight = 120;
+
+struct MockDesktopBar {
+ bool auto_hiding_enabled;
+ AutoHidingDesktopBar::Visibility visibility;
+ int thickness;
+};
+
+class MockAutoHidingDesktopBarImpl :
+ public BasePanelBrowserTest::MockAutoHidingDesktopBar {
+ public:
+ explicit MockAutoHidingDesktopBarImpl(Observer* observer);
+ virtual ~MockAutoHidingDesktopBarImpl() { }
+
+ // Overridden from AutoHidingDesktopBar:
+ virtual void UpdateWorkArea(const gfx::Rect& work_area) OVERRIDE;
+ virtual bool IsEnabled(Alignment alignment) OVERRIDE;
+ virtual int GetThickness(Alignment alignment) const OVERRIDE;
+ virtual Visibility GetVisibility(Alignment alignment) const OVERRIDE;
+
+ // Overridden from MockAutoHidingDesktopBar:
+ virtual void EnableAutoHiding(Alignment alignment,
+ bool enabled,
+ int thickness) OVERRIDE;
+ virtual void SetVisibility(Alignment alignment,
+ Visibility visibility) OVERRIDE;
+ virtual void SetThickness(Alignment alignment, int thickness) OVERRIDE;
+
+ void set_observer(Observer* observer) { observer_ = observer; }
+
+ private:
+ void NotifyVisibilityChange(Alignment alignment, Visibility visibility);
+ void NotifyThicknessChange();
+
+ Observer* observer_;
+ MockDesktopBar mock_desktop_bars[3];
+ ScopedRunnableMethodFactory<MockAutoHidingDesktopBarImpl> method_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockAutoHidingDesktopBarImpl);
+};
+
+
+MockAutoHidingDesktopBarImpl::MockAutoHidingDesktopBarImpl(
+ AutoHidingDesktopBar::Observer* observer)
+ : observer_(observer),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
+ memset(mock_desktop_bars, 0, sizeof(mock_desktop_bars));
+}
+
+void MockAutoHidingDesktopBarImpl::UpdateWorkArea(
+ const gfx::Rect& work_area) {
+}
+
+bool MockAutoHidingDesktopBarImpl::IsEnabled(
+ AutoHidingDesktopBar::Alignment alignment) {
+ return mock_desktop_bars[static_cast<int>(alignment)].auto_hiding_enabled;
+}
+
+int MockAutoHidingDesktopBarImpl::GetThickness(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ return mock_desktop_bars[static_cast<int>(alignment)].thickness;
+}
+
+AutoHidingDesktopBar::Visibility
+MockAutoHidingDesktopBarImpl::GetVisibility(
+ AutoHidingDesktopBar::Alignment alignment) const {
+ return mock_desktop_bars[static_cast<int>(alignment)].visibility;
+}
+
+void MockAutoHidingDesktopBarImpl::EnableAutoHiding(
+ AutoHidingDesktopBar::Alignment alignment, bool enabled, int thickness) {
+ MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
+ bar->auto_hiding_enabled = enabled;
+ bar->thickness = thickness;
+ observer_->OnAutoHidingDesktopBarThicknessChanged();
+}
+
+void MockAutoHidingDesktopBarImpl::SetVisibility(
+ AutoHidingDesktopBar::Alignment alignment,
+ AutoHidingDesktopBar::Visibility visibility) {
+ MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
+ if (!bar->auto_hiding_enabled)
+ return;
+ if (visibility == bar->visibility)
+ return;
+ bar->visibility = visibility;
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &MockAutoHidingDesktopBarImpl::NotifyVisibilityChange,
+ alignment,
+ visibility));
+}
+
+void MockAutoHidingDesktopBarImpl::SetThickness(
+ AutoHidingDesktopBar::Alignment alignment, int thickness) {
+ MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]);
+ if (!bar->auto_hiding_enabled)
+ return;
+ if (thickness == bar->thickness)
+ return;
+ bar->thickness = thickness;
+ MessageLoop::current()->PostTask(
+ FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &MockAutoHidingDesktopBarImpl::NotifyThicknessChange));
+}
+
+void MockAutoHidingDesktopBarImpl::NotifyVisibilityChange(
+ AutoHidingDesktopBar::Alignment alignment,
+ AutoHidingDesktopBar::Visibility visibility) {
+ observer_->OnAutoHidingDesktopBarVisibilityChanged(alignment, visibility);
+}
+
+void MockAutoHidingDesktopBarImpl::NotifyThicknessChange() {
+ observer_->OnAutoHidingDesktopBarThicknessChanged();
+}
+
+} // namespace
+
+BasePanelBrowserTest::BasePanelBrowserTest()
+ : InProcessBrowserTest(),
+ testing_work_area_(0, 0, kTestingWorkAreaWidth,
+ kTestingWorkAreaHeight) {
+#if defined(OS_MACOSX)
+ FindBarBridge::disable_animations_during_testing_ = true;
+#endif
+}
+
+BasePanelBrowserTest::~BasePanelBrowserTest() {
+}
+
+void BasePanelBrowserTest::SetUpCommandLine(CommandLine* command_line) {
+ command_line->AppendSwitch(switches::kEnablePanels);
+}
+
+void BasePanelBrowserTest::SetUpOnMainThread() {
+ InProcessBrowserTest::SetUpOnMainThread();
+
+ // Setup the work area and desktop bar so that we have consistent testing
+ // environment for all panel related tests.
+ PanelManager* panel_manager = PanelManager::GetInstance();
+ mock_auto_hiding_desktop_bar_ = new MockAutoHidingDesktopBarImpl(
+ panel_manager);
+ panel_manager->set_auto_hiding_desktop_bar(mock_auto_hiding_desktop_bar_);
+ panel_manager->SetWorkAreaForTesting(testing_work_area_);
+}
+
+Panel* BasePanelBrowserTest::CreatePanelWithParams(
+ const CreatePanelParams& params) {
+ // Opening panels on a Mac causes NSWindowController of the Panel window
+ // to be autoreleased. We need a pool drained after it's done so the test
+ // can close correctly. The NSWindowController of the Panel window controls
+ // lifetime of the Browser object so we want to release it as soon as
+ // possible. In real Chrome, this is done by message pump.
+ // On non-Mac platform, this is an empty class.
+ base::mac::ScopedNSAutoreleasePool autorelease_pool;
+
+ Browser* panel_browser = Browser::CreateForApp(Browser::TYPE_PANEL,
+ params.name,
+ params.bounds,
+ browser()->profile());
+ EXPECT_TRUE(panel_browser->is_type_panel());
+
+ TabContentsWrapper* tab_contents =
+ new TabContentsWrapper(new TestTabContents(browser()->profile(), NULL));
+ panel_browser->AddTab(tab_contents, PageTransition::LINK);
+
+ Panel* panel = static_cast<Panel*>(panel_browser->window());
+ if (params.show_flag == SHOW_AS_ACTIVE)
+ panel->Show();
+ else
+ panel->ShowInactive();
+ MessageLoopForUI::current()->RunAllPending();
+
+ return panel;
+}
+
+Panel* BasePanelBrowserTest::CreatePanelWithBounds(
+ const std::string& panel_name, const gfx::Rect& bounds) {
+ CreatePanelParams params(panel_name, bounds, SHOW_AS_ACTIVE);
+ return CreatePanelWithParams(params);
+}
+
+Panel* BasePanelBrowserTest::CreatePanel(const std::string& panel_name) {
+ CreatePanelParams params(panel_name, gfx::Rect(), SHOW_AS_ACTIVE);
+ return CreatePanelWithParams(params);
+}
+
+scoped_refptr<Extension> BasePanelBrowserTest::CreateExtension(
+ const FilePath::StringType& path,
+ Extension::Location location,
+ const DictionaryValue& extra_value) {
+#if defined(OS_WIN)
+ FilePath full_path(FILE_PATH_LITERAL("c:\\"));
+#else
+ FilePath full_path(FILE_PATH_LITERAL("/"));
+#endif
+ full_path = full_path.Append(path);
+
+ scoped_ptr<DictionaryValue> input_value(extra_value.DeepCopy());
+ input_value->SetString(extension_manifest_keys::kVersion, "1.0.0.0");
+ input_value->SetString(extension_manifest_keys::kName, "Sample Extension");
+
+ std::string error;
+ scoped_refptr<Extension> extension = Extension::Create(
+ full_path, location, *input_value,
+ Extension::STRICT_ERROR_CHECKS, &error);
+ EXPECT_TRUE(extension.get());
+ EXPECT_STREQ("", error.c_str());
+ browser()->GetProfile()->GetExtensionService()->OnLoadSingleExtension(
+ extension.get(), false);
+ return extension;
+}
diff --git a/chrome/browser/ui/panels/base_panel_browser_test.h b/chrome/browser/ui/panels/base_panel_browser_test.h
new file mode 100644
index 0000000..2f08401
--- /dev/null
+++ b/chrome/browser/ui/panels/base_panel_browser_test.h
@@ -0,0 +1,76 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_PANELS_BASE_PANEL_BROWSER_TEST_H_
+#define CHROME_BROWSER_UI_PANELS_BASE_PANEL_BROWSER_TEST_H_
+#pragma once
+
+#include "base/task.h"
+#include "base/values.h"
+#include "base/memory/scoped_ptr.h"
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
+#include "chrome/common/extensions/extension.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "ui/gfx/rect.h"
+
+class Panel;
+
+class BasePanelBrowserTest : public InProcessBrowserTest {
+ public:
+ class MockAutoHidingDesktopBar : public AutoHidingDesktopBar {
+ public:
+ virtual ~MockAutoHidingDesktopBar() { }
+
+ virtual void EnableAutoHiding(Alignment alignment,
+ bool enabled,
+ int thickness) = 0;
+ virtual void SetVisibility(Alignment alignment, Visibility visibility) = 0;
+ virtual void SetThickness(Alignment alignment, int thickness) = 0;
+ };
+
+ BasePanelBrowserTest();
+ virtual ~BasePanelBrowserTest();
+
+ virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
+ virtual void SetUpOnMainThread() OVERRIDE;
+
+ protected:
+ enum ShowFlag { SHOW_AS_ACTIVE, SHOW_AS_INACTIVE };
+
+ struct CreatePanelParams {
+ std::string name;
+ gfx::Rect bounds;
+ ShowFlag show_flag;
+
+ CreatePanelParams(const std::string& name,
+ const gfx::Rect& bounds,
+ ShowFlag show_flag)
+ : name(name),
+ bounds(bounds),
+ show_flag(show_flag) {
+ }
+ };
+
+ Panel* CreatePanelWithParams(const CreatePanelParams& params);
+ Panel* CreatePanelWithBounds(const std::string& panel_name,
+ const gfx::Rect& bounds);
+ Panel* CreatePanel(const std::string& panel_name);
+
+ scoped_refptr<Extension> CreateExtension(const FilePath::StringType& path,
+ Extension::Location location,
+ const DictionaryValue& extra_value);
+
+ gfx::Rect testing_work_area() const { return testing_work_area_; }
+
+ MockAutoHidingDesktopBar* mock_auto_hiding_desktop_bar() const {
+ return mock_auto_hiding_desktop_bar_.get();
+ }
+
+ private:
+
+ gfx::Rect testing_work_area_;
+ scoped_refptr<MockAutoHidingDesktopBar> mock_auto_hiding_desktop_bar_;
+};
+
+#endif // CHROME_BROWSER_UI_PANELS_BASE_PANEL_BROWSER_TEST_H_
diff --git a/chrome/browser/ui/panels/panel_browser_view.cc b/chrome/browser/ui/panels/panel_browser_view.cc
index 854d703..603b6d6 100644
--- a/chrome/browser/ui/panels/panel_browser_view.cc
+++ b/chrome/browser/ui/panels/panel_browser_view.cc
@@ -84,7 +84,7 @@ bool PanelBrowserView::CanMaximize() const {
void PanelBrowserView::SetBounds(const gfx::Rect& bounds) {
bounds_ = bounds;
- //// No animation if the panel is being dragged.
+ // No animation if the panel is being dragged.
if (mouse_dragging_) {
::BrowserView::SetBounds(bounds);
return;
@@ -207,8 +207,10 @@ void PanelBrowserView::OnPanelExpansionStateChanged(
break;
}
+ int bottom = panel_->manager()->GetBottomPositionForExpansionState(
+ expansion_state);
gfx::Rect bounds = bounds_;
- bounds.set_y(bounds.y() + bounds.height() - height);
+ bounds.set_y(bottom - height);
bounds.set_height(height);
SetBounds(bounds);
}
diff --git a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
index 9fe9db7..6f7d563 100644
--- a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/command_line.h"
#include "base/i18n/time_formatting.h"
+#include "base/memory/scoped_ptr.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/panels/base_panel_browser_test.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_browser_frame_view.h"
#include "chrome/browser/ui/panels/panel_browser_view.h"
@@ -16,7 +16,6 @@
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension.h"
-#include "chrome/test/base/in_process_browser_test.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -28,13 +27,9 @@
#include "views/controls/link.h"
#include "views/controls/textfield/textfield.h"
-class PanelBrowserViewTest : public InProcessBrowserTest {
+class PanelBrowserViewTest : public BasePanelBrowserTest {
public:
- PanelBrowserViewTest() : InProcessBrowserTest() { }
-
- virtual void SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitch(switches::kEnablePanels);
- }
+ PanelBrowserViewTest() : BasePanelBrowserTest() { }
protected:
struct MenuItem {
@@ -71,19 +66,7 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
bool is_cursor_in_view_;
};
- enum ShowFlag { SHOW_AS_ACTIVE, SHOW_AS_INACTIVE };
-
- PanelBrowserView* CreatePanelBrowserView(const std::string& panel_name,
- ShowFlag show_flag) {
- Browser* panel_browser = Browser::CreateForApp(Browser::TYPE_PANEL,
- panel_name,
- gfx::Rect(),
- browser()->profile());
- Panel* panel = static_cast<Panel*>(panel_browser->window());
- if (show_flag == SHOW_AS_ACTIVE)
- panel->Show();
- else
- panel->ShowInactive();
+ PanelBrowserView* GetBrowserView(Panel* panel) {
return static_cast<PanelBrowserView*>(panel->native_panel());
}
@@ -119,37 +102,22 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
const std::string& homepage_url,
const std::string& options_page) {
// Creates a testing extension.
-#if defined(OS_WIN)
- FilePath full_path(FILE_PATH_LITERAL("c:\\"));
-#else
- FilePath full_path(FILE_PATH_LITERAL("/"));
-#endif
- full_path = full_path.Append(path);
- DictionaryValue input_value;
- input_value.SetString(extension_manifest_keys::kVersion, "1.0.0.0");
- input_value.SetString(extension_manifest_keys::kName, "Sample Extension");
+ DictionaryValue extra_value;
if (!homepage_url.empty()) {
- input_value.SetString(extension_manifest_keys::kHomepageURL,
+ extra_value.SetString(extension_manifest_keys::kHomepageURL,
homepage_url);
}
if (!options_page.empty()) {
- input_value.SetString(extension_manifest_keys::kOptionsPage,
+ extra_value.SetString(extension_manifest_keys::kOptionsPage,
options_page);
}
- std::string error;
- scoped_refptr<Extension> extension = Extension::Create(
- full_path, location, input_value, Extension::STRICT_ERROR_CHECKS,
- &error);
- ASSERT_TRUE(extension.get());
- EXPECT_STREQ("", error.c_str());
- browser()->GetProfile()->GetExtensionService()->OnLoadSingleExtension(
- extension.get(), false);
+ scoped_refptr<Extension> extension = CreateExtension(
+ path, location, extra_value);
// Creates a panel with the app name that comes from the extension ID.
- PanelBrowserView* browser_view = CreatePanelBrowserView(
- web_app::GenerateApplicationNameFromExtensionId(extension->id()),
- SHOW_AS_ACTIVE);
- PanelBrowserFrameView* frame_view = browser_view->GetFrameView();
+ Panel* panel = CreatePanel(
+ web_app::GenerateApplicationNameFromExtensionId(extension->id()));
+ PanelBrowserFrameView* frame_view = GetBrowserView(panel)->GetFrameView();
frame_view->EnsureSettingsMenuCreated();
@@ -175,54 +143,70 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
arraysize(expected_panel_menu_items),
expected_panel_menu_items);
- browser_view->panel()->Close();
+ panel->Close();
}
void TestShowPanelActiveOrInactive() {
- PanelBrowserView* browser_view1 = CreatePanelBrowserView("PanelTest1",
- SHOW_AS_ACTIVE);
+ CreatePanelParams params1("PanelTest1", gfx::Rect(), SHOW_AS_ACTIVE);
+ Panel* panel1 = CreatePanelWithParams(params1);
+ PanelBrowserView* browser_view1 = GetBrowserView(panel1);
PanelBrowserFrameView* frame_view1 = browser_view1->GetFrameView();
- EXPECT_TRUE(browser_view1->panel()->IsActive());
+ EXPECT_TRUE(panel1->IsActive());
EXPECT_EQ(PanelBrowserFrameView::PAINT_AS_ACTIVE,
frame_view1->paint_state_);
- PanelBrowserView* browser_view2 = CreatePanelBrowserView("PanelTest2",
- SHOW_AS_INACTIVE);
+ CreatePanelParams params2("PanelTest2", gfx::Rect(), SHOW_AS_INACTIVE);
+ Panel* panel2 = CreatePanelWithParams(params2);
+ PanelBrowserView* browser_view2 = GetBrowserView(panel2);
PanelBrowserFrameView* frame_view2 = browser_view2->GetFrameView();
- EXPECT_FALSE(browser_view2->panel()->IsActive());
+ EXPECT_FALSE(panel2->IsActive());
EXPECT_EQ(PanelBrowserFrameView::PAINT_AS_INACTIVE,
frame_view2->paint_state_);
- browser_view1->panel()->Close();
- browser_view2->panel()->Close();
+ panel1->Close();
+ panel2->Close();
}
// We put all the testing logic in this class instead of the test so that
// we do not need to declare each new test as a friend of PanelBrowserView
// for the purpose of accessing its private members.
- void TestMinimizeAndRestore() {
- PanelBrowserView* browser_view1 = CreatePanelBrowserView("PanelTest1",
- SHOW_AS_ACTIVE);
- Panel* panel1 = browser_view1->panel_.get();
+ void TestMinimizeAndRestore(bool enable_auto_hiding) {
+ PanelManager* panel_manager = PanelManager::GetInstance();
+ int expected_bottom_on_minimized = testing_work_area().height();
+ int expected_bottom_on_unminimized = expected_bottom_on_minimized;
+
+ // Turn on auto-hiding if requested.
+ static const int bottom_thickness = 40;
+ mock_auto_hiding_desktop_bar()->EnableAutoHiding(
+ AutoHidingDesktopBar::ALIGN_BOTTOM,
+ enable_auto_hiding,
+ bottom_thickness);
+ if (enable_auto_hiding)
+ expected_bottom_on_unminimized -= bottom_thickness;
+
+ // Create and test one panel first.
+ Panel* panel1 = CreatePanel("PanelTest1");
+ PanelBrowserView* browser_view1 = GetBrowserView(panel1);
PanelBrowserFrameView* frame_view1 = browser_view1->GetFrameView();
// Test minimizing/restoring an individual panel.
EXPECT_EQ(Panel::EXPANDED, panel1->expansion_state());
int initial_height = panel1->GetBounds().height();
- int titlebar_height =
- browser_view1->GetFrameView()->NonClientTopBorderHeight();
+ int titlebar_height = frame_view1->NonClientTopBorderHeight();
panel1->SetExpansionState(Panel::MINIMIZED);
EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
EXPECT_LT(panel1->GetBounds().height(), titlebar_height);
EXPECT_GT(panel1->GetBounds().height(), 0);
+ EXPECT_EQ(expected_bottom_on_minimized, panel1->GetBounds().bottom());
EXPECT_TRUE(IsMouseWatcherStarted());
- EXPECT_FALSE(panel1->IsActive());
WaitTillBoundsAnimationFinished(browser_view1);
+ EXPECT_FALSE(panel1->IsActive());
panel1->SetExpansionState(Panel::TITLE_ONLY);
EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
EXPECT_EQ(titlebar_height, panel1->GetBounds().height());
+ EXPECT_EQ(expected_bottom_on_unminimized, panel1->GetBounds().bottom());
WaitTillBoundsAnimationFinished(browser_view1);
EXPECT_TRUE(frame_view1->close_button_->IsVisible());
EXPECT_TRUE(frame_view1->title_icon_->IsVisible());
@@ -231,6 +215,7 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
panel1->SetExpansionState(Panel::EXPANDED);
EXPECT_EQ(Panel::EXPANDED, panel1->expansion_state());
EXPECT_EQ(initial_height, panel1->GetBounds().height());
+ EXPECT_EQ(expected_bottom_on_unminimized, panel1->GetBounds().bottom());
WaitTillBoundsAnimationFinished(browser_view1);
EXPECT_TRUE(frame_view1->close_button_->IsVisible());
EXPECT_TRUE(frame_view1->title_icon_->IsVisible());
@@ -239,59 +224,60 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
panel1->SetExpansionState(Panel::TITLE_ONLY);
EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
EXPECT_EQ(titlebar_height, panel1->GetBounds().height());
+ EXPECT_EQ(expected_bottom_on_unminimized, panel1->GetBounds().bottom());
panel1->SetExpansionState(Panel::MINIMIZED);
EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
EXPECT_LT(panel1->GetBounds().height(), titlebar_height);
EXPECT_GT(panel1->GetBounds().height(), 0);
+ EXPECT_EQ(expected_bottom_on_minimized, panel1->GetBounds().bottom());
// Create 2 more panels for more testing.
- PanelBrowserView* browser_view2 = CreatePanelBrowserView("PanelTest2",
- SHOW_AS_ACTIVE);
- Panel* panel2 = browser_view2->panel_.get();
-
- PanelBrowserView* browser_view3 = CreatePanelBrowserView("PanelTest3",
- SHOW_AS_ACTIVE);
- Panel* panel3 = browser_view3->panel_.get();
+ Panel* panel2 = CreatePanel("PanelTest2");
+ Panel* panel3 = CreatePanel("PanelTest3");
// Test bringing up or down the title-bar of all minimized panels.
EXPECT_EQ(Panel::EXPANDED, panel2->expansion_state());
panel3->SetExpansionState(Panel::MINIMIZED);
EXPECT_EQ(Panel::MINIMIZED, panel3->expansion_state());
- PanelManager* panel_manager = PanelManager::GetInstance();
-
- panel_manager->BringUpOrDownTitlebarForAllMinimizedPanels(true);
+ mock_auto_hiding_desktop_bar()->SetVisibility(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, AutoHidingDesktopBar::VISIBLE);
+ panel_manager->BringUpOrDownTitlebars(true);
+ MessageLoop::current()->RunAllPending();
EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
EXPECT_EQ(Panel::EXPANDED, panel2->expansion_state());
EXPECT_EQ(Panel::TITLE_ONLY, panel3->expansion_state());
- panel_manager->BringUpOrDownTitlebarForAllMinimizedPanels(false);
+ mock_auto_hiding_desktop_bar()->SetVisibility(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, AutoHidingDesktopBar::HIDDEN);
+ panel_manager->BringUpOrDownTitlebars(false);
+ MessageLoop::current()->RunAllPending();
EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
EXPECT_EQ(Panel::EXPANDED, panel2->expansion_state());
EXPECT_EQ(Panel::MINIMIZED, panel3->expansion_state());
// Test if it is OK to bring up title-bar given the mouse position.
- EXPECT_TRUE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_TRUE(panel_manager->ShouldBringUpTitlebars(
panel1->GetBounds().x(), panel1->GetBounds().y()));
- EXPECT_FALSE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_FALSE(panel_manager->ShouldBringUpTitlebars(
panel2->GetBounds().x(), panel2->GetBounds().y()));
- EXPECT_TRUE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_TRUE(panel_manager->ShouldBringUpTitlebars(
panel3->GetBounds().right() - 1, panel3->GetBounds().bottom() - 1));
- EXPECT_TRUE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_TRUE(panel_manager->ShouldBringUpTitlebars(
panel3->GetBounds().right() - 1, panel3->GetBounds().bottom() + 10));
- EXPECT_FALSE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_FALSE(panel_manager->ShouldBringUpTitlebars(
0, 0));
// Test that the panel in title-only state should not be minimized
// regardless of the current mouse position when the panel is being dragged.
panel1->SetExpansionState(Panel::TITLE_ONLY);
- EXPECT_FALSE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_FALSE(panel_manager->ShouldBringUpTitlebars(
0, 0));
browser_view1->OnTitlebarMousePressed(panel1->GetBounds().origin());
browser_view1->OnTitlebarMouseDragged(
panel1->GetBounds().origin().Subtract(gfx::Point(5, 5)));
- EXPECT_TRUE(panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
+ EXPECT_TRUE(panel_manager->ShouldBringUpTitlebars(
0, 0));
browser_view1->OnTitlebarMouseReleased();
@@ -304,10 +290,9 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
}
void TestDrawAttention() {
- PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest",
- SHOW_AS_ACTIVE);
+ Panel* panel = CreatePanel("PanelTest");
+ PanelBrowserView* browser_view = GetBrowserView(panel);
PanelBrowserFrameView* frame_view = browser_view->GetFrameView();
- Panel* panel = browser_view->panel_.get();
SkColor attention_color = frame_view->GetTitleColor(
PanelBrowserFrameView::PAINT_FOR_ATTENTION);
@@ -345,12 +330,10 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
// Test that we cannot bring up other minimized panel if the mouse is over
// the panel that draws attension.
EXPECT_FALSE(PanelManager::GetInstance()->
- ShouldBringUpTitlebarForAllMinimizedPanels(
- panel->GetBounds().x(), panel->GetBounds().y()));
+ ShouldBringUpTitlebars(panel->GetBounds().x(), panel->GetBounds().y()));
// Test that we cannot bring down the panel that is drawing the attention.
- PanelManager::GetInstance()->BringUpOrDownTitlebarForAllMinimizedPanels(
- false);
+ PanelManager::GetInstance()->BringUpOrDownTitlebars(false);
EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
// Test that the attention is cleared.
@@ -362,13 +345,54 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
panel->Close();
}
+
+ void TestChangeAutoHideTaskBarThickness() {
+ int bottom_bar_thickness = 20;
+ int right_bar_thickness = 30;
+ mock_auto_hiding_desktop_bar()->EnableAutoHiding(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, true, bottom_bar_thickness);
+ mock_auto_hiding_desktop_bar()->EnableAutoHiding(
+ AutoHidingDesktopBar::ALIGN_RIGHT, true, right_bar_thickness);
+
+ Panel* panel = CreatePanel("PanelTest");
+ EXPECT_EQ(testing_work_area().height() - bottom_bar_thickness,
+ panel->GetBounds().bottom());
+ EXPECT_EQ(testing_work_area().right() - right_bar_thickness,
+ panel->GetBounds().right());
+
+ bottom_bar_thickness += 10;
+ right_bar_thickness += 15;
+ mock_auto_hiding_desktop_bar()->SetThickness(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, bottom_bar_thickness);
+ mock_auto_hiding_desktop_bar()->SetThickness(
+ AutoHidingDesktopBar::ALIGN_RIGHT, right_bar_thickness);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(testing_work_area().height() - bottom_bar_thickness,
+ panel->GetBounds().bottom());
+ EXPECT_EQ(testing_work_area().right() - right_bar_thickness,
+ panel->GetBounds().right());
+
+ bottom_bar_thickness -= 20;
+ right_bar_thickness -= 10;
+ mock_auto_hiding_desktop_bar()->SetThickness(
+ AutoHidingDesktopBar::ALIGN_BOTTOM, bottom_bar_thickness);
+ mock_auto_hiding_desktop_bar()->SetThickness(
+ AutoHidingDesktopBar::ALIGN_RIGHT, right_bar_thickness);
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(testing_work_area().height() - bottom_bar_thickness,
+ panel->GetBounds().bottom());
+ EXPECT_EQ(testing_work_area().right() - right_bar_thickness,
+ panel->GetBounds().right());
+
+ panel->Close();
+ }
};
// Panel is not supported for Linux view yet.
#if !defined(OS_LINUX) || !defined(TOOLKIT_VIEWS)
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) {
- PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest",
- SHOW_AS_ACTIVE);
+ Panel* panel = CreatePanel("PanelTest");
+ PanelBrowserView* browser_view = GetBrowserView(panel);
PanelBrowserFrameView* frame_view = browser_view->GetFrameView();
// The bounds animation should not be triggered when the panel is up for the
@@ -418,7 +442,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) {
SkColor title_label_color2 = frame_view->title_label_->GetColor();
EXPECT_NE(title_label_color1, title_label_color2);
- browser_view->panel()->Close();
+ panel->Close();
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowPanelActiveOrInactive) {
@@ -426,9 +450,8 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowPanelActiveOrInactive) {
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideSettingsButton) {
- PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest",
- SHOW_AS_ACTIVE);
- PanelBrowserFrameView* frame_view = browser_view->GetFrameView();
+ Panel* panel = CreatePanel("PanelTest");
+ PanelBrowserFrameView* frame_view = GetBrowserView(panel)->GetFrameView();
// Create and hook up the MockMouseWatcher so that we can simulate if the
// mouse is over the panel.
@@ -438,7 +461,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideSettingsButton) {
// When the panel is created, it is active. Since we cannot programatically
// bring the panel back to active state once it is deactivated, we have to
// test the cases that the panel is active first.
- EXPECT_TRUE(browser_view->panel()->IsActive());
+ EXPECT_TRUE(panel->IsActive());
// When the panel is active, the settings button should always be visible.
mouse_watcher->MoveMouse(true);
@@ -448,8 +471,8 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideSettingsButton) {
// When the panel is inactive, the options button is active per the mouse over
// the panel or not.
- browser_view->panel()->Deactivate();
- EXPECT_FALSE(browser_view->panel()->IsActive());
+ panel->Deactivate();
+ EXPECT_FALSE(panel->IsActive());
mouse_watcher->MoveMouse(true);
EXPECT_TRUE(frame_view->settings_button_->IsVisible());
@@ -458,8 +481,8 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideSettingsButton) {
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, SetBoundsAnimation) {
- PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest",
- SHOW_AS_ACTIVE);
+ Panel* panel = CreatePanel("PanelTest");
+ PanelBrowserView* browser_view = GetBrowserView(panel);
// Validate that animation should be triggered when SetBounds is called.
gfx::Rect target_bounds(browser_view->GetBounds());
@@ -482,7 +505,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, SetBoundsAnimation) {
EXPECT_FALSE(browser_view->bounds_animator_->is_animating());
browser_view->OnTitlebarMouseCaptureLost();
- browser_view->panel()->Close();
+ panel->Close();
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreateSettingsMenu) {
@@ -494,11 +517,21 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreateSettingsMenu) {
"http://home", "options.html");
}
-IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, MinimizeAndRestore) {
- TestMinimizeAndRestore();
+IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest,
+ MinimizeAndRestoreOnNormalTaskBar) {
+ TestMinimizeAndRestore(false);
+}
+
+IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest,
+ MinimizeAndRestoreOnAutoHideTaskBar) {
+ TestMinimizeAndRestore(true);
}
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, DrawAttention) {
TestDrawAttention();
}
+
+IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ChangeAutoHideTaskBarThickness) {
+ TestChangeAutoHideTaskBarThickness();
+}
#endif
diff --git a/chrome/browser/ui/panels/panel_browsertest.cc b/chrome/browser/ui/panels/panel_browsertest.cc
index 4934fd7..025aa79 100644
--- a/chrome/browser/ui/panels/panel_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browsertest.cc
@@ -2,75 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/command_line.h"
-#include "base/mac/scoped_nsautorelease_pool.h"
-#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/find_bar/find_bar.h"
#include "chrome/browser/ui/find_bar/find_bar_controller.h"
+#include "chrome/browser/ui/panels/base_panel_browser_test.h"
#include "chrome/browser/ui/panels/native_panel.h"
#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/panels/panel_manager.h"
-#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_notification_types.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
-#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/browser/download/download_manager.h"
#include "content/browser/net/url_request_mock_http_job.h"
-#include "content/browser/tab_contents/test_tab_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_MACOSX)
-#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
-#endif
-
-class PanelBrowserTest : public InProcessBrowserTest {
+class PanelBrowserTest : public BasePanelBrowserTest {
public:
- PanelBrowserTest() : InProcessBrowserTest() {
-#if defined(OS_MACOSX)
- FindBarBridge::disable_animations_during_testing_ = true;
-#endif
- }
-
- virtual void SetUpCommandLine(CommandLine* command_line) {
- command_line->AppendSwitch(switches::kEnablePanels);
+ PanelBrowserTest() : BasePanelBrowserTest() {
}
protected:
- Panel* CreatePanel(const std::string& name, const gfx::Rect& bounds) {
- // Opening panels on a Mac causes NSWindowController of the Panel window
- // to be autoreleased. We need a pool drained after it's done so the test
- // can close correctly. The NSWindowController of the Panel window controls
- // lifetime of the Browser object so we want to release it as soon as
- // possible. In real Chrome, this is done by message pump.
- // On non-Mac platform, this is an empty class.
- base::mac::ScopedNSAutoreleasePool autorelease_pool;
-
- Browser* panel_browser = Browser::CreateForApp(Browser::TYPE_PANEL,
- name,
- bounds,
- browser()->profile());
- EXPECT_TRUE(panel_browser->is_type_panel());
-
- TabContentsWrapper* tab_contents =
- new TabContentsWrapper(new TestTabContents(browser()->profile(), NULL));
- panel_browser->AddTab(tab_contents, PageTransition::LINK);
-
- Panel* panel = static_cast<Panel*>(panel_browser->window());
- panel->Show();
- MessageLoopForUI::current()->RunAllPending();
-
- return panel;
- }
-
void CloseWindowAndWait(Browser* browser) {
// Closing a browser window may involve several async tasks. Need to use
// message pump and wait for the notification.
@@ -84,51 +39,30 @@ class PanelBrowserTest : public InProcessBrowserTest {
EXPECT_EQ(browser_count - 1, BrowserList::size());
}
- // Creates a testing extension.
- scoped_refptr<Extension> CreateExtension(const FilePath::StringType& path) {
-#if defined(OS_WIN)
- FilePath full_path(FILE_PATH_LITERAL("c:\\"));
-#else
- FilePath full_path(FILE_PATH_LITERAL("/"));
-#endif
- full_path = full_path.Append(path);
- DictionaryValue input_value;
- input_value.SetString(extension_manifest_keys::kVersion, "1.0.0.0");
- input_value.SetString(extension_manifest_keys::kName, "Sample Extension");
- std::string error;
- scoped_refptr<Extension> extension = Extension::Create(
- full_path, Extension::INVALID, input_value,
- Extension::STRICT_ERROR_CHECKS, &error);
- EXPECT_TRUE(extension.get());
- EXPECT_STREQ("", error.c_str());
- browser()->GetProfile()->GetExtensionService()->OnLoadSingleExtension(
- extension.get(), false);
- return extension;
- }
-
void TestCreatePanelOnOverflow() {
PanelManager* panel_manager = PanelManager::GetInstance();
EXPECT_EQ(0, panel_manager->num_panels()); // No panels initially.
- // Specify the work area for testing purpose.
- panel_manager->SetWorkArea(gfx::Rect(0, 0, 800, 600));
-
// Create testing extensions.
+ DictionaryValue empty_value;
scoped_refptr<Extension> extension1 =
- CreateExtension(FILE_PATH_LITERAL("extension1"));
+ CreateExtension(FILE_PATH_LITERAL("extension1"),
+ Extension::INVALID, empty_value);
scoped_refptr<Extension> extension2 =
- CreateExtension(FILE_PATH_LITERAL("extension2"));
+ CreateExtension(FILE_PATH_LITERAL("extension2"),
+ Extension::INVALID, empty_value);
scoped_refptr<Extension> extension3 =
- CreateExtension(FILE_PATH_LITERAL("extension3"));
+ CreateExtension(FILE_PATH_LITERAL("extension3"),
+ Extension::INVALID, empty_value);
// First, create 3 panels.
- Panel* panel1 = CreatePanel(
+ Panel* panel1 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension1->id()),
gfx::Rect(0, 0, 250, 200));
- Panel* panel2 = CreatePanel(
+ Panel* panel2 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension2->id()),
gfx::Rect(0, 0, 300, 200));
- Panel* panel3 = CreatePanel(
+ Panel* panel3 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension1->id()),
gfx::Rect(0, 0, 200, 200));
ASSERT_EQ(3, panel_manager->num_panels());
@@ -137,7 +71,7 @@ class PanelBrowserTest : public InProcessBrowserTest {
ui_test_utils::WindowedNotificationObserver signal(
chrome::NOTIFICATION_BROWSER_CLOSED,
Source<Browser>(panel2->browser()));
- Panel* panel4 = CreatePanel(
+ Panel* panel4 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension2->id()),
gfx::Rect(0, 0, 280, 200));
signal.Wait();
@@ -149,7 +83,7 @@ class PanelBrowserTest : public InProcessBrowserTest {
ui_test_utils::WindowedNotificationObserver signal2(
chrome::NOTIFICATION_BROWSER_CLOSED,
Source<Browser>(panel4->browser()));
- Panel* panel5 = CreatePanel(
+ Panel* panel5 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension3->id()),
gfx::Rect(0, 0, 300, 200));
signal2.Wait();
@@ -164,7 +98,7 @@ class PanelBrowserTest : public InProcessBrowserTest {
ui_test_utils::WindowedNotificationObserver signal4(
chrome::NOTIFICATION_BROWSER_CLOSED,
Source<Browser>(panel5->browser()));
- Panel* panel6 = CreatePanel(
+ Panel* panel6 = CreatePanelWithBounds(
web_app::GenerateApplicationNameFromExtensionId(extension3->id()),
gfx::Rect(0, 0, 500, 200));
signal3.Wait();
@@ -176,10 +110,6 @@ class PanelBrowserTest : public InProcessBrowserTest {
panel6->Close();
}
- void SetWorkArea(const gfx::Rect& work_area) {
- PanelManager::GetInstance()->SetWorkArea(gfx::Rect(0, 0, 800, 600));
- }
-
int horizontal_spacing() {
return PanelManager::horizontal_spacing();
}
@@ -296,7 +226,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreatePanel) {
PanelManager* panel_manager = PanelManager::GetInstance();
EXPECT_EQ(0, panel_manager->num_panels()); // No panels initially.
- Panel* panel = CreatePanel("PanelTest", gfx::Rect());
+ Panel* panel = CreatePanel("PanelTest");
EXPECT_EQ(1, panel_manager->num_panels());
gfx::Rect bounds = panel->GetBounds();
@@ -311,7 +241,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreatePanel) {
}
IN_PROC_BROWSER_TEST_F(PanelBrowserTest, FindBar) {
- Panel* panel = CreatePanel("PanelTest", gfx::Rect(0, 0, 400, 400));
+ Panel* panel = CreatePanelWithBounds("PanelTest", gfx::Rect(0, 0, 400, 400));
Browser* browser = panel->browser();
browser->ShowFindBar();
ASSERT_TRUE(browser->GetFindBarController()->find_bar()->IsFindBarVisible());
@@ -329,9 +259,6 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreatePanelOnOverflow) {
#endif
IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DragPanels) {
- // Set work area to make the test consistent on different monitor sizes.
- SetWorkArea(gfx::Rect(0, 0, 800, 600));
-
static const int max_panels = 3;
static const int zero_delta = 0;
static const int small_delta = 10;
@@ -347,7 +274,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DragPanels) {
// Tests with a single panel.
{
- CreatePanel("PanelTest1", gfx::Rect(0, 0, 100, 100));
+ CreatePanelWithBounds("PanelTest1", gfx::Rect(0, 0, 100, 100));
// Drag left.
expected_delta_x_after_drag[0] = -big_delta;
@@ -385,7 +312,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DragPanels) {
// Tests with two panels.
{
- CreatePanel("PanelTest2", gfx::Rect(0, 0, 120, 120));
+ CreatePanelWithBounds("PanelTest2", gfx::Rect(0, 0, 120, 120));
// Drag left, small delta, expect no shuffle.
{
@@ -458,7 +385,7 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_DragPanels) {
// Tests with three panels.
{
- CreatePanel("PanelTest3", gfx::Rect(0, 0, 110, 110));
+ CreatePanelWithBounds("PanelTest3", gfx::Rect(0, 0, 110, 110));
// Drag leftmost panel to become rightmost with two shuffles.
// We test both shuffles.
diff --git a/chrome/browser/ui/panels/panel_manager.cc b/chrome/browser/ui/panels/panel_manager.cc
index 4374a72a6..20c0198 100644
--- a/chrome/browser/ui/panels/panel_manager.cc
+++ b/chrome/browser/ui/panels/panel_manager.cc
@@ -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 int kPanelDefaultHeightPixels = 290;
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 @@ void PanelManager::SetWorkArea(const gfx::Rect& work_area) {
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 @@ void PanelManager::FindAndClosePanelOnOverflow(const Extension* extension) {
}
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 @@ void PanelManager::DoRemove(Panel* panel) {
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 @@ void PanelManager::EndDragging(bool cancelled) {
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 @@ bool PanelManager::ShouldBringUpTitlebarForAllMinimizedPanels(
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::BringUpOrDownTitlebarForAllMinimizedPanels(bool bring_up) {
}
}
-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() {
diff --git a/chrome/browser/ui/panels/panel_manager.h b/chrome/browser/ui/panels/panel_manager.h
index 7dacd55..998f91f 100644
--- a/chrome/browser/ui/panels/panel_manager.h
+++ b/chrome/browser/ui/panels/panel_manager.h
@@ -8,7 +8,10 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/task.h"
+#include "chrome/browser/ui/panels/auto_hiding_desktop_bar.h"
#include "chrome/browser/ui/panels/panel.h"
#include "ui/gfx/rect.h"
@@ -16,12 +19,16 @@ class Browser;
class Panel;
// This class manages a set of panels.
-class PanelManager {
+// Note that the ref count is needed by using PostTask in the implementation.
+class PanelManager : public AutoHidingDesktopBar::Observer,
+ public base::RefCounted<PanelManager> {
public:
+ typedef std::vector<Panel*> Panels;
+
// Returns a single instance.
static PanelManager* GetInstance();
- ~PanelManager();
+ virtual ~PanelManager();
// Called when the display is changed, i.e. work area is updated.
void OnDisplayChanged();
@@ -38,32 +45,62 @@ class PanelManager {
void Drag(int delta_x);
void EndDragging(bool cancelled);
- // Should we bring up the titlebar, given the current mouse point?
- bool ShouldBringUpTitlebarForAllMinimizedPanels(int mouse_x,
- int mouse_y) const;
+ // Returns true if we should bring up the titlebars, given the current mouse
+ // point.
+ bool ShouldBringUpTitlebars(int mouse_x, int mouse_y) const;
+
+ // Brings up or down the titlebars for all minimized panels.
+ void BringUpOrDownTitlebars(bool bring_up);
- // Brings up or down the title-bar for all minimized panels.
- void BringUpOrDownTitlebarForAllMinimizedPanels(bool bring_up);
+ // Returns the bottom position for the panel per its expansion state. If auto-
+ // hide bottom bar is present, we want to move the minimized panel to the
+ // bottom of the screen, not the bottom of the work area.
+ int GetBottomPositionForExpansionState(
+ Panel::ExpansionState expansion_state) const;
int num_panels() const { return panels_.size(); }
bool is_dragging_panel() const;
- private:
- friend class PanelBrowserTest;
+#ifdef UNIT_TEST
+ const Panels& panels() const { return panels_; }
+ static int horizontal_spacing() { return kPanelsHorizontalSpacing; }
- typedef std::vector<Panel*> Panels;
+ const gfx::Rect& work_area() const {
+ return work_area_;
+ }
- PanelManager();
+ void set_auto_hiding_desktop_bar(
+ AutoHidingDesktopBar* auto_hiding_desktop_bar) {
+ auto_hiding_desktop_bar_ = auto_hiding_desktop_bar;
+ }
-#if UNIT_TEST
- const Panels& panels() const { return panels_; }
- static int horizontal_spacing() { return kPanelsHorizontalSpacing; }
+ void SetWorkAreaForTesting(const gfx::Rect& work_area) {
+ SetWorkArea(work_area);
+ }
#endif
+ private:
+ enum TitlebarAction {
+ NO_ACTION,
+ BRING_UP,
+ BRING_DOWN
+ };
+
+ PanelManager();
+
+ // Overridden from AutoHidingDesktopBar::Observer:
+ virtual void OnAutoHidingDesktopBarThicknessChanged() OVERRIDE;
+ virtual void OnAutoHidingDesktopBarVisibilityChanged(
+ AutoHidingDesktopBar::Alignment alignment,
+ AutoHidingDesktopBar::Visibility visibility) OVERRIDE;
+
// Applies the new work area. This is called by OnDisplayChanged and the test
// code.
void SetWorkArea(const gfx::Rect& work_area);
+ // Adjusts the work area to exclude the influence of auto-hiding desktop bars.
+ void AdjustWorkAreaForAutoHidingDesktopBars();
+
// Handles all the panels that're delayed to be removed.
void DelayedRemove();
@@ -73,13 +110,7 @@ class PanelManager {
// Rearranges the positions of the panels starting from the given iterator.
// This is called when the display space has been changed, i.e. working
// area being changed or a panel being closed.
- void Rearrange(Panels::iterator iter_to_start);
-
- // Computes the bounds for next panel.
- // |allow_size_change| is used to indicate if the panel size can be changed to
- // fall within the size constraint, e.g., when the panel is created.
- // Returns true if computed bounds are within the displayable area.
- bool ComputeBoundsForNextPanel(gfx::Rect* bounds, bool allow_size_change);
+ void Rearrange(Panels::iterator iter_to_start, int rightmost_position);
// Finds one panel to close so that we may have space for the new panel
// created by |extension|.
@@ -89,7 +120,15 @@ class PanelManager {
void DragLeft();
void DragRight();
- // Horizontal spacing between panels. Used for unit testing.
+ // Checks if the titlebars have been brought up or down. If not, do not wait
+ // for the notifications to trigger it any more, and start to bring them up or
+ // down immediately.
+ void DelayedBringUpOrDownTitlebarsCheck();
+
+ // Does the real job of bringing up or down the titlebars.
+ void DoBringUpOrDownTitlebars(bool bring_up);
+
+ int GetRightMostAvaialblePosition() const;
Panels panels_;
@@ -97,15 +136,15 @@ class PanelManager {
// when we're in the process of the dragging.
Panels panels_pending_to_remove_;
- // Current work area used in computing the panel bounds.
+ // The maximum work area avaialble. This area does not include the area taken
+ // by the always-visible (non-auto-hiding) desktop bars.
gfx::Rect work_area_;
- // Used in computing the bounds of the next panel.
- int max_width_;
- int max_height_;
- int min_x_;
- int current_x_;
- int bottom_edge_y_;
+ // The useable work area for computing the panel bounds. This area excludes
+ // the potential area that could be taken by the auto-hiding desktop
+ // bars (we only consider those bars that are aligned to bottom, left, and
+ // right of the screen edges) when they become fully visible.
+ gfx::Rect adjusted_work_area_;
// Panel to drag.
size_t dragging_panel_index_;
@@ -119,6 +158,12 @@ class PanelManager {
// to when the dragging ends.
gfx::Rect dragging_panel_bounds_;
+ scoped_refptr<AutoHidingDesktopBar> auto_hiding_desktop_bar_;
+
+ TitlebarAction delayed_titlebar_action_;
+
+ ScopedRunnableMethodFactory<PanelManager> method_factory_;
+
static const int kPanelsHorizontalSpacing = 4;
DISALLOW_COPY_AND_ASSIGN(PanelManager);
diff --git a/chrome/browser/ui/panels/panel_mouse_watcher_win.cc b/chrome/browser/ui/panels/panel_mouse_watcher_win.cc
index 590125b..cb7a6ed 100644
--- a/chrome/browser/ui/panels/panel_mouse_watcher_win.cc
+++ b/chrome/browser/ui/panels/panel_mouse_watcher_win.cc
@@ -36,7 +36,7 @@ class PanelMouseWatcherWin {
void OnMouseAction(int mouse_x, int mouse_y);
HHOOK mouse_hook_;
- bool bring_up_titlebar_;
+ bool bring_up_titlebars_;
DISALLOW_COPY_AND_ASSIGN(PanelMouseWatcherWin);
};
@@ -45,7 +45,7 @@ scoped_ptr<PanelMouseWatcherWin> mouse_watcher;
PanelMouseWatcherWin::PanelMouseWatcherWin()
: mouse_hook_(NULL),
- bring_up_titlebar_(false) {
+ bring_up_titlebars_(false) {
mouse_hook_ = ::SetWindowsHookEx(
WH_MOUSE_LL, MouseHookProc, GetCurrentModuleHandle(), 0);
DCHECK(mouse_hook_);
@@ -69,14 +69,13 @@ LRESULT CALLBACK PanelMouseWatcherWin::MouseHookProc(int code,
void PanelMouseWatcherWin::OnMouseAction(int mouse_x, int mouse_y) {
PanelManager* panel_manager = PanelManager::GetInstance();
- bool bring_up_titlebar =
- panel_manager->ShouldBringUpTitlebarForAllMinimizedPanels(
- mouse_x, mouse_y);
- if (bring_up_titlebar == bring_up_titlebar_)
+ bool bring_up_titlebars = panel_manager->ShouldBringUpTitlebars(
+ mouse_x, mouse_y);
+ if (bring_up_titlebars == bring_up_titlebars_)
return;
- bring_up_titlebar_ = bring_up_titlebar;
+ bring_up_titlebars_ = bring_up_titlebars;
- panel_manager->BringUpOrDownTitlebarForAllMinimizedPanels(bring_up_titlebar);
+ panel_manager->BringUpOrDownTitlebars(bring_up_titlebars);
}
} // namespace
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 4dbb767..2c39a0f 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2975,6 +2975,12 @@
'browser/ui/omnibox/omnibox_view.h',
'browser/ui/options/options_util.cc',
'browser/ui/options/options_util.h',
+ 'browser/ui/panels/auto_hiding_desktop_bar_chromeos.cc',
+ 'browser/ui/panels/auto_hiding_desktop_bar_cocoa.mm',
+ 'browser/ui/panels/auto_hiding_desktop_bar_gtk.cc',
+ 'browser/ui/panels/auto_hiding_desktop_bar_win.cc',
+ 'browser/ui/panels/auto_hiding_desktop_bar_win.h',
+ 'browser/ui/panels/auto_hiding_desktop_bar.h',
'browser/ui/panels/native_panel.h',
'browser/ui/panels/panel.cc',
'browser/ui/panels/panel.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 0e20965..fe7f1ba 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1873,6 +1873,7 @@
'browser/ui/intents/intents_model_unittest.cc',
'browser/ui/login/login_prompt_unittest.cc',
'browser/ui/omnibox/omnibox_view_unittest.cc',
+ 'browser/ui/panels/auto_hiding_desktop_bar_win_unittest.cc',
'browser/ui/panels/panel_browser_window_cocoa_unittest.mm',
'browser/ui/search_engines/keyword_editor_controller_unittest.cc',
'browser/ui/shell_dialogs_unittest.cc',
@@ -2570,6 +2571,8 @@
'browser/ui/find_bar/find_bar_host_browsertest.cc',
'browser/ui/gtk/view_id_util_browsertest.cc',
'browser/ui/login/login_prompt_browsertest.cc',
+ 'browser/ui/panels/base_panel_browser_test.cc',
+ 'browser/ui/panels/base_panel_browser_test.h',
'browser/ui/panels/panel_app_browsertest.cc',
'browser/ui/panels/panel_browsertest.cc',
'browser/ui/panels/panel_browser_view_browsertest.cc',
diff --git a/views/widget/monitor_win.cc b/views/widget/monitor_win.cc
index 8e60b90..d840893 100644
--- a/views/widget/monitor_win.cc
+++ b/views/widget/monitor_win.cc
@@ -4,7 +4,7 @@
#include "views/widget/monitor_win.h"
-#include <windows.h>
+#include <shellapi.h>
#include "base/logging.h"
#include "ui/gfx/rect.h"
@@ -24,4 +24,14 @@ gfx::Rect GetMonitorBoundsForRect(const gfx::Rect& rect) {
return gfx::Rect();
}
+HWND GetTopmostAutoHideTaskbarForEdge(UINT edge, HMONITOR monitor) {
+ APPBARDATA taskbar_data = { sizeof APPBARDATA, NULL, 0, edge };
+ HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR,
+ &taskbar_data));
+ return (::IsWindow(taskbar) && (monitor != NULL) &&
+ (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
+ (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST)) ?
+ taskbar : NULL;
+}
+
} // namespace views
diff --git a/views/widget/monitor_win.h b/views/widget/monitor_win.h
index ac92f9b..7ceacfa 100644
--- a/views/widget/monitor_win.h
+++ b/views/widget/monitor_win.h
@@ -6,6 +6,7 @@
#define VIEWS_WIDGET_MONITOR_WIN_H_
#pragma once
+#include <windows.h>
#include "views/views_export.h"
namespace gfx {
@@ -18,6 +19,11 @@ namespace views {
// intersection with the specified rectangle.
VIEWS_EXPORT gfx::Rect GetMonitorBoundsForRect(const gfx::Rect& rect);
+// Returns the always-on-top auto-hiding taskbar for edge |edge| (one of
+// ABE_LEFT, TOP, RIGHT, or BOTTOM) of monitor |monitor|. NULL is returned
+// if nothing is found.
+VIEWS_EXPORT HWND GetTopmostAutoHideTaskbarForEdge(UINT edge, HMONITOR monitor);
+
} // namespace views
#endif // VIEWS_WIDGET_MONITOR_WIN_H_
diff --git a/views/widget/native_widget_win.cc b/views/widget/native_widget_win.cc
index 2701173..a1bb956 100644
--- a/views/widget/native_widget_win.cc
+++ b/views/widget/native_widget_win.cc
@@ -39,6 +39,7 @@
#include "views/widget/aero_tooltip_manager.h"
#include "views/widget/child_window_message_processor.h"
#include "views/widget/drop_target_win.h"
+#include "views/widget/monitor_win.h"
#include "views/widget/native_widget_delegate.h"
#include "views/widget/native_widget_views.h"
#include "views/widget/root_view.h"
@@ -285,19 +286,6 @@ bool GetMonitorAndRects(const RECT& rect,
return true;
}
-// Returns true if edge |edge| (one of ABE_LEFT, TOP, RIGHT, or BOTTOM) of
-// monitor |monitor| has an auto-hiding taskbar that's always-on-top.
-bool EdgeHasTopmostAutoHideTaskbar(UINT edge, HMONITOR monitor) {
- APPBARDATA taskbar_data = { 0 };
- taskbar_data.cbSize = sizeof APPBARDATA;
- taskbar_data.uEdge = edge;
- HWND taskbar = reinterpret_cast<HWND>(SHAppBarMessage(ABM_GETAUTOHIDEBAR,
- &taskbar_data));
- return ::IsWindow(taskbar) && (monitor != NULL) &&
- (MonitorFromWindow(taskbar, MONITOR_DEFAULTTONULL) == monitor) &&
- (GetWindowLong(taskbar, GWL_EXSTYLE) & WS_EX_TOPMOST);
-}
-
// Links the HWND to its NativeWidget.
const char* const kNativeWidgetKey = "__VIEWS_NATIVE_WIDGET__";
@@ -1639,9 +1627,9 @@ LRESULT NativeWidgetWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
return 0;
}
}
- if (EdgeHasTopmostAutoHideTaskbar(ABE_LEFT, monitor))
+ if (GetTopmostAutoHideTaskbarForEdge(ABE_LEFT, monitor))
client_rect->left += kAutoHideTaskbarThicknessPx;
- if (EdgeHasTopmostAutoHideTaskbar(ABE_TOP, monitor)) {
+ if (GetTopmostAutoHideTaskbarForEdge(ABE_TOP, monitor)) {
if (GetWidget()->ShouldUseNativeFrame()) {
// Tricky bit. Due to a bug in DwmDefWindowProc()'s handling of
// WM_NCHITTEST, having any nonclient area atop the window causes the
@@ -1657,9 +1645,9 @@ LRESULT NativeWidgetWin::OnNCCalcSize(BOOL mode, LPARAM l_param) {
client_rect->top += kAutoHideTaskbarThicknessPx;
}
}
- if (EdgeHasTopmostAutoHideTaskbar(ABE_RIGHT, monitor))
+ if (GetTopmostAutoHideTaskbarForEdge(ABE_RIGHT, monitor))
client_rect->right -= kAutoHideTaskbarThicknessPx;
- if (EdgeHasTopmostAutoHideTaskbar(ABE_BOTTOM, monitor))
+ if (GetTopmostAutoHideTaskbarForEdge(ABE_BOTTOM, monitor))
client_rect->bottom -= kAutoHideTaskbarThicknessPx;
// We cannot return WVR_REDRAW when there is nonclient area, or Windows