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

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
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 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 135
137 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver); 136 DISALLOW_COPY_AND_ASSIGN(SystemTrayLayerAnimationObserver);
138 }; 137 };
139 138
140 } // namespace internal 139 } // namespace internal
141 140
142 // SystemTray 141 // SystemTray
143 142
144 using internal::SystemTrayBubble; 143 using internal::SystemTrayBubble;
145 using internal::SystemTrayLayerAnimationObserver; 144 using internal::SystemTrayLayerAnimationObserver;
145 using internal::TrayBubbleView;
146 146
147 SystemTray::SystemTray() 147 SystemTray::SystemTray()
148 : items_(), 148 : items_(),
149 accessibility_observer_(NULL), 149 accessibility_observer_(NULL),
150 audio_observer_(NULL), 150 audio_observer_(NULL),
151 bluetooth_observer_(NULL), 151 bluetooth_observer_(NULL),
152 brightness_observer_(NULL), 152 brightness_observer_(NULL),
153 caps_lock_observer_(NULL), 153 caps_lock_observer_(NULL),
154 clock_observer_(NULL), 154 clock_observer_(NULL),
155 drive_observer_(NULL), 155 drive_observer_(NULL),
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 PreferredSizeChanged(); 245 PreferredSizeChanged();
246 tray_item_map_[item] = tray_item; 246 tray_item_map_[item] = tray_item;
247 } 247 }
248 } 248 }
249 249
250 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { 250 void SystemTray::RemoveTrayItem(SystemTrayItem* item) {
251 NOTIMPLEMENTED(); 251 NOTIMPLEMENTED();
252 } 252 }
253 253
254 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { 254 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) {
255 ShowDefaultViewWithOffset(creation_type, -1); 255 ShowDefaultViewWithOffset(creation_type,
256 TrayBubbleView::InitParams::kArrowDefaultOffset);
256 } 257 }
257 258
258 void SystemTray::ShowDetailedView(SystemTrayItem* item, 259 void SystemTray::ShowDetailedView(SystemTrayItem* item,
259 int close_delay, 260 int close_delay,
260 bool activate, 261 bool activate,
261 BubbleCreationType creation_type) { 262 BubbleCreationType creation_type) {
262 std::vector<SystemTrayItem*> items; 263 std::vector<SystemTrayItem*> items;
263 items.push_back(item); 264 items.push_back(item);
264 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item)); 265 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item));
265 bubble_->StartAutoCloseTimer(close_delay); 266 bubble_->StartAutoCloseTimer(close_delay);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 Shell::GetInstance()->shelf()->UpdateAutoHideState(); 357 Shell::GetInstance()->shelf()->UpdateAutoHideState();
357 } 358 }
358 } else if (bubble == notification_bubble_) { 359 } else if (bubble == notification_bubble_) {
359 notification_bubble_.reset(); 360 notification_bubble_.reset();
360 } else { 361 } else {
361 NOTREACHED(); 362 NOTREACHED();
362 } 363 }
363 } 364 }
364 365
365 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { 366 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const {
367 // Don't attempt to align the arrow if the shelf is on the left or right.
368 if (shelf_alignment() != SHELF_ALIGNMENT_BOTTOM)
369 return TrayBubbleView::InitParams::kArrowDefaultOffset;
370
366 std::map<SystemTrayItem*, views::View*>::const_iterator it = 371 std::map<SystemTrayItem*, views::View*>::const_iterator it =
367 tray_item_map_.find(item); 372 tray_item_map_.find(item);
368 if (it == tray_item_map_.end()) 373 if (it == tray_item_map_.end())
369 return -1; 374 return TrayBubbleView::InitParams::kArrowDefaultOffset;
370 375
371 const views::View* item_view = it->second; 376 const views::View* item_view = it->second;
372 gfx::Rect item_bounds = item_view->bounds(); 377 gfx::Rect rect(item_view->width() / 2, 0, 0, 0);
373 if (!item_bounds.IsEmpty()) { 378 gfx::Rect item_bounds = item_view->ConvertRectToWidget(rect);
374 int x_offset = item_bounds.x() + item_bounds.width() / 2; 379 if (!item_view->bounds().IsEmpty())
375 return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset; 380 return item_bounds.x();
376 }
377 381
378 // The bounds of item could be still empty. It could happen in the case that 382 // The bounds of item could be still empty if it does not have a visible
379 // the view appears for the first time in the current session, because the 383 // tray view. In that case, use the default (minimum) offset.
380 // bounds is not calculated yet. In that case, we want to guess the offset 384 return TrayBubbleView::InitParams::kArrowDefaultOffset;
381 // from the position of its parent.
382 int x_offset = 0;
383 for (int i = 0; i < tray_container_->child_count(); ++i) {
384 const views::View* child = tray_container_->child_at(i);
385 if (child == item_view)
386 return base::i18n::IsRTL() ?
387 x_offset : tray_container_->width() - x_offset;
388
389 if (!child->visible())
390 continue;
391 x_offset = child->bounds().right();
392 }
393
394 return -1;
395 } 385 }
396 386
397 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, 387 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type,
398 int arrow_offset) { 388 int arrow_offset) {
399 ShowItems(items_.get(), false, true, creation_type, arrow_offset); 389 ShowItems(items_.get(), false, true, creation_type, arrow_offset);
400 } 390 }
401 391
402 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, 392 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items,
403 bool detailed, 393 bool detailed,
404 bool can_activate, 394 bool can_activate,
405 BubbleCreationType creation_type, 395 BubbleCreationType creation_type,
406 int arrow_offset) { 396 int arrow_offset) {
407 // Destroy any existing bubble and create a new one. 397 // Destroy any existing bubble and create a new one.
408 SystemTrayBubble::BubbleType bubble_type = detailed ? 398 SystemTrayBubble::BubbleType bubble_type = detailed ?
409 SystemTrayBubble::BUBBLE_TYPE_DETAILED : 399 SystemTrayBubble::BUBBLE_TYPE_DETAILED :
410 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; 400 SystemTrayBubble::BUBBLE_TYPE_DEFAULT;
411 401
412 // Destroy the notification bubble here so that it doesn't get rebuilt 402 // Destroy the notification bubble here so that it doesn't get rebuilt
413 // while we add items to the main bubble_ (e.g. in HideNotificationView). 403 // while we add items to the main bubble_ (e.g. in HideNotificationView).
414 notification_bubble_.reset(); 404 notification_bubble_.reset();
415 405
416 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { 406 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) {
417 bubble_->UpdateView(items, bubble_type); 407 bubble_->UpdateView(items, bubble_type);
418 } else { 408 } else {
419 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); 409 bubble_.reset(new SystemTrayBubble(this, items, bubble_type));
420 ash::SystemTrayDelegate* delegate = 410 ash::SystemTrayDelegate* delegate =
421 ash::Shell::GetInstance()->tray_delegate(); 411 ash::Shell::GetInstance()->tray_delegate();
422 views::View* anchor = tray_container_; 412 views::View* anchor = tray_container_;
423 SystemTrayBubble::InitParams init_params( 413 TrayBubbleView::InitParams init_params(TrayBubbleView::ANCHOR_TYPE_TRAY,
424 SystemTrayBubble::ANCHOR_TYPE_TRAY, 414 shelf_alignment());
425 shelf_alignment());
426 init_params.anchor = anchor;
427 init_params.can_activate = can_activate; 415 init_params.can_activate = can_activate;
428 init_params.login_status = delegate->GetUserLoginStatus();
429 if (arrow_offset >= 0)
430 init_params.arrow_offset = arrow_offset;
431 if (detailed) 416 if (detailed)
432 init_params.max_height = default_bubble_height_; 417 init_params.max_height = default_bubble_height_;
433 bubble_->InitView(init_params); 418 init_params.arrow_offset = arrow_offset;
419 bubble_->InitView(anchor, init_params, delegate->GetUserLoginStatus());
434 } 420 }
435 // Save height of default view for creating detailed views directly. 421 // Save height of default view for creating detailed views directly.
436 if (!detailed) 422 if (!detailed)
437 default_bubble_height_ = bubble_->bubble_view()->height(); 423 default_bubble_height_ = bubble_->bubble_view()->height();
438 424
439 if (detailed && items.size() > 0) 425 if (detailed && items.size() > 0)
440 detailed_item_ = items[0]; 426 detailed_item_ = items[0];
441 else 427 else
442 detailed_item_ = NULL; 428 detailed_item_ = NULL;
443 429
(...skipping 25 matching lines...) Expand all
469 items.push_back(*iter); 455 items.push_back(*iter);
470 } 456 }
471 notification_bubble_.reset(new SystemTrayBubble( 457 notification_bubble_.reset(new SystemTrayBubble(
472 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); 458 this, items, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
473 } else { 459 } else {
474 // Show all notifications. 460 // Show all notifications.
475 notification_bubble_.reset(new SystemTrayBubble( 461 notification_bubble_.reset(new SystemTrayBubble(
476 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); 462 this, notification_items_, SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION));
477 } 463 }
478 views::View* anchor; 464 views::View* anchor;
479 SystemTrayBubble::AnchorType anchor_type; 465 TrayBubbleView::AnchorType anchor_type;
480 if (bubble_.get()) { 466 if (bubble_.get()) {
481 anchor = bubble_->bubble_view(); 467 anchor = bubble_->bubble_view();
482 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; 468 anchor_type = TrayBubbleView::ANCHOR_TYPE_BUBBLE;
483 } else { 469 } else {
484 anchor = tray_container_; 470 anchor = tray_container_;
485 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; 471 anchor_type = TrayBubbleView::ANCHOR_TYPE_TRAY;
486 } 472 }
487 SystemTrayBubble::InitParams init_params(anchor_type, shelf_alignment()); 473 TrayBubbleView::InitParams init_params(anchor_type, shelf_alignment());
488 init_params.anchor = anchor; 474 init_params.arrow_offset = GetTrayXOffset(notification_items_[0]);
489 init_params.login_status = 475 user::LoginStatus login_status =
490 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); 476 Shell::GetInstance()->tray_delegate()->GetUserLoginStatus();
491 int arrow_offset = GetTrayXOffset(notification_items_[0]); 477 notification_bubble_->InitView(anchor, init_params, login_status);
492 if (arrow_offset >= 0)
493 init_params.arrow_offset = arrow_offset;
494 notification_bubble_->InitView(init_params);
495 if (hide_notifications_) 478 if (hide_notifications_)
496 notification_bubble_->SetVisible(false); 479 notification_bubble_->SetVisible(false);
497 } 480 }
498 481
499 void SystemTray::UpdateNotificationAnchor() { 482 void SystemTray::UpdateNotificationAnchor() {
500 if (!notification_bubble_.get()) 483 if (!notification_bubble_.get())
501 return; 484 return;
502 notification_bubble_->bubble_view()->UpdateAnchor(); 485 notification_bubble_->bubble_view()->UpdateAnchor();
503 // Ensure that the notification buble is above the launcher/status area. 486 // Ensure that the notification buble is above the launcher/status area.
504 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); 487 notification_bubble_->bubble_view()->GetWidget()->StackAtTop();
(...skipping 18 matching lines...) Expand all
523 } 506 }
524 } 507 }
525 508
526 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) { 509 void SystemTray::SetShelfAlignment(ShelfAlignment alignment) {
527 if (alignment == shelf_alignment()) 510 if (alignment == shelf_alignment())
528 return; 511 return;
529 internal::TrayBackgroundView::SetShelfAlignment(alignment); 512 internal::TrayBackgroundView::SetShelfAlignment(alignment);
530 UpdateAfterShelfAlignmentChange(alignment); 513 UpdateAfterShelfAlignmentChange(alignment);
531 SetBorder(); 514 SetBorder();
532 tray_container_->UpdateLayout(alignment); 515 tray_container_->UpdateLayout(alignment);
516 // Destroy an existing bubble so that it is rebuilt correctly.
517 bubble_.reset();
518 // Rebuild any notification bubble.
519 if (notification_bubble_.get()) {
520 notification_bubble_.reset();
521 UpdateNotificationBubble();
522 }
533 } 523 }
534 524
535 bool SystemTray::PerformAction(const views::Event& event) { 525 bool SystemTray::PerformAction(const views::Event& event) {
536 // If we're already showing the default view, hide it; otherwise, show it 526 // If we're already showing the default view, hide it; otherwise, show it
537 // (and hide any popup that's currently shown). 527 // (and hide any popup that's currently shown).
538 if (bubble_.get() && 528 if (bubble_.get() &&
539 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { 529 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) {
540 bubble_->Close(); 530 bubble_->Close();
541 } else { 531 } else {
542 int arrow_offset = -1; 532 int arrow_offset = TrayBubbleView::InitParams::kArrowDefaultOffset;
543 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) { 533 if (event.IsMouseEvent() || event.type() == ui::ET_GESTURE_TAP) {
544 const views::LocatedEvent& located_event = 534 const views::LocatedEvent& located_event =
545 static_cast<const views::LocatedEvent&>(event); 535 static_cast<const views::LocatedEvent&>(event);
546 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) 536 if (shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) {
547 arrow_offset = base::i18n::IsRTL() ? 537 gfx::Rect bounds(located_event.x(), 0, 0, 0);
548 located_event.x() : tray_container_->width() - located_event.x(); 538 bounds = ConvertRectToWidget(bounds);
539 arrow_offset = bounds.x();
540 }
549 } 541 }
550 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); 542 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset);
551 } 543 }
552 return true; 544 return true;
553 } 545 }
554 546
555 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { 547 void SystemTray::OnMouseEntered(const views::MouseEvent& event) {
556 TrayBackgroundView::OnMouseEntered(event); 548 TrayBackgroundView::OnMouseEntered(event);
557 should_show_launcher_ = true; 549 should_show_launcher_ = true;
558 } 550 }
(...skipping 19 matching lines...) Expand all
578 570
579 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) { 571 void SystemTray::OnPaintFocusBorder(gfx::Canvas* canvas) {
580 // The tray itself expands to the right and bottom edge of the screen to make 572 // The tray itself expands to the right and bottom edge of the screen to make
581 // sure clicking on the edges brings up the popup. However, the focus border 573 // sure clicking on the edges brings up the popup. However, the focus border
582 // should be only around the container. 574 // should be only around the container.
583 if (GetWidget() && GetWidget()->IsActive()) 575 if (GetWidget() && GetWidget()->IsActive())
584 canvas->DrawFocusRect(tray_container_->bounds()); 576 canvas->DrawFocusRect(tray_container_->bounds());
585 } 577 }
586 578
587 } // namespace ash 579 } // 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.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698