Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1697)

Unified Diff: chrome/browser/notifications/balloon_collection_impl.cc

Issue 8503037: Fix the problem that notifications and panels overlap. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix per feedback Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/notifications/balloon_collection_impl.cc
diff --git a/chrome/browser/notifications/balloon_collection_impl.cc b/chrome/browser/notifications/balloon_collection_impl.cc
index 9d234c222aa41ebe7753061c00b7ec4f1c3bccbc..173c78caba6898a8077e4e7417204a0e0fc3d279 100644
--- a/chrome/browser/notifications/balloon_collection_impl.cc
+++ b/chrome/browser/notifications/balloon_collection_impl.cc
@@ -10,7 +10,13 @@
#include "chrome/browser/notifications/balloon.h"
#include "chrome/browser/notifications/balloon_host.h"
#include "chrome/browser/notifications/notification.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/panels/panel_manager.h"
+#include "chrome/browser/ui/panels/panel.h"
#include "chrome/browser/ui/window_sizer.h"
+#include "chrome/common/chrome_notification_types.h"
+#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/notification_service.h"
#include "ui/gfx/rect.h"
#include "ui/gfx/size.h"
@@ -27,6 +33,9 @@ const int kMinAllowedBalloonCount = 2;
// there is a relayout, in milliseconds.
const int kRepositionDelay = 300;
+// The spacing between the balloon and the panel.
+const int kVerticalSpacingBetweenBalloonAndPanel = 5;
+
} // namespace
BalloonCollectionImpl::BalloonCollectionImpl()
@@ -35,6 +44,12 @@ BalloonCollectionImpl::BalloonCollectionImpl()
added_as_message_loop_observer_(false)
#endif
{
+ registrar_.Add(this, chrome::NOTIFICATION_PANEL_ADDED,
+ content::NotificationService::AllSources());
+ registrar_.Add(this, chrome::NOTIFICATION_PANEL_REMOVED,
+ content::NotificationService::AllSources());
+ registrar_.Add(this, chrome::NOTIFICATION_PANEL_CHANGED_BOUNDS,
+ content::NotificationService::AllSources());
SetPositionPreference(BalloonCollection::DEFAULT_POSITION);
}
@@ -153,6 +168,26 @@ const BalloonCollection::Balloons& BalloonCollectionImpl::GetActiveBalloons() {
return base_.balloons();
}
+void BalloonCollectionImpl::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ gfx::Rect bounds;
+ switch (type) {
+ case chrome::NOTIFICATION_PANEL_CHANGED_BOUNDS:
+ bounds = content::Source<Panel>(source).ptr()->GetBounds();
+ // Fall through.
+ case chrome::NOTIFICATION_PANEL_ADDED:
+ case chrome::NOTIFICATION_PANEL_REMOVED:
+ if (layout_.ComputeOffsetToMoveAbovePanels(bounds))
+ PositionBalloons(true);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) {
const Balloons& balloons = base_.balloons();
@@ -231,7 +266,9 @@ void BalloonCollectionImpl::HandleMouseMoveEvent() {
}
#endif
-BalloonCollectionImpl::Layout::Layout() : placement_(INVALID) {
+BalloonCollectionImpl::Layout::Layout()
+ : placement_(INVALID),
+ offset_to_move_above_panels_(0) {
RefreshSystemMetrics();
}
@@ -245,24 +282,30 @@ void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size,
}
gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const {
+ // For lower-left and lower-right positioning, we need to add an offset
+ // to ensure balloons to stay on top of panels to avoid overlapping.
int x = 0;
int y = 0;
switch (placement_) {
- case VERTICALLY_FROM_TOP_LEFT:
+ case VERTICALLY_FROM_TOP_LEFT: {
x = work_area_.x() + HorizontalEdgeMargin();
- y = work_area_.y() + VerticalEdgeMargin();
+ y = work_area_.y() + VerticalEdgeMargin() + offset_to_move_above_panels_;
break;
- case VERTICALLY_FROM_TOP_RIGHT:
+ }
+ case VERTICALLY_FROM_TOP_RIGHT: {
x = work_area_.right() - HorizontalEdgeMargin();
- y = work_area_.y() + VerticalEdgeMargin();
+ y = work_area_.y() + VerticalEdgeMargin() + offset_to_move_above_panels_;
break;
+ }
case VERTICALLY_FROM_BOTTOM_LEFT:
x = work_area_.x() + HorizontalEdgeMargin();
- y = work_area_.bottom() - VerticalEdgeMargin();
+ y = work_area_.bottom() - VerticalEdgeMargin() -
+ offset_to_move_above_panels_;
break;
case VERTICALLY_FROM_BOTTOM_RIGHT:
x = work_area_.right() - HorizontalEdgeMargin();
- y = work_area_.bottom() - VerticalEdgeMargin();
+ y = work_area_.bottom() - VerticalEdgeMargin() -
+ offset_to_move_above_panels_;
break;
default:
NOTREACHED();
@@ -311,30 +354,21 @@ gfx::Point BalloonCollectionImpl::Layout::NextPosition(
}
gfx::Point BalloonCollectionImpl::Layout::OffScreenLocation() const {
- int x = 0;
- int y = 0;
+ gfx::Point location = GetLayoutOrigin();
switch (placement_) {
case VERTICALLY_FROM_TOP_LEFT:
- x = work_area_.x() + HorizontalEdgeMargin();
- y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin();
- break;
- case VERTICALLY_FROM_TOP_RIGHT:
- x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin();
- y = work_area_.y() + kBalloonMaxHeight + VerticalEdgeMargin();
- break;
case VERTICALLY_FROM_BOTTOM_LEFT:
- x = work_area_.x() + HorizontalEdgeMargin();
- y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin();
+ location.Offset(0, kBalloonMaxHeight);
break;
+ case VERTICALLY_FROM_TOP_RIGHT:
case VERTICALLY_FROM_BOTTOM_RIGHT:
- x = work_area_.right() - kBalloonMaxWidth - HorizontalEdgeMargin();
- y = work_area_.bottom() + kBalloonMaxHeight + VerticalEdgeMargin();
+ location.Offset(-kBalloonMaxWidth, kBalloonMaxHeight);
break;
default:
NOTREACHED();
break;
}
- return gfx::Point(x, y);
+ return location;
}
bool BalloonCollectionImpl::Layout::RequiresOffsets() const {
@@ -363,6 +397,68 @@ gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits(
std::min(max_balloon_height(), size.height())));
}
+bool BalloonCollectionImpl::Layout::ComputeOffsetToMoveAbovePanels(
+ const gfx::Rect& panel_bounds) {
+ const PanelManager::Panels& panels = PanelManager::GetInstance()->panels();
+ int offset_to_move_above_panels = 0;
+
+ // The offset is the maximum height of panels that could overlap with the
+ // balloons.
+ if (NeedToMoveAboveLeftSidePanels()) {
+ // If the affecting panel does not lie in the balloon area, no need to
+ // update the offset.
+ if (!panel_bounds.IsEmpty() &&
+ (panel_bounds.right() <= work_area_.x() ||
+ panel_bounds.x() >= work_area_.x() + max_balloon_width())) {
+ return false;
+ }
+
+ for (PanelManager::Panels::const_reverse_iterator iter = panels.rbegin();
+ iter != panels.rend(); ++iter) {
+ // No need to check panels beyond the area occupied by the balloons.
+ if ((*iter)->GetBounds().x() >= work_area_.x() + max_balloon_width())
jennb 2011/11/11 23:02:43 FYI, until your overflow changes are in, this will
+ break;
+
+ int current_height = (*iter)->GetBounds().height();
+ if (current_height > offset_to_move_above_panels)
+ offset_to_move_above_panels = current_height;
+ }
+ } else if (NeedToMoveAboveRightSidePanels()) {
+ // If the affecting panel does not lie in the balloon area, no need to
+ // update the offset.
+ if (!panel_bounds.IsEmpty() &&
+ (panel_bounds.right() <= work_area_.right() - max_balloon_width() ||
+ panel_bounds.x() >= work_area_.right())) {
+ return false;
+ }
+
+ for (PanelManager::Panels::const_iterator iter = panels.begin();
+ iter != panels.end(); ++iter) {
+ // No need to check panels beyond the area occupied by the balloons.
+ if ((*iter)->GetBounds().right() <=
+ work_area_.right() - max_balloon_width())
+ break;
+
+ int current_height = (*iter)->GetBounds().height();
+ if (current_height > offset_to_move_above_panels)
+ offset_to_move_above_panels = current_height;
+ }
+ }
+
+ // Ensure that we have some sort of margin between the 1st balloon and the
+ // panel beneath it even the vertical edge margin is 0 as on Mac.
+ if (offset_to_move_above_panels && !VerticalEdgeMargin())
+ offset_to_move_above_panels += kVerticalSpacingBetweenBalloonAndPanel;
+
+ // If no change is detected, return false to indicate that we do not need to
+ // reposition balloons.
+ if (offset_to_move_above_panels_ == offset_to_move_above_panels)
+ return false;
+
+ offset_to_move_above_panels_ = offset_to_move_above_panels;
+ return true;
+}
+
bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() {
bool changed = false;

Powered by Google App Engine
This is Rietveld 408576698