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_impl.h" 6 7#include "base/message_loop/message_loop.h" 8#include "base/time/time.h" 9#include "mojo/services/gles2/gles2_impl.h" 10#include "mojo/services/native_viewport/native_viewport.h" 11#include "ui/events/event.h" 12 13namespace mojo { 14namespace services { 15namespace { 16 17bool IsRateLimitedEventType(ui::Event* event) { 18 return event->type() == ui::ET_MOUSE_MOVED || 19 event->type() == ui::ET_MOUSE_DRAGGED || 20 event->type() == ui::ET_TOUCH_MOVED; 21} 22 23} 24 25//////////////////////////////////////////////////////////////////////////////// 26// NativeViewportImpl, public: 27 28NativeViewportImpl::NativeViewportImpl(shell::Context* context, 29 ScopedMessagePipeHandle pipe) 30 : context_(context), 31 widget_(gfx::kNullAcceleratedWidget), 32 waiting_for_event_ack_(false), 33 pending_event_timestamp_(0), 34 client_(pipe.Pass()) { 35 client_.SetPeer(this); 36} 37 38NativeViewportImpl::~NativeViewportImpl() { 39} 40 41//////////////////////////////////////////////////////////////////////////////// 42// NativeViewportImpl, NativeViewportStub overrides: 43 44void NativeViewportImpl::Open() { 45 native_viewport_ = services::NativeViewport::Create(context_, this); 46 native_viewport_->Init(); 47 client_->OnCreated(); 48} 49 50void NativeViewportImpl::Close() { 51 DCHECK(native_viewport_); 52 native_viewport_->Close(); 53} 54 55void NativeViewportImpl::CreateGLES2Context( 56 ScopedMessagePipeHandle gles2_client) { 57 gles2_.reset(new GLES2Impl(gles2_client.Pass())); 58 CreateGLES2ContextIfNeeded(); 59} 60 61void NativeViewportImpl::AckEvent(const Event& event) { 62 DCHECK_EQ(event.time_stamp(), pending_event_timestamp_); 63 waiting_for_event_ack_ = false; 64} 65 66//////////////////////////////////////////////////////////////////////////////// 67// NativeViewportImpl, NativeViewportDelegate implementation: 68 69void NativeViewportImpl::OnResized(const gfx::Size& size) { 70} 71 72void NativeViewportImpl::OnAcceleratedWidgetAvailable( 73 gfx::AcceleratedWidget widget) { 74 widget_ = widget; 75 CreateGLES2ContextIfNeeded(); 76} 77 78bool NativeViewportImpl::OnEvent(ui::Event* ui_event) { 79 // Must not return early before updating capture. 80 switch (ui_event->type()) { 81 case ui::ET_MOUSE_PRESSED: 82 case ui::ET_TOUCH_PRESSED: 83 native_viewport_->SetCapture(); 84 break; 85 case ui::ET_MOUSE_RELEASED: 86 case ui::ET_TOUCH_RELEASED: 87 native_viewport_->ReleaseCapture(); 88 break; 89 default: 90 break; 91 } 92 93 if (waiting_for_event_ack_ && IsRateLimitedEventType(ui_event)) 94 return false; 95 96 AllocationScope scope; 97 98 Event::Builder event; 99 event.set_action(ui_event->type()); 100 pending_event_timestamp_ = ui_event->time_stamp().ToInternalValue(); 101 event.set_time_stamp(pending_event_timestamp_); 102 103 if (ui_event->IsMouseEvent() || ui_event->IsTouchEvent()) { 104 ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(ui_event); 105 Point::Builder location; 106 location.set_x(located_event->location().x()); 107 location.set_y(located_event->location().y()); 108 event.set_location(location.Finish()); 109 } 110 111 if (ui_event->IsTouchEvent()) { 112 ui::TouchEvent* touch_event = static_cast<ui::TouchEvent*>(ui_event); 113 TouchData::Builder touch_data; 114 touch_data.set_pointer_id(touch_event->touch_id()); 115 event.set_touch_data(touch_data.Finish()); 116 } 117 118 client_->OnEvent(event.Finish()); 119 waiting_for_event_ack_ = true; 120 return false; 121} 122 123void NativeViewportImpl::OnDestroyed() { 124 // TODO(beng): 125 // Destroying |gles2_| on the shell thread here hits thread checker asserts. 126 // All code must stop touching the AcceleratedWidget at this point as it is 127 // dead after this call stack. jamesr said we probably should make our own 128 // GLSurface and simply tell it to stop touching the AcceleratedWidget 129 // via Destroy() but we have no good way of doing that right now given our 130 // current threading model so james' recommendation was just to wait until 131 // after we move the gl service out of process. 132 // gles2_.reset(); 133 client_->OnDestroyed(); 134} 135 136//////////////////////////////////////////////////////////////////////////////// 137// NativeViewportImpl, private: 138 139void NativeViewportImpl::CreateGLES2ContextIfNeeded() { 140 if (widget_ == gfx::kNullAcceleratedWidget || !gles2_) 141 return; 142 gles2_->CreateContext(widget_, native_viewport_->GetSize()); 143} 144 145} // namespace services 146} // namespace mojo 147