| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 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/common/shelf/shelf_window_watcher.h" | 5 #include "ash/common/shelf/shelf_window_watcher.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "ash/common/shelf/shelf_constants.h" | 10 #include "ash/common/shelf/shelf_constants.h" |
| 11 #include "ash/common/shelf/shelf_model.h" | 11 #include "ash/common/shelf/shelf_model.h" |
| 12 #include "ash/common/shelf/shelf_window_watcher_item_delegate.h" | 12 #include "ash/common/shelf/shelf_window_watcher_item_delegate.h" |
| 13 #include "ash/common/wm/window_state.h" | 13 #include "ash/common/wm/window_state.h" |
| 14 #include "ash/common/wm_shell.h" | 14 #include "ash/common/wm_shell.h" |
| 15 #include "ash/common/wm_window.h" | 15 #include "ash/common/wm_window.h" |
| 16 #include "ash/common/wm_window_property.h" | 16 #include "ash/common/wm_window_property.h" |
| 17 #include "ash/public/cpp/shell_window_ids.h" | 17 #include "ash/public/cpp/shell_window_ids.h" |
| 18 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
| 19 #include "ui/display/display.h" | 19 #include "ui/display/display.h" |
| 20 #include "ui/display/screen.h" | 20 #include "ui/display/screen.h" |
| 21 #include "ui/gfx/image/image_skia.h" | 21 #include "ui/gfx/image/image_skia.h" |
| 22 #include "ui/resources/grit/ui_resources.h" |
| 22 | 23 |
| 23 namespace ash { | 24 namespace ash { |
| 24 namespace { | 25 namespace { |
| 25 | 26 |
| 26 // Update the ShelfItem from relevant window properties. | 27 // Update the ShelfItem from relevant window properties. |
| 27 void UpdateShelfItemForWindow(ShelfItem* item, WmWindow* window) { | 28 void UpdateShelfItemForWindow(ShelfItem* item, WmWindow* window) { |
| 28 item->type = static_cast<ShelfItemType>( | 29 item->type = static_cast<ShelfItemType>( |
| 29 window->GetIntProperty(WmWindowProperty::SHELF_ITEM_TYPE)); | 30 window->GetIntProperty(WmWindowProperty::SHELF_ITEM_TYPE)); |
| 30 const int icon = | |
| 31 window->GetIntProperty(WmWindowProperty::SHELF_ICON_RESOURCE_ID); | |
| 32 if (icon != kInvalidImageResourceID) | |
| 33 item->image = *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(icon); | |
| 34 } | |
| 35 | 31 |
| 36 // Returns true if |window| has a ShelfItem added by ShelfWindowWatcher. | 32 item->status = STATUS_RUNNING; |
| 37 bool HasShelfItemForWindow(WmWindow* window) { | 33 if (window->IsActive()) |
| 38 return window->GetIntProperty(WmWindowProperty::SHELF_ITEM_TYPE) != | 34 item->status = STATUS_ACTIVE; |
| 39 TYPE_UNDEFINED && | 35 else if (window->GetBoolProperty(WmWindowProperty::DRAW_ATTENTION)) |
| 40 window->GetIntProperty(WmWindowProperty::SHELF_ID) != kInvalidShelfID; | 36 item->status = STATUS_ATTENTION; |
| 37 |
| 38 item->app_id = window->GetStringProperty(WmWindowProperty::APP_ID); |
| 39 |
| 40 // Prefer app icons over window icons, they're typically larger. |
| 41 gfx::ImageSkia image = window->GetAppIcon(); |
| 42 if (image.isNull()) |
| 43 image = window->GetWindowIcon(); |
| 44 if (image.isNull()) { |
| 45 int icon = window->GetIntProperty(WmWindowProperty::SHELF_ICON_RESOURCE_ID); |
| 46 if (icon != kInvalidImageResourceID) |
| 47 image = *ResourceBundle::GetSharedInstance().GetImageSkiaNamed(icon); |
| 48 } |
| 49 item->image = image; |
| 41 } | 50 } |
| 42 | 51 |
| 43 } // namespace | 52 } // namespace |
| 44 | 53 |
| 45 ShelfWindowWatcher::ContainerWindowObserver::ContainerWindowObserver( | 54 ShelfWindowWatcher::ContainerWindowObserver::ContainerWindowObserver( |
| 46 ShelfWindowWatcher* window_watcher) | 55 ShelfWindowWatcher* window_watcher) |
| 47 : window_watcher_(window_watcher) {} | 56 : window_watcher_(window_watcher) {} |
| 48 | 57 |
| 49 ShelfWindowWatcher::ContainerWindowObserver::~ContainerWindowObserver() {} | 58 ShelfWindowWatcher::ContainerWindowObserver::~ContainerWindowObserver() {} |
| 50 | 59 |
| 51 void ShelfWindowWatcher::ContainerWindowObserver::OnWindowTreeChanged( | 60 void ShelfWindowWatcher::ContainerWindowObserver::OnWindowTreeChanged( |
| 52 WmWindow* window, | 61 WmWindow* window, |
| 53 const TreeChangeParams& params) { | 62 const TreeChangeParams& params) { |
| 54 if (!params.old_parent && params.new_parent && | 63 if (!params.old_parent && params.new_parent && |
| 55 params.new_parent->GetShellWindowId() == | 64 (params.new_parent->GetShellWindowId() == |
| 56 kShellWindowId_DefaultContainer) { | 65 kShellWindowId_DefaultContainer || |
| 57 // A new window was created in the default container. | 66 params.new_parent->GetShellWindowId() == |
| 67 kShellWindowId_PanelContainer)) { |
| 68 // A new window was created in the default container or the panel container. |
| 58 window_watcher_->OnUserWindowAdded(params.target); | 69 window_watcher_->OnUserWindowAdded(params.target); |
| 59 } | 70 } |
| 60 } | 71 } |
| 61 | 72 |
| 62 void ShelfWindowWatcher::ContainerWindowObserver::OnWindowDestroying( | 73 void ShelfWindowWatcher::ContainerWindowObserver::OnWindowDestroying( |
| 63 WmWindow* window) { | 74 WmWindow* window) { |
| 64 window_watcher_->OnContainerWindowDestroying(window); | 75 window_watcher_->OnContainerWindowDestroying(window); |
| 65 } | 76 } |
| 66 | 77 |
| 67 //////////////////////////////////////////////////////////////////////////////// | 78 //////////////////////////////////////////////////////////////////////////////// |
| 68 | 79 |
| 69 ShelfWindowWatcher::UserWindowObserver::UserWindowObserver( | 80 ShelfWindowWatcher::UserWindowObserver::UserWindowObserver( |
| 70 ShelfWindowWatcher* window_watcher) | 81 ShelfWindowWatcher* window_watcher) |
| 71 : window_watcher_(window_watcher) {} | 82 : window_watcher_(window_watcher) {} |
| 72 | 83 |
| 73 ShelfWindowWatcher::UserWindowObserver::~UserWindowObserver() {} | 84 ShelfWindowWatcher::UserWindowObserver::~UserWindowObserver() {} |
| 74 | 85 |
| 75 void ShelfWindowWatcher::UserWindowObserver::OnWindowPropertyChanged( | 86 void ShelfWindowWatcher::UserWindowObserver::OnWindowPropertyChanged( |
| 76 WmWindow* window, | 87 WmWindow* window, |
| 77 WmWindowProperty property) { | 88 WmWindowProperty property) { |
| 78 if (property == WmWindowProperty::SHELF_ITEM_TYPE || | 89 if (property == WmWindowProperty::APP_ICON || |
| 79 property == WmWindowProperty::SHELF_ICON_RESOURCE_ID) { | 90 property == WmWindowProperty::APP_ID || |
| 91 property == WmWindowProperty::DRAW_ATTENTION || |
| 92 property == WmWindowProperty::SHELF_ITEM_TYPE || |
| 93 property == WmWindowProperty::SHELF_ICON_RESOURCE_ID || |
| 94 property == WmWindowProperty::WINDOW_ICON) { |
| 80 window_watcher_->OnUserWindowPropertyChanged(window); | 95 window_watcher_->OnUserWindowPropertyChanged(window); |
| 81 } | 96 } |
| 82 } | 97 } |
| 83 | 98 |
| 84 void ShelfWindowWatcher::UserWindowObserver::OnWindowDestroying( | 99 void ShelfWindowWatcher::UserWindowObserver::OnWindowDestroying( |
| 85 WmWindow* window) { | 100 WmWindow* window) { |
| 86 window_watcher_->OnUserWindowDestroying(window); | 101 window_watcher_->OnUserWindowDestroying(window); |
| 87 } | 102 } |
| 88 | 103 |
| 89 //////////////////////////////////////////////////////////////////////////////// | 104 //////////////////////////////////////////////////////////////////////////////// |
| 90 | 105 |
| 91 ShelfWindowWatcher::ShelfWindowWatcher(ShelfModel* model) | 106 ShelfWindowWatcher::ShelfWindowWatcher(ShelfModel* model) |
| 92 : model_(model), | 107 : model_(model), |
| 93 container_window_observer_(this), | 108 container_window_observer_(this), |
| 94 user_window_observer_(this), | 109 user_window_observer_(this), |
| 95 observed_container_windows_(&container_window_observer_), | 110 observed_container_windows_(&container_window_observer_), |
| 96 observed_user_windows_(&user_window_observer_) { | 111 observed_user_windows_(&user_window_observer_) { |
| 97 WmShell::Get()->AddActivationObserver(this); | 112 WmShell::Get()->AddActivationObserver(this); |
| 98 for (WmWindow* root : WmShell::Get()->GetAllRootWindows()) { | 113 for (WmWindow* root : WmShell::Get()->GetAllRootWindows()) { |
| 99 observed_container_windows_.Add( | 114 observed_container_windows_.Add( |
| 100 root->GetChildByShellWindowId(kShellWindowId_DefaultContainer)); | 115 root->GetChildByShellWindowId(kShellWindowId_DefaultContainer)); |
| 116 observed_container_windows_.Add( |
| 117 root->GetChildByShellWindowId(kShellWindowId_PanelContainer)); |
| 101 } | 118 } |
| 102 | 119 |
| 103 display::Screen::GetScreen()->AddObserver(this); | 120 display::Screen::GetScreen()->AddObserver(this); |
| 104 } | 121 } |
| 105 | 122 |
| 106 ShelfWindowWatcher::~ShelfWindowWatcher() { | 123 ShelfWindowWatcher::~ShelfWindowWatcher() { |
| 107 display::Screen::GetScreen()->RemoveObserver(this); | 124 display::Screen::GetScreen()->RemoveObserver(this); |
| 108 WmShell::Get()->RemoveActivationObserver(this); | 125 WmShell::Get()->RemoveActivationObserver(this); |
| 109 } | 126 } |
| 110 | 127 |
| 111 void ShelfWindowWatcher::AddShelfItem(WmWindow* window) { | 128 void ShelfWindowWatcher::AddShelfItem(WmWindow* window) { |
| 129 user_windows_with_items_.insert(window); |
| 112 ShelfItem item; | 130 ShelfItem item; |
| 113 ShelfID id = model_->next_id(); | 131 ShelfID id = model_->next_id(); |
| 114 item.status = window->IsActive() ? STATUS_ACTIVE : STATUS_RUNNING; | |
| 115 UpdateShelfItemForWindow(&item, window); | 132 UpdateShelfItemForWindow(&item, window); |
| 116 window->SetIntProperty(WmWindowProperty::SHELF_ID, id); | 133 window->SetIntProperty(WmWindowProperty::SHELF_ID, id); |
| 117 std::unique_ptr<ShelfItemDelegate> item_delegate( | 134 std::unique_ptr<ShelfItemDelegate> item_delegate( |
| 118 new ShelfWindowWatcherItemDelegate(window)); | 135 new ShelfWindowWatcherItemDelegate(id, window)); |
| 119 model_->SetShelfItemDelegate(id, std::move(item_delegate)); | 136 model_->SetShelfItemDelegate(id, std::move(item_delegate)); |
| 120 model_->Add(item); | 137 // Panels are inserted on the left so as not to push all existing panels over. |
| 138 model_->AddAt(item.type == TYPE_APP_PANEL ? 0 : model_->item_count(), item); |
| 121 } | 139 } |
| 122 | 140 |
| 123 void ShelfWindowWatcher::RemoveShelfItem(WmWindow* window) { | 141 void ShelfWindowWatcher::RemoveShelfItem(WmWindow* window) { |
| 142 user_windows_with_items_.erase(window); |
| 124 int shelf_id = window->GetIntProperty(WmWindowProperty::SHELF_ID); | 143 int shelf_id = window->GetIntProperty(WmWindowProperty::SHELF_ID); |
| 125 DCHECK_NE(shelf_id, kInvalidShelfID); | 144 DCHECK_NE(shelf_id, kInvalidShelfID); |
| 126 int index = model_->ItemIndexByID(shelf_id); | 145 int index = model_->ItemIndexByID(shelf_id); |
| 127 DCHECK_GE(index, 0); | 146 DCHECK_GE(index, 0); |
| 128 model_->RemoveItemAt(index); | 147 model_->RemoveItemAt(index); |
| 129 window->SetIntProperty(WmWindowProperty::SHELF_ID, kInvalidShelfID); | 148 window->SetIntProperty(WmWindowProperty::SHELF_ID, kInvalidShelfID); |
| 130 } | 149 } |
| 131 | 150 |
| 132 void ShelfWindowWatcher::OnContainerWindowDestroying(WmWindow* container) { | 151 void ShelfWindowWatcher::OnContainerWindowDestroying(WmWindow* container) { |
| 133 observed_container_windows_.Remove(container); | 152 observed_container_windows_.Remove(container); |
| 134 } | 153 } |
| 135 | 154 |
| 136 void ShelfWindowWatcher::UpdateShelfItemStatus(WmWindow* window, | |
| 137 bool is_active) { | |
| 138 int index = GetShelfItemIndexForWindow(window); | |
| 139 DCHECK_GE(index, 0); | |
| 140 | |
| 141 ShelfItem item = model_->items()[index]; | |
| 142 item.status = is_active ? STATUS_ACTIVE : STATUS_RUNNING; | |
| 143 model_->Set(index, item); | |
| 144 } | |
| 145 | |
| 146 int ShelfWindowWatcher::GetShelfItemIndexForWindow(WmWindow* window) const { | 155 int ShelfWindowWatcher::GetShelfItemIndexForWindow(WmWindow* window) const { |
| 147 return model_->ItemIndexByID( | 156 return model_->ItemIndexByID( |
| 148 window->GetIntProperty(WmWindowProperty::SHELF_ID)); | 157 window->GetIntProperty(WmWindowProperty::SHELF_ID)); |
| 149 } | 158 } |
| 150 | 159 |
| 151 void ShelfWindowWatcher::OnUserWindowAdded(WmWindow* window) { | 160 void ShelfWindowWatcher::OnUserWindowAdded(WmWindow* window) { |
| 152 // The window may already be tracked from when it was added to a different | 161 // The window may already be tracked from a prior display or parent container. |
| 153 // display or because an existing window added its shelf item properties. | |
| 154 if (observed_user_windows_.IsObserving(window)) | 162 if (observed_user_windows_.IsObserving(window)) |
| 155 return; | 163 return; |
| 156 | 164 |
| 157 observed_user_windows_.Add(window); | 165 observed_user_windows_.Add(window); |
| 158 | 166 |
| 159 // Add a ShelfItem if |window| has a valid ShelfItemType on creation. | 167 // Add, update, or remove a ShelfItem for |window|, as needed. |
| 160 if (window->GetIntProperty(WmWindowProperty::SHELF_ITEM_TYPE) != | 168 OnUserWindowPropertyChanged(window); |
| 161 TYPE_UNDEFINED && | |
| 162 window->GetIntProperty(WmWindowProperty::SHELF_ID) == kInvalidShelfID) { | |
| 163 AddShelfItem(window); | |
| 164 } | |
| 165 } | 169 } |
| 166 | 170 |
| 167 void ShelfWindowWatcher::OnUserWindowDestroying(WmWindow* window) { | 171 void ShelfWindowWatcher::OnUserWindowDestroying(WmWindow* window) { |
| 168 if (observed_user_windows_.IsObserving(window)) | 172 if (observed_user_windows_.IsObserving(window)) |
| 169 observed_user_windows_.Remove(window); | 173 observed_user_windows_.Remove(window); |
| 170 | 174 |
| 171 if (HasShelfItemForWindow(window)) | 175 if (user_windows_with_items_.count(window) > 0) |
| 172 RemoveShelfItem(window); | 176 RemoveShelfItem(window); |
| 177 DCHECK_EQ(0u, user_windows_with_items_.count(window)); |
| 173 } | 178 } |
| 174 | 179 |
| 175 void ShelfWindowWatcher::OnUserWindowPropertyChanged(WmWindow* window) { | 180 void ShelfWindowWatcher::OnUserWindowPropertyChanged(WmWindow* window) { |
| 176 if (window->GetIntProperty(WmWindowProperty::SHELF_ITEM_TYPE) == | 181 if (window->GetIntProperty(WmWindowProperty::SHELF_ITEM_TYPE) == |
| 177 TYPE_UNDEFINED) { | 182 TYPE_UNDEFINED) { |
| 178 // Removes ShelfItem for |window| when it has a ShelfItem. | 183 // Remove |window|'s ShelfItem if it was added by this ShelfWindowWatcher. |
| 179 if (window->GetIntProperty(WmWindowProperty::SHELF_ID) != kInvalidShelfID) | 184 if (user_windows_with_items_.count(window) > 0) |
| 180 RemoveShelfItem(window); | 185 RemoveShelfItem(window); |
| 181 return; | 186 return; |
| 182 } | 187 } |
| 183 | 188 |
| 184 // Update an existing ShelfItem for |window| when a property has changed. | 189 // Update an existing ShelfItem for |window| when a property has changed. |
| 185 if (HasShelfItemForWindow(window)) { | 190 int index = GetShelfItemIndexForWindow(window); |
| 186 int index = GetShelfItemIndexForWindow(window); | 191 if (index > 0) { |
| 187 DCHECK_GE(index, 0); | |
| 188 ShelfItem item = model_->items()[index]; | 192 ShelfItem item = model_->items()[index]; |
| 189 UpdateShelfItemForWindow(&item, window); | 193 UpdateShelfItemForWindow(&item, window); |
| 190 model_->Set(index, item); | 194 model_->Set(index, item); |
| 191 return; | 195 return; |
| 192 } | 196 } |
| 193 | 197 |
| 194 // Creates a new ShelfItem for |window|. | 198 // Creates a new ShelfItem for |window|. |
| 195 AddShelfItem(window); | 199 AddShelfItem(window); |
| 196 } | 200 } |
| 197 | 201 |
| 198 void ShelfWindowWatcher::OnWindowActivated(WmWindow* gained_active, | 202 void ShelfWindowWatcher::OnWindowActivated(WmWindow* gained_active, |
| 199 WmWindow* lost_active) { | 203 WmWindow* lost_active) { |
| 200 if (gained_active && HasShelfItemForWindow(gained_active)) | 204 if (gained_active && user_windows_with_items_.count(gained_active) > 0) |
| 201 UpdateShelfItemStatus(gained_active, true); | 205 OnUserWindowPropertyChanged(gained_active); |
| 202 if (lost_active && HasShelfItemForWindow(lost_active)) | 206 if (lost_active && user_windows_with_items_.count(lost_active) > 0) |
| 203 UpdateShelfItemStatus(lost_active, false); | 207 OnUserWindowPropertyChanged(lost_active); |
| 204 } | 208 } |
| 205 | 209 |
| 206 void ShelfWindowWatcher::OnDisplayAdded(const display::Display& new_display) { | 210 void ShelfWindowWatcher::OnDisplayAdded(const display::Display& new_display) { |
| 207 WmWindow* root = WmShell::Get()->GetRootWindowForDisplayId(new_display.id()); | 211 WmWindow* root = WmShell::Get()->GetRootWindowForDisplayId(new_display.id()); |
| 208 | 212 |
| 209 // When the primary root window's display get removed, the existing root | 213 // When the primary root window's display get removed, the existing root |
| 210 // window is taken over by the new display and the observer is already set. | 214 // window is taken over by the new display and the observer is already set. |
| 211 WmWindow* container = | 215 WmWindow* default_container = |
| 212 root->GetChildByShellWindowId(kShellWindowId_DefaultContainer); | 216 root->GetChildByShellWindowId(kShellWindowId_DefaultContainer); |
| 213 if (!observed_container_windows_.IsObserving(container)) | 217 if (!observed_container_windows_.IsObserving(default_container)) |
| 214 observed_container_windows_.Add(container); | 218 observed_container_windows_.Add(default_container); |
| 219 WmWindow* panel_container = |
| 220 root->GetChildByShellWindowId(kShellWindowId_PanelContainer); |
| 221 if (!observed_container_windows_.IsObserving(panel_container)) |
| 222 observed_container_windows_.Add(panel_container); |
| 215 } | 223 } |
| 216 | 224 |
| 217 void ShelfWindowWatcher::OnDisplayRemoved(const display::Display& old_display) { | 225 void ShelfWindowWatcher::OnDisplayRemoved(const display::Display& old_display) { |
| 218 } | 226 } |
| 219 | 227 |
| 220 void ShelfWindowWatcher::OnDisplayMetricsChanged(const display::Display&, | 228 void ShelfWindowWatcher::OnDisplayMetricsChanged(const display::Display&, |
| 221 uint32_t) {} | 229 uint32_t) {} |
| 222 | 230 |
| 223 } // namespace ash | 231 } // namespace ash |
| OLD | NEW |