window_watcher.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/shell/window_watcher.h"
6
7#include "ash/display/display_controller.h"
8#include "ash/launcher/launcher.h"
9#include "ash/launcher/launcher_item_delegate_manager.h"
10#include "ash/launcher/launcher_model.h"
11#include "ash/shelf/shelf_widget.h"
12#include "ash/shell.h"
13#include "ash/shell/window_watcher_launcher_item_delegate.h"
14#include "ash/shell_window_ids.h"
15#include "ui/aura/root_window.h"
16#include "ui/aura/window.h"
17#include "ui/gfx/display.h"
18
19namespace ash {
20namespace shell {
21
22class WindowWatcher::WorkspaceWindowWatcher : public aura::WindowObserver {
23 public:
24  explicit WorkspaceWindowWatcher(WindowWatcher* watcher) : watcher_(watcher) {
25  }
26
27  virtual ~WorkspaceWindowWatcher() {
28  }
29
30  virtual void OnWindowAdded(aura::Window* new_window) OVERRIDE {
31    new_window->AddObserver(watcher_);
32  }
33
34  virtual void OnWillRemoveWindow(aura::Window* window) OVERRIDE {
35    DCHECK(window->children().empty());
36    window->RemoveObserver(watcher_);
37  }
38
39  void RootWindowAdded(aura::RootWindow* root) {
40    aura::Window* panel_container = ash::Shell::GetContainer(
41        root,
42        internal::kShellWindowId_PanelContainer);
43    panel_container->AddObserver(watcher_);
44
45    aura::Window* container =
46        Launcher::ForWindow(root)->shelf_widget()->window_container();
47    container->AddObserver(this);
48    for (size_t i = 0; i < container->children().size(); ++i)
49      container->children()[i]->AddObserver(watcher_);
50  }
51
52  void RootWindowRemoved(aura::RootWindow* root) {
53    aura::Window* panel_container = ash::Shell::GetContainer(
54        root,
55        internal::kShellWindowId_PanelContainer);
56    panel_container->RemoveObserver(watcher_);
57
58    aura::Window* container =
59        Launcher::ForWindow(root)->shelf_widget()->window_container();
60    container->RemoveObserver(this);
61    for (size_t i = 0; i < container->children().size(); ++i)
62      container->children()[i]->RemoveObserver(watcher_);
63  }
64
65 private:
66  WindowWatcher* watcher_;
67
68  DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowWatcher);
69};
70
71WindowWatcher::WindowWatcher() {
72  workspace_window_watcher_.reset(new WorkspaceWindowWatcher(this));
73  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
74  for (Shell::RootWindowList::iterator iter = root_windows.begin();
75       iter != root_windows.end(); ++ iter) {
76    workspace_window_watcher_->RootWindowAdded(*iter);
77  }
78}
79
80WindowWatcher::~WindowWatcher() {
81  Shell::RootWindowList root_windows = Shell::GetAllRootWindows();
82  for (Shell::RootWindowList::iterator iter = root_windows.begin();
83       iter != root_windows.end(); ++ iter) {
84    workspace_window_watcher_->RootWindowRemoved(*iter);
85  }
86}
87
88aura::Window* WindowWatcher::GetWindowByID(ash::LauncherID id) {
89  IDToWindow::const_iterator i = id_to_window_.find(id);
90  return i != id_to_window_.end() ? i->second : NULL;
91}
92
93ash::LauncherID WindowWatcher::GetIDByWindow(aura::Window* window) const {
94  for (IDToWindow::const_iterator i = id_to_window_.begin();
95       i != id_to_window_.end(); ++i) {
96    if (i->second == window)
97      return i->first;
98  }
99  return 0;  // TODO: add a constant for this.
100}
101
102// aura::WindowObserver overrides:
103void WindowWatcher::OnWindowAdded(aura::Window* new_window) {
104  if (new_window->type() != aura::client::WINDOW_TYPE_NORMAL &&
105      new_window->type() != aura::client::WINDOW_TYPE_PANEL)
106    return;
107
108  static int image_count = 0;
109  ash::LauncherModel* model = Shell::GetInstance()->launcher_model();
110  ash::LauncherItem item;
111  item.type = new_window->type() == aura::client::WINDOW_TYPE_PANEL ?
112      ash::TYPE_APP_PANEL : ash::TYPE_PLATFORM_APP;
113  ash::LauncherID id = model->next_id();
114  id_to_window_[id] = new_window;
115
116  SkBitmap icon_bitmap;
117  icon_bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
118  icon_bitmap.allocPixels();
119  icon_bitmap.eraseARGB(255,
120                        image_count == 0 ? 255 : 0,
121                        image_count == 1 ? 255 : 0,
122                        image_count == 2 ? 255 : 0);
123  image_count = (image_count + 1) % 3;
124  item.image = gfx::ImageSkia(gfx::ImageSkiaRep(icon_bitmap, 1.0f));
125
126  model->Add(item);
127
128  ash::LauncherItemDelegateManager* manager =
129      ash::Shell::GetInstance()->launcher_item_delegate_manager();
130  scoped_ptr<LauncherItemDelegate> delegate(
131      new WindowWatcherLauncherItemDelegate(id, this));
132  manager->SetLauncherItemDelegate(id, delegate.Pass());
133}
134
135void WindowWatcher::OnWillRemoveWindow(aura::Window* window) {
136  for (IDToWindow::iterator i = id_to_window_.begin();
137       i != id_to_window_.end(); ++i) {
138    if (i->second == window) {
139      ash::LauncherModel* model = Shell::GetInstance()->launcher_model();
140      int index = model->ItemIndexByID(i->first);
141      DCHECK_NE(-1, index);
142      model->RemoveItemAt(index);
143      id_to_window_.erase(i);
144      break;
145    }
146  }
147}
148
149void WindowWatcher::OnDisplayBoundsChanged(const gfx::Display& display) {
150}
151
152void WindowWatcher::OnDisplayAdded(const gfx::Display& new_display) {
153  aura::RootWindow* root = Shell::GetInstance()->display_controller()->
154      GetRootWindowForDisplayId(new_display.id());
155  workspace_window_watcher_->RootWindowAdded(root);
156}
157
158void WindowWatcher::OnDisplayRemoved(const gfx::Display& old_display) {
159  // All windows in the display has already been removed, so no need to
160  // remove observers.
161}
162
163}  // namespace shell
164}  // namespace ash
165