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

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: Rebase Created 8 years, 4 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') | no next file with comments »
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 if (item_view->bounds().IsEmpty()) {
376 if (!item_bounds.IsEmpty()) { 381 // The bounds of item could be still empty if it does not have a visible
377 int x_offset = item_bounds.x() + item_bounds.width() / 2; 382 // tray view. In that case, use the default (minimum) offset.
378 return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset; 383 return TrayBubbleView::InitParams::kArrowDefaultOffset;
379 } 384 }
380 385
381 // The bounds of item could be still empty. It could happen in the case that 386 gfx::Point point(item_view->width() / 2, 0);
382 // the view appears for the first time in the current session, because the 387 ConvertPointToWidget(item_view, &point);
383 // bounds is not calculated yet. In that case, we want to guess the offset 388 return point.x();
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 } 389 }
399 390
400 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, 391 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type,
401 int arrow_offset) { 392 int arrow_offset) {
402 ShowItems(items_.get(), false, true, creation_type, arrow_offset); 393 ShowItems(items_.get(), false, true, creation_type, arrow_offset);
403 } 394 }
404 395
405 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, 396 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
406 bool detailed, 397 bool detailed,
407 bool can_activate, 398 bool can_activate,
408 BubbleCreationType creation_type, 399 BubbleCreationType creation_type,
409 int arrow_offset) { 400 int arrow_offset) {
410 // Destroy any existing bubble and create a new one. 401 // Destroy any existing bubble and create a new one.
411 SystemTrayBubble::BubbleType bubble_type = detailed ? 402 SystemTrayBubble::BubbleType bubble_type = detailed ?
412 SystemTrayBubble::BUBBLE_TYPE_DETAILED : 403 SystemTrayBubble::BUBBLE_TYPE_DETAILED :
413 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; 404 SystemTrayBubble::BUBBLE_TYPE_DEFAULT;
414 405
415 // Destroy the notification bubble here so that it doesn't get rebuilt 406 // 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). 407 // while we add items to the main bubble_ (e.g. in HideNotificationView).
417 notification_bubble_.reset(); 408 notification_bubble_.reset();
418 409
419 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { 410 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) {
420 bubble_->UpdateView(items, bubble_type); 411 bubble_->UpdateView(items, bubble_type);
421 } else { 412 } else {
422 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); 413 bubble_.reset(new SystemTrayBubble(this, items, bubble_type));
423 ash::SystemTrayDelegate* delegate = 414 ash::SystemTrayDelegate* delegate =
424 ash::Shell::GetInstance()->tray_delegate(); 415 ash::Shell::GetInstance()->tray_delegate();
425 views::View* anchor = tray_container_; 416 views::View* anchor = tray_container_;
426 SystemTrayBubble::InitParams init_params( 417 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY,
427 SystemTrayBubble::ANCHOR_TYPE_TRAY, 418 shelf_alignment());
428 shelf_alignment());
429 init_params.anchor = anchor;
430 init_params.can_activate = can_activate; 419 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) 420 if (detailed)
435 init_params.max_height = default_bubble_height_; 421 init_params.max_height = default_bubble_height_;
436 bubble_->InitView(init_params); 422 init_params.arrow_offset = arrow_offset;
423 bubble_->InitView(anchor, init_params, delegate->GetUserLoginStatus());
437 } 424 }
438 // Save height of default view for creating detailed views directly. 425 // Save height of default view for creating detailed views directly.
439 if (!detailed) 426 if (!detailed)
440 default_bubble_height_ = bubble_->bubble_view()->height(); 427 default_bubble_height_ = bubble_->bubble_view()->height();
441 428
442 if (detailed && items.size() > 0) 429 if (detailed && items.size() > 0)
443 detailed_item_ = items[0]; 430 detailed_item_ = items[0];
444 else 431 else
445 detailed_item_ = NULL; 432 detailed_item_ = NULL;
446 433
(...skipping 25 matching lines...) Expand all
472 items.push_back(*iter); 459 items.push_back(*iter);
473 } 460 }
474 notification_bubble_.reset(new SystemTrayBubble( 461 notification_bubble_.reset(new SystemTrayBubble(
475 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); 462 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
476 } else { 463 } else {
477 // Show all notifications. 464 // Show all notifications.
478 notification_bubble_.reset(new SystemTrayBubble( 465 notification_bubble_.reset(new SystemTrayBubble(
479 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); 466 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
480 } 467 }
481 views::View* anchor; 468 views::View* anchor;
482 SystemTrayBubble::AnchorType anchor_type; 469 TrayBubbleView::AnchorType anchor_type;
483 if (bubble_.get()) { 470 if (bubble_.get()) {
484 anchor = bubble_->bubble_view(); 471 anchor = bubble_->bubble_view();
485 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; 472 anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE;
486 } else { 473 } else {
487 anchor = tray_container_; 474 anchor = tray_container_;
488 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; 475 anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY;
489 } 476 }
490 SystemTrayBubble::InitParams init_params(anchor_type, shelf_alignment()); 477 TrayBubbleView::InitParams init_params(anchor_type, shelf_alignment());
491 init_params.anchor = anchor; 478 init_params.arrow_offset = GetTrayXOffset(notification_items_[0]);
492 init_params.login_status = 479 init_params.arrow_color = kBackgroundColor;
493 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); 480 user::LoginStatus login_status =
494 int arrow_offset = GetTrayXOffset(notification_items_[0]); 481 Shell::GetInstance()->tray_delegate()->GetUserLoginStatus();
495 if (arrow_offset >= 0) 482 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_) 483 if (hide_notifications_)
499 notification_bubble_->SetVisible(false); 484 notification_bubble_->SetVisible(false);
500 } 485 }
501 486
502 void SystemTray::UpdateNotificationAnchor() { 487 void SystemTray::UpdateNotificationAnchor() {
503 if (!notification_bubble_.get()) 488 if (!notification_bubble_.get())
504 return; 489 return;
505 notification_bubble_->bubble_view()->UpdateBubble(); 490 notification_bubble_->bubble_view()->UpdateBubble();
506 // Ensure that the notification buble is above the launcher/status area. 491 // Ensure that the notification buble is above the launcher/status area.
507 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); 492 notification_bubble_->bubble_view()->GetWidget()->StackAtTop();
(...skipping 18 matching lines...) Expand all
526 } 511 }
527 } 512 }
528 513
529 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { 514 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) {
530 if (alignment == shelf_alignment()) 515 if (alignment == shelf_alignment())
531 return; 516 return;
532 internal::TrayBackgroundView::SetShelfAlignment(alignment); 517 internal::TrayBackgroundView::SetShelfAlignment(alignment);
533 UpdateAfterShelfAlignmentChange(alignment); 518 UpdateAfterShelfAlignmentChange(alignment);
534 SetBorder(); 519 SetBorder();
535 tray_container_->UpdateLayout(alignment); 520 tray_container_->UpdateLayout(alignment);
536 // Destroy an existing bubble so that it is rebuilt correctly. 521 // Destroy any existing bubble so that it is rebuilt correctly.
537 bubble_.reset(); 522 bubble_.reset();
538 // Rebuild any notification bubble. 523 // Rebuild any notification bubble.
539 if (notification_bubble_.get()) { 524 if (notification_bubble_.get()) {
540 notification_bubble_.reset(); 525 notification_bubble_.reset();
541 UpdateNotificationBubble(); 526 UpdateNotificationBubble();
542 } 527 }
543 } 528 }
544 529
545 bool SystemTray::PerformAction(const views::Event& event) { 530 bool SystemTray::PerformAction(const views::Event& event) {
546 // If we're already showing the default view, hide it; otherwise, show it 531 // If we're already showing the default view, hide it; otherwise, show it
547 // (and hide any popup that's currently shown). 532 // (and hide any popup that's currently shown).
548 if (bubble_.get() && 533 if (bubble_.get() &&
549 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { 534 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) {
550 bubble_->Close(); 535 bubble_->Close();
551 } else { 536 } else {
552 int arrow_offset = -1; 537 int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset;
553 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { 538 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) {
554 const views::LocatedEvent& located_event = 539 const views::LocatedEvent& located_event =
555 static_cast<const views::LocatedEvent&>(event); 540 static_cast<const views::LocatedEvent&>(event);
556 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) 541 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
557 arrow_offset = base::i18n::IsRTL() ? 542 gfx::Point point(located_event.x(), 0);
558 located_event.x() : tray_container_->width() - located_event.x(); 543 ConvertPointToWidget(this, &point);
544 arrow_offset = point.x();
545 }
559 } 546 }
560 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); 547 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset);
561 } 548 }
562 return true; 549 return true;
563 } 550 }
564 551
565 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { 552 void SystemTray::OnMouseEntered(const views::MouseEvent& event) {
566 TrayBackgroundView::OnMouseEntered(event); 553 TrayBackgroundView::OnMouseEntered(event);
567 should_show_launcher_ = true; 554 should_show_launcher_ = true;
568 } 555 }
(...skipping 19 matching lines...) Expand all
588 575
589 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { 576 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) {
590 // The tray itself expands to the right and bottom edge of the screen to make 577 // The tray itself expands to the right and bottom edge of the screen to make
591 // sure clicking on the edges brings up the popup. However, the focus border 578 // sure clicking on the edges brings up the popup. However, the focus border
592 // should be only around the container. 579 // should be only around the container.
593 if (GetWidget() && GetWidget()->IsActive()) 580 if (GetWidget() && GetWidget()->IsActive())
594 DrawBorder(canvas, GetContentsBounds()); 581 DrawBorder(canvas, GetContentsBounds());
595 } 582 }
596 583
597 } // namespace ash 584 } // namespace ash
OLDNEW
« no previous file with comments | « no previous file | ash/system/tray/system_tray_bubble.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698