1 // Copyright 2013 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.h" 6 7 #include <algorithm> 8 #include <cmath> 9 10 #include "ash/focus_cycler.h" 11 #include "ash/root_window_controller.h" 12 #include "ash/screen_util.h" 13 #include "ash/shelf/shelf_delegate.h" 14 #include "ash/shelf/shelf_item_delegate.h" 15 #include "ash/shelf/shelf_item_delegate_manager.h" 16 #include "ash/shelf/shelf_layout_manager.h" 17 #include "ash/shelf/shelf_model.h" 18 #include "ash/shelf/shelf_navigator.h" 19 #include "ash/shelf/shelf_util.h" 20 #include "ash/shelf/shelf_view.h" 21 #include "ash/shelf/shelf_widget.h" 22 #include "ash/shell.h" 23 #include "ash/shell_delegate.h" 24 #include "ash/shell_window_ids.h" 25 #include "ash/wm/window_properties.h" 26 #include "ui/aura/window.h" 27 #include "ui/aura/window_event_dispatcher.h" 28 #include "ui/aura/window_observer.h" 29 #include "ui/compositor/layer.h" 30 #include "ui/gfx/canvas.h" 31 #include "ui/gfx/image/image.h" 32 #include "ui/gfx/image/image_skia_operations.h" 33 #include "ui/gfx/skbitmap_operations.h" 34 #include "ui/views/accessible_pane_view.h" 35 #include "ui/views/widget/widget.h" 36 #include "ui/views/widget/widget_delegate.h" 37 #include "ui/wm/public/activation_client.h" 38 39 namespace ash { 40 41 const char Shelf::kNativeViewName[] = "ShelfView"; 42 43 Shelf::Shelf(ShelfModel* shelf_model, 44 ShelfDelegate* shelf_delegate, 45 ShelfWidget* shelf_widget) 46 : shelf_view_(NULL), 47 alignment_(shelf_widget->GetAlignment()), 48 delegate_(shelf_delegate), 49 shelf_widget_(shelf_widget) { 50 shelf_view_ = new ShelfView( 51 shelf_model, delegate_, shelf_widget_->shelf_layout_manager()); 52 shelf_view_->Init(); 53 shelf_widget_->GetContentsView()->AddChildView(shelf_view_); 54 shelf_widget_->GetNativeView()->SetName(kNativeViewName); 55 delegate_->OnShelfCreated(this); 56 } 57 58 Shelf::~Shelf() { 59 delegate_->OnShelfDestroyed(this); 60 } 61 62 // static 63 Shelf* Shelf::ForPrimaryDisplay() { 64 ShelfWidget* shelf_widget = 65 RootWindowController::ForShelf(Shell::GetPrimaryRootWindow())->shelf(); 66 return shelf_widget ? shelf_widget->shelf() : NULL; 67 } 68 69 // static 70 Shelf* Shelf::ForWindow(aura::Window* window) { 71 ShelfWidget* shelf_widget = RootWindowController::ForShelf(window)->shelf(); 72 return shelf_widget ? shelf_widget->shelf() : NULL; 73 } 74 75 void Shelf::SetAlignment(ShelfAlignment alignment) { 76 alignment_ = alignment; 77 shelf_view_->OnShelfAlignmentChanged(); 78 // ShelfLayoutManager will resize the shelf. 79 } 80 81 gfx::Rect Shelf::GetScreenBoundsOfItemIconForWindow( 82 const aura::Window* window) { 83 ShelfID id = GetShelfIDForWindow(window); 84 gfx::Rect bounds(shelf_view_->GetIdealBoundsOfItemIcon(id)); 85 gfx::Point screen_origin; 86 views::View::ConvertPointToScreen(shelf_view_, &screen_origin); 87 return gfx::Rect(screen_origin.x() + bounds.x(), 88 screen_origin.y() + bounds.y(), 89 bounds.width(), 90 bounds.height()); 91 } 92 93 void Shelf::UpdateIconPositionForWindow(aura::Window* window) { 94 shelf_view_->UpdatePanelIconPosition( 95 GetShelfIDForWindow(window), 96 ScreenUtil::ConvertRectFromScreen( 97 shelf_widget()->GetNativeView(), 98 window->GetBoundsInScreen()).CenterPoint()); 99 } 100 101 void Shelf::ActivateShelfItem(int index) { 102 // We pass in a keyboard event which will then trigger a switch to the 103 // next item if the current one is already active. 104 ui::KeyEvent event(ui::ET_KEY_RELEASED, 105 ui::VKEY_UNKNOWN, // The actual key gets ignored. 106 ui::EF_NONE); 107 108 const ShelfItem& item = shelf_view_->model()->items()[index]; 109 ShelfItemDelegate* item_delegate = 110 Shell::GetInstance()->shelf_item_delegate_manager()->GetShelfItemDelegate( 111 item.id); 112 item_delegate->ItemSelected(event); 113 } 114 115 void Shelf::CycleWindowLinear(CycleDirection direction) { 116 int item_index = GetNextActivatedItemIndex( 117 *(shelf_view_->model()), direction); 118 if (item_index >= 0) 119 ActivateShelfItem(item_index); 120 } 121 122 void Shelf::AddIconObserver(ShelfIconObserver* observer) { 123 shelf_view_->AddIconObserver(observer); 124 } 125 126 void Shelf::RemoveIconObserver(ShelfIconObserver* observer) { 127 shelf_view_->RemoveIconObserver(observer); 128 } 129 130 bool Shelf::IsShowingMenu() const { 131 return shelf_view_->IsShowingMenu(); 132 } 133 134 bool Shelf::IsShowingOverflowBubble() const { 135 return shelf_view_->IsShowingOverflowBubble(); 136 } 137 138 void Shelf::SetVisible(bool visible) const { 139 shelf_view_->SetVisible(visible); 140 } 141 142 bool Shelf::IsVisible() const { 143 return shelf_view_->visible(); 144 } 145 146 void Shelf::SchedulePaint() { 147 shelf_view_->SchedulePaintForAllButtons(); 148 } 149 150 views::View* Shelf::GetAppListButtonView() const { 151 return shelf_view_->GetAppListButtonView(); 152 } 153 154 void Shelf::LaunchAppIndexAt(int item_index) { 155 ShelfModel* shelf_model = shelf_view_->model(); 156 const ShelfItems& items = shelf_model->items(); 157 int item_count = shelf_model->item_count(); 158 int indexes_left = item_index >= 0 ? item_index : item_count; 159 int found_index = -1; 160 161 // Iterating until we have hit the index we are interested in which 162 // is true once indexes_left becomes negative. 163 for (int i = 0; i < item_count && indexes_left >= 0; i++) { 164 if (items[i].type != TYPE_APP_LIST) { 165 found_index = i; 166 indexes_left--; 167 } 168 } 169 170 // There are two ways how found_index can be valid: a.) the nth item was 171 // found (which is true when indexes_left is -1) or b.) the last item was 172 // requested (which is true when index was passed in as a negative number). 173 if (found_index >= 0 && (indexes_left == -1 || item_index < 0)) { 174 // Then set this one as active (or advance to the next item of its kind). 175 ActivateShelfItem(found_index); 176 } 177 } 178 179 void Shelf::SetShelfViewBounds(gfx::Rect bounds) { 180 shelf_view_->SetBoundsRect(bounds); 181 } 182 183 gfx::Rect Shelf::GetShelfViewBounds() const { 184 return shelf_view_->bounds(); 185 } 186 187 gfx::Rect Shelf::GetVisibleItemsBoundsInScreen() const { 188 return shelf_view_->GetVisibleItemsBoundsInScreen(); 189 } 190 191 app_list::ApplicationDragAndDropHost* Shelf::GetDragAndDropHostForAppList() { 192 return shelf_view_; 193 } 194 195 } // namespace ash 196