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

Side by Side 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. 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/notifications/balloon_collection_impl.h" 5 #include "chrome/browser/notifications/balloon_collection_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "chrome/browser/notifications/balloon.h" 10 #include "chrome/browser/notifications/balloon.h"
11 #include "chrome/browser/notifications/balloon_host.h" 11 #include "chrome/browser/notifications/balloon_host.h"
12 #include "chrome/browser/notifications/notification.h" 12 #include "chrome/browser/notifications/notification.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/panels/panel_manager.h"
15 #include "chrome/browser/ui/panels/panel.h"
13 #include "chrome/browser/ui/window_sizer.h" 16 #include "chrome/browser/ui/window_sizer.h"
17 #include "chrome/common/chrome_notification_types.h"
18 #include "content/public/browser/notification_registrar.h"
19 #include "content/public/browser/notification_service.h"
14 #include "ui/gfx/rect.h" 20 #include "ui/gfx/rect.h"
15 #include "ui/gfx/size.h" 21 #include "ui/gfx/size.h"
16 22
17 namespace { 23 namespace {
18 24
19 // Portion of the screen allotted for notifications. When notification balloons 25 // Portion of the screen allotted for notifications. When notification balloons
20 // extend over this, no new notifications are shown until some are closed. 26 // extend over this, no new notifications are shown until some are closed.
21 const double kPercentBalloonFillFactor = 0.7; 27 const double kPercentBalloonFillFactor = 0.7;
22 28
23 // Allow at least this number of balloons on the screen. 29 // Allow at least this number of balloons on the screen.
24 const int kMinAllowedBalloonCount = 2; 30 const int kMinAllowedBalloonCount = 2;
25 31
26 // Delay from the mouse leaving the balloon collection before 32 // Delay from the mouse leaving the balloon collection before
27 // there is a relayout, in milliseconds. 33 // there is a relayout, in milliseconds.
28 const int kRepositionDelay = 300; 34 const int kRepositionDelay = 300;
29 35
30 } // namespace 36 } // namespace
31 37
32 BalloonCollectionImpl::BalloonCollectionImpl() 38 BalloonCollectionImpl::BalloonCollectionImpl()
33 #if USE_OFFSETS 39 #if USE_OFFSETS
34 : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)), 40 : ALLOW_THIS_IN_INITIALIZER_LIST(reposition_factory_(this)),
35 added_as_message_loop_observer_(false) 41 added_as_message_loop_observer_(false)
36 #endif 42 #endif
37 { 43 {
44 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_WINDOW_READY,
45 content::NotificationService::AllSources());
46 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
47 content::NotificationService::AllSources());
48 registrar_.Add(this, chrome::NOTIFICATION_PANEL_CHANGED_BOUNDS,
49 content::NotificationService::AllSources());
38 50
39 SetPositionPreference(BalloonCollection::DEFAULT_POSITION); 51 SetPositionPreference(BalloonCollection::DEFAULT_POSITION);
40 } 52 }
41 53
42 BalloonCollectionImpl::~BalloonCollectionImpl() { 54 BalloonCollectionImpl::~BalloonCollectionImpl() {
43 } 55 }
44 56
45 void BalloonCollectionImpl::Add(const Notification& notification, 57 void BalloonCollectionImpl::Add(const Notification& notification,
46 Profile* profile) { 58 Profile* profile) {
47 Balloon* new_balloon = MakeBalloon(notification, profile); 59 Balloon* new_balloon = MakeBalloon(notification, profile);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
146 158
147 // This is used only for testing. 159 // This is used only for testing.
148 if (!on_collection_changed_callback_.is_null()) 160 if (!on_collection_changed_callback_.is_null())
149 on_collection_changed_callback_.Run(); 161 on_collection_changed_callback_.Run();
150 } 162 }
151 163
152 const BalloonCollection::Balloons& BalloonCollectionImpl::GetActiveBalloons() { 164 const BalloonCollection::Balloons& BalloonCollectionImpl::GetActiveBalloons() {
153 return base_.balloons(); 165 return base_.balloons();
154 } 166 }
155 167
168 void BalloonCollectionImpl::Observe(
169 int type,
170 const content::NotificationSource& source,
171 const content::NotificationDetails& details) {
172 switch (type) {
173 case chrome::NOTIFICATION_BROWSER_WINDOW_READY:
174 case chrome::NOTIFICATION_BROWSER_CLOSED: {
175 Browser* browser = content::Source<Browser>(source).ptr();
176 if (browser->is_type_panel())
177 PositionBalloons(true);
178 break;
179 }
180 case chrome::NOTIFICATION_PANEL_CHANGED_BOUNDS:
181 PositionBalloons(true);
182 break;
183 default:
184 NOTREACHED();
185 break;
186 }
187 }
188
156 void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) { 189 void BalloonCollectionImpl::PositionBalloonsInternal(bool reposition) {
157 const Balloons& balloons = base_.balloons(); 190 const Balloons& balloons = base_.balloons();
158 191
159 layout_.RefreshSystemMetrics(); 192 layout_.RefreshSystemMetrics();
160 gfx::Point origin = layout_.GetLayoutOrigin(); 193 gfx::Point origin = layout_.GetLayoutOrigin();
161 for (Balloons::const_iterator it = balloons.begin(); 194 for (Balloons::const_iterator it = balloons.begin();
162 it != balloons.end(); 195 it != balloons.end();
163 ++it) { 196 ++it) {
164 gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin); 197 gfx::Point upper_left = layout_.NextPosition((*it)->GetViewSize(), &origin);
165 (*it)->SetPosition(upper_left, reposition); 198 (*it)->SetPosition(upper_left, reposition);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
224 reposition_factory_.GetWeakPtr()), 257 reposition_factory_.GetWeakPtr()),
225 kRepositionDelay); 258 kRepositionDelay);
226 } 259 }
227 } else { 260 } else {
228 // Mouse moved back into the region. Cancel the reposition. 261 // Mouse moved back into the region. Cancel the reposition.
229 reposition_factory_.InvalidateWeakPtrs(); 262 reposition_factory_.InvalidateWeakPtrs();
230 } 263 }
231 } 264 }
232 #endif 265 #endif
233 266
234 BalloonCollectionImpl::Layout::Layout() : placement_(INVALID) { 267 BalloonCollectionImpl::Layout::Layout()
268 : placement_(INVALID),
269 bottom_left_offset_to_move_above_panels_(0),
270 bottom_right_offset_to_move_above_panels_(0) {
235 RefreshSystemMetrics(); 271 RefreshSystemMetrics();
236 } 272 }
237 273
238 void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size, 274 void BalloonCollectionImpl::Layout::GetMaxLinearSize(int* max_balloon_size,
239 int* total_size) const { 275 int* total_size) const {
240 DCHECK(max_balloon_size && total_size); 276 DCHECK(max_balloon_size && total_size);
241 277
242 // All placement schemes are vertical, so we only care about height. 278 // All placement schemes are vertical, so we only care about height.
243 *total_size = work_area_.height(); 279 *total_size = work_area_.height();
244 *max_balloon_size = max_balloon_height(); 280 *max_balloon_size = max_balloon_height();
245 } 281 }
246 282
247 gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const { 283 gfx::Point BalloonCollectionImpl::Layout::GetLayoutOrigin() const {
248 int x = 0; 284 int x = 0;
249 int y = 0; 285 int y = 0;
250 switch (placement_) { 286 switch (placement_) {
251 case VERTICALLY_FROM_TOP_LEFT: 287 case VERTICALLY_FROM_TOP_LEFT:
252 x = work_area_.x() + HorizontalEdgeMargin(); 288 x = work_area_.x() + HorizontalEdgeMargin();
253 y = work_area_.y() + VerticalEdgeMargin(); 289 y = work_area_.y() + VerticalEdgeMargin();
254 break; 290 break;
255 case VERTICALLY_FROM_TOP_RIGHT: 291 case VERTICALLY_FROM_TOP_RIGHT:
256 x = work_area_.right() - HorizontalEdgeMargin(); 292 x = work_area_.right() - HorizontalEdgeMargin();
257 y = work_area_.y() + VerticalEdgeMargin(); 293 y = work_area_.y() + VerticalEdgeMargin();
258 break; 294 break;
259 case VERTICALLY_FROM_BOTTOM_LEFT: 295 case VERTICALLY_FROM_BOTTOM_LEFT:
260 x = work_area_.x() + HorizontalEdgeMargin(); 296 x = work_area_.x() + HorizontalEdgeMargin();
261 y = work_area_.bottom() - VerticalEdgeMargin(); 297 // For this placement, balloon needs to stay on top of left-most panels
298 // to avoid overlapping.
299 y = work_area_.bottom() - VerticalEdgeMargin() -
300 bottom_left_offset_to_move_above_panels_;
262 break; 301 break;
263 case VERTICALLY_FROM_BOTTOM_RIGHT: 302 case VERTICALLY_FROM_BOTTOM_RIGHT:
264 x = work_area_.right() - HorizontalEdgeMargin(); 303 x = work_area_.right() - HorizontalEdgeMargin();
265 y = work_area_.bottom() - VerticalEdgeMargin(); 304 // For this placement, balloon needs to stay on top of right-most panels
305 // to avoid overlapping.
306 y = work_area_.bottom() - VerticalEdgeMargin() -
307 bottom_right_offset_to_move_above_panels_;
266 break; 308 break;
267 default: 309 default:
268 NOTREACHED(); 310 NOTREACHED();
269 break; 311 break;
270 } 312 }
271 return gfx::Point(x, y); 313 return gfx::Point(x, y);
272 } 314 }
273 315
274 gfx::Point BalloonCollectionImpl::Layout::NextPosition( 316 gfx::Point BalloonCollectionImpl::Layout::NextPosition(
275 const gfx::Size& balloon_size, 317 const gfx::Size& balloon_size,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits( 398 gfx::Size BalloonCollectionImpl::Layout::ConstrainToSizeLimits(
357 const gfx::Size& size) { 399 const gfx::Size& size) {
358 // restrict to the min & max sizes 400 // restrict to the min & max sizes
359 return gfx::Size( 401 return gfx::Size(
360 std::max(min_balloon_width(), 402 std::max(min_balloon_width(),
361 std::min(max_balloon_width(), size.width())), 403 std::min(max_balloon_width(), size.width())),
362 std::max(min_balloon_height(), 404 std::max(min_balloon_height(),
363 std::min(max_balloon_height(), size.height()))); 405 std::min(max_balloon_height(), size.height())));
364 } 406 }
365 407
408 void BalloonCollectionImpl::Layout::ComputeOffsetsToMoveAbovePanels() {
409 const PanelManager::Panels& panels = PanelManager::GetInstance()->panels();
410
411 // For balloons that are aligned vertically from bottom-right corner, the
412 // offset is the maximum height of the right-most panels that could overlap
413 // with the balloons.
414 bottom_right_offset_to_move_above_panels_ = 0;
415 for (PanelManager::Panels::const_iterator iter = panels.begin();
416 iter != panels.end(); ++iter) {
417 if ((*iter)->GetBounds().right() <=
418 work_area_.right() - max_balloon_width())
419 break;
420 int current_height = (*iter)->GetBounds().height();
421 if (current_height > bottom_right_offset_to_move_above_panels_)
422 bottom_right_offset_to_move_above_panels_ = current_height;
423 }
424
425 // For balloons that are aligned vertically from bottom-left corner, the
426 // offset is the maximum height of the left-most panels that could overlap
427 // with the balloons.
428 bottom_left_offset_to_move_above_panels_ = 0;
429 for (PanelManager::Panels::const_reverse_iterator iter = panels.rbegin();
430 iter != panels.rend(); ++iter) {
431 if ((*iter)->GetBounds().x() > work_area_.x() + max_balloon_width())
432 break;
433 int current_height = (*iter)->GetBounds().height();
434 if (current_height > bottom_left_offset_to_move_above_panels_)
435 bottom_left_offset_to_move_above_panels_ = current_height;
436 }
437 }
438
366 bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() { 439 bool BalloonCollectionImpl::Layout::RefreshSystemMetrics() {
367 bool changed = false; 440 bool changed = false;
368 441
369 #if defined(OS_MACOSX) 442 #if defined(OS_MACOSX)
370 gfx::Rect new_work_area = GetMacWorkArea(); 443 gfx::Rect new_work_area = GetMacWorkArea();
371 #else 444 #else
372 scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider( 445 scoped_ptr<WindowSizer::MonitorInfoProvider> info_provider(
373 WindowSizer::CreateDefaultMonitorInfoProvider()); 446 WindowSizer::CreateDefaultMonitorInfoProvider());
374 gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea(); 447 gfx::Rect new_work_area = info_provider->GetPrimaryMonitorWorkArea();
375 #endif 448 #endif
376 if (!work_area_.Equals(new_work_area)) { 449 if (!work_area_.Equals(new_work_area)) {
377 work_area_.SetRect(new_work_area.x(), new_work_area.y(), 450 work_area_.SetRect(new_work_area.x(), new_work_area.y(),
378 new_work_area.width(), new_work_area.height()); 451 new_work_area.width(), new_work_area.height());
379 changed = true; 452 changed = true;
380 } 453 }
381 454
455 ComputeOffsetsToMoveAbovePanels();
456
382 return changed; 457 return changed;
383 } 458 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698