summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-24 21:53:16 +0000
committerjianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-24 21:53:16 +0000
commit092a2fab32125a0cc94ac732f0ee881c36c3009b (patch)
treeb2ecb21be6877cdc9bd4d927e0cc3d209ef70131
parent9b793154110730b74cb18ff2d52211d01d805bb6 (diff)
downloadchromium_src-092a2fab32125a0cc94ac732f0ee881c36c3009b.zip
chromium_src-092a2fab32125a0cc94ac732f0ee881c36c3009b.tar.gz
chromium_src-092a2fab32125a0cc94ac732f0ee881c36c3009b.tar.bz2
Make info button appear only when mouse is over the panel or the panel has focus.
BUG=none TEST=panel_browser_view_browsertest Review URL: http://codereview.chromium.org/7055001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@86499 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/ui/panels/panel.cc4
-rw-r--r--chrome/browser/ui/panels/panel_browser_frame_view.cc72
-rw-r--r--chrome/browser/ui/panels/panel_browser_frame_view.h41
-rw-r--r--chrome/browser/ui/panels/panel_browser_view.h1
-rw-r--r--chrome/browser/ui/panels/panel_browser_view_browsertest.cc78
5 files changed, 173 insertions, 23 deletions
diff --git a/chrome/browser/ui/panels/panel.cc b/chrome/browser/ui/panels/panel.cc
index 1ffd500a..770c9869 100644
--- a/chrome/browser/ui/panels/panel.cc
+++ b/chrome/browser/ui/panels/panel.cc
@@ -78,11 +78,11 @@ void Panel::Close() {
}
void Panel::Activate() {
- NOTIMPLEMENTED();
+ browser_window_->Activate();
}
void Panel::Deactivate() {
- NOTIMPLEMENTED();
+ browser_window_->Deactivate();
}
bool Panel::IsActive() const {
diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.cc b/chrome/browser/ui/panels/panel_browser_frame_view.cc
index e85f8b2..c5bc4fa 100644
--- a/chrome/browser/ui/panels/panel_browser_frame_view.cc
+++ b/chrome/browser/ui/panels/panel_browser_frame_view.cc
@@ -21,6 +21,7 @@
#include "views/controls/button/image_button.h"
#include "views/controls/label.h"
#include "views/painter.h"
+#include "views/screen.h"
#include "views/window/window.h"
#include "views/window/window_shape.h"
@@ -129,6 +130,60 @@ void EnsureResourcesInitialized() {
} // namespace
+// PanelBrowserFrameView::MouseWatcher -----------------------------------------
+
+PanelBrowserFrameView::MouseWatcher::MouseWatcher(PanelBrowserFrameView* view)
+ : view_(view),
+ is_mouse_within_(false) {
+ MessageLoopForUI::current()->AddObserver(this);
+}
+
+PanelBrowserFrameView::MouseWatcher::~MouseWatcher() {
+ MessageLoopForUI::current()->RemoveObserver(this);
+}
+
+bool PanelBrowserFrameView::MouseWatcher::IsCursorInViewBounds() const {
+ gfx::Point cursor_point = views::Screen::GetCursorScreenPoint();
+ return view_->browser_view_->GetBounds().Contains(cursor_point.x(),
+ cursor_point.y());
+}
+
+#if defined(OS_WIN)
+void PanelBrowserFrameView::MouseWatcher::DidProcessMessage(const MSG& msg) {
+ switch (msg.message) {
+ case WM_MOUSEMOVE:
+ case WM_NCMOUSEMOVE:
+ case WM_MOUSELEAVE:
+ case WM_NCMOUSELEAVE:
+ HandleGlobalMouseMoveEvent();
+ break;
+ default:
+ break;
+ }
+}
+#else
+void PanelBrowserFrameView::MouseWatcher::DidProcessEvent(GdkEvent* event) {
+ switch (event->type) {
+ case GDK_MOTION_NOTIFY:
+ case GDK_LEAVE_NOTIFY:
+ HandleGlobalMouseMoveEvent();
+ break;
+ default:
+ break;
+ }
+}
+#endif
+
+void PanelBrowserFrameView::MouseWatcher::HandleGlobalMouseMoveEvent() {
+ bool is_mouse_within = IsCursorInViewBounds();
+ if (is_mouse_within == is_mouse_within_)
+ return;
+ is_mouse_within_ = is_mouse_within;
+ view_->OnMouseEnterOrLeaveWindow(is_mouse_within_);
+}
+
+// PanelBrowserFrameView -------------------------------------------------------
+
PanelBrowserFrameView::PanelBrowserFrameView(BrowserFrame* frame,
PanelBrowserView* browser_view)
: BrowserNonClientFrameView(),
@@ -153,9 +208,7 @@ PanelBrowserFrameView::PanelBrowserFrameView(BrowserFrame* frame,
UTF16ToWide(l10n_util::GetStringUTF16(IDS_ACCNAME_ABOUT_PANEL)));
info_button_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_ACCNAME_ABOUT_PANEL));
- // TODO(jianli): Hide info button by default and show it when mouse is over
- // panel.
- // info_button_->SetVisible(false);
+ info_button_->SetVisible(false);
AddChildView(info_button_);
close_button_ = new views::ImageButton(this);
@@ -178,6 +231,8 @@ PanelBrowserFrameView::PanelBrowserFrameView(BrowserFrame* frame,
title_label_ = new views::Label(std::wstring());
title_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
AddChildView(title_label_);
+
+ mouse_watcher_.reset(new MouseWatcher(this));
}
PanelBrowserFrameView::~PanelBrowserFrameView() {
@@ -479,5 +534,16 @@ void PanelBrowserFrameView::UpdateTitleBar() {
}
void PanelBrowserFrameView::OnActivationChanged(bool active) {
+ UpdateInfoButtonVisibility(active, mouse_watcher_->IsCursorInViewBounds());
SchedulePaint();
}
+
+void PanelBrowserFrameView::OnMouseEnterOrLeaveWindow(bool mouse_entered) {
+ UpdateInfoButtonVisibility(browser_view_->panel()->IsActive(),
+ mouse_entered);
+}
+
+void PanelBrowserFrameView::UpdateInfoButtonVisibility(bool active,
+ bool cursor_in_view) {
+ info_button_->SetVisible(active || cursor_in_view);
+}
diff --git a/chrome/browser/ui/panels/panel_browser_frame_view.h b/chrome/browser/ui/panels/panel_browser_frame_view.h
index bf42e3e..2923208 100644
--- a/chrome/browser/ui/panels/panel_browser_frame_view.h
+++ b/chrome/browser/ui/panels/panel_browser_frame_view.h
@@ -7,6 +7,7 @@
#pragma once
#include "base/gtest_prod_util.h"
+#include "base/message_loop.h"
#include "base/scoped_ptr.h"
#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
#include "chrome/browser/ui/views/tab_icon_view.h"
@@ -66,6 +67,7 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView,
private:
friend class PanelBrowserViewTest;
FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, CreatePanel);
+ FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, ShowOrHideInfoButton);
enum PaintState {
NOT_PAINTED,
@@ -73,6 +75,30 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView,
PAINT_AS_ACTIVE
};
+ class MouseWatcher : public MessageLoopForUI::Observer {
+ public:
+ explicit MouseWatcher(PanelBrowserFrameView* view);
+ virtual ~MouseWatcher();
+
+ virtual bool IsCursorInViewBounds() const;
+
+ #if defined(OS_WIN)
+ virtual void WillProcessMessage(const MSG& msg) OVERRIDE { }
+ virtual void DidProcessMessage(const MSG& msg) OVERRIDE;
+ #else
+ virtual void WillProcessEvent(GdkEvent* event) OVERRIDE { }
+ virtual void DidProcessEvent(GdkEvent* event) OVERRIDE;
+ #endif
+
+ private:
+ void HandleGlobalMouseMoveEvent();
+
+ PanelBrowserFrameView* view_;
+ bool is_mouse_within_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseWatcher);
+ };
+
// Returns the thickness of the entire nonclient left, right, and bottom
// borders, including both the window frame and any client edge.
int NonClientBorderThickness() const;
@@ -88,6 +114,20 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView,
void PaintFrameBorder(gfx::Canvas* canvas);
void PaintClientEdge(gfx::Canvas* canvas);
+ // Called by MouseWatcher to notify if the mouse enters or leaves the window.
+ void OnMouseEnterOrLeaveWindow(bool mouse_entered);
+
+ // Make info button visible if either of the conditions is met:
+ // 1) The panel is active, i.e. having focus.
+ // 2) The mouse is over the panel.
+ void UpdateInfoButtonVisibility(bool active, bool cursor_in_view);
+
+#ifdef UNIT_TEST
+ void set_mouse_watcher(MouseWatcher* mouse_watcher) {
+ mouse_watcher_.reset(mouse_watcher);
+ }
+#endif
+
// The frame that hosts this view. This is a weak reference such that frame_
// will always be valid in the lifetime of this view.
BrowserFrame* frame_;
@@ -103,6 +143,7 @@ class PanelBrowserFrameView : public BrowserNonClientFrameView,
TabIconView* title_icon_;
views::Label* title_label_;
gfx::Rect client_view_bounds_;
+ scoped_ptr<MouseWatcher> mouse_watcher_;
DISALLOW_COPY_AND_ASSIGN(PanelBrowserFrameView);
};
diff --git a/chrome/browser/ui/panels/panel_browser_view.h b/chrome/browser/ui/panels/panel_browser_view.h
index 17549a3..e643fc8 100644
--- a/chrome/browser/ui/panels/panel_browser_view.h
+++ b/chrome/browser/ui/panels/panel_browser_view.h
@@ -31,6 +31,7 @@ class PanelBrowserView : public ::BrowserView {
private:
friend class PanelBrowserViewTest;
FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, CreatePanel);
+ FRIEND_TEST_ALL_PREFIXES(PanelBrowserViewTest, ShowOrHideInfoButton);
// Overridden from BrowserView:
virtual void Init() OVERRIDE;
diff --git a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
index 2026000..50b4924 100644
--- a/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
+++ b/chrome/browser/ui/panels/panel_browser_view_browsertest.cc
@@ -13,10 +13,7 @@
#include "chrome/test/in_process_browser_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "views/controls/button/image_button.h"
-#include "views/controls/button/menu_button.h"
#include "views/controls/label.h"
-#include "views/controls/menu/menu_2.h"
-
class PanelBrowserViewTest : public InProcessBrowserTest {
public:
@@ -27,6 +24,35 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
}
protected:
+ class MockMouseWatcher : public PanelBrowserFrameView::MouseWatcher {
+ public:
+ explicit MockMouseWatcher(PanelBrowserFrameView* view)
+ : PanelBrowserFrameView::MouseWatcher(view),
+ is_cursor_in_view_(false) {
+ }
+
+ virtual bool IsCursorInViewBounds() const {
+ return is_cursor_in_view_;
+ }
+
+ void MoveMouse(bool is_cursor_in_view) {
+ is_cursor_in_view_ = is_cursor_in_view;
+
+#if defined(OS_WIN)
+ MSG msg;
+ msg.message = WM_MOUSEMOVE;
+ DidProcessMessage(msg);
+#else
+ GdkEvent event;
+ event.type = GDK_MOTION_NOTIFY;
+ DidProcessEvent(&event);
+#endif
+ }
+
+ private:
+ bool is_cursor_in_view_;
+ };
+
PanelBrowserView* CreatePanelBrowserView(const std::string& panel_name) {
Browser* panel_browser = Browser::CreateForApp(Browser::TYPE_PANEL,
panel_name,
@@ -37,20 +63,6 @@ class PanelBrowserViewTest : public InProcessBrowserTest {
static_cast<Panel*>(panel_browser->window())->browser_window());
}
- void ValidateOptionsMenuItems(
- ui::SimpleMenuModel* options_menu_contents, size_t count, int* ids) {
- ASSERT_TRUE(options_menu_contents);
- EXPECT_EQ(static_cast<int>(count), options_menu_contents->GetItemCount());
- for (size_t i = 0; i < count; ++i) {
- if (ids[i] == -1) {
- EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
- options_menu_contents->GetTypeAt(i));
- } else {
- EXPECT_EQ(ids[i] , options_menu_contents->GetCommandIdAt(i));
- }
- }
- }
-
void ValidateDragging(PanelBrowserView** browser_views,
size_t num_browser_views,
size_t index_to_drag,
@@ -155,7 +167,6 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) {
// These controls should be visible.
EXPECT_TRUE(frame_view->title_icon_->IsVisible());
EXPECT_TRUE(frame_view->title_label_->IsVisible());
- EXPECT_TRUE(frame_view->info_button_->IsVisible());
EXPECT_TRUE(frame_view->close_button_->IsVisible());
// Validate their layouts.
@@ -190,6 +201,37 @@ IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, CreatePanel) {
EXPECT_NE(title_label_font1.GetStyle(), title_label_font2.GetStyle());
}
+IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, ShowOrHideInfoButton) {
+ PanelBrowserView* browser_view = CreatePanelBrowserView("PanelTest");
+ PanelBrowserFrameView* frame_view = browser_view->GetFrameView();
+
+ // Create and hook up the MockMouseWatcher so that we can simulate if the
+ // mouse is over the panel.
+ MockMouseWatcher* mouse_watcher = new MockMouseWatcher(frame_view);
+ frame_view->set_mouse_watcher(mouse_watcher);
+
+ // 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());
+
+ // When the panel is active, the info button should always be visible.
+ mouse_watcher->MoveMouse(true);
+ EXPECT_TRUE(frame_view->info_button_->IsVisible());
+ mouse_watcher->MoveMouse(false);
+ EXPECT_TRUE(frame_view->info_button_->IsVisible());
+
+ // When the panel is inactive, the info button is active per the mouse over
+ // the panel or not.
+ browser_view->panel()->Deactivate();
+ EXPECT_FALSE(browser_view->panel()->IsActive());
+
+ mouse_watcher->MoveMouse(true);
+ EXPECT_TRUE(frame_view->info_button_->IsVisible());
+ mouse_watcher->MoveMouse(false);
+ EXPECT_FALSE(frame_view->info_button_->IsVisible());
+}
+
IN_PROC_BROWSER_TEST_F(PanelBrowserViewTest, TitleBarMouseEvent) {
// TODO(jianli): Move the test to platform-independent PanelManager unittest.