Home | History | Annotate | Download | only in env
      1 // Copyright 2014 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 "athena/env/public/athena_env.h"
      6 
      7 #include <vector>
      8 
      9 #include "athena/util/fill_layout_manager.h"
     10 #include "base/sys_info.h"
     11 #include "ui/aura/client/aura_constants.h"
     12 #include "ui/aura/client/cursor_client.h"
     13 #include "ui/aura/client/default_capture_client.h"
     14 #include "ui/aura/env.h"
     15 #include "ui/aura/test/test_screen.h"
     16 #include "ui/aura/window_event_dispatcher.h"
     17 #include "ui/aura/window_tree_host.h"
     18 #include "ui/aura/window_tree_host_observer.h"
     19 #include "ui/base/cursor/cursor.h"
     20 #include "ui/base/cursor/image_cursors.h"
     21 #include "ui/chromeos/user_activity_power_manager_notifier.h"
     22 #include "ui/display/chromeos/display_configurator.h"
     23 #include "ui/display/types/display_mode.h"
     24 #include "ui/display/types/display_snapshot.h"
     25 #include "ui/gfx/screen.h"
     26 #include "ui/wm/core/compound_event_filter.h"
     27 #include "ui/wm/core/cursor_manager.h"
     28 #include "ui/wm/core/input_method_event_filter.h"
     29 #include "ui/wm/core/native_cursor_manager.h"
     30 #include "ui/wm/core/native_cursor_manager_delegate.h"
     31 #include "ui/wm/core/user_activity_detector.h"
     32 
     33 namespace athena {
     34 
     35 namespace {
     36 
     37 AthenaEnv* instance = NULL;
     38 
     39 // Screen object used during shutdown.
     40 gfx::Screen* screen_for_shutdown = NULL;
     41 
     42 // TODO(flackr:oshima): Remove this once athena switches to share
     43 // ash::DisplayManager.
     44 class ScreenForShutdown : public gfx::Screen {
     45  public:
     46   // Creates and sets the screen for shutdown. Deletes existing one if any.
     47   static void Create(const gfx::Screen* screen) {
     48     delete screen_for_shutdown;
     49     screen_for_shutdown = new ScreenForShutdown(screen->GetPrimaryDisplay());
     50     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE,
     51                                    screen_for_shutdown);
     52   }
     53 
     54  private:
     55   explicit ScreenForShutdown(const gfx::Display& primary_display)
     56       : primary_display_(primary_display) {}
     57 
     58   // gfx::Screen overrides:
     59   virtual bool IsDIPEnabled() OVERRIDE { return true; }
     60   virtual gfx::Point GetCursorScreenPoint() OVERRIDE { return gfx::Point(); }
     61   virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { return NULL; }
     62   virtual gfx::NativeWindow GetWindowAtScreenPoint(
     63       const gfx::Point& point) OVERRIDE {
     64     return NULL;
     65   }
     66   virtual int GetNumDisplays() const OVERRIDE { return 1; }
     67   virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE {
     68     std::vector<gfx::Display> displays(1, primary_display_);
     69     return displays;
     70   }
     71   virtual gfx::Display GetDisplayNearestWindow(
     72       gfx::NativeView view) const OVERRIDE {
     73     return primary_display_;
     74   }
     75   virtual gfx::Display GetDisplayNearestPoint(
     76       const gfx::Point& point) const OVERRIDE {
     77     return primary_display_;
     78   }
     79   virtual gfx::Display GetDisplayMatching(
     80       const gfx::Rect& match_rect) const OVERRIDE {
     81     return primary_display_;
     82   }
     83   virtual gfx::Display GetPrimaryDisplay() const OVERRIDE {
     84     return primary_display_;
     85   }
     86   virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE {
     87     NOTREACHED() << "Observer should not be added during shutdown";
     88   }
     89   virtual void RemoveObserver(gfx::DisplayObserver* observer) OVERRIDE {}
     90 
     91   const gfx::Display primary_display_;
     92 
     93   DISALLOW_COPY_AND_ASSIGN(ScreenForShutdown);
     94 };
     95 
     96 // A class that bridges the gap between CursorManager and Aura. It borrows
     97 // heavily from AshNativeCursorManager.
     98 class AthenaNativeCursorManager : public wm::NativeCursorManager {
     99  public:
    100   explicit AthenaNativeCursorManager(aura::WindowTreeHost* host)
    101       : host_(host), image_cursors_(new ui::ImageCursors) {}
    102   virtual ~AthenaNativeCursorManager() {}
    103 
    104   // wm::NativeCursorManager overrides.
    105   virtual void SetDisplay(const gfx::Display& display,
    106                           wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
    107     if (image_cursors_->SetDisplay(display, display.device_scale_factor()))
    108       SetCursor(delegate->GetCursor(), delegate);
    109   }
    110 
    111   virtual void SetCursor(gfx::NativeCursor cursor,
    112                          wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
    113     image_cursors_->SetPlatformCursor(&cursor);
    114     cursor.set_device_scale_factor(image_cursors_->GetScale());
    115     delegate->CommitCursor(cursor);
    116 
    117     if (delegate->IsCursorVisible())
    118       ApplyCursor(cursor);
    119   }
    120 
    121   virtual void SetVisibility(
    122       bool visible,
    123       wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
    124     delegate->CommitVisibility(visible);
    125 
    126     if (visible) {
    127       SetCursor(delegate->GetCursor(), delegate);
    128     } else {
    129       gfx::NativeCursor invisible_cursor(ui::kCursorNone);
    130       image_cursors_->SetPlatformCursor(&invisible_cursor);
    131       ApplyCursor(invisible_cursor);
    132     }
    133   }
    134 
    135   virtual void SetCursorSet(
    136       ui::CursorSetType cursor_set,
    137       wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
    138     image_cursors_->SetCursorSet(cursor_set);
    139     delegate->CommitCursorSet(cursor_set);
    140     if (delegate->IsCursorVisible())
    141       SetCursor(delegate->GetCursor(), delegate);
    142   }
    143 
    144   virtual void SetMouseEventsEnabled(
    145       bool enabled,
    146       wm::NativeCursorManagerDelegate* delegate) OVERRIDE {
    147     delegate->CommitMouseEventsEnabled(enabled);
    148     SetVisibility(delegate->IsCursorVisible(), delegate);
    149   }
    150 
    151  private:
    152   // Sets |cursor| as the active cursor within Aura.
    153   void ApplyCursor(gfx::NativeCursor cursor) { host_->SetCursor(cursor); }
    154 
    155   aura::WindowTreeHost* host_;  // Not owned.
    156 
    157   scoped_ptr<ui::ImageCursors> image_cursors_;
    158 
    159   DISALLOW_COPY_AND_ASSIGN(AthenaNativeCursorManager);
    160 };
    161 
    162 class AthenaEnvImpl : public AthenaEnv,
    163                       public aura::WindowTreeHostObserver,
    164                       public ui::DisplayConfigurator::Observer {
    165  public:
    166   AthenaEnvImpl() : display_configurator_(new ui::DisplayConfigurator) {
    167     display_configurator_->Init(false);
    168     display_configurator_->ForceInitialConfigure(0);
    169     display_configurator_->AddObserver(this);
    170 
    171     gfx::Size screen_size = GetPrimaryDisplaySize();
    172     if (screen_size.IsEmpty()) {
    173       // TODO(oshima): Remove this hack.
    174       if (base::SysInfo::IsRunningOnChromeOS())
    175         screen_size.SetSize(2560, 1600);
    176       else
    177         screen_size.SetSize(1280, 720);
    178     }
    179     screen_.reset(aura::TestScreen::Create(screen_size));
    180 
    181     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
    182     host_.reset(screen_->CreateHostForPrimaryDisplay());
    183     host_->InitHost();
    184 
    185     aura::Window* root_window = GetHost()->window();
    186     input_method_filter_.reset(
    187         new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
    188     input_method_filter_->SetInputMethodPropertyInRootWindow(root_window);
    189 
    190     root_window_event_filter_.reset(new wm::CompoundEventFilter);
    191     host_->window()->AddPreTargetHandler(root_window_event_filter_.get());
    192 
    193     input_method_filter_.reset(
    194         new wm::InputMethodEventFilter(host_->GetAcceleratedWidget()));
    195     input_method_filter_->SetInputMethodPropertyInRootWindow(host_->window());
    196     root_window_event_filter_->AddHandler(input_method_filter_.get());
    197 
    198     capture_client_.reset(
    199         new aura::client::DefaultCaptureClient(host_->window()));
    200 
    201     // Ensure new windows fill the display.
    202     root_window->SetLayoutManager(new FillLayoutManager(root_window));
    203 
    204     cursor_manager_.reset(
    205         new wm::CursorManager(scoped_ptr<wm::NativeCursorManager>(
    206             new AthenaNativeCursorManager(host_.get()))));
    207     cursor_manager_->SetDisplay(
    208         gfx::Screen::GetNativeScreen()->GetPrimaryDisplay());
    209     cursor_manager_->SetCursor(ui::kCursorPointer);
    210     aura::client::SetCursorClient(host_->window(), cursor_manager_.get());
    211 
    212     user_activity_detector_.reset(new wm::UserActivityDetector);
    213     host_->event_processor()->GetRootTarget()->AddPreTargetHandler(
    214         user_activity_detector_.get());
    215     user_activity_notifier_.reset(new ui::UserActivityPowerManagerNotifier(
    216         user_activity_detector_.get()));
    217 
    218     host_->AddObserver(this);
    219     host_->Show();
    220 
    221     DCHECK(!instance);
    222     instance = this;
    223   }
    224 
    225   virtual ~AthenaEnvImpl() {
    226     instance = NULL;
    227 
    228     host_->RemoveObserver(this);
    229     if (input_method_filter_)
    230       root_window_event_filter_->RemoveHandler(input_method_filter_.get());
    231     if (user_activity_detector_) {
    232       host_->event_processor()->GetRootTarget()->RemovePreTargetHandler(
    233           user_activity_detector_.get());
    234     }
    235     root_window_event_filter_.reset();
    236     capture_client_.reset();
    237     input_method_filter_.reset();
    238     cursor_manager_.reset();
    239     user_activity_notifier_.reset();
    240     user_activity_detector_.reset();
    241 
    242     input_method_filter_.reset();
    243     host_.reset();
    244 
    245     ScreenForShutdown::Create(screen_.get());
    246     screen_.reset();
    247     aura::Env::DeleteInstance();
    248 
    249     display_configurator_->RemoveObserver(this);
    250     display_configurator_.reset();
    251   }
    252 
    253  private:
    254   struct Finder {
    255     explicit Finder(const base::Closure& c) : closure(c) {}
    256     bool operator()(const base::Closure& other) {
    257       return closure.Equals(other);
    258     }
    259     base::Closure closure;
    260   };
    261 
    262   // AthenaEnv:
    263   virtual aura::WindowTreeHost* GetHost() OVERRIDE { return host_.get(); }
    264 
    265   virtual void SetDisplayWorkAreaInsets(const gfx::Insets& insets) OVERRIDE {
    266     screen_->SetWorkAreaInsets(insets);
    267   }
    268 
    269   virtual void AddTerminatingCallback(const base::Closure& closure) OVERRIDE {
    270     if (closure.is_null())
    271       return;
    272     DCHECK(terminating_callbacks_.end() ==
    273            std::find_if(terminating_callbacks_.begin(),
    274                         terminating_callbacks_.end(),
    275                         Finder(closure)));
    276     terminating_callbacks_.push_back(closure);
    277   }
    278 
    279   virtual void RemoveTerminatingCallback(
    280       const base::Closure& closure) OVERRIDE {
    281     std::vector<base::Closure>::iterator iter =
    282         std::find_if(terminating_callbacks_.begin(),
    283                      terminating_callbacks_.end(),
    284                      Finder(closure));
    285     if (iter != terminating_callbacks_.end())
    286       terminating_callbacks_.erase(iter);
    287   }
    288 
    289   virtual void OnTerminating() OVERRIDE {
    290     for (std::vector<base::Closure>::iterator iter =
    291              terminating_callbacks_.begin();
    292          iter != terminating_callbacks_.end();
    293          ++iter) {
    294       iter->Run();
    295     }
    296   }
    297 
    298   // ui::DisplayConfigurator::Observer:
    299   virtual void OnDisplayModeChanged(const std::vector<
    300       ui::DisplayConfigurator::DisplayState>& displays) OVERRIDE {
    301     gfx::Size size = GetPrimaryDisplaySize();
    302     if (!size.IsEmpty())
    303       host_->UpdateRootWindowSize(size);
    304   }
    305 
    306   // aura::WindowTreeHostObserver:
    307   virtual void OnHostCloseRequested(const aura::WindowTreeHost* host) OVERRIDE {
    308     base::MessageLoopForUI::current()->PostTask(
    309         FROM_HERE, base::MessageLoop::QuitClosure());
    310   }
    311 
    312   gfx::Size GetPrimaryDisplaySize() const {
    313     const std::vector<ui::DisplayConfigurator::DisplayState>& displays =
    314         display_configurator_->cached_displays();
    315     if (displays.empty())
    316       return gfx::Size();
    317     const ui::DisplayMode* mode = displays[0].display->current_mode();
    318     return mode ? mode->size() : gfx::Size();
    319   }
    320 
    321   scoped_ptr<aura::TestScreen> screen_;
    322   scoped_ptr<aura::WindowTreeHost> host_;
    323 
    324   scoped_ptr<wm::InputMethodEventFilter> input_method_filter_;
    325   scoped_ptr<wm::CompoundEventFilter> root_window_event_filter_;
    326   scoped_ptr<aura::client::DefaultCaptureClient> capture_client_;
    327   scoped_ptr<wm::CursorManager> cursor_manager_;
    328   scoped_ptr<wm::UserActivityDetector> user_activity_detector_;
    329   scoped_ptr<ui::DisplayConfigurator> display_configurator_;
    330   scoped_ptr<ui::UserActivityPowerManagerNotifier> user_activity_notifier_;
    331 
    332   std::vector<base::Closure> terminating_callbacks_;
    333 
    334   DISALLOW_COPY_AND_ASSIGN(AthenaEnvImpl);
    335 };
    336 
    337 }  // namespace
    338 
    339 // static
    340 void AthenaEnv::Create() {
    341   DCHECK(!instance);
    342   new AthenaEnvImpl();
    343 }
    344 
    345 AthenaEnv* AthenaEnv::Get() {
    346   DCHECK(instance);
    347   return instance;
    348 }
    349 
    350 // static
    351 
    352 // static
    353 void AthenaEnv::Shutdown() {
    354   DCHECK(instance);
    355   delete instance;
    356 }
    357 
    358 }  // namespace athena
    359