| OLD | NEW |
| 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 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 } | 236 } |
| 237 | 237 |
| 238 void SystemTray::AddTrayItem(SystemTrayItem* item) { | 238 void SystemTray::AddTrayItem(SystemTrayItem* item) { |
| 239 items_.push_back(item); | 239 items_.push_back(item); |
| 240 | 240 |
| 241 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); | 241 SystemTrayDelegate* delegate = Shell::GetInstance()->tray_delegate(); |
| 242 views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus()); | 242 views::View* tray_item = item->CreateTrayView(delegate->GetUserLoginStatus()); |
| 243 if (tray_item) { | 243 if (tray_item) { |
| 244 tray_container_->AddChildViewAt(tray_item, 0); | 244 tray_container_->AddChildViewAt(tray_item, 0); |
| 245 PreferredSizeChanged(); | 245 PreferredSizeChanged(); |
| 246 tray_item_map_[item] = tray_item; |
| 246 } | 247 } |
| 247 } | 248 } |
| 248 | 249 |
| 249 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { | 250 void SystemTray::RemoveTrayItem(SystemTrayItem* item) { |
| 250 NOTIMPLEMENTED(); | 251 NOTIMPLEMENTED(); |
| 251 } | 252 } |
| 252 | 253 |
| 253 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { | 254 void SystemTray::ShowDefaultView(BubbleCreationType creation_type) { |
| 254 ShowItems(items_.get(), false, true, creation_type); | 255 ShowDefaultViewWithOffset(creation_type, -1); |
| 255 } | 256 } |
| 256 | 257 |
| 257 void SystemTray::ShowDetailedView(SystemTrayItem* item, | 258 void SystemTray::ShowDetailedView(SystemTrayItem* item, |
| 258 int close_delay, | 259 int close_delay, |
| 259 bool activate, | 260 bool activate, |
| 260 BubbleCreationType creation_type) { | 261 BubbleCreationType creation_type) { |
| 261 std::vector<SystemTrayItem*> items; | 262 std::vector<SystemTrayItem*> items; |
| 262 items.push_back(item); | 263 items.push_back(item); |
| 263 ShowItems(items, true, activate, creation_type); | 264 ShowItems(items, true, activate, creation_type, GetTrayXOffset(item)); |
| 264 bubble_->StartAutoCloseTimer(close_delay); | 265 bubble_->StartAutoCloseTimer(close_delay); |
| 265 } | 266 } |
| 266 | 267 |
| 267 void SystemTray::ShowNotificationView(SystemTrayItem* item) { | 268 void SystemTray::ShowNotificationView(SystemTrayItem* item) { |
| 268 if (std::find(notification_items_.begin(), notification_items_.end(), item) | 269 if (std::find(notification_items_.begin(), notification_items_.end(), item) |
| 269 != notification_items_.end()) | 270 != notification_items_.end()) |
| 270 return; | 271 return; |
| 271 notification_items_.push_back(item); | 272 notification_items_.push_back(item); |
| 272 UpdateNotificationBubble(); | 273 UpdateNotificationBubble(); |
| 273 } | 274 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 NOTREACHED(); | 329 NOTREACHED(); |
| 329 } | 330 } |
| 330 } | 331 } |
| 331 | 332 |
| 332 void SystemTray::SetPaintsBackground( | 333 void SystemTray::SetPaintsBackground( |
| 333 bool value, | 334 bool value, |
| 334 internal::BackgroundAnimator::ChangeType change_type) { | 335 internal::BackgroundAnimator::ChangeType change_type) { |
| 335 hide_background_animator_.SetPaintsBackground(value, change_type); | 336 hide_background_animator_.SetPaintsBackground(value, change_type); |
| 336 } | 337 } |
| 337 | 338 |
| 339 int SystemTray::GetTrayXOffset(SystemTrayItem* item) const { |
| 340 std::map<SystemTrayItem*, views::View*>::const_iterator it = |
| 341 tray_item_map_.find(item); |
| 342 if (it == tray_item_map_.end()) |
| 343 return -1; |
| 344 |
| 345 const views::View* item_view = it->second; |
| 346 gfx::Rect item_bounds = item_view->bounds(); |
| 347 if (!item_bounds.IsEmpty()) { |
| 348 int x_offset = item_bounds.x() + item_bounds.width() / 2; |
| 349 return base::i18n::IsRTL() ? x_offset : tray_container_->width() - x_offset; |
| 350 } |
| 351 |
| 352 // The bounds of item could be still empty. It could happen in the case that |
| 353 // the view appears for the first time in the current session, because the |
| 354 // bounds is not calculated yet. In that case, we want to guess the offset |
| 355 // from the position of its parent. |
| 356 int x_offset = 0; |
| 357 for (int i = 0; i < tray_container_->child_count(); ++i) { |
| 358 const views::View* child = tray_container_->child_at(i); |
| 359 if (child == item_view) |
| 360 return base::i18n::IsRTL() ? |
| 361 x_offset : tray_container_->width() - x_offset; |
| 362 |
| 363 if (!child->visible()) |
| 364 continue; |
| 365 x_offset = child->bounds().right(); |
| 366 } |
| 367 |
| 368 return -1; |
| 369 } |
| 370 |
| 371 void SystemTray::ShowDefaultViewWithOffset(BubbleCreationType creation_type, |
| 372 int arrow_offset) { |
| 373 ShowItems(items_.get(), false, true, creation_type, arrow_offset); |
| 374 } |
| 375 |
| 338 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, | 376 void SystemTray::ShowItems(const std::vector<SystemTrayItem*>& items, |
| 339 bool detailed, | 377 bool detailed, |
| 340 bool can_activate, | 378 bool can_activate, |
| 341 BubbleCreationType creation_type) { | 379 BubbleCreationType creation_type, |
| 380 int arrow_offset) { |
| 342 // Destroy any existing bubble and create a new one. | 381 // Destroy any existing bubble and create a new one. |
| 343 SystemTrayBubble::BubbleType bubble_type = detailed ? | 382 SystemTrayBubble::BubbleType bubble_type = detailed ? |
| 344 SystemTrayBubble::BUBBLE_TYPE_DETAILED : | 383 SystemTrayBubble::BUBBLE_TYPE_DETAILED : |
| 345 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; | 384 SystemTrayBubble::BUBBLE_TYPE_DEFAULT; |
| 346 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { | 385 if (bubble_.get() && creation_type == BUBBLE_USE_EXISTING) { |
| 347 bubble_->UpdateView(items, bubble_type); | 386 bubble_->UpdateView(items, bubble_type); |
| 348 } else { | 387 } else { |
| 349 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); | 388 bubble_.reset(new SystemTrayBubble(this, items, bubble_type)); |
| 350 ash::SystemTrayDelegate* delegate = | 389 ash::SystemTrayDelegate* delegate = |
| 351 ash::Shell::GetInstance()->tray_delegate(); | 390 ash::Shell::GetInstance()->tray_delegate(); |
| 352 bubble_->InitView(tray_container_, SystemTrayBubble::ANCHOR_TYPE_TRAY, | 391 views::View* anchor = tray_container_; |
| 353 can_activate, delegate->GetUserLoginStatus()); | 392 SystemTrayBubble::InitParams init_params( |
| 393 SystemTrayBubble::ANCHOR_TYPE_TRAY); |
| 394 init_params.anchor = anchor; |
| 395 init_params.can_activate = can_activate; |
| 396 init_params.login_status = delegate->GetUserLoginStatus(); |
| 397 if (arrow_offset >= 0) |
| 398 init_params.arrow_offset = arrow_offset; |
| 399 bubble_->InitView(init_params); |
| 354 } | 400 } |
| 355 // If we have focus the shelf should be visible and we need to continue | 401 // If we have focus the shelf should be visible and we need to continue |
| 356 // showing the shelf when the popup is shown. | 402 // showing the shelf when the popup is shown. |
| 357 if (GetWidget()->IsActive()) | 403 if (GetWidget()->IsActive()) |
| 358 should_show_launcher_ = true; | 404 should_show_launcher_ = true; |
| 359 UpdateNotificationBubble(); // State changed, re-create notifications. | 405 UpdateNotificationBubble(); // State changed, re-create notifications. |
| 360 } | 406 } |
| 361 | 407 |
| 362 void SystemTray::UpdateNotificationBubble() { | 408 void SystemTray::UpdateNotificationBubble() { |
| 363 // Only show the notification buble if we have notifications and we are not | 409 // Only show the notification buble if we have notifications and we are not |
| 364 // showing the default bubble. | 410 // showing the default bubble. |
| 365 if (notification_items_.empty() || | 411 if (notification_items_.empty() || |
| 366 (bubble_.get() && | 412 (bubble_.get() && |
| 367 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) { | 413 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT)) { |
| 368 notification_bubble_.reset(); | 414 notification_bubble_.reset(); |
| 369 return; | 415 return; |
| 370 } | 416 } |
| 371 notification_bubble_.reset( | 417 notification_bubble_.reset( |
| 372 new SystemTrayBubble(this, notification_items_, | 418 new SystemTrayBubble(this, notification_items_, |
| 373 SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); | 419 SystemTrayBubble::BUBBLE_TYPE_NOTIFICATION)); |
| 374 views::View* anchor; | 420 views::View* anchor; |
| 375 SystemTrayBubble::AnchorType anchor_type; | 421 SystemTrayBubble::AnchorType anchor_type; |
| 376 if (bubble_.get()) { | 422 if (bubble_.get()) { |
| 377 anchor = bubble_->bubble_view(); | 423 anchor = bubble_->bubble_view(); |
| 378 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; | 424 anchor_type = SystemTrayBubble::ANCHOR_TYPE_BUBBLE; |
| 379 } else { | 425 } else { |
| 380 anchor = tray_container_; | 426 anchor = tray_container_; |
| 381 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; | 427 anchor_type = SystemTrayBubble::ANCHOR_TYPE_TRAY; |
| 382 } | 428 } |
| 383 notification_bubble_->InitView( | 429 SystemTrayBubble::InitParams init_params(anchor_type); |
| 384 anchor, anchor_type, | 430 init_params.anchor = anchor; |
| 385 false /* can_activate */, | 431 init_params.login_status = |
| 386 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus()); | 432 ash::Shell::GetInstance()->tray_delegate()->GetUserLoginStatus(); |
| 433 int arrow_offset = GetTrayXOffset(notification_items_[0]); |
| 434 if (arrow_offset >= 0) |
| 435 init_params.arrow_offset = arrow_offset; |
| 436 notification_bubble_->InitView(init_params); |
| 387 } | 437 } |
| 388 | 438 |
| 389 void SystemTray::UpdateNotificationAnchor() { | 439 void SystemTray::UpdateNotificationAnchor() { |
| 390 if (!notification_bubble_.get()) | 440 if (!notification_bubble_.get()) |
| 391 return; | 441 return; |
| 392 notification_bubble_->bubble_view()->UpdateAnchor(); | 442 notification_bubble_->bubble_view()->UpdateAnchor(); |
| 393 // Ensure that the notification buble is above the launcher/status area. | 443 // Ensure that the notification buble is above the launcher/status area. |
| 394 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); | 444 notification_bubble_->bubble_view()->GetWidget()->StackAtTop(); |
| 395 } | 445 } |
| 396 | 446 |
| 397 bool SystemTray::PerformAction(const views::Event& event) { | 447 bool SystemTray::PerformAction(const views::Event& event) { |
| 398 // If we're already showing the default view, hide it; otherwise, show it | 448 // If we're already showing the default view, hide it; otherwise, show it |
| 399 // (and hide any popup that's currently shown). | 449 // (and hide any popup that's currently shown). |
| 400 if (bubble_.get() && | 450 if (bubble_.get() && |
| 401 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { | 451 bubble_->bubble_type() == SystemTrayBubble::BUBBLE_TYPE_DEFAULT) { |
| 402 bubble_->Close(); | 452 bubble_->Close(); |
| 403 } else { | 453 } else { |
| 404 ShowDefaultView(BUBBLE_CREATE_NEW); | 454 int arrow_offset = -1; |
| 455 if (event.IsMouseEvent() || event.IsTouchEvent()) { |
| 456 const views::LocatedEvent& located_event = |
| 457 static_cast<const views::LocatedEvent&>(event); |
| 458 arrow_offset = base::i18n::IsRTL() ? |
| 459 located_event.x() : tray_container_->width() - located_event.x(); |
| 460 } |
| 461 ShowDefaultViewWithOffset(BUBBLE_CREATE_NEW, arrow_offset); |
| 405 } | 462 } |
| 406 return true; | 463 return true; |
| 407 } | 464 } |
| 408 | 465 |
| 409 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { | 466 void SystemTray::OnMouseEntered(const views::MouseEvent& event) { |
| 410 should_show_launcher_ = true; | 467 should_show_launcher_ = true; |
| 411 hover_background_animator_.SetPaintsBackground(true, | 468 hover_background_animator_.SetPaintsBackground(true, |
| 412 internal::BackgroundAnimator::CHANGE_ANIMATE); | 469 internal::BackgroundAnimator::CHANGE_ANIMATE); |
| 413 } | 470 } |
| 414 | 471 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 440 canvas->DrawFocusRect(tray_container_->bounds()); | 497 canvas->DrawFocusRect(tray_container_->bounds()); |
| 441 } | 498 } |
| 442 | 499 |
| 443 void SystemTray::UpdateBackground(int alpha) { | 500 void SystemTray::UpdateBackground(int alpha) { |
| 444 background_->set_alpha(hide_background_animator_.alpha() + | 501 background_->set_alpha(hide_background_animator_.alpha() + |
| 445 hover_background_animator_.alpha()); | 502 hover_background_animator_.alpha()); |
| 446 SchedulePaint(); | 503 SchedulePaint(); |
| 447 } | 504 } |
| 448 | 505 |
| 449 } // namespace ash | 506 } // namespace ash |
| OLD | NEW |