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 3 // found in the LICENSE file. 4 5 #include "ash/shelf/shelf_widget.h" 6 7 #include "ash/ash_switches.h" 8 #include "ash/focus_cycler.h" 9 #include "ash/root_window_controller.h" 10 #include "ash/session_state_delegate.h" 11 #include "ash/shelf/shelf_delegate.h" 12 #include "ash/shelf/shelf_layout_manager.h" 13 #include "ash/shelf/shelf_model.h" 14 #include "ash/shelf/shelf_navigator.h" 15 #include "ash/shelf/shelf_view.h" 16 #include "ash/shelf/shelf_widget.h" 17 #include "ash/shell.h" 18 #include "ash/shell_window_ids.h" 19 #include "ash/system/tray/system_tray_delegate.h" 20 #include "ash/wm/status_area_layout_manager.h" 21 #include "ash/wm/window_properties.h" 22 #include "ash/wm/workspace_controller.h" 23 #include "grit/ash_resources.h" 24 #include "ui/aura/client/activation_client.h" 25 #include "ui/aura/root_window.h" 26 #include "ui/aura/window.h" 27 #include "ui/aura/window_observer.h" 28 #include "ui/base/resource/resource_bundle.h" 29 #include "ui/compositor/layer.h" 30 #include "ui/compositor/scoped_layer_animation_settings.h" 31 #include "ui/events/event_constants.h" 32 #include "ui/gfx/canvas.h" 33 #include "ui/gfx/image/image.h" 34 #include "ui/gfx/image/image_skia_operations.h" 35 #include "ui/gfx/skbitmap_operations.h" 36 #include "ui/views/accessible_pane_view.h" 37 #include "ui/views/widget/widget.h" 38 #include "ui/views/widget/widget_delegate.h" 39 40 namespace { 41 // Size of black border at bottom (or side) of launcher. 42 const int kNumBlackPixels = 3; 43 // Alpha to paint dimming image with. 44 const int kDimAlpha = 128; 45 46 // The time to dim and un-dim. 47 const int kTimeToDimMs = 3000; // Slow in dimming. 48 const int kTimeToUnDimMs = 200; // Fast in activating. 49 50 // Class used to slightly dim shelf items when maximized and visible. 51 class DimmerView : public views::View, 52 public views::WidgetDelegate, 53 ash::internal::BackgroundAnimatorDelegate { 54 public: 55 // If |disable_dimming_animations_for_test| is set, all alpha animations will 56 // be performed instantly. 57 DimmerView(ash::ShelfWidget* shelf_widget, 58 bool disable_dimming_animations_for_test); 59 virtual ~DimmerView(); 60 61 // Called by |DimmerEventFilter| when the mouse |hovered| state changes. 62 void SetHovered(bool hovered); 63 64 // Force the dimmer to be undimmed. 65 void ForceUndimming(bool force); 66 67 // views::WidgetDelegate overrides: 68 virtual views::Widget* GetWidget() OVERRIDE { 69 return View::GetWidget(); 70 } 71 virtual const views::Widget* GetWidget() const OVERRIDE { 72 return View::GetWidget(); 73 } 74 75 // ash::internal::BackgroundAnimatorDelegate overrides: 76 virtual void UpdateBackground(int alpha) OVERRIDE { 77 alpha_ = alpha; 78 SchedulePaint(); 79 } 80 81 // views::View overrides: 82 virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE; 83 84 // A function to test the current alpha used. 85 int get_dimming_alpha_for_test() { return alpha_; } 86 87 private: 88 // This class monitors mouse events to see if it is on top of the launcher. 89 class DimmerEventFilter : public ui::EventHandler { 90 public: 91 explicit DimmerEventFilter(DimmerView* owner); 92 virtual ~DimmerEventFilter(); 93 94 // Overridden from ui::EventHandler: 95 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE; 96 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE; 97 98 private: 99 // The owning class. 100 DimmerView* owner_; 101 102 // TRUE if the mouse is inside the shelf. 103 bool mouse_inside_; 104 105 // TRUE if a touch event is inside the shelf. 106 bool touch_inside_; 107 108 DISALLOW_COPY_AND_ASSIGN(DimmerEventFilter); 109 }; 110 111 // The owning shelf. 112 ash::ShelfWidget* shelf_; 113 114 // The alpha to use for covering the shelf. 115 int alpha_; 116 117 // True if the event filter claims that we should not be dimmed. 118 bool is_hovered_; 119 120 // True if someone forces us not to be dimmed (e.g. a menu is open). 121 bool force_hovered_; 122 123 // True if animations should be suppressed for a test. 124 bool disable_dimming_animations_for_test_; 125 126 // The animator for the background transitions. 127 ash::internal::BackgroundAnimator background_animator_; 128 129 // Notification of entering / exiting of the shelf area by mouse. 130 scoped_ptr<DimmerEventFilter> event_filter_; 131 132 DISALLOW_COPY_AND_ASSIGN(DimmerView); 133 }; 134 135 DimmerView::DimmerView(ash::ShelfWidget* shelf_widget, 136 bool disable_dimming_animations_for_test) 137 : shelf_(shelf_widget), 138 alpha_(kDimAlpha), 139 is_hovered_(false), 140 force_hovered_(false), 141 disable_dimming_animations_for_test_(disable_dimming_animations_for_test), 142 background_animator_(this, 0, kDimAlpha) { 143 event_filter_.reset(new DimmerEventFilter(this)); 144 // Make sure it is undimmed at the beginning and then fire off the dimming 145 // animation. 146 background_animator_.SetPaintsBackground(false, 147 ash::BACKGROUND_CHANGE_IMMEDIATE); 148 SetHovered(false); 149 } 150 151 DimmerView::~DimmerView() { 152 } 153 154 void DimmerView::SetHovered(bool hovered) { 155 // Remember the hovered state so that we can correct the state once a 156 // possible force state has disappeared. 157 is_hovered_ = hovered; 158 // Undimm also if we were forced to by e.g. an open menu. 159 hovered |= force_hovered_; 160 background_animator_.SetDuration(hovered ? kTimeToUnDimMs : kTimeToDimMs); 161 background_animator_.SetPaintsBackground(!hovered, 162 disable_dimming_animations_for_test_ ? 163 ash::BACKGROUND_CHANGE_IMMEDIATE : ash::BACKGROUND_CHANGE_ANIMATE); 164 } 165 166 void DimmerView::ForceUndimming(bool force) { 167 bool previous = force_hovered_; 168 force_hovered_ = force; 169 // If the forced change does change the result we apply the change. 170 if (is_hovered_ || force_hovered_ != is_hovered_ || previous) 171 SetHovered(is_hovered_); 172 } 173 174 void DimmerView::OnPaintBackground(gfx::Canvas* canvas) { 175 SkPaint paint; 176 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 177 gfx::ImageSkia launcher_background = 178 *rb.GetImageNamed(IDR_AURA_LAUNCHER_DIMMING).ToImageSkia(); 179 180 if (shelf_->GetAlignment() != ash::SHELF_ALIGNMENT_BOTTOM) { 181 launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage( 182 launcher_background, 183 shelf_->shelf_layout_manager()->SelectValueForShelfAlignment( 184 SkBitmapOperations::ROTATION_90_CW, 185 SkBitmapOperations::ROTATION_90_CW, 186 SkBitmapOperations::ROTATION_270_CW, 187 SkBitmapOperations::ROTATION_180_CW)); 188 } 189 paint.setAlpha(alpha_); 190 canvas->DrawImageInt( 191 launcher_background, 192 0, 0, launcher_background.width(), launcher_background.height(), 193 0, 0, width(), height(), 194 false, 195 paint); 196 } 197 198 DimmerView::DimmerEventFilter::DimmerEventFilter(DimmerView* owner) 199 : owner_(owner), 200 mouse_inside_(false), 201 touch_inside_(false) { 202 ash::Shell::GetInstance()->AddPreTargetHandler(this); 203 } 204 205 DimmerView::DimmerEventFilter::~DimmerEventFilter() { 206 ash::Shell::GetInstance()->RemovePreTargetHandler(this); 207 } 208 209 void DimmerView::DimmerEventFilter::OnMouseEvent(ui::MouseEvent* event) { 210 if (event->type() != ui::ET_MOUSE_MOVED && 211 event->type() != ui::ET_MOUSE_DRAGGED) 212 return; 213 bool inside = owner_->GetBoundsInScreen().Contains(event->root_location()); 214 if (mouse_inside_ || touch_inside_ != inside || touch_inside_) 215 owner_->SetHovered(inside || touch_inside_); 216 mouse_inside_ = inside; 217 } 218 219 void DimmerView::DimmerEventFilter::OnTouchEvent(ui::TouchEvent* event) { 220 bool touch_inside = false; 221 if (event->type() != ui::ET_TOUCH_RELEASED && 222 event->type() != ui::ET_TOUCH_CANCELLED) 223 touch_inside = owner_->GetBoundsInScreen().Contains(event->root_location()); 224 225 if (mouse_inside_ || touch_inside_ != mouse_inside_ || touch_inside) 226 owner_->SetHovered(mouse_inside_ || touch_inside); 227 touch_inside_ = touch_inside; 228 } 229 230 } // namespace 231 232 namespace ash { 233 234 // The contents view of the Shelf. This view contains ShelfView and 235 // sizes it to the width of the shelf minus the size of the status area. 236 class ShelfWidget::DelegateView : public views::WidgetDelegate, 237 public views::AccessiblePaneView, 238 public internal::BackgroundAnimatorDelegate, 239 public aura::WindowObserver { 240 public: 241 explicit DelegateView(ShelfWidget* shelf); 242 virtual ~DelegateView(); 243 244 void set_focus_cycler(internal::FocusCycler* focus_cycler) { 245 focus_cycler_ = focus_cycler; 246 } 247 internal::FocusCycler* focus_cycler() { 248 return focus_cycler_; 249 } 250 251 ui::Layer* opaque_background() { return &opaque_background_; } 252 253 // Set if the shelf area is dimmed (eg when a window is maximized). 254 void SetDimmed(bool dimmed); 255 bool GetDimmed() const; 256 257 void SetParentLayer(ui::Layer* layer); 258 259 // views::View overrides: 260 virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE; 261 262 // views::WidgetDelegateView overrides: 263 virtual views::Widget* GetWidget() OVERRIDE { 264 return View::GetWidget(); 265 } 266 virtual const views::Widget* GetWidget() const OVERRIDE { 267 return View::GetWidget(); 268 } 269 270 virtual bool CanActivate() const OVERRIDE; 271 virtual void Layout() OVERRIDE; 272 virtual void ReorderChildLayers(ui::Layer* parent_layer) OVERRIDE; 273 // This will be called when the parent local bounds change. 274 virtual void OnBoundsChanged(const gfx::Rect& old_bounds) OVERRIDE; 275 276 // aura::WindowObserver overrides: 277 // This will be called when the shelf itself changes its absolute position. 278 // Since the |dimmer_| panel needs to be placed in screen coordinates it needs 279 // to be repositioned. The difference to the OnBoundsChanged call above is 280 // that this gets also triggered when the shelf only moves. 281 virtual void OnWindowBoundsChanged(aura::Window* window, 282 const gfx::Rect& old_bounds, 283 const gfx::Rect& new_bounds) OVERRIDE; 284 285 // BackgroundAnimatorDelegate overrides: 286 virtual void UpdateBackground(int alpha) OVERRIDE; 287 288 // Force the shelf to be presented in an undimmed state. 289 void ForceUndimming(bool force); 290 291 // A function to test the current alpha used by the dimming bar. If there is 292 // no dimmer active, the function will return -1. 293 int GetDimmingAlphaForTest(); 294 295 // A function to test the bounds of the dimming bar. Returns gfx::Rect() if 296 // the dimmer is inactive. 297 gfx::Rect GetDimmerBoundsForTest(); 298 299 // Disable dimming animations for running tests. This needs to be called 300 // prior to the creation of of the |dimmer_|. 301 void disable_dimming_animations_for_test() { 302 disable_dimming_animations_for_test_ = true; 303 } 304 305 private: 306 ShelfWidget* shelf_; 307 scoped_ptr<views::Widget> dimmer_; 308 internal::FocusCycler* focus_cycler_; 309 int alpha_; 310 ui::Layer opaque_background_; 311 312 // The view which does the dimming. 313 DimmerView* dimmer_view_; 314 315 // True if dimming animations should be turned off. 316 bool disable_dimming_animations_for_test_; 317 318 DISALLOW_COPY_AND_ASSIGN(DelegateView); 319 }; 320 321 ShelfWidget::DelegateView::DelegateView(ShelfWidget* shelf) 322 : shelf_(shelf), 323 focus_cycler_(NULL), 324 alpha_(0), 325 opaque_background_(ui::LAYER_SOLID_COLOR), 326 dimmer_view_(NULL), 327 disable_dimming_animations_for_test_(false) { 328 set_allow_deactivate_on_esc(true); 329 opaque_background_.SetColor(SK_ColorBLACK); 330 opaque_background_.SetBounds(GetLocalBounds()); 331 opaque_background_.SetOpacity(0.0f); 332 } 333 334 ShelfWidget::DelegateView::~DelegateView() { 335 // Make sure that the dimmer goes away since it might have set an observer. 336 SetDimmed(false); 337 } 338 339 void ShelfWidget::DelegateView::SetDimmed(bool value) { 340 if (value == (dimmer_.get() != NULL)) 341 return; 342 343 if (value) { 344 dimmer_.reset(new views::Widget); 345 views::Widget::InitParams params( 346 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 347 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 348 params.can_activate = false; 349 params.accept_events = false; 350 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 351 params.parent = shelf_->GetNativeView(); 352 dimmer_->Init(params); 353 dimmer_->GetNativeWindow()->SetName("ShelfDimmer"); 354 dimmer_->SetBounds(shelf_->GetWindowBoundsInScreen()); 355 // The launcher should not take focus when it is initially shown. 356 dimmer_->set_focus_on_creation(false); 357 dimmer_view_ = new DimmerView(shelf_, disable_dimming_animations_for_test_); 358 dimmer_->SetContentsView(dimmer_view_); 359 dimmer_->GetNativeView()->SetName("ShelfDimmerView"); 360 dimmer_->Show(); 361 shelf_->GetNativeView()->AddObserver(this); 362 } else { 363 // Some unit tests will come here with a destroyed window. 364 if (shelf_->GetNativeView()) 365 shelf_->GetNativeView()->RemoveObserver(this); 366 dimmer_view_ = NULL; 367 dimmer_.reset(NULL); 368 } 369 } 370 371 bool ShelfWidget::DelegateView::GetDimmed() const { 372 return dimmer_.get() && dimmer_->IsVisible(); 373 } 374 375 void ShelfWidget::DelegateView::SetParentLayer(ui::Layer* layer) { 376 layer->Add(&opaque_background_); 377 ReorderLayers(); 378 } 379 380 void ShelfWidget::DelegateView::OnPaintBackground(gfx::Canvas* canvas) { 381 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 382 gfx::ImageSkia launcher_background = 383 *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_BACKGROUND); 384 if (SHELF_ALIGNMENT_BOTTOM != shelf_->GetAlignment()) 385 launcher_background = gfx::ImageSkiaOperations::CreateRotatedImage( 386 launcher_background, 387 shelf_->shelf_layout_manager()->SelectValueForShelfAlignment( 388 SkBitmapOperations::ROTATION_90_CW, 389 SkBitmapOperations::ROTATION_90_CW, 390 SkBitmapOperations::ROTATION_270_CW, 391 SkBitmapOperations::ROTATION_180_CW)); 392 const gfx::Rect dock_bounds(shelf_->shelf_layout_manager()->dock_bounds()); 393 SkPaint paint; 394 paint.setAlpha(alpha_); 395 canvas->DrawImageInt( 396 launcher_background, 397 0, 0, launcher_background.width(), launcher_background.height(), 398 (SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() && 399 dock_bounds.x() == 0 && dock_bounds.width() > 0) ? 400 dock_bounds.width() : 0, 0, 401 SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() ? 402 width() - dock_bounds.width() : width(), height(), 403 false, 404 paint); 405 if (SHELF_ALIGNMENT_BOTTOM == shelf_->GetAlignment() && 406 dock_bounds.width() > 0) { 407 // The part of the shelf background that is in the corner below the docked 408 // windows close to the work area is an arched gradient that blends 409 // vertically oriented docked background and horizontal shelf. 410 gfx::ImageSkia launcher_corner = 411 *rb.GetImageSkiaNamed(IDR_AURA_LAUNCHER_CORNER); 412 if (dock_bounds.x() == 0) { 413 launcher_corner = gfx::ImageSkiaOperations::CreateRotatedImage( 414 launcher_corner, SkBitmapOperations::ROTATION_90_CW); 415 } 416 canvas->DrawImageInt( 417 launcher_corner, 418 0, 0, launcher_corner.width(), launcher_corner.height(), 419 dock_bounds.x() > 0 ? dock_bounds.x() : dock_bounds.width() - height(), 420 0, 421 height(), height(), 422 false, 423 paint); 424 // The part of the shelf background that is just below the docked windows 425 // is drawn using the last (lowest) 1-pixel tall strip of the image asset. 426 // This avoids showing the border 3D shadow between the shelf and the dock. 427 canvas->DrawImageInt( 428 launcher_background, 429 0, launcher_background.height() - 1, launcher_background.width(), 1, 430 dock_bounds.x() > 0 ? dock_bounds.x() + height() : 0, 0, 431 dock_bounds.width() - height(), height(), 432 false, 433 paint); 434 } 435 gfx::Rect black_rect = 436 shelf_->shelf_layout_manager()->SelectValueForShelfAlignment( 437 gfx::Rect(0, height() - kNumBlackPixels, width(), kNumBlackPixels), 438 gfx::Rect(0, 0, kNumBlackPixels, height()), 439 gfx::Rect(width() - kNumBlackPixels, 0, kNumBlackPixels, height()), 440 gfx::Rect(0, 0, width(), kNumBlackPixels)); 441 canvas->FillRect(black_rect, SK_ColorBLACK); 442 } 443 444 bool ShelfWidget::DelegateView::CanActivate() const { 445 // Allow to activate as fallback. 446 if (shelf_->activating_as_fallback_) 447 return true; 448 // Allow to activate from the focus cycler. 449 if (focus_cycler_ && focus_cycler_->widget_activating() == GetWidget()) 450 return true; 451 // Disallow activating in other cases, especially when using mouse. 452 return false; 453 } 454 455 void ShelfWidget::DelegateView::Layout() { 456 for(int i = 0; i < child_count(); ++i) { 457 if (shelf_->shelf_layout_manager()->IsHorizontalAlignment()) { 458 child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(), 459 child_at(i)->width(), height()); 460 } else { 461 child_at(i)->SetBounds(child_at(i)->x(), child_at(i)->y(), 462 width(), child_at(i)->height()); 463 } 464 } 465 } 466 467 void ShelfWidget::DelegateView::ReorderChildLayers(ui::Layer* parent_layer) { 468 views::View::ReorderChildLayers(parent_layer); 469 parent_layer->StackAtBottom(&opaque_background_); 470 } 471 472 void ShelfWidget::DelegateView::OnBoundsChanged(const gfx::Rect& old_bounds) { 473 opaque_background_.SetBounds(GetLocalBounds()); 474 if (dimmer_) 475 dimmer_->SetBounds(GetBoundsInScreen()); 476 } 477 478 void ShelfWidget::DelegateView::OnWindowBoundsChanged( 479 aura::Window* window, 480 const gfx::Rect& old_bounds, 481 const gfx::Rect& new_bounds) { 482 // Coming here the shelf got repositioned and since the |dimmer_| is placed 483 // in screen coordinates and not relative to the parent it needs to be 484 // repositioned accordingly. 485 dimmer_->SetBounds(GetBoundsInScreen()); 486 } 487 488 void ShelfWidget::DelegateView::ForceUndimming(bool force) { 489 if (GetDimmed()) 490 dimmer_view_->ForceUndimming(force); 491 } 492 493 int ShelfWidget::DelegateView::GetDimmingAlphaForTest() { 494 if (GetDimmed()) 495 return dimmer_view_->get_dimming_alpha_for_test(); 496 return -1; 497 } 498 499 gfx::Rect ShelfWidget::DelegateView::GetDimmerBoundsForTest() { 500 if (GetDimmed()) 501 return dimmer_view_->GetBoundsInScreen(); 502 return gfx::Rect(); 503 } 504 505 void ShelfWidget::DelegateView::UpdateBackground(int alpha) { 506 alpha_ = alpha; 507 SchedulePaint(); 508 } 509 510 ShelfWidget::ShelfWidget(aura::Window* shelf_container, 511 aura::Window* status_container, 512 internal::WorkspaceController* workspace_controller) 513 : delegate_view_(new DelegateView(this)), 514 background_animator_(delegate_view_, 0, kLauncherBackgroundAlpha), 515 activating_as_fallback_(false), 516 window_container_(shelf_container) { 517 views::Widget::InitParams params( 518 views::Widget::InitParams::TYPE_WINDOW_FRAMELESS); 519 params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW; 520 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 521 params.parent = shelf_container; 522 params.delegate = delegate_view_; 523 Init(params); 524 525 // The shelf should not take focus when initially shown. 526 set_focus_on_creation(false); 527 SetContentsView(delegate_view_); 528 delegate_view_->SetParentLayer(GetLayer()); 529 530 status_area_widget_ = new internal::StatusAreaWidget(status_container); 531 status_area_widget_->CreateTrayViews(); 532 if (Shell::GetInstance()->session_state_delegate()-> 533 IsActiveUserSessionStarted()) { 534 status_area_widget_->Show(); 535 } 536 Shell::GetInstance()->focus_cycler()->AddWidget(status_area_widget_); 537 538 shelf_layout_manager_ = new internal::ShelfLayoutManager(this); 539 shelf_layout_manager_->AddObserver(this); 540 shelf_container->SetLayoutManager(shelf_layout_manager_); 541 shelf_layout_manager_->set_workspace_controller(workspace_controller); 542 workspace_controller->SetShelf(shelf_layout_manager_); 543 544 status_container->SetLayoutManager( 545 new internal::StatusAreaLayoutManager(this)); 546 547 views::Widget::AddObserver(this); 548 } 549 550 ShelfWidget::~ShelfWidget() { 551 RemoveObserver(this); 552 } 553 554 void ShelfWidget::SetPaintsBackground( 555 ShelfBackgroundType background_type, 556 BackgroundAnimatorChangeType change_type) { 557 ui::Layer* opaque_background = delegate_view_->opaque_background(); 558 float target_opacity = 559 (background_type == SHELF_BACKGROUND_MAXIMIZED) ? 1.0f : 0.0f; 560 scoped_ptr<ui::ScopedLayerAnimationSettings> opaque_background_animation; 561 if (change_type != BACKGROUND_CHANGE_IMMEDIATE) { 562 opaque_background_animation.reset(new ui::ScopedLayerAnimationSettings( 563 opaque_background->GetAnimator())); 564 opaque_background_animation->SetTransitionDuration( 565 base::TimeDelta::FromMilliseconds(kTimeToSwitchBackgroundMs)); 566 } 567 opaque_background->SetOpacity(target_opacity); 568 569 // TODO(mukai): use ui::Layer on both opaque_background and normal background 570 // retire background_animator_ at all. It would be simpler. 571 // See also DockedBackgroundWidget::SetPaintsBackground. 572 background_animator_.SetPaintsBackground( 573 background_type != SHELF_BACKGROUND_DEFAULT, 574 change_type); 575 delegate_view_->SchedulePaint(); 576 } 577 578 ShelfBackgroundType ShelfWidget::GetBackgroundType() const { 579 if (delegate_view_->opaque_background()->GetTargetOpacity() == 1.0f) 580 return SHELF_BACKGROUND_MAXIMIZED; 581 if (background_animator_.paints_background()) 582 return SHELF_BACKGROUND_OVERLAP; 583 584 return SHELF_BACKGROUND_DEFAULT; 585 } 586 587 // static 588 bool ShelfWidget::ShelfAlignmentAllowed() { 589 if (!ash::switches::ShowShelfAlignmentMenu()) 590 return false; 591 user::LoginStatus login_status = 592 Shell::GetInstance()->system_tray_delegate()->GetUserLoginStatus(); 593 594 switch (login_status) { 595 case user::LOGGED_IN_USER: 596 case user::LOGGED_IN_OWNER: 597 return true; 598 case user::LOGGED_IN_LOCKED: 599 case user::LOGGED_IN_PUBLIC: 600 case user::LOGGED_IN_LOCALLY_MANAGED: 601 case user::LOGGED_IN_GUEST: 602 case user::LOGGED_IN_RETAIL_MODE: 603 case user::LOGGED_IN_KIOSK_APP: 604 case user::LOGGED_IN_NONE: 605 return false; 606 } 607 608 DCHECK(false); 609 return false; 610 } 611 612 ShelfAlignment ShelfWidget::GetAlignment() const { 613 return shelf_layout_manager_->GetAlignment(); 614 } 615 616 void ShelfWidget::SetAlignment(ShelfAlignment alignment) { 617 if (launcher_) 618 launcher_->SetAlignment(alignment); 619 status_area_widget_->SetShelfAlignment(alignment); 620 delegate_view_->SchedulePaint(); 621 } 622 623 void ShelfWidget::SetDimsShelf(bool dimming) { 624 delegate_view_->SetDimmed(dimming); 625 // Repaint all children, allowing updates to reflect dimmed state eg: 626 // status area background, app list button and overflow button. 627 if (launcher_) 628 launcher_->SchedulePaint(); 629 status_area_widget_->GetContentsView()->SchedulePaint(); 630 } 631 632 bool ShelfWidget::GetDimsShelf() const { 633 return delegate_view_->GetDimmed(); 634 } 635 636 void ShelfWidget::CreateLauncher() { 637 if (launcher_) 638 return; 639 640 Shell* shell = Shell::GetInstance(); 641 // This needs to be called before shelf_model(). 642 ShelfDelegate* shelf_delegate = shell->GetShelfDelegate(); 643 if (!shelf_delegate) 644 return; // Not ready to create Launcher 645 646 launcher_.reset(new Launcher(shell->shelf_model(), 647 shell->GetShelfDelegate(), 648 this)); 649 SetFocusCycler(shell->focus_cycler()); 650 651 // Inform the root window controller. 652 internal::RootWindowController::ForWindow(window_container_)-> 653 OnLauncherCreated(); 654 655 launcher_->SetVisible( 656 shell->session_state_delegate()->IsActiveUserSessionStarted()); 657 shelf_layout_manager_->LayoutShelf(); 658 Show(); 659 } 660 661 bool ShelfWidget::IsLauncherVisible() const { 662 return launcher_.get() && launcher_->IsVisible(); 663 } 664 665 void ShelfWidget::SetLauncherVisibility(bool visible) { 666 if (launcher_) 667 launcher_->SetVisible(visible); 668 } 669 670 void ShelfWidget::SetFocusCycler(internal::FocusCycler* focus_cycler) { 671 delegate_view_->set_focus_cycler(focus_cycler); 672 if (focus_cycler) 673 focus_cycler->AddWidget(this); 674 } 675 676 internal::FocusCycler* ShelfWidget::GetFocusCycler() { 677 return delegate_view_->focus_cycler(); 678 } 679 680 void ShelfWidget::ShutdownStatusAreaWidget() { 681 if (status_area_widget_) 682 status_area_widget_->Shutdown(); 683 status_area_widget_ = NULL; 684 } 685 686 void ShelfWidget::ForceUndimming(bool force) { 687 delegate_view_->ForceUndimming(force); 688 } 689 690 void ShelfWidget::OnWidgetActivationChanged(views::Widget* widget, 691 bool active) { 692 activating_as_fallback_ = false; 693 if (active) 694 delegate_view_->SetPaneFocusAndFocusDefault(); 695 else 696 delegate_view_->GetFocusManager()->ClearFocus(); 697 } 698 699 int ShelfWidget::GetDimmingAlphaForTest() { 700 if (delegate_view_) 701 return delegate_view_->GetDimmingAlphaForTest(); 702 return -1; 703 } 704 705 gfx::Rect ShelfWidget::GetDimmerBoundsForTest() { 706 if (delegate_view_) 707 return delegate_view_->GetDimmerBoundsForTest(); 708 return gfx::Rect(); 709 } 710 711 void ShelfWidget::DisableDimmingAnimationsForTest() { 712 DCHECK(delegate_view_); 713 return delegate_view_->disable_dimming_animations_for_test(); 714 } 715 716 void ShelfWidget::WillDeleteShelf() { 717 shelf_layout_manager_->RemoveObserver(this); 718 shelf_layout_manager_ = NULL; 719 } 720 721 } // namespace ash 722