summaryrefslogtreecommitdiffstats
path: root/ash/system
diff options
context:
space:
mode:
authormukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-09 01:30:49 +0000
committermukai@chromium.org <mukai@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-09 01:30:49 +0000
commite66d28be8f2cf6cb25dc8976e02fafcd3fb0d6ef (patch)
treeda4f5c963951f632f25855240979ddf33b3e7885 /ash/system
parente26f032cb91a7fd33ec93b4d13dffa0b2568b3ec (diff)
downloadchromium_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.cc2
-rw-r--r--ash/system/tray/tray_background_view.h3
-rw-r--r--ash/system/tray/tray_bubble_wrapper.cc4
-rw-r--r--ash/system/tray/tray_bubble_wrapper.h6
-rw-r--r--ash/system/tray/tray_event_filter.cc73
-rw-r--r--ash/system/tray/tray_event_filter.h9
-rw-r--r--ash/system/web_notification/web_notification_tray.cc3
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_;