Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 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/launcher/launcher.h" |
| 6 | |
| 7 | #include <algorithm> |
| 8 | #include <cmath> |
| 9 | |
| 10 | #include "ash/focus_cycler.h" |
| 11 | #include "ash/launcher/launcher_delegate.h" |
| 12 | #include "ash/launcher/launcher_model.h" |
| 13 | #include "ash/launcher/launcher_navigator.h" |
| 14 | #include "ash/launcher/launcher_view.h" |
| 15 | #include "ash/root_window_controller.h" |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 16 | #include "ash/screen_ash.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 17 | #include "ash/shelf/shelf_layout_manager.h" |
| 18 | #include "ash/shelf/shelf_widget.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 19 | #include "ash/shell.h" |
| 20 | #include "ash/shell_delegate.h" |
| 21 | #include "ash/shell_window_ids.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 22 | #include "ash/wm/property_util.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 23 | #include "ash/wm/window_properties.h" |
| 24 | #include "grit/ash_resources.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 25 | #include "ui/aura/client/activation_client.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 26 | #include "ui/aura/root_window.h" |
| 27 | #include "ui/aura/window.h" |
| 28 | #include "ui/aura/window_observer.h" |
| 29 | #include "ui/base/resource/resource_bundle.h" |
| 30 | #include "ui/compositor/layer.h" |
| 31 | #include "ui/gfx/canvas.h" |
| 32 | #include "ui/gfx/image/image.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 33 | #include "ui/gfx/image/image_skia_operations.h" |
| 34 | #include "ui/gfx/skbitmap_operations.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 35 | #include "ui/views/accessible_pane_view.h" |
| 36 | #include "ui/views/widget/widget.h" |
| 37 | #include "ui/views/widget/widget_delegate.h" |
| 38 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 39 | namespace ash { |
| 40 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 41 | const char Launcher::kNativeViewName[] = "LauncherView"; |
| 42 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 43 | Launcher::Launcher(LauncherModel* launcher_model, |
| 44 | LauncherDelegate* launcher_delegate, |
| 45 | ShelfWidget* shelf_widget) |
| 46 | : launcher_view_(NULL), |
| 47 | alignment_(shelf_widget->GetAlignment()), |
| 48 | delegate_(launcher_delegate), |
| 49 | shelf_widget_(shelf_widget) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 50 | launcher_view_ = new internal::LauncherView( |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 51 | launcher_model, delegate_, shelf_widget_->shelf_layout_manager()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 52 | launcher_view_->Init(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 53 | shelf_widget_->GetContentsView()->AddChildView(launcher_view_); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 54 | shelf_widget_->GetNativeView()->SetName(kNativeViewName); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 55 | delegate_->OnLauncherCreated(this); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | Launcher::~Launcher() { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 59 | delegate_->OnLauncherDestroyed(this); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 60 | } |
| 61 | |
| 62 | // static |
| 63 | Launcher* Launcher::ForPrimaryDisplay() { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 64 | ShelfWidget* shelf_widget = internal::RootWindowController::ForLauncher( |
| 65 | Shell::GetPrimaryRootWindow())->shelf(); |
| 66 | return shelf_widget ? shelf_widget->launcher() : NULL; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 67 | } |
| 68 | |
| 69 | // static |
| 70 | Launcher* Launcher::ForWindow(aura::Window* window) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 71 | ShelfWidget* shelf_widget = |
| 72 | internal::RootWindowController::ForLauncher(window)->shelf(); |
| 73 | return shelf_widget ? shelf_widget->launcher() : NULL; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 74 | } |
| 75 | |
| 76 | void Launcher::SetAlignment(ShelfAlignment alignment) { |
| 77 | alignment_ = alignment; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 78 | launcher_view_->OnShelfAlignmentChanged(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 79 | // ShelfLayoutManager will resize the launcher. |
| 80 | } |
| 81 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 82 | gfx::Rect Launcher::GetScreenBoundsOfItemIconForWindow(aura::Window* window) { |
| 83 | LauncherID id = delegate_->GetIDByWindow(window); |
| 84 | gfx::Rect bounds(launcher_view_->GetIdealBoundsOfItemIcon(id)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 85 | gfx::Point screen_origin; |
| 86 | views::View::ConvertPointToScreen(launcher_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 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 93 | void Launcher::UpdateIconPositionForWindow(aura::Window* window) { |
| 94 | launcher_view_->UpdatePanelIconPosition( |
| 95 | delegate_->GetIDByWindow(window), |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 96 | ash::ScreenAsh::ConvertRectFromScreen( |
| 97 | shelf_widget()->GetNativeView(), |
| 98 | window->GetBoundsInScreen()).CenterPoint()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 99 | } |
| 100 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 101 | void Launcher::ActivateLauncherItem(int index) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 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 | false); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 108 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 109 | const ash::LauncherItems& items = |
| 110 | launcher_view_->model()->items(); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 111 | delegate_->ItemSelected(items[index], event); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | void Launcher::CycleWindowLinear(CycleDirection direction) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 115 | int item_index = GetNextActivatedItemIndex( |
| 116 | *(launcher_view_->model()), direction); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 117 | if (item_index >= 0) |
| 118 | ActivateLauncherItem(item_index); |
| 119 | } |
| 120 | |
| 121 | void Launcher::AddIconObserver(LauncherIconObserver* observer) { |
| 122 | launcher_view_->AddIconObserver(observer); |
| 123 | } |
| 124 | |
| 125 | void Launcher::RemoveIconObserver(LauncherIconObserver* observer) { |
| 126 | launcher_view_->RemoveIconObserver(observer); |
| 127 | } |
| 128 | |
| 129 | bool Launcher::IsShowingMenu() const { |
| 130 | return launcher_view_->IsShowingMenu(); |
| 131 | } |
| 132 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 133 | bool Launcher::IsShowingOverflowBubble() const { |
| 134 | return launcher_view_->IsShowingOverflowBubble(); |
| 135 | } |
| 136 | |
| 137 | void Launcher::SetVisible(bool visible) const { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 138 | launcher_view_->SetVisible(visible); |
| 139 | } |
| 140 | |
| 141 | bool Launcher::IsVisible() const { |
| 142 | return launcher_view_->visible(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 143 | } |
| 144 | |
| 145 | views::View* Launcher::GetAppListButtonView() const { |
| 146 | return launcher_view_->GetAppListButtonView(); |
| 147 | } |
| 148 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 149 | void Launcher::LaunchAppIndexAt(int item_index) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 150 | LauncherModel* launcher_model = launcher_view_->model(); |
| 151 | const LauncherItems& items = launcher_model->items(); |
| 152 | int item_count = launcher_model->item_count(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 153 | int indexes_left = item_index >= 0 ? item_index : item_count; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 154 | int found_index = -1; |
| 155 | |
| 156 | // Iterating until we have hit the index we are interested in which |
| 157 | // is true once indexes_left becomes negative. |
| 158 | for (int i = 0; i < item_count && indexes_left >= 0; i++) { |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 159 | if (items[i].type != TYPE_APP_LIST) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 160 | found_index = i; |
| 161 | indexes_left--; |
| 162 | } |
| 163 | } |
| 164 | |
| 165 | // There are two ways how found_index can be valid: a.) the nth item was |
| 166 | // found (which is true when indexes_left is -1) or b.) the last item was |
| 167 | // requested (which is true when index was passed in as a negative number). |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 168 | if (found_index >= 0 && (indexes_left == -1 || item_index < 0) && |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 169 | (delegate_->IsPerAppLauncher() || |
| 170 | (items[found_index].status == ash::STATUS_RUNNING || |
| 171 | items[found_index].status == ash::STATUS_CLOSED))) { |
| 172 | // Then set this one as active (or advance to the next item of its kind). |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 173 | ActivateLauncherItem(found_index); |
| 174 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 175 | } |
| 176 | |
| 177 | internal::LauncherView* Launcher::GetLauncherViewForTest() { |
| 178 | return launcher_view_; |
| 179 | } |
| 180 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 181 | void Launcher::SetLauncherViewBounds(gfx::Rect bounds) { |
| 182 | launcher_view_->SetBoundsRect(bounds); |
| 183 | } |
| 184 | |
| 185 | gfx::Rect Launcher::GetLauncherViewBounds() const { |
| 186 | return launcher_view_->bounds(); |
| 187 | } |
| 188 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 189 | app_list::ApplicationDragAndDropHost* Launcher::GetDragAndDropHostForAppList() { |
| 190 | return launcher_view_; |
| 191 | } |
| 192 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 193 | } // namespace ash |