Home | History | Annotate | Download | only in native_viewport
      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 "mojo/services/native_viewport/native_viewport_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/macros.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/time/time.h"
     11 #include "mojo/public/cpp/application/application_delegate.h"
     12 #include "mojo/public/cpp/application/application_impl.h"
     13 #include "mojo/public/cpp/application/interface_factory.h"
     14 #include "mojo/services/native_viewport/platform_viewport_headless.h"
     15 #include "mojo/services/native_viewport/viewport_surface.h"
     16 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
     17 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
     18 #include "mojo/services/public/cpp/surfaces/surfaces_type_converters.h"
     19 #include "ui/events/event.h"
     20 
     21 namespace mojo {
     22 namespace {
     23 
     24 bool IsRateLimitedEventType(ui::Event* event) {
     25   return event->type() == ui::ET_MOUSE_MOVED ||
     26          event->type() == ui::ET_MOUSE_DRAGGED ||
     27          event->type() == ui::ET_TOUCH_MOVED;
     28 }
     29 
     30 }  // namespace
     31 
     32 NativeViewportImpl::NativeViewportImpl(ApplicationImpl* app, bool is_headless)
     33     : is_headless_(is_headless),
     34       widget_id_(0u),
     35       waiting_for_event_ack_(false),
     36       weak_factory_(this) {
     37   app->ConnectToService("mojo:mojo_surfaces_service", &surfaces_service_);
     38   // TODO(jamesr): Should be mojo_gpu_service
     39   app->ConnectToService("mojo:mojo_native_viewport_service", &gpu_service_);
     40 }
     41 
     42 NativeViewportImpl::~NativeViewportImpl() {
     43   // Destroy the NativeViewport early on as it may call us back during
     44   // destruction and we want to be in a known state.
     45   platform_viewport_.reset();
     46 }
     47 
     48 void NativeViewportImpl::Create(SizePtr bounds) {
     49   if (is_headless_)
     50     platform_viewport_ = PlatformViewportHeadless::Create(this);
     51   else
     52     platform_viewport_ = PlatformViewport::Create(this);
     53   gfx::Rect rect = gfx::Rect(bounds.To<gfx::Size>());
     54   platform_viewport_->Init(rect);
     55   OnBoundsChanged(rect);
     56 }
     57 
     58 void NativeViewportImpl::Show() {
     59   platform_viewport_->Show();
     60 }
     61 
     62 void NativeViewportImpl::Hide() {
     63   platform_viewport_->Hide();
     64 }
     65 
     66 void NativeViewportImpl::Close() {
     67   DCHECK(platform_viewport_);
     68   platform_viewport_->Close();
     69 }
     70 
     71 void NativeViewportImpl::SetBounds(SizePtr bounds) {
     72   platform_viewport_->SetBounds(gfx::Rect(bounds.To<gfx::Size>()));
     73 }
     74 
     75 void NativeViewportImpl::SubmittedFrame(SurfaceIdPtr child_surface_id) {
     76   if (child_surface_id_.is_null()) {
     77     // If this is the first indication that the client will use surfaces,
     78     // initialize that system.
     79     // TODO(jamesr): When everything is converted to surfaces initialize this
     80     // eagerly.
     81     viewport_surface_.reset(
     82         new ViewportSurface(surfaces_service_.get(),
     83                             gpu_service_.get(),
     84                             bounds_.size(),
     85                             child_surface_id.To<cc::SurfaceId>()));
     86     if (widget_id_)
     87       viewport_surface_->SetWidgetId(widget_id_);
     88   }
     89   child_surface_id_ = child_surface_id.To<cc::SurfaceId>();
     90   if (viewport_surface_)
     91     viewport_surface_->SetChildId(child_surface_id_);
     92 }
     93 
     94 void NativeViewportImpl::OnBoundsChanged(const gfx::Rect& bounds) {
     95   bounds_ = bounds;
     96   client()->OnBoundsChanged(Size::From(bounds.size()));
     97   if (viewport_surface_)
     98     viewport_surface_->SetSize(bounds.size());
     99 }
    100 
    101 void NativeViewportImpl::OnAcceleratedWidgetAvailable(
    102     gfx::AcceleratedWidget widget) {
    103   widget_id_ = static_cast<uint64_t>(bit_cast<uintptr_t>(widget));
    104   // TODO(jamesr): Remove once everything is converted to surfaces.
    105   client()->OnCreated(widget_id_);
    106   if (viewport_surface_)
    107     viewport_surface_->SetWidgetId(widget_id_);
    108 }
    109 
    110 bool NativeViewportImpl::OnEvent(ui::Event* ui_event) {
    111   // Must not return early before updating capture.
    112   switch (ui_event->type()) {
    113     case ui::ET_MOUSE_PRESSED:
    114     case ui::ET_TOUCH_PRESSED:
    115       platform_viewport_->SetCapture();
    116       break;
    117     case ui::ET_MOUSE_RELEASED:
    118     case ui::ET_TOUCH_RELEASED:
    119       platform_viewport_->ReleaseCapture();
    120       break;
    121     default:
    122       break;
    123   }
    124 
    125   if (waiting_for_event_ack_ && IsRateLimitedEventType(ui_event))
    126     return false;
    127 
    128   client()->OnEvent(
    129       Event::From(*ui_event),
    130       base::Bind(&NativeViewportImpl::AckEvent, weak_factory_.GetWeakPtr()));
    131   waiting_for_event_ack_ = true;
    132   return false;
    133 }
    134 
    135 void NativeViewportImpl::OnDestroyed() {
    136   client()->OnDestroyed();
    137 }
    138 
    139 void NativeViewportImpl::AckEvent() {
    140   waiting_for_event_ack_ = false;
    141 }
    142 
    143 }  // namespace mojo
    144 
    145