diff options
author | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-13 21:10:54 +0000 |
---|---|---|
committer | sadrul@chromium.org <sadrul@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-13 21:10:54 +0000 |
commit | 38c39b06af1141f104b2c35a6975c7861d19ebbe (patch) | |
tree | 13421eae93050987720979267020eb8a0702cebb | |
parent | ec389b968684720aac295eaab274115878ab8112 (diff) | |
download | chromium_src-38c39b06af1141f104b2c35a6975c7861d19ebbe.zip chromium_src-38c39b06af1141f104b2c35a6975c7861d19ebbe.tar.gz chromium_src-38c39b06af1141f104b2c35a6975c7861d19ebbe.tar.bz2 |
Add Widget::Observer for observing Widgets.
Use this new observation technique to avoid a crash in views-desktop when the
active widget is closed.
BUG=none
TEST=Run views_desktop, close a window, click, it doesn't crash!
Review URL: http://codereview.chromium.org/7342015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@92415 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 246 insertions, 42 deletions
diff --git a/chrome/browser/chromeos/frame/panel_browser_view.cc b/chrome/browser/chromeos/frame/panel_browser_view.cc index 8991305..d8b677c8 100644 --- a/chrome/browser/chromeos/frame/panel_browser_view.cc +++ b/chrome/browser/chromeos/frame/panel_browser_view.cc @@ -112,8 +112,12 @@ bool PanelBrowserView::GetSavedWindowBounds(gfx::Rect* bounds) const { return res; } -void PanelBrowserView::OnWindowActivationChanged(bool active) { - ::BrowserView::OnWindowActivationChanged(active); +//////////////////////////////////////////////////////////////////////////////// +// views::Widget::Observer overrides. + +void PanelBrowserView::OnWidgetActivationChanged(views::Widget* widget, + bool active) { + ::BrowserView::OnWidgetActivationChanged(widget, active); if (panel_controller_.get()) { if (active) panel_controller_->OnFocusIn(); diff --git a/chrome/browser/chromeos/frame/panel_browser_view.h b/chrome/browser/chromeos/frame/panel_browser_view.h index a567cae..2c19ae8 100644 --- a/chrome/browser/chromeos/frame/panel_browser_view.h +++ b/chrome/browser/chromeos/frame/panel_browser_view.h @@ -35,7 +35,10 @@ class PanelBrowserView : public ::BrowserView, virtual WindowOpenDisposition GetDispositionForPopupBounds( const gfx::Rect& bounds) OVERRIDE; virtual bool GetSavedWindowBounds(gfx::Rect* bounds) const OVERRIDE; - virtual void OnWindowActivationChanged(bool active) OVERRIDE; + + // views::Widget::Observer overrides. + virtual void OnWidgetActivationChanged(views::Widget* widget, + bool active) OVERRIDE; // BrowserView : TabStripModelObserver overrides. virtual void TabChangedAt(TabContentsWrapper* contents, diff --git a/chrome/browser/chromeos/login/user_controller.cc b/chrome/browser/chromeos/login/user_controller.cc index b513997..8f11e92 100644 --- a/chrome/browser/chromeos/login/user_controller.cc +++ b/chrome/browser/chromeos/login/user_controller.cc @@ -70,10 +70,6 @@ class UserController::ControlsWidgetDelegate : public views::WidgetDelegate { return view_; } - virtual void OnWidgetActivated(bool active) OVERRIDE { - controller_->OnWidgetActivated(active); - } - virtual views::Widget* GetWidget() OVERRIDE { return view_->GetWidget(); } @@ -256,18 +252,6 @@ std::string UserController::GetAccessibleUserLabel() { //////////////////////////////////////////////////////////////////////////////// // UserController, WidgetDelegate implementation: // -void UserController::OnWidgetActivated(bool active) { - is_user_selected_ = active; - if (active) { - delegate_->OnUserSelected(this); - user_view_->SetRemoveButtonVisible( - !is_new_user_ && !is_guest_ && !is_owner_); - } else { - user_view_->SetRemoveButtonVisible(false); - delegate_->ClearErrors(); - } -} - views::Widget* UserController::GetWidget() { return NULL; } @@ -338,6 +322,22 @@ bool UserController::IsUserSelected() const { } //////////////////////////////////////////////////////////////////////////////// +// UserController, views::Widget::Observer implementation: +// +void UserController::OnWidgetActivationChanged(views::Widget* widget, + bool active) { + is_user_selected_ = active; + if (active) { + delegate_->OnUserSelected(this); + user_view_->SetRemoveButtonVisible( + !is_new_user_ && !is_guest_ && !is_owner_); + } else { + user_view_->SetRemoveButtonVisible(false); + delegate_->ClearErrors(); + } +} + +//////////////////////////////////////////////////////////////////////////////// // UserController, private: // void UserController::ConfigureAndShow(Widget* widget, @@ -394,6 +394,7 @@ void UserController::SetupControlsWidget( new ControlsWidgetDelegate(this, control_view)); controls_widget_ = CreateControlsWidget(controls_widget_delegate_.get(), gfx::Rect(*width, *height)); + controls_widget_->AddObserver(this); ConfigureAndShow(controls_widget_, index, WM_IPC_WINDOW_LOGIN_CONTROLS, control_view); } @@ -416,6 +417,7 @@ Widget* UserController::CreateImageWidget(int index) { Widget* widget = CreateClickNotifyingWidget(this, gfx::Rect(user_view_->GetPreferredSize())); + widget->AddObserver(this); ConfigureAndShow(widget, index, WM_IPC_WINDOW_LOGIN_IMAGE, user_view_); return widget; diff --git a/chrome/browser/chromeos/login/user_controller.h b/chrome/browser/chromeos/login/user_controller.h index 4f3ca49..c085caa 100644 --- a/chrome/browser/chromeos/login/user_controller.h +++ b/chrome/browser/chromeos/login/user_controller.h @@ -16,6 +16,7 @@ #include "chrome/browser/chromeos/login/user_view.h" #include "chrome/browser/chromeos/wm_ipc.h" #include "testing/gtest/include/gtest/gtest_prod.h" +#include "views/widget/widget.h" #include "views/widget/widget_delegate.h" namespace views { @@ -31,7 +32,8 @@ class ThrobberManager; // the nececessary set of UserControllers. class UserController : public views::WidgetDelegate, public NewUserView::Delegate, - public UserView::Delegate { + public UserView::Delegate, + public views::Widget::Observer { public: class Delegate { public: @@ -109,7 +111,6 @@ class UserController : public views::WidgetDelegate, std::string GetAccessibleUserLabel(); // views::WidgetDelegate implementation: - virtual void OnWidgetActivated(bool active) OVERRIDE; virtual views::Widget* GetWidget() OVERRIDE; virtual const views::Widget* GetWidget() const OVERRIDE; @@ -129,6 +130,10 @@ class UserController : public views::WidgetDelegate, // UsernameView::Delegate implementation: virtual void OnLocaleChanged() OVERRIDE; + // Overridden from views::Widget::Observer. + virtual void OnWidgetActivationChanged(views::Widget* widget, + bool active) OVERRIDE; + // Padding between the user windows. static const int kPadding; diff --git a/chrome/browser/ui/panels/panel_browser_view.cc b/chrome/browser/ui/panels/panel_browser_view.cc index 838a4d7..922b0d5 100644 --- a/chrome/browser/ui/panels/panel_browser_view.cc +++ b/chrome/browser/ui/panels/panel_browser_view.cc @@ -54,6 +54,7 @@ void PanelBrowserView::Init() { } void PanelBrowserView::Close() { + GetWidget()->RemoveObserver(this); closed_ = true; // Cancel any currently running animation since we're closing down. @@ -108,8 +109,9 @@ bool PanelBrowserView::GetSavedWindowBounds(gfx::Rect* bounds) const { return true; } -void PanelBrowserView::OnWindowActivationChanged(bool active) { - ::BrowserView::OnWindowActivationChanged(active); +void PanelBrowserView::OnWidgetActivationChanged(views::Widget* widget, + bool active) { + ::BrowserView::OnWidgetActivationChanged(widget, active); #if defined(OS_WIN) // The panel window is in focus (actually accepting keystrokes) if it is diff --git a/chrome/browser/ui/panels/panel_browser_view.h b/chrome/browser/ui/panels/panel_browser_view.h index 885ed370..553366a 100644 --- a/chrome/browser/ui/panels/panel_browser_view.h +++ b/chrome/browser/ui/panels/panel_browser_view.h @@ -54,7 +54,6 @@ class PanelBrowserView : public BrowserView, virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE; virtual void UpdateTitleBar() OVERRIDE; virtual bool GetSavedWindowBounds(gfx::Rect* bounds) const OVERRIDE; - virtual void OnWindowActivationChanged(bool active) OVERRIDE; virtual bool AcceleratorPressed(const views::Accelerator& accelerator) OVERRIDE; @@ -63,6 +62,10 @@ class PanelBrowserView : public BrowserView, virtual void OnWorkAreaChanged() OVERRIDE; virtual bool WillProcessWorkAreaChange() const OVERRIDE; + // Overridden from views::Widget::Observer + virtual void OnWidgetActivationChanged(views::Widget* widget, + bool active) OVERRIDE; + // Overridden from NativePanel: virtual void ShowPanel() OVERRIDE; virtual void ShowPanelInactive() OVERRIDE; diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 7cb5cfb..8ec5e24 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc @@ -975,6 +975,7 @@ void BrowserView::DestroyBrowser() { // After this returns other parts of Chrome are going to be shutdown. Close // the window now so that we are deleted immediately and aren't left holding // references to deleted objects. + GetWidget()->RemoveObserver(this); frame_->CloseNow(); } @@ -1664,7 +1665,8 @@ views::ClientView* BrowserView::CreateClientView(views::Widget* widget) { return this; } -void BrowserView::OnWindowActivationChanged(bool active) { +void BrowserView::OnWidgetActivationChanged(views::Widget* widget, + bool active) { if (active) { BrowserList::SetLastActive(browser_.get()); browser_->OnWindowActivated(); @@ -1892,6 +1894,8 @@ ToolbarView* BrowserView::CreateToolbar() const { } void BrowserView::Init() { + GetWidget()->AddObserver(this); + SetLayoutManager(CreateLayoutManager()); // Stow a pointer to this object onto the window handle so that we can get at // it later when all we have is a native view. diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h index 9da0d76..6610151 100644 --- a/chrome/browser/ui/views/frame/browser_view.h +++ b/chrome/browser/ui/views/frame/browser_view.h @@ -85,6 +85,7 @@ class BrowserView : public BrowserBubbleHost, public TabStripModelObserver, public ui::SimpleMenuModel::Delegate, public views::WidgetDelegate, + public views::Widget::Observer, public views::ClientView, public InfoBarContainer::Delegate, public views::SingleSplitView::Observer { @@ -395,12 +396,15 @@ class BrowserView : public BrowserBubbleHost, virtual bool GetSavedMaximizedState(bool* maximized) const OVERRIDE; virtual views::View* GetContentsView() OVERRIDE; virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE; - virtual void OnWindowActivationChanged(bool active) OVERRIDE; virtual void OnWindowBeginUserBoundsChange() OVERRIDE; virtual void OnWidgetMove() OVERRIDE; virtual views::Widget* GetWidget() OVERRIDE; virtual const views::Widget* GetWidget() const OVERRIDE; + // Overridden from views::Widget::Observer + virtual void OnWidgetActivationChanged(views::Widget* widget, + bool active) OVERRIDE; + // Overridden from views::ClientView: virtual bool CanClose() OVERRIDE; virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE; diff --git a/views/desktop/desktop_window_view.cc b/views/desktop/desktop_window_view.cc index 050c64e..e291bfc 100644 --- a/views/desktop/desktop_window_view.cc +++ b/views/desktop/desktop_window_view.cc @@ -124,6 +124,8 @@ void DesktopWindowView::ActivateWidget(Widget* widget) { widget->MoveToTop(); active_widget_ = static_cast<NativeWidgetViews*>(widget->native_widget()); active_widget_->OnActivate(true); + if (!widget->HasObserver(this)) + widget->AddObserver(this); } } @@ -189,5 +191,19 @@ View* DesktopWindowView::GetContentsView() { return this; } +void DesktopWindowView::OnWidgetClosing(Widget* widget) { + if (active_widget_ && static_cast<internal::NativeWidgetPrivate*> + (active_widget_)->GetWidget() == widget) + active_widget_ = NULL; +} + +void DesktopWindowView::OnWidgetVisibilityChanged(Widget* widget, + bool visible) { +} + +void DesktopWindowView::OnWidgetActivationChanged(Widget* widget, + bool active) { +} + } // namespace desktop } // namespace views diff --git a/views/desktop/desktop_window_view.h b/views/desktop/desktop_window_view.h index 011f4be..b222f13 100644 --- a/views/desktop/desktop_window_view.h +++ b/views/desktop/desktop_window_view.h @@ -6,6 +6,7 @@ #define VIEWS_DESKTOP_DESKTOP_WINDOW_H_ #include "views/view.h" +#include "views/widget/widget.h" #include "views/widget/widget_delegate.h" namespace views { @@ -13,7 +14,8 @@ class NativeWidgetViews; namespace desktop { -class DesktopWindowView : public WidgetDelegateView { +class DesktopWindowView : public WidgetDelegateView, + public Widget::Observer { public: static DesktopWindowView* desktop_window_view; @@ -45,6 +47,11 @@ class DesktopWindowView : public WidgetDelegateView { virtual void WindowClosing() OVERRIDE; virtual View* GetContentsView() OVERRIDE; + // Overridden from Widget::Observer. + virtual void OnWidgetClosing(Widget* widget) OVERRIDE; + virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) OVERRIDE; + virtual void OnWidgetActivationChanged(Widget* widget, bool active) OVERRIDE; + NativeWidgetViews* active_widget_; DISALLOW_COPY_AND_ASSIGN(DesktopWindowView); diff --git a/views/widget/native_widget_delegate.h b/views/widget/native_widget_delegate.h index 41b4246..20456fb 100644 --- a/views/widget/native_widget_delegate.h +++ b/views/widget/native_widget_delegate.h @@ -49,6 +49,9 @@ class NativeWidgetDelegate { virtual void OnNativeFocus(gfx::NativeView focused_view) = 0; virtual void OnNativeBlur(gfx::NativeView focused_view) = 0; + // Called when the window is shown/hidden. + virtual void OnNativeWidgetVisibilityChanged(bool visible) = 0; + // Called when the native widget is created. virtual void OnNativeWidgetCreated() = 0; diff --git a/views/widget/native_widget_gtk.cc b/views/widget/native_widget_gtk.cc index e474f71..14a4f31 100644 --- a/views/widget/native_widget_gtk.cc +++ b/views/widget/native_widget_gtk.cc @@ -1196,6 +1196,7 @@ void NativeWidgetGtk::Show() { gtk_widget_show(widget_); if (widget_->window) gdk_window_raise(widget_->window); + delegate_->OnNativeWidgetVisibilityChanged(true); } } @@ -1204,6 +1205,7 @@ void NativeWidgetGtk::Hide() { gtk_widget_hide(widget_); if (widget_->window) gdk_window_lower(widget_->window); + delegate_->OnNativeWidgetVisibilityChanged(false); } } diff --git a/views/widget/native_widget_view.cc b/views/widget/native_widget_view.cc index 8983ec6..9a2af69 100644 --- a/views/widget/native_widget_view.cc +++ b/views/widget/native_widget_view.cc @@ -118,6 +118,11 @@ bool NativeWidgetView::OnMouseWheel(const MouseWheelEvent& event) { return delegate()->OnMouseEvent(event); } +void NativeWidgetView::VisibilityChanged(View* starting_from, + bool visible) { + delegate()->OnNativeWidgetVisibilityChanged(visible); +} + void NativeWidgetView::OnFocus() { // TODO(beng): check if we have to do this. //delegate()->OnNativeFocus(NULL); diff --git a/views/widget/native_widget_view.h b/views/widget/native_widget_view.h index a0e7fd4..c99d5fc 100644 --- a/views/widget/native_widget_view.h +++ b/views/widget/native_widget_view.h @@ -60,6 +60,7 @@ class NativeWidgetView : public View { virtual bool OnKeyPressed(const KeyEvent& event) OVERRIDE; virtual bool OnKeyReleased(const KeyEvent& event) OVERRIDE; virtual bool OnMouseWheel(const MouseWheelEvent& event) OVERRIDE; + virtual void VisibilityChanged(View* starting_from, bool is_visible) OVERRIDE; virtual void OnFocus() OVERRIDE; virtual void OnBlur() OVERRIDE; virtual std::string GetClassName() const OVERRIDE; diff --git a/views/widget/native_widget_views.cc b/views/widget/native_widget_views.cc index 2f1476d..0a03e77 100644 --- a/views/widget/native_widget_views.cc +++ b/views/widget/native_widget_views.cc @@ -307,6 +307,7 @@ bool NativeWidgetViews::IsVisible() const { } void NativeWidgetViews::Activate() { + // Enable WidgetObserverTest.ActivationChange when this is implemented. NOTIMPLEMENTED(); } @@ -358,7 +359,7 @@ void NativeWidgetViews::Minimize() { } bool NativeWidgetViews::IsMaximized() const { - NOTIMPLEMENTED(); + // NOTIMPLEMENTED(); return false; } diff --git a/views/widget/native_widget_win.cc b/views/widget/native_widget_win.cc index 684edec..98c080c 100644 --- a/views/widget/native_widget_win.cc +++ b/views/widget/native_widget_win.cc @@ -2065,6 +2065,10 @@ void NativeWidgetWin::OnWindowPosChanging(WINDOWPOS* window_pos) { void NativeWidgetWin::OnWindowPosChanged(WINDOWPOS* window_pos) { if (DidClientAreaSizeChange(window_pos)) ClientAreaSizeChanged(); + if (window_pos->flags & SWP_SHOWWINDOW) + delegate_->OnNativeWidgetVisibilityChanged(true); + else if (window_pos->flags & SWP_HIDEWINDOW) + delegate_->OnNativeWidgetVisibilityChanged(false); SetMsgHandled(FALSE); } diff --git a/views/widget/widget.cc b/views/widget/widget.cc index dcca28c..047cf05 100644 --- a/views/widget/widget.cc +++ b/views/widget/widget.cc @@ -293,6 +293,18 @@ gfx::NativeWindow Widget::GetNativeWindow() const { return native_widget_->GetNativeWindow(); } +void Widget::AddObserver(Widget::Observer* observer) { + observers_.AddObserver(observer); +} + +void Widget::RemoveObserver(Widget::Observer* observer) { + observers_.RemoveObserver(observer); +} + +bool Widget::HasObserver(Widget::Observer* observer) { + return observers_.HasObserver(observer); +} + bool Widget::GetAccelerator(int cmd_id, ui::Accelerator* accelerator) { return false; } @@ -732,9 +744,8 @@ void Widget::OnNativeWidgetActivationChanged(bool active) { if (!active) SaveWindowPosition(); - // TODO(beng): merge these two. - widget_delegate_->OnWidgetActivated(active); - widget_delegate_->OnWindowActivationChanged(active); + FOR_EACH_OBSERVER(Observer, observers_, + OnWidgetActivationChanged(this, active)); } void Widget::OnNativeFocus(gfx::NativeView focused_view) { @@ -749,6 +760,11 @@ void Widget::OnNativeBlur(gfx::NativeView focused_view) { focused_view); } +void Widget::OnNativeWidgetVisibilityChanged(bool visible) { + FOR_EACH_OBSERVER(Observer, observers_, + OnWidgetVisibilityChanged(this, visible)); +} + void Widget::OnNativeWidgetCreated() { if (GetTopLevelWidget() == this) { // Only the top level Widget in a native widget hierarchy has a focus @@ -766,6 +782,7 @@ void Widget::OnNativeWidgetCreated() { } void Widget::OnNativeWidgetDestroying() { + FOR_EACH_OBSERVER(Observer, observers_, OnWidgetClosing(this)); if (non_client_view_) non_client_view_->WindowClosing(); widget_delegate_->WindowClosing(); diff --git a/views/widget/widget.h b/views/widget/widget.h index bc16530..99e706f 100644 --- a/views/widget/widget.h +++ b/views/widget/widget.h @@ -9,6 +9,7 @@ #include <stack> #include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" #include "ui/base/accessibility/accessibility_types.h" #include "ui/gfx/native_widget_types.h" #include "ui/gfx/rect.h" @@ -89,6 +90,14 @@ class RootView; class Widget : public internal::NativeWidgetDelegate, public FocusTraversable { public: + // Observers can listen to various events on the Widgets. + class Observer { + public: + virtual void OnWidgetClosing(Widget* widget) {} + virtual void OnWidgetVisibilityChanged(Widget* widget, bool visible) {} + virtual void OnWidgetActivationChanged(Widget* widget, bool active) {} + }; + typedef std::set<Widget*> Widgets; enum FrameType { @@ -221,6 +230,11 @@ class Widget : public internal::NativeWidgetDelegate, // TYPE_WINDOW. gfx::NativeWindow GetNativeWindow() const; + // Add/remove observer. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + bool HasObserver(Observer* observer); + // Returns the accelerator given a command id. Returns false if there is // no accelerator associated with a given id, which is a common condition. virtual bool GetAccelerator(int cmd_id, ui::Accelerator* accelerator); @@ -521,6 +535,7 @@ class Widget : public internal::NativeWidgetDelegate, virtual void OnNativeWidgetActivationChanged(bool active) OVERRIDE; virtual void OnNativeFocus(gfx::NativeView focused_view) OVERRIDE; virtual void OnNativeBlur(gfx::NativeView focused_view) OVERRIDE; + virtual void OnNativeWidgetVisibilityChanged(bool visible) OVERRIDE; virtual void OnNativeWidgetCreated() OVERRIDE; virtual void OnNativeWidgetDestroying() OVERRIDE; virtual void OnNativeWidgetDestroyed() OVERRIDE; @@ -591,6 +606,8 @@ class Widget : public internal::NativeWidgetDelegate, internal::NativeWidgetPrivate* native_widget_; + ObserverList<Observer> observers_; + // Non-owned pointer to the Widget's delegate. May be NULL if no delegate is // being used. WidgetDelegate* widget_delegate_; diff --git a/views/widget/widget_delegate.cc b/views/widget/widget_delegate.cc index f2f16b7..b302254 100644 --- a/views/widget/widget_delegate.cc +++ b/views/widget/widget_delegate.cc @@ -18,9 +18,6 @@ namespace views { WidgetDelegate::WidgetDelegate() : default_contents_view_(NULL) { } -void WidgetDelegate::OnWidgetActivated(bool active) { -} - void WidgetDelegate::OnWidgetMove() { } diff --git a/views/widget/widget_delegate.h b/views/widget/widget_delegate.h index 6a6b254..8dc21bc 100644 --- a/views/widget/widget_delegate.h +++ b/views/widget/widget_delegate.h @@ -31,11 +31,6 @@ class WidgetDelegate { public: WidgetDelegate(); - // Called whenever the widget is activated or deactivated. - // TODO(beng): This should be consolidated with - // WindowDelegate::OnWindowActivationChanged(). - virtual void OnWidgetActivated(bool active); - // Called whenever the widget's position changes. virtual void OnWidgetMove(); @@ -127,9 +122,6 @@ class WidgetDelegate { // this time if necessary. virtual void DeleteDelegate() {} - // Called when the window's activation state changes. - virtual void OnWindowActivationChanged(bool active) {} - // Called when the user begins/ends to change the bounds of the window. virtual void OnWindowBeginUserBoundsChange() {} virtual void OnWindowEndUserBoundsChange() {} diff --git a/views/widget/widget_unittest.cc b/views/widget/widget_unittest.cc index a6e219d..4710348 100644 --- a/views/widget/widget_unittest.cc +++ b/views/widget/widget_unittest.cc @@ -398,5 +398,120 @@ TEST_F(WidgetOwnershipTest, EXPECT_TRUE(state.native_widget_deleted); } +//////////////////////////////////////////////////////////////////////////////// +// Widget observer tests. +// + +class WidgetObserverTest : public WidgetTest, + Widget::Observer { + public: + WidgetObserverTest() + : active_(NULL), + widget_closed_(NULL), + widget_activated_(NULL), + widget_shown_(NULL), + widget_hidden_(NULL) { + } + + virtual ~WidgetObserverTest() {} + + virtual void OnWidgetClosing(Widget* widget) OVERRIDE { + if (active_ == widget) + active_ = NULL; + widget_closed_ = widget; + } + + virtual void OnWidgetActivationChanged(Widget* widget, + bool active) OVERRIDE { + if (active) { + widget_activated_ = widget; + active_ = widget; + } else + widget_deactivated_ = widget; + } + + virtual void OnWidgetVisibilityChanged(Widget* widget, + bool visible) OVERRIDE { + if (visible) + widget_shown_ = widget; + else + widget_hidden_ = widget; + } + + void reset() { + active_ = NULL; + widget_closed_ = NULL; + widget_activated_ = NULL; + widget_deactivated_ = NULL; + widget_shown_ = NULL; + widget_hidden_ = NULL; + } + + Widget* NewWidget() { + Widget* widget = CreateChildNativeWidgetViews(); + widget->AddObserver(this); + return widget; + } + + const Widget* active() const { return active_; } + const Widget* widget_closed() const { return widget_closed_; } + const Widget* widget_activated() const { return widget_activated_; } + const Widget* widget_deactivated() const { return widget_deactivated_; } + const Widget* widget_shown() const { return widget_shown_; } + const Widget* widget_hidden() const { return widget_hidden_; } + + private: + + Widget* active_; + + Widget* widget_closed_; + Widget* widget_activated_; + Widget* widget_deactivated_; + Widget* widget_shown_; + Widget* widget_hidden_; +}; + +// TODO: This test should be enabled when NativeWidgetViews::Activate is +// implemented. +TEST_F(WidgetObserverTest, DISABLED_ActivationChange) { + Widget* toplevel = CreateTopLevelPlatformWidget(); + views_delegate.set_default_parent_view(toplevel->GetRootView()); + + Widget* child1 = NewWidget(); + Widget* child2 = NewWidget(); + + reset(); + + child1->Activate(); + EXPECT_EQ(child1, widget_activated()); + + child2->Activate(); + EXPECT_EQ(child1, widget_deactivated()); + EXPECT_EQ(child2, widget_activated()); + EXPECT_EQ(child2, active()); +} + +TEST_F(WidgetObserverTest, VisibilityChange) { + Widget* toplevel = CreateTopLevelPlatformWidget(); + views_delegate.set_default_parent_view(toplevel->GetRootView()); + + Widget* child1 = NewWidget(); + Widget* child2 = NewWidget(); + + reset(); + + child1->Hide(); + EXPECT_EQ(child1, widget_hidden()); + + child2->Hide(); + EXPECT_EQ(child2, widget_hidden()); + + child1->Show(); + EXPECT_EQ(child1, widget_shown()); + + child2->Show(); + EXPECT_EQ(child2, widget_shown()); +} + } // namespace } // namespace views |