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