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

Side by Side Diff: ash/system/tray/system_tray.cc

Issue 10808066: Fix position of web notification bubble and arrow (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: . Created 8 years, 5 months 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
« no previous file with comments | « no previous file | ash/system/tray/system_tray_bubble.h » ('j') | ash/system/tray/tray_bubble_view.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "ash/system/tray/system_tray.h" 5 #include "ash/system/tray/system_tray.h"
6 6
7 #include "ash/shell.h" 7 #include "ash/shell.h"
8 #include "ash/shell/panel_window.h" 8 #include "ash/shell/panel_window.h"
9 #include "ash/shell_window_ids.h" 9 #include "ash/shell_window_ids.h"
10 #include "ash/system/audio/tray_volume.h" 10 #include "ash/system/audio/tray_volume.h"
(...skipping 12 matching lines...) Expand all
23 #include "ash/system/tray/system_tray_bubble.h" 23 #include "ash/system/tray/system_tray_bubble.h"
24 #include "ash/system/tray/system_tray_delegate.h" 24 #include "ash/system/tray/system_tray_delegate.h"
25 #include "ash/system/tray/system_tray_item.h" 25 #include "ash/system/tray/system_tray_item.h"
26 #include "ash/system/tray/tray_constants.h" 26 #include "ash/system/tray/tray_constants.h"
27 #include "ash/system/tray_accessibility.h" 27 #include "ash/system/tray_accessibility.h"
28 #include "ash/system/tray_caps_lock.h" 28 #include "ash/system/tray_caps_lock.h"
29 #include "ash/system/tray_update.h" 29 #include "ash/system/tray_update.h"
30 #include "ash/system/user/login_status.h" 30 #include "ash/system/user/login_status.h"
31 #include "ash/system/user/tray_user.h" 31 #include "ash/system/user/tray_user.h"
32 #include "ash/wm/shelf_layout_manager.h" 32 #include "ash/wm/shelf_layout_manager.h"
33 #include "base/i18n/rtl.h"
34 #include "base/logging.h" 33 #include "base/logging.h"
35 #include "base/timer.h" 34 #include "base/timer.h"
36 #include "base/utf_string_conversions.h" 35 #include "base/utf_string_conversions.h"
37 #include "grit/ash_strings.h" 36 #include "grit/ash_strings.h"
38 #include "ui/aura/root_window.h" 37 #include "ui/aura/root_window.h"
39 #include "ui/base/accessibility/accessible_view_state.h" 38 #include "ui/base/accessibility/accessible_view_state.h"
40 #include "ui/base/events.h" 39 #include "ui/base/events.h"
41 #include "ui/base/l10n/l10n_util.h" 40 #include "ui/base/l10n/l10n_util.h"
42 #include "ui/compositor/layer.h" 41 #include "ui/compositor/layer.h"
43 #include "ui/gfx/canvas.h" 42 #include "ui/gfx/canvas.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 136
138 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver); 137 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver);
139 }; 138 };
140 139
141 } // namespace internal 140 } // namespace internal
142 141
143 // SystemTray 142 // SystemTray
144 143
145 using internal::SystemTrayBubble; 144 using internal::SystemTrayBubble;
146 using internal::SystemTrayLayerAnimationObserver; 145 using internal::SystemTrayLayerAnimationObserver;
146 using internal::TrayBubbleView;
147 147
148 SystemTray::SystemTray() 148 SystemTray::SystemTray()
149 : items_(), 149 : items_(),
150 accessibility_observer_(NULL), 150 accessibility_observer_(NULL),
151 audio_observer_(NULL), 151 audio_observer_(NULL),
152 bluetooth_observer_(NULL), 152 bluetooth_observer_(NULL),
153 brightness_observer_(NULL), 153 brightness_observer_(NULL),
154 caps_lock_observer_(NULL), 154 caps_lock_observer_(NULL),
155 clock_observer_(NULL), 155 clock_observer_(NULL),
156 drive_observer_(NULL), 156 drive_observer_(NULL),
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
249 PreferredSizeChanged(); 249 PreferredSizeChanged();
250 tray_item_map_[item] = tray_item; 250 tray_item_map_[item] = tray_item;
251 } 251 }
252 } 252 }
253 253
254 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { 254 void SystemTray::RemoveTrayItem(SystemTrayItem* item) {
255 NOTIMPLEMENTED(); 255 NOTIMPLEMENTED();
256 } 256 }
257 257
258 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { 258 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) {
259 ShowDefaultViewWithOffset(creation_type, -1); 259 ShowDefaultViewWithOffset(creation_type,
260 TrayBubbleView::InitParams::kArrowDefaultOffset);
260 } 261 }
261 262
262 void SystemTray::ShowDetailedView(SystemTrayItem* item, 263 void SystemTray::ShowDetailedView(SystemTrayItem* item,
263 int close_delay, 264 int close_delay,
264 bool activate, 265 bool activate,
265 BubbleCreationType creation_type) { 266 BubbleCreationType creation_type) {
266 std::vector<SystemTrayItem*> items; 267 std::vector<SystemTrayItem*> items;
267 items.push_back(item); 268 items.push_back(item);
268 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item)); 269 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item));
269 bubble_->StartAutoCloseTimer(close_delay); 270 bubble_->StartAutoCloseTimer(close_delay);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 Shell::GetInstance()->shelf()->UpdateAutoHideState(); 360 Shell::GetInstance()->shelf()->UpdateAutoHideState();
360 } 361 }
361 } else if (bubble == notification_bubble_) { 362 } else if (bubble == notification_bubble_) {
362 notification_bubble_.reset(); 363 notification_bubble_.reset();
363 } else { 364 } else {
364 NOTREACHED(); 365 NOTREACHED();
365 } 366 }
366 } 367 }
367 368
368 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { 369 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const {
370 // Don't attempt to align the arrow if the shelf is on the left or right.
371 if (shelf_alignment() != SHELF_ALIGNMENT_BOTTOM)
372 return TrayBubbleView::InitParams::kArrowDefaultOffset;
373
369 std::map<SystemTrayItem*, views::View*>::const_iterator it = 374 std::map<SystemTrayItem*, views::View*>::const_iterator it =
370 tray_item_map_.find(item); 375 tray_item_map_.find(item);
371 if (it == tray_item_map_.end()) 376 if (it == tray_item_map_.end())
372 return -1; 377 return TrayBubbleView::InitParams::kArrowDefaultOffset;
373 378
374 const views::View* item_view = it->second; 379 const views::View* item_view = it->second;
375 gfx::Rect item_bounds = item_view->bounds(); 380 gfx::Rect rect(item_view->width() / 2, 0, 0, 0);
msw 2012/07/27 20:32:04 nit: use a Point and ConvertPointToWidget; assign
stevenjb 2012/07/30 20:09:03 Done.
376 if (!item_bounds.IsEmpty()) { 381 gfx::Rect item_bounds = item_view->ConvertRectToWidget(rect);
377 int x_offset = item_bounds.x() + item_bounds.width() / 2; 382 if (!item_view->bounds().IsEmpty())
msw 2012/07/27 20:32:04 Invert the check and make this an early return of
stevenjb 2012/07/30 20:09:03 Good call, done.
378 return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset; 383 return item_bounds.x();
379 }
380 384
381 // The bounds of item could be still empty. It could happen in the case that 385 // The bounds of item could be still empty if it does not have a visible
382 // the view appears for the first time in the current session, because the 386 // tray view. In that case, use the default (minimum) offset.
383 // bounds is not calculated yet. In that case, we want to guess the offset 387 return TrayBubbleView::InitParams::kArrowDefaultOffset;
384 // from the position of its parent.
385 int x_offset = 0;
386 for (int i = 0; i < tray_container_->child_count(); ++i) {
387 const views::View* child = tray_container_->child_at(i);
388 if (child == item_view)
389 return base::i18n::IsRTL() ?
390 x_offset : tray_container_->width() - x_offset;
391
392 if (!child->visible())
393 continue;
394 x_offset = child->bounds().right();
395 }
396
397 return -1;
398 } 388 }
399 389
400 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, 390 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type,
401 int arrow_offset) { 391 int arrow_offset) {
402 ShowItems(items_.get(), false, true, creation_type, arrow_offset); 392 ShowItems(items_.get(), false, true, creation_type, arrow_offset);
403 } 393 }
404 394
405 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, 395 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
406 bool detailed, 396 bool detailed,
407 bool can_activate, 397 bool can_activate,
408 BubbleCreationType creation_type, 398 BubbleCreationType creation_type,
409 int arrow_offset) { 399 int arrow_offset) {
410 // Destroy any existing bubble and create a new one. 400 // Destroy any existing bubble and create a new one.
411 SystemTrayBubble::BubbleType bubble_type = detailed ? 401 SystemTrayBubble::BubbleType bubble_type = detailed ?
412 SystemTrayBubble::BUBBLE_TYPE_DETAILED : 402 SystemTrayBubble::BUBBLE_TYPE_DETAILED :
413 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; 403 SystemTrayBubble::BUBBLE_TYPE_DEFAULT;
414 404
415 // Destroy the notification bubble here so that it doesn't get rebuilt 405 // Destroy the notification bubble here so that it doesn't get rebuilt
416 // while we add items to the main bubble_ (e.g. in HideNotificationView). 406 // while we add items to the main bubble_ (e.g. in HideNotificationView).
417 notification_bubble_.reset(); 407 notification_bubble_.reset();
418 408
419 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { 409 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) {
420 bubble_->UpdateView(items, bubble_type); 410 bubble_->UpdateView(items, bubble_type);
421 } else { 411 } else {
422 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); 412 bubble_.reset(new SystemTrayBubble(this, items, bubble_type));
423 ash::SystemTrayDelegate* delegate = 413 ash::SystemTrayDelegate* delegate =
424 ash::Shell::GetInstance()->tray_delegate(); 414 ash::Shell::GetInstance()->tray_delegate();
425 views::View* anchor = tray_container_; 415 views::View* anchor = tray_container_;
426 SystemTrayBubble::InitParams init_params( 416 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY,
427 SystemTrayBubble::ANCHOR_TYPE_TRAY, 417 shelf_alignment());
428 shelf_alignment());
429 init_params.anchor = anchor;
430 init_params.can_activate = can_activate; 418 init_params.can_activate = can_activate;
431 init_params.login_status = delegate->GetUserLoginStatus();
432 if (arrow_offset >= 0)
433 init_params.arrow_offset = arrow_offset;
434 if (detailed) 419 if (detailed)
435 init_params.max_height = default_bubble_height_; 420 init_params.max_height = default_bubble_height_;
436 bubble_->InitView(init_params); 421 init_params.arrow_offset = arrow_offset;
422 bubble_->InitView(anchor, init_params, delegate->GetUserLoginStatus());
437 } 423 }
438 // Save height of default view for creating detailed views directly. 424 // Save height of default view for creating detailed views directly.
439 if (!detailed) 425 if (!detailed)
440 default_bubble_height_ = bubble_->bubble_view()->height(); 426 default_bubble_height_ = bubble_->bubble_view()->height();
441 427
442 if (detailed && items.size() > 0) 428 if (detailed && items.size() > 0)
443 detailed_item_ = items[0]; 429 detailed_item_ = items[0];
444 else 430 else
445 detailed_item_ = NULL; 431 detailed_item_ = NULL;
446 432
(...skipping 25 matching lines...) Expand all
472 items.push_back(*iter); 458 items.push_back(*iter);
473 } 459 }
474 notification_bubble_.reset(new SystemTrayBubble( 460 notification_bubble_.reset(new SystemTrayBubble(
475 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); 461 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
476 } else { 462 } else {
477 // Show all notifications. 463 // Show all notifications.
478 notification_bubble_.reset(new SystemTrayBubble( 464 notification_bubble_.reset(new SystemTrayBubble(
479 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); 465 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
480 } 466 }
481 views::View* anchor; 467 views::View* anchor;
482 SystemTrayBubble::AnchorType anchor_type; 468 TrayBubbleView::AnchorType anchor_type;
483 if (bubble_.get()) { 469 if (bubble_.get()) {
484 anchor = bubble_->bubble_view(); 470 anchor = bubble_->bubble_view();
485 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; 471 anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE;
486 } else { 472 } else {
487 anchor = tray_container_; 473 anchor = tray_container_;
488 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; 474 anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY;
489 } 475 }
490 SystemTrayBubble::InitParams init_params(anchor_type, shelf_alignment()); 476 TrayBubbleView::InitParams init_params(anchor_type, shelf_alignment());
491 init_params.anchor = anchor; 477 init_params.arrow_offset = GetTrayXOffset(notification_items_[0]);
492 init_params.login_status = 478 init_params.arrow_color = kBackgroundColor;
493 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); 479 user::LoginStatus login_status =
494 int arrow_offset = GetTrayXOffset(notification_items_[0]); 480 Shell::GetInstance()->tray_delegate()->GetUserLoginStatus();
495 if (arrow_offset >= 0) 481 notification_bubble_->InitView(anchor, init_params, login_status);
496 init_params.arrow_offset = arrow_offset;
497 notification_bubble_->InitView(init_params);
498 if (hide_notifications_) 482 if (hide_notifications_)
499 notification_bubble_->SetVisible(false); 483 notification_bubble_->SetVisible(false);
500 } 484 }
501 485
502 void SystemTray::UpdateNotificationAnchor() { 486 void SystemTray::UpdateNotificationAnchor() {
503 if (!notification_bubble_.get()) 487 if (!notification_bubble_.get())
504 return; 488 return;
505 notification_bubble_->bubble_view()->UpdateAnchor(); 489 notification_bubble_->bubble_view()->UpdateBubble();
506 // Ensure that the notification buble is above the launcher/status area. 490 // Ensure that the notification buble is above the launcher/status area.
507 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); 491 notification_bubble_->bubble_view()->GetWidget()->StackAtTop();
508 } 492 }
509 493
510 void SystemTray::SetBorder() { 494 void SystemTray::SetBorder() {
511 // Change the border padding for different shelf alignment. 495 // Change the border padding for different shelf alignment.
512 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { 496 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
513 set_border(views::Border::CreateEmptyBorder(0, 0, 497 set_border(views::Border::CreateEmptyBorder(0, 0,
514 kPaddingFromBottomOfScreenBottomAlignment, 498 kPaddingFromBottomOfScreenBottomAlignment,
515 kPaddingFromRightEdgeOfScreenBottomAlignment)); 499 kPaddingFromRightEdgeOfScreenBottomAlignment));
(...skipping 10 matching lines...) Expand all
526 } 510 }
527 } 511 }
528 512
529 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { 513 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) {
530 if (alignment == shelf_alignment()) 514 if (alignment == shelf_alignment())
531 return; 515 return;
532 internal::TrayBackgroundView::SetShelfAlignment(alignment); 516 internal::TrayBackgroundView::SetShelfAlignment(alignment);
533 UpdateAfterShelfAlignmentChange(alignment); 517 UpdateAfterShelfAlignmentChange(alignment);
534 SetBorder(); 518 SetBorder();
535 tray_container_->UpdateLayout(alignment); 519 tray_container_->UpdateLayout(alignment);
520 // Destroy an existing bubble so that it is rebuilt correctly.
msw 2012/07/27 20:32:04 nit: not sure if you meant to write "any".
stevenjb 2012/07/30 20:09:03 Done.
521 bubble_.reset();
522 // Rebuild any notification bubble.
523 if (notification_bubble_.get()) {
524 notification_bubble_.reset();
525 UpdateNotificationBubble();
526 }
536 } 527 }
537 528
538 bool SystemTray::PerformAction(const views::Event& event) { 529 bool SystemTray::PerformAction(const views::Event& event) {
539 // If we're already showing the default view, hide it; otherwise, show it 530 // If we're already showing the default view, hide it; otherwise, show it
540 // (and hide any popup that's currently shown). 531 // (and hide any popup that's currently shown).
541 if (bubble_.get() && 532 if (bubble_.get() &&
542 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { 533 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) {
543 bubble_->Close(); 534 bubble_->Close();
544 } else { 535 } else {
545 int arrow_offset = -1; 536 int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset;
546 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { 537 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) {
547 const views::LocatedEvent& located_event = 538 const views::LocatedEvent& located_event =
548 static_cast<const views::LocatedEvent&>(event); 539 static_cast<const views::LocatedEvent&>(event);
549 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) 540 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
550 arrow_offset = base::i18n::IsRTL() ? 541 gfx::Rect bounds(located_event.x(), 0, 0, 0);
msw 2012/07/27 20:32:04 nit: use a Point and ConvertPointToWidget.
stevenjb 2012/07/30 20:09:03 Done.
551 located_event.x() : tray_container_->width() - located_event.x(); 542 bounds = ConvertRectToWidget(bounds);
543 arrow_offset = bounds.x();
544 }
552 } 545 }
553 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); 546 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset);
554 } 547 }
555 return true; 548 return true;
556 } 549 }
557 550
558 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { 551 void SystemTray::OnMouseEntered(const views::MouseEvent& event) {
559 TrayBackgroundView::OnMouseEntered(event); 552 TrayBackgroundView::OnMouseEntered(event);
560 should_show_launcher_ = true; 553 should_show_launcher_ = true;
561 } 554 }
(...skipping 19 matching lines...) Expand all
581 574
582 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { 575 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) {
583 // The tray itself expands to the right and bottom edge of the screen to make 576 // The tray itself expands to the right and bottom edge of the screen to make
584 // sure clicking on the edges brings up the popup. However, the focus border 577 // sure clicking on the edges brings up the popup. However, the focus border
585 // should be only around the container. 578 // should be only around the container.
586 if (GetWidget() && GetWidget()->IsActive()) 579 if (GetWidget() && GetWidget()->IsActive())
587 DrawBorder(canvas, GetContentsBounds()); 580 DrawBorder(canvas, GetContentsBounds());
588 } 581 }
589 582
590 } // namespace ash 583 } // namespace ash
OLDNEW
« no previous file with comments | « no previous file | ash/system/tray/system_tray_bubble.h » ('j') | ash/system/tray/tray_bubble_view.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698