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.
5 #include "mojo/services/native_viewport/native_viewport_service.h"
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"
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;
31 class NativeViewportImpl
32 : public InterfaceImpl<mojo::NativeViewport>,
33 public NativeViewportDelegate {
35 NativeViewportImpl(shell::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();
46 virtual void Create(RectPtr bounds) OVERRIDE {
48 services::NativeViewport::Create(context_, this);
49 native_viewport_->Init(bounds.To<gfx::Rect>());
50 client()->OnCreated();
51 OnBoundsChanged(bounds.To<gfx::Rect>());
54 virtual void Show() OVERRIDE {
55 native_viewport_->Show();
58 virtual void Hide() OVERRIDE {
59 native_viewport_->Hide();
62 virtual void Close() OVERRIDE {
63 command_buffer_.reset();
64 DCHECK(native_viewport_);
65 native_viewport_->Close();
68 virtual void SetBounds(RectPtr bounds) OVERRIDE {
69 native_viewport_->SetBounds(bounds.To<gfx::Rect>());
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";
78 command_buffer_request_ = command_buffer_request.Pass();
79 CreateCommandBufferIfNeeded();
83 waiting_for_event_ack_ = false;
86 void CreateCommandBufferIfNeeded() {
87 if (!command_buffer_request_.is_pending())
89 DCHECK(!command_buffer_.get());
90 if (widget_ == gfx::kNullAcceleratedWidget)
92 gfx::Size size = native_viewport_->GetSize();
95 command_buffer_.reset(
96 new CommandBufferImpl(widget_, native_viewport_->GetSize()));
97 BindToRequest(command_buffer_.get(), &command_buffer_request_);
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();
107 case ui::ET_MOUSE_RELEASED:
108 case ui::ET_TOUCH_RELEASED:
109 native_viewport_->ReleaseCapture();
115 if (waiting_for_event_ack_ && IsRateLimitedEventType(ui_event))
119 TypeConverter<EventPtr, ui::Event>::ConvertFrom(*ui_event),
120 base::Bind(&NativeViewportImpl::AckEvent,
121 weak_factory_.GetWeakPtr()));
122 waiting_for_event_ack_ = true;
126 virtual void OnAcceleratedWidgetAvailable(
127 gfx::AcceleratedWidget widget) OVERRIDE {
129 CreateCommandBufferIfNeeded();
132 virtual void OnBoundsChanged(const gfx::Rect& bounds) OVERRIDE {
133 CreateCommandBufferIfNeeded();
134 client()->OnBoundsChanged(Rect::From(bounds));
137 virtual void OnDestroyed() OVERRIDE {
138 command_buffer_.reset();
139 client()->OnDestroyed();
140 base::MessageLoop::current()->Quit();
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_;
153 } // namespace services
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);