diff options
author | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-09 01:30:49 +0000 |
---|---|---|
committer | mukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-09 01:30:49 +0000 |
commit | e66d28be8f2cf6cb25dc8976e02fafcd3fb0d6ef (patch) | |
tree | da4f5c963951f632f25855240979ddf33b3e7885 /ash/system | |
parent | e26f032cb91a7fd33ec93b4d13dffa0b2568b3ec (diff) | |
download | chromium_src-e66d28be8f2cf6cb25dc8976e02fafcd3fb0d6ef.zip chromium_src-e66d28be8f2cf6cb25dc8976e02fafcd3fb0d6ef.tar.gz chromium_src-e66d28be8f2cf6cb25dc8976e02fafcd3fb0d6ef.tar.bz2 |
Allows tray_event_filter to handle multiple bubbles.
Currently tray_event_filter is owned by tray_bubble_wrapper, but
its location event handler wants to care about multiple bubble wrappers.
A typical situation is that the system notification (like power notification)
appears when the detailed view is opened. Click inside of the detailed view
will be handled by tray_event_filter for the power notification and it will
close the detailed view through ClickOutsideBubble() unexpectedly.
Now the tray_event_filter is owned by tray_background_view and can handle
outside-detection for all of bubbles.
BUG=167118
Review URL: https://chromiumcodereview.appspot.com/12207049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181581 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ash/system')
-rw-r--r-- | ash/system/tray/tray_background_view.cc | 2 | ||||
-rw-r--r-- | ash/system/tray/tray_background_view.h | 3 | ||||
-rw-r--r-- | ash/system/tray/tray_bubble_wrapper.cc | 4 | ||||
-rw-r--r-- | ash/system/tray/tray_bubble_wrapper.h | 6 | ||||
-rw-r--r-- | ash/system/tray/tray_event_filter.cc | 73 | ||||
-rw-r--r-- | ash/system/tray/tray_event_filter.h | 9 | ||||
-rw-r--r-- | ash/system/web_notification/web_notification_tray.cc | 3 |
7 files changed, 69 insertions, 31 deletions
diff --git a/ash/system/tray/tray_background_view.cc b/ash/system/tray/tray_background_view.cc index ec2cd05..f4c2907 100644 --- a/ash/system/tray/tray_background_view.cc +++ b/ash/system/tray/tray_background_view.cc @@ -12,6 +12,7 @@ #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_delegate.h" #include "ash/system/tray/tray_constants.h" +#include "ash/system/tray/tray_event_filter.h" #include "ash/wm/property_util.h" #include "ash/wm/shelf_layout_manager.h" #include "ash/wm/window_animations.h" @@ -181,6 +182,7 @@ TrayBackgroundView::TrayBackgroundView( tray_container_ = new TrayContainer(shelf_alignment_); SetContents(tray_container_); + tray_event_filter_.reset(new TrayEventFilter); } TrayBackgroundView::~TrayBackgroundView() { diff --git a/ash/system/tray/tray_background_view.h b/ash/system/tray/tray_background_view.h index ecd78e5..b5b14ef 100644 --- a/ash/system/tray/tray_background_view.h +++ b/ash/system/tray/tray_background_view.h @@ -16,6 +16,7 @@ namespace internal { class ShelfLayoutManager; class StatusAreaWidget; +class TrayEventFilter; class TrayBackground; // Base class for children of StatusAreaWidget: SystemTray, WebNotificationTray. // This class handles setting and animating the background when the Launcher @@ -128,6 +129,7 @@ class ASH_EXPORT TrayBackgroundView : public internal::ActionableView, } TrayContainer* tray_container() const { return tray_container_; } ShelfAlignment shelf_alignment() const { return shelf_alignment_; } + TrayEventFilter* tray_event_filter() { return tray_event_filter_.get(); } ShelfLayoutManager* GetShelfLayoutManager(); @@ -156,6 +158,7 @@ class ASH_EXPORT TrayBackgroundView : public internal::ActionableView, internal::BackgroundAnimator hide_background_animator_; internal::BackgroundAnimator hover_background_animator_; scoped_ptr<TrayWidgetObserver> widget_observer_; + scoped_ptr<TrayEventFilter> tray_event_filter_; DISALLOW_COPY_AND_ASSIGN(TrayBackgroundView); }; diff --git a/ash/system/tray/tray_bubble_wrapper.cc b/ash/system/tray/tray_bubble_wrapper.cc index 01b4ba0..75651c2 100644 --- a/ash/system/tray/tray_bubble_wrapper.cc +++ b/ash/system/tray/tray_bubble_wrapper.cc @@ -26,11 +26,11 @@ TrayBubbleWrapper::TrayBubbleWrapper(TrayBackgroundView* tray, tray_->UpdateBubbleViewArrow(bubble_view_); bubble_view_->InitializeAndShowBubble(); - tray_event_filter_.reset(new TrayEventFilter(this)); + tray->tray_event_filter()->AddWrapper(this); } TrayBubbleWrapper::~TrayBubbleWrapper() { - tray_event_filter_.reset(); + tray_->tray_event_filter()->RemoveWrapper(this); if (bubble_widget_) { bubble_widget_->RemoveObserver(this); bubble_widget_->Close(); diff --git a/ash/system/tray/tray_bubble_wrapper.h b/ash/system/tray/tray_bubble_wrapper.h index 3af47d5..baa5416 100644 --- a/ash/system/tray/tray_bubble_wrapper.h +++ b/ash/system/tray/tray_bubble_wrapper.h @@ -30,15 +30,15 @@ class TrayBubbleWrapper : public views::WidgetObserver { // views::WidgetObserver overrides: virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE; + const TrayBackgroundView* tray() const { return tray_; } TrayBackgroundView* tray() { return tray_; } - views::TrayBubbleView* bubble_view() { return bubble_view_; } - views::Widget* bubble_widget() { return bubble_widget_; } + const views::TrayBubbleView* bubble_view() const { return bubble_view_; } + const views::Widget* bubble_widget() const { return bubble_widget_; } private: TrayBackgroundView* tray_; views::TrayBubbleView* bubble_view_; // unowned views::Widget* bubble_widget_; - scoped_ptr<TrayEventFilter> tray_event_filter_; DISALLOW_COPY_AND_ASSIGN(TrayBubbleWrapper); }; diff --git a/ash/system/tray/tray_event_filter.cc b/ash/system/tray/tray_event_filter.cc index 48211ea..f2192e5 100644 --- a/ash/system/tray/tray_event_filter.cc +++ b/ash/system/tray/tray_event_filter.cc @@ -21,13 +21,24 @@ namespace ash { namespace internal { -TrayEventFilter::TrayEventFilter(TrayBubbleWrapper* wrapper) - : wrapper_(wrapper) { - ash::Shell::GetInstance()->AddPreTargetHandler(this); +TrayEventFilter::TrayEventFilter() { } TrayEventFilter::~TrayEventFilter() { - ash::Shell::GetInstance()->RemovePreTargetHandler(this); + DCHECK(wrappers_.empty()); +} + +void TrayEventFilter::AddWrapper(TrayBubbleWrapper* wrapper) { + bool was_empty = wrappers_.empty(); + wrappers_.insert(wrapper); + if (was_empty && !wrappers_.empty()) + ash::Shell::GetInstance()->AddPreTargetHandler(this); +} + +void TrayEventFilter::RemoveWrapper(TrayBubbleWrapper* wrapper) { + wrappers_.erase(wrapper); + if (wrappers_.empty()) + ash::Shell::GetInstance()->RemovePreTargetHandler(this); } void TrayEventFilter::OnMouseEvent(ui::MouseEvent* event) { @@ -53,30 +64,50 @@ bool TrayEventFilter::ProcessLocatedEvent(ui::LocatedEvent* event) { return false; } } - views::Widget* bubble_widget = wrapper_->bubble_widget(); - if (!bubble_widget) - return false; - gfx::Rect bounds = bubble_widget->GetWindowBoundsInScreen(); - bounds.Inset(wrapper_->bubble_view()->GetBorderInsets()); - aura::RootWindow* root = bubble_widget->GetNativeView()->GetRootWindow(); - aura::client::ScreenPositionClient* screen_position_client = - aura::client::GetScreenPositionClient(root); - gfx::Point screen_point(event->root_location()); - screen_position_client->ConvertPointToScreen(root, &screen_point); + // Check the boundary for all wrappers, and do not handle the event if it + // happens inside of any of those wrappers. + for (std::set<TrayBubbleWrapper*>::const_iterator iter = wrappers_.begin(); + iter != wrappers_.end(); ++iter) { + const TrayBubbleWrapper* wrapper = *iter; + const views::Widget* bubble_widget = wrapper->bubble_widget(); + if (!bubble_widget) + continue; + + gfx::Rect bounds = bubble_widget->GetWindowBoundsInScreen(); + bounds.Inset(wrapper->bubble_view()->GetBorderInsets()); + aura::RootWindow* root = bubble_widget->GetNativeView()->GetRootWindow(); + aura::client::ScreenPositionClient* screen_position_client = + aura::client::GetScreenPositionClient(root); + gfx::Point screen_point(event->root_location()); + screen_position_client->ConvertPointToScreen(root, &screen_point); - if (bounds.Contains(screen_point)) - return false; - if (wrapper_->tray()) { - // If the user clicks on the parent tray, don't process the event here, - // let the tray logic handle the event and determine show/hide behavior. - bounds = wrapper_->tray()->GetBoundsInScreen(); if (bounds.Contains(screen_point)) return false; + if (wrapper->tray()) { + // If the user clicks on the parent tray, don't process the event here, + // let the tray logic handle the event and determine show/hide behavior. + bounds = wrapper->tray()->GetBoundsInScreen(); + if (bounds.Contains(screen_point)) + return false; + } } + // Handle clicking outside the bubble and tray and return true if the // event was handled. - return wrapper_->tray()->ClickedOutsideBubble(); + // Cannot iterate |wrappers_| directly, because clicking outside will remove + // the wrapper, which shrinks |wrappers_| unsafely. + std::set<TrayBackgroundView*> trays; + for (std::set<TrayBubbleWrapper*>::iterator iter = wrappers_.begin(); + iter != wrappers_.end(); ++iter) { + trays.insert((*iter)->tray()); + } + bool handled = false; + for (std::set<TrayBackgroundView*>::iterator iter = trays.begin(); + iter != trays.end(); ++iter) { + handled |= (*iter)->ClickedOutsideBubble(); + } + return handled; } } // namespace internal diff --git a/ash/system/tray/tray_event_filter.h b/ash/system/tray/tray_event_filter.h index 5e7fa6f..5ee8e27 100644 --- a/ash/system/tray/tray_event_filter.h +++ b/ash/system/tray/tray_event_filter.h @@ -5,6 +5,8 @@ #ifndef ASH_SYSTEM_TRAY_TRAY_EVENT_FILTER_H_ #define ASH_SYSTEM_TRAY_TRAY_EVENT_FILTER_H_ +#include <set> + #include "base/basictypes.h" #include "ui/base/events/event.h" #include "ui/base/events/event_handler.h" @@ -22,9 +24,12 @@ class TrayBubbleWrapper; class TrayEventFilter : public ui::EventHandler { public: - explicit TrayEventFilter(TrayBubbleWrapper* wrapper); + explicit TrayEventFilter(); virtual ~TrayEventFilter(); + void AddWrapper(TrayBubbleWrapper* wrapper); + void RemoveWrapper(TrayBubbleWrapper* wrapper); + // Overridden from ui::EventHandler. virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; @@ -33,7 +38,7 @@ class TrayEventFilter : public ui::EventHandler { // Returns true if the event is handled. bool ProcessLocatedEvent(ui::LocatedEvent* event); - TrayBubbleWrapper* wrapper_; + std::set<TrayBubbleWrapper*> wrappers_; DISALLOW_COPY_AND_ASSIGN(TrayEventFilter); }; diff --git a/ash/system/web_notification/web_notification_tray.cc b/ash/system/web_notification/web_notification_tray.cc index 4cb6f3b..3db837c 100644 --- a/ash/system/web_notification/web_notification_tray.cc +++ b/ash/system/web_notification/web_notification_tray.cc @@ -74,9 +74,6 @@ class WebNotificationBubbleWrapper { // Convenience accessors. views::TrayBubbleView* bubble_view() const { return bubble_->bubble_view(); } - views::Widget* bubble_widget() const { - return bubble_wrapper_->bubble_widget(); - } private: scoped_ptr<message_center::MessageBubbleBase> bubble_; |