text: // Copyright 2013 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 "mojo/public/c/gles2/gles2.h"
  #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
  #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
  #include "mojo/services/view_manager/context_factory_impl.h"
  #include "mojo/services/view_manager/root_node_manager.h"
  #include "mojo/services/view_manager/window_tree_host_impl.h"
  #include "ui/aura/env.h"
  #include "ui/aura/layout_manager.h"
  #include "ui/aura/window.h"
  #include "ui/aura/window_event_dispatcher.h"
  #include "ui/compositor/compositor.h"
  #include "ui/events/event.h"
  #include "ui/events/event_constants.h"
  #include "ui/gfx/geometry/insets.h"
  #include "ui/gfx/geometry/rect.h"
  
  namespace mojo {
  namespace service {
  
  // TODO(sky): nuke this. It shouldn't be static.
  // static
  ContextFactoryImpl* WindowTreeHostImpl::context_factory_ = NULL;
  
  ////////////////////////////////////////////////////////////////////////////////
  // RootLayoutManager, layout management for the root window's (one) child
  
  class RootLayoutManager : public aura::LayoutManager {
   public:
    RootLayoutManager() : child_(NULL) {}
  
    // Overridden from aura::LayoutManager
    virtual void OnWindowResized() OVERRIDE;
    virtual void OnWindowAddedToLayout(aura::Window* child) OVERRIDE;
    virtual void OnWillRemoveWindowFromLayout(aura::Window* child) OVERRIDE {}
    virtual void OnWindowRemovedFromLayout(aura::Window* child) OVERRIDE {}
    virtual void OnChildWindowVisibilityChanged(aura::Window* child,
                                                bool visible) OVERRIDE {}
    virtual void SetChildBounds(aura::Window* child,
                                const gfx::Rect& requested_bounds) OVERRIDE;
   private:
    aura::Window* child_;
  
    DISALLOW_COPY_AND_ASSIGN(RootLayoutManager);
  };
  
  void RootLayoutManager::OnWindowResized() {
    if (child_)
      child_->SetBounds(gfx::Rect(child_->parent()->bounds().size()));
  }
  
  void RootLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
    DCHECK(!child_);
    child_ = child;
  }
  
  void RootLayoutManager::SetChildBounds(aura::Window* child,
                                         const gfx::Rect& requested_bounds) {
    SetChildBoundsDirect(child, gfx::Rect(requested_bounds.size()));
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // WindowTreeHostImpl, public:
  
  WindowTreeHostImpl::WindowTreeHostImpl(
      NativeViewportPtr viewport,
      GpuPtr gpu_service,
      const gfx::Rect& bounds,
      const Callback<void()>& compositor_created_callback,
      const Callback<void()>& native_viewport_closed_callback,
      const Callback<void(EventPtr)>& event_received_callback)
      : native_viewport_(viewport.Pass()),
        gpu_service_(gpu_service.Pass()),
        widget_(gfx::kNullAcceleratedWidget),
        compositor_created_callback_(compositor_created_callback),
        native_viewport_closed_callback_(native_viewport_closed_callback),
        event_received_callback_(event_received_callback),
        bounds_(bounds) {
    native_viewport_.set_client(this);
    native_viewport_->Create(Rect::From(bounds));
    native_viewport_->Show();
  
    window()->SetLayoutManager(new RootLayoutManager());
  }
  
  WindowTreeHostImpl::~WindowTreeHostImpl() {
    DestroyCompositor();
    DestroyDispatcher();
    delete context_factory_;
    context_factory_ = NULL;
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // WindowTreeHostImpl, aura::WindowTreeHost implementation:
  
  ui::EventSource* WindowTreeHostImpl::GetEventSource() {
    return this;
  }
  
  gfx::AcceleratedWidget WindowTreeHostImpl::GetAcceleratedWidget() {
    return widget_;
  }
  
  void WindowTreeHostImpl::Show() {
    window()->Show();
  }
  
  void WindowTreeHostImpl::Hide() {
    native_viewport_->Hide();
    window()->Hide();
  }
  
  gfx::Rect WindowTreeHostImpl::GetBounds() const {
    return bounds_;
  }
  
  void WindowTreeHostImpl::SetBounds(const gfx::Rect& bounds) {
    native_viewport_->SetBounds(Rect::From(bounds));
  }
  
  gfx::Point WindowTreeHostImpl::GetLocationOnNativeScreen() const {
    return gfx::Point(0, 0);
  }
  
  void WindowTreeHostImpl::SetCapture() {
    NOTIMPLEMENTED();
  }
  
  void WindowTreeHostImpl::ReleaseCapture() {
    NOTIMPLEMENTED();
  }
  
  void WindowTreeHostImpl::PostNativeEvent(
      const base::NativeEvent& native_event) {
    NOTIMPLEMENTED();
  }
  
  void WindowTreeHostImpl::SetCursorNative(gfx::NativeCursor cursor) {
    NOTIMPLEMENTED();
  }
  
  void WindowTreeHostImpl::MoveCursorToNative(const gfx::Point& location) {
    NOTIMPLEMENTED();
  }
  
  void WindowTreeHostImpl::OnCursorVisibilityChangedNative(bool show) {
    NOTIMPLEMENTED();
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // WindowTreeHostImpl, ui::EventSource implementation:
  
  ui::EventProcessor* WindowTreeHostImpl::GetEventProcessor() {
    return dispatcher();
  }
  
  ////////////////////////////////////////////////////////////////////////////////
  // WindowTreeHostImpl, NativeViewportClient implementation:
  
  void WindowTreeHostImpl::OnCreated(uint64_t native_viewport_id) {
    CommandBufferPtr cb;
    gpu_service_->CreateOnscreenGLES2Context(
        native_viewport_id, Size::From(bounds_.size()), Get(&cb));
    widget_ = bit_cast<gfx::AcceleratedWidget>(
        static_cast<uintptr_t>(native_viewport_id));
  
    // The ContextFactory must exist before any Compositors are created.
    if (context_factory_) {
      delete context_factory_;
      context_factory_ = NULL;
    }
    context_factory_ = new ContextFactoryImpl(cb.PassMessagePipe());
    aura::Env::GetInstance()->set_context_factory(context_factory_);
  
    CreateCompositor(gfx::kNullAcceleratedWidget);
    compositor_created_callback_.Run();
  }
  
  void WindowTreeHostImpl::OnBoundsChanged(RectPtr bounds) {
    bounds_ = bounds.To<gfx::Rect>();
    if (context_factory_)
      OnHostResized(bounds_.size());
  }
  
  void WindowTreeHostImpl::OnDestroyed() {
    DestroyCompositor();
    native_viewport_closed_callback_.Run();
    // TODO(beng): quit the message loop once we are on our own thread.
  }
  
  void WindowTreeHostImpl::OnEvent(EventPtr event,
                                   const mojo::Callback<void()>& callback) {
    event_received_callback_.Run(event.Pass());
    callback.Run();
  };
  
  }  // namespace service
  }  // namespace mojo
  