diff options
author | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-24 21:53:16 +0000 |
---|---|---|
committer | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-24 21:53:16 +0000 |
commit | 092a2fab32125a0cc94ac732f0ee881c36c3009b (patch) | |
tree | b2ecb21be6877cdc9bd4d927e0cc3d209ef70131 | |
parent | 9b793154110730b74cb18ff2d52211d01d805bb6 (diff) | |
download | chromium_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.cc | 4 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_frame_view.cc | 72 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_frame_view.h | 41 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_view.h | 1 | ||||
-rw-r--r-- | chrome/browser/ui/panels/panel_browser_view_browsertest.cc | 78 |
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. |