text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "ui/aura/env.h"
  
  #include "base/lazy_instance.h"
  #include "base/threading/thread_local.h"
  #include "ui/aura/env_observer.h"
  #include "ui/aura/input_state_lookup.h"
  #include "ui/events/event_target_iterator.h"
  #include "ui/events/platform/platform_event_source.h"
  
  #if defined(USE_OZONE)
  #include "ui/ozone/public/ozone_platform.h"
  #endif
  
  namespace aura {
  
  namespace {
  
  // Env is thread local so that aura may be used on multiple threads.
  base::LazyInstance<base::ThreadLocalPointer<Env> >::Leaky lazy_tls_ptr =
      LAZY_INSTANCE_INITIALIZER;
  
  }  // namespace
  
  ////////////////////////////////////////////////////////////////////////////////
  // Env, public:
  
  // static
  void Env::CreateInstance(bool create_event_source) {
    if (!lazy_tls_ptr.Pointer()->Get())
      (new Env())->Init(create_event_source);
  }
  
  // static
  Env* Env::GetInstance() {
    Env* env = lazy_tls_ptr.Pointer()->Get();
    DCHECK(env) << "Env::CreateInstance must be called before getting the "
                   "instance of Env.";
    return env;
  }
  
  // static
  void Env::DeleteInstance() {
    delete lazy_tls_ptr.Pointer()->Get();
  }
  
  void Env::AddObserver(EnvObserver* observer) {
    observers_.AddObserver(observer);
  }
  
  void Env::RemoveObserver(EnvObserver* observer) {
    observers_.RemoveObserver(observer);
  }
  
  bool Env::IsMouseButtonDown() const {
    return input_state_lookup_.get() ? input_state_lookup_->IsMouseButtonDown() :
        mouse_button_flags_ != 0;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Env, private:
  
  Env::Env()
      : mouse_button_flags_(0),
        is_touch_down_(false),
        input_state_lookup_(InputStateLookup::Create().Pass()),
        context_factory_(NULL) {
    DCHECK(lazy_tls_ptr.Pointer()->Get() == NULL);
    lazy_tls_ptr.Pointer()->Set(this);
  }
  
  Env::~Env() {
    FOR_EACH_OBSERVER(EnvObserver, observers_, OnWillDestroyEnv());
    DCHECK_EQ(this, lazy_tls_ptr.Pointer()->Get());
    lazy_tls_ptr.Pointer()->Set(NULL);
  }
  
  void Env::Init(bool create_event_source) {
  #if defined(USE_OZONE)
    // The ozone platform can provide its own event source. So initialize the
    // platform before creating the default event source.
    ui::OzonePlatform::InitializeForUI();
  #endif
    if (create_event_source && !ui::PlatformEventSource::GetInstance())
      event_source_ = ui::PlatformEventSource::CreateDefault();
  }
  
  void Env::NotifyWindowInitialized(Window* window) {
    FOR_EACH_OBSERVER(EnvObserver, observers_, OnWindowInitialized(window));
  }
  
  void Env::NotifyHostInitialized(WindowTreeHost* host) {
    FOR_EACH_OBSERVER(EnvObserver, observers_, OnHostInitialized(host));
  }
  
  void Env::NotifyHostActivated(WindowTreeHost* host) {
    FOR_EACH_OBSERVER(EnvObserver, observers_, OnHostActivated(host));
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // Env, ui::EventTarget implementation:
  
  bool Env::CanAcceptEvent(const ui::Event& event) {
    return true;
  }
  
  ui::EventTarget* Env::GetParentTarget() {
    return NULL;
  }
  
  scoped_ptr<ui::EventTargetIterator> Env::GetChildIterator() const {
    return nullptr;
  }
  
  ui::EventTargeter* Env::GetEventTargeter() {
    NOTREACHED();
    return NULL;
  }
  
  }  // namespace aura
  