Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / mojo / services / native_viewport / native_viewport_service.cc
1 // Copyright 2013 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_service.h"
6
7 #include "base/macros.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/time/time.h"
11 #include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
12 #include "mojo/services/gles2/command_buffer_impl.h"
13 #include "mojo/services/native_viewport/native_viewport.h"
14 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
15 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
16 #include "mojo/services/public/interfaces/native_viewport/native_viewport.mojom.h"
17 #include "ui/events/event.h"
18
19 namespace mojo {
20 namespace services {
21 namespace {
22
23 bool IsRateLimitedEventType(ui::Event* event) {
24   return event->type() == ui::ET_MOUSE_MOVED ||
25          event->type() == ui::ET_MOUSE_DRAGGED ||
26          event->type() == ui::ET_TOUCH_MOVED;
27 }
28
29 }
30
31 class NativeViewportImpl
32     : public InterfaceImpl<mojo::NativeViewport>,
33       public NativeViewportDelegate {
34  public:
35   NativeViewportImpl(shell::Context* context)
36       : context_(context),
37         widget_(gfx::kNullAcceleratedWidget),
38         waiting_for_event_ack_(false),
39         weak_factory_(this) {}
40   virtual ~NativeViewportImpl() {
41     // Destroy the NativeViewport early on as it may call us back during
42     // destruction and we want to be in a known state.
43     native_viewport_.reset();
44   }
45
46   virtual void Create(RectPtr bounds) OVERRIDE {
47     native_viewport_ =
48         services::NativeViewport::Create(context_, this);
49     native_viewport_->Init(bounds.To<gfx::Rect>());
50     client()->OnCreated();
51     OnBoundsChanged(bounds.To<gfx::Rect>());
52   }
53
54   virtual void Show() OVERRIDE {
55     native_viewport_->Show();
56   }
57
58   virtual void Hide() OVERRIDE {
59     native_viewport_->Hide();
60   }
61
62   virtual void Close() OVERRIDE {
63     command_buffer_.reset();
64     DCHECK(native_viewport_);
65     native_viewport_->Close();
66   }
67
68   virtual void SetBounds(RectPtr bounds) OVERRIDE {
69     native_viewport_->SetBounds(bounds.To<gfx::Rect>());
70   }
71
72   virtual void CreateGLES2Context(
73       InterfaceRequest<CommandBuffer> command_buffer_request) OVERRIDE {
74     if (command_buffer_.get() || command_buffer_request_.is_pending()) {
75       LOG(ERROR) << "Can't create multiple contexts on a NativeViewport";
76       return;
77     }
78     command_buffer_request_ = command_buffer_request.Pass();
79     CreateCommandBufferIfNeeded();
80   }
81
82   void AckEvent() {
83     waiting_for_event_ack_ = false;
84   }
85
86   void CreateCommandBufferIfNeeded() {
87     if (!command_buffer_request_.is_pending())
88       return;
89     DCHECK(!command_buffer_.get());
90     if (widget_ == gfx::kNullAcceleratedWidget)
91       return;
92     gfx::Size size = native_viewport_->GetSize();
93     if (size.IsEmpty())
94       return;
95     command_buffer_.reset(
96         new CommandBufferImpl(widget_, native_viewport_->GetSize()));
97     BindToRequest(command_buffer_.get(), &command_buffer_request_);
98   }
99
100   virtual bool OnEvent(ui::Event* ui_event) OVERRIDE {
101     // Must not return early before updating capture.
102     switch (ui_event->type()) {
103     case ui::ET_MOUSE_PRESSED:
104     case ui::ET_TOUCH_PRESSED:
105       native_viewport_->SetCapture();
106       break;
107     case ui::ET_MOUSE_RELEASED:
108     case ui::ET_TOUCH_RELEASED:
109       native_viewport_->ReleaseCapture();
110       break;
111     default:
112       break;
113     }
114
115     if (waiting_for_event_ack_ && IsRateLimitedEventType(ui_event))
116       return false;
117
118     client()->OnEvent(
119         TypeConverter<EventPtr, ui::Event>::ConvertFrom(*ui_event),
120         base::Bind(&NativeViewportImpl::AckEvent,
121                    weak_factory_.GetWeakPtr()));
122     waiting_for_event_ack_ = true;
123     return false;
124   }
125
126   virtual void OnAcceleratedWidgetAvailable(
127       gfx::AcceleratedWidget widget) OVERRIDE {
128     widget_ = widget;
129     CreateCommandBufferIfNeeded();
130   }
131
132   virtual void OnBoundsChanged(const gfx::Rect& bounds) OVERRIDE {
133     CreateCommandBufferIfNeeded();
134     client()->OnBoundsChanged(Rect::From(bounds));
135   }
136
137   virtual void OnDestroyed() OVERRIDE {
138     command_buffer_.reset();
139     client()->OnDestroyed();
140     base::MessageLoop::current()->Quit();
141   }
142
143  private:
144   shell::Context* context_;
145   gfx::AcceleratedWidget widget_;
146   scoped_ptr<services::NativeViewport> native_viewport_;
147   InterfaceRequest<CommandBuffer> command_buffer_request_;
148   scoped_ptr<CommandBufferImpl> command_buffer_;
149   bool waiting_for_event_ack_;
150   base::WeakPtrFactory<NativeViewportImpl> weak_factory_;
151 };
152
153 }  // namespace services
154 }  // namespace mojo
155
156
157 MOJO_NATIVE_VIEWPORT_EXPORT mojo::Application*
158     CreateNativeViewportService(
159         mojo::shell::Context* context,
160         mojo::ScopedMessagePipeHandle service_provider_handle) {
161   mojo::Application* app = new mojo::Application(
162       service_provider_handle.Pass());
163   app->AddService<mojo::services::NativeViewportImpl>(context);
164   return app;
165 }