Fix build break
[chromium-blink-merge.git] / content / renderer / render_widget_fullscreen_pepper.cc
blobb1eeecdfb00df1d6183a4ec6a2aef6bef9d64126
1 // Copyright (c) 2012 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 "content/renderer/render_widget_fullscreen_pepper.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/message_loop.h"
12 #include "content/common/gpu/client/gpu_channel_host.h"
13 #include "content/common/view_messages.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/renderer/gpu/render_widget_compositor.h"
16 #include "content/renderer/pepper/pepper_platform_context_3d_impl.h"
17 #include "content/renderer/render_thread_impl.h"
18 #include "gpu/command_buffer/client/gles2_implementation.h"
19 #include "skia/ext/platform_canvas.h"
20 #include "third_party/WebKit/Source/Platform/chromium/public/WebCanvas.h"
21 #include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
22 #include "third_party/WebKit/Source/Platform/chromium/public/WebLayer.h"
23 #include "third_party/WebKit/Source/Platform/chromium/public/WebSize.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
26 #include "ui/gfx/size_conversions.h"
27 #include "ui/gl/gpu_preference.h"
28 #include "webkit/plugins/ppapi/plugin_delegate.h"
29 #include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
31 using WebKit::WebCanvas;
32 using WebKit::WebCompositionUnderline;
33 using WebKit::WebCursorInfo;
34 using WebKit::WebGestureEvent;
35 using WebKit::WebInputEvent;
36 using WebKit::WebMouseEvent;
37 using WebKit::WebMouseWheelEvent;
38 using WebKit::WebPoint;
39 using WebKit::WebRect;
40 using WebKit::WebSize;
41 using WebKit::WebString;
42 using WebKit::WebTextDirection;
43 using WebKit::WebTextInputType;
44 using WebKit::WebVector;
45 using WebKit::WebWidget;
46 using WebKit::WGC3Dintptr;
48 namespace content {
50 namespace {
52 // See third_party/WebKit/Source/WebCore/dom/WheelEvent.h.
53 const float kTickDivisor = 120.0f;
55 class FullscreenMouseLockDispatcher : public MouseLockDispatcher {
56 public:
57 explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget);
58 virtual ~FullscreenMouseLockDispatcher();
60 private:
61 // MouseLockDispatcher implementation.
62 virtual void SendLockMouseRequest(bool unlocked_by_target) OVERRIDE;
63 virtual void SendUnlockMouseRequest() OVERRIDE;
65 RenderWidgetFullscreenPepper* widget_;
67 DISALLOW_COPY_AND_ASSIGN(FullscreenMouseLockDispatcher);
70 WebMouseEvent WebMouseEventFromGestureEvent(const WebGestureEvent& gesture) {
71 WebMouseEvent mouse;
73 switch (gesture.type) {
74 case WebInputEvent::GestureScrollBegin:
75 mouse.type = WebInputEvent::MouseDown;
76 break;
78 case WebInputEvent::GestureScrollUpdate:
79 mouse.type = WebInputEvent::MouseMove;
80 break;
82 case WebInputEvent::GestureFlingStart:
83 if (gesture.sourceDevice == WebGestureEvent::Touchscreen) {
84 // A scroll gesture on the touchscreen may end with a GestureScrollEnd
85 // when there is no velocity, or a GestureFlingStart when it has a
86 // velocity. In both cases, it should end the drag that was initiated by
87 // the GestureScrollBegin (and subsequent GestureScrollUpdate) events.
88 mouse.type = WebInputEvent::MouseUp;
89 break;
90 } else {
91 return mouse;
93 case WebInputEvent::GestureScrollEnd:
94 mouse.type = WebInputEvent::MouseUp;
95 break;
97 default:
98 break;
101 if (mouse.type == WebInputEvent::Undefined)
102 return mouse;
104 mouse.timeStampSeconds = gesture.timeStampSeconds;
105 mouse.modifiers = gesture.modifiers | WebInputEvent::LeftButtonDown;
106 mouse.button = WebMouseEvent::ButtonLeft;
107 mouse.clickCount = (mouse.type == WebInputEvent::MouseDown ||
108 mouse.type == WebInputEvent::MouseUp);
110 mouse.x = gesture.x;
111 mouse.y = gesture.y;
112 mouse.windowX = gesture.globalX;
113 mouse.windowY = gesture.globalY;
114 mouse.globalX = gesture.globalX;
115 mouse.globalY = gesture.globalY;
117 return mouse;
120 FullscreenMouseLockDispatcher::FullscreenMouseLockDispatcher(
121 RenderWidgetFullscreenPepper* widget) : widget_(widget) {
124 FullscreenMouseLockDispatcher::~FullscreenMouseLockDispatcher() {
127 void FullscreenMouseLockDispatcher::SendLockMouseRequest(
128 bool unlocked_by_target) {
129 widget_->Send(new ViewHostMsg_LockMouse(widget_->routing_id(), false,
130 unlocked_by_target, true));
133 void FullscreenMouseLockDispatcher::SendUnlockMouseRequest() {
134 widget_->Send(new ViewHostMsg_UnlockMouse(widget_->routing_id()));
137 // WebWidget that simply wraps the pepper plugin.
138 class PepperWidget : public WebWidget {
139 public:
140 explicit PepperWidget(RenderWidgetFullscreenPepper* widget)
141 : widget_(widget) {
144 virtual ~PepperWidget() {}
146 // WebWidget API
147 virtual void close() {
148 delete this;
151 virtual WebSize size() {
152 return size_;
155 virtual void willStartLiveResize() {
158 virtual void resize(const WebSize& size) {
159 if (!widget_->plugin())
160 return;
162 size_ = size;
163 WebRect plugin_rect(0, 0, size_.width, size_.height);
164 widget_->plugin()->ViewChanged(plugin_rect, plugin_rect,
165 std::vector<gfx::Rect>());
166 widget_->Invalidate();
169 virtual void willEndLiveResize() {
172 virtual void animate(double frameBeginTime) {
175 virtual void layout() {
178 virtual void paint(WebCanvas* canvas, const WebRect& rect, PaintOptions) {
179 if (!widget_->plugin())
180 return;
182 SkAutoCanvasRestore auto_restore(canvas, true);
183 float canvas_scale = widget_->deviceScaleFactor();
184 canvas->scale(canvas_scale, canvas_scale);
186 WebRect plugin_rect(0, 0, size_.width, size_.height);
187 widget_->plugin()->Paint(canvas, plugin_rect, rect);
190 virtual void setCompositorSurfaceReady() {
193 virtual void composite(bool finish) {
196 virtual void themeChanged() {
197 NOTIMPLEMENTED();
200 virtual bool handleInputEvent(const WebInputEvent& event) {
201 if (!widget_->plugin())
202 return false;
204 // This cursor info is ignored, we always set the cursor directly from
205 // RenderWidgetFullscreenPepper::DidChangeCursor.
206 WebCursorInfo cursor;
208 // Pepper plugins do not accept gesture events. So do not send the gesture
209 // events directly to the plugin. Instead, try to convert them to equivalent
210 // mouse events, and then send to the plugin.
211 if (WebInputEvent::isGestureEventType(event.type)) {
212 bool result = false;
213 const WebGestureEvent* gesture_event =
214 static_cast<const WebGestureEvent*>(&event);
215 switch (event.type) {
216 case WebInputEvent::GestureTap: {
217 WebMouseEvent mouse;
219 mouse.timeStampSeconds = gesture_event->timeStampSeconds;
220 mouse.type = WebInputEvent::MouseMove;
221 mouse.modifiers = gesture_event->modifiers;
223 mouse.x = gesture_event->x;
224 mouse.y = gesture_event->y;
225 mouse.windowX = gesture_event->globalX;
226 mouse.windowY = gesture_event->globalY;
227 mouse.globalX = gesture_event->globalX;
228 mouse.globalY = gesture_event->globalY;
229 mouse.movementX = 0;
230 mouse.movementY = 0;
231 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
233 mouse.type = WebInputEvent::MouseDown;
234 mouse.button = WebMouseEvent::ButtonLeft;
235 mouse.clickCount = gesture_event->data.tap.tapCount;
236 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
238 mouse.type = WebInputEvent::MouseUp;
239 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
240 break;
243 default: {
244 WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event);
245 if (mouse.type != WebInputEvent::Undefined)
246 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
247 break;
250 return result;
253 bool result = widget_->plugin()->HandleInputEvent(event, &cursor);
255 // For normal web pages, WebViewImpl does input event translations and
256 // generates context menu events. Since we don't have a WebView, we need to
257 // do the necessary translation ourselves.
258 if (WebInputEvent::isMouseEventType(event.type)) {
259 const WebMouseEvent& mouse_event =
260 reinterpret_cast<const WebMouseEvent&>(event);
261 bool send_context_menu_event = false;
262 // On Mac/Linux, we handle it on mouse down.
263 // On Windows, we handle it on mouse up.
264 #if defined(OS_WIN)
265 send_context_menu_event =
266 mouse_event.type == WebInputEvent::MouseUp &&
267 mouse_event.button == WebMouseEvent::ButtonRight;
268 #elif defined(OS_MACOSX)
269 send_context_menu_event =
270 mouse_event.type == WebInputEvent::MouseDown &&
271 (mouse_event.button == WebMouseEvent::ButtonRight ||
272 (mouse_event.button == WebMouseEvent::ButtonLeft &&
273 mouse_event.modifiers & WebMouseEvent::ControlKey));
274 #else
275 send_context_menu_event =
276 mouse_event.type == WebInputEvent::MouseDown &&
277 mouse_event.button == WebMouseEvent::ButtonRight;
278 #endif
279 if (send_context_menu_event) {
280 WebMouseEvent context_menu_event(mouse_event);
281 context_menu_event.type = WebInputEvent::ContextMenu;
282 widget_->plugin()->HandleInputEvent(context_menu_event, &cursor);
285 return result;
288 virtual void mouseCaptureLost() {
289 NOTIMPLEMENTED();
292 virtual void setFocus(bool focus) {
293 NOTIMPLEMENTED();
296 // TODO(piman): figure out IME and implement these if necessary.
297 virtual bool setComposition(
298 const WebString& text,
299 const WebVector<WebCompositionUnderline>& underlines,
300 int selectionStart,
301 int selectionEnd) {
302 return false;
305 virtual bool confirmComposition() {
306 return false;
309 virtual bool compositionRange(size_t* location, size_t* length) {
310 return false;
313 virtual bool confirmComposition(const WebString& text) {
314 return false;
317 virtual WebTextInputType textInputType() {
318 return WebKit::WebTextInputTypeNone;
321 virtual WebRect caretOrSelectionBounds() {
322 return WebRect();
325 virtual bool selectionRange(WebPoint& start, WebPoint& end) const {
326 return false;
329 virtual bool caretOrSelectionRange(size_t* location, size_t* length) {
330 return false;
333 virtual void setTextDirection(WebTextDirection) {
336 virtual bool isAcceleratedCompositingActive() const {
337 return widget_->plugin() && widget_->is_compositing();
340 private:
341 RenderWidgetFullscreenPepper* widget_;
342 WebSize size_;
344 DISALLOW_COPY_AND_ASSIGN(PepperWidget);
347 } // anonymous namespace
349 // static
350 RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
351 int32 opener_id, webkit::ppapi::PluginInstance* plugin,
352 const GURL& active_url,
353 const WebKit::WebScreenInfo& screen_info) {
354 DCHECK_NE(MSG_ROUTING_NONE, opener_id);
355 scoped_refptr<RenderWidgetFullscreenPepper> widget(
356 new RenderWidgetFullscreenPepper(plugin, active_url, screen_info));
357 widget->Init(opener_id);
358 widget->AddRef();
359 return widget.get();
362 RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
363 webkit::ppapi::PluginInstance* plugin,
364 const GURL& active_url,
365 const WebKit::WebScreenInfo& screen_info)
366 : RenderWidgetFullscreen(screen_info),
367 active_url_(active_url),
368 plugin_(plugin),
369 layer_(NULL),
370 mouse_lock_dispatcher_(new FullscreenMouseLockDispatcher(
371 ALLOW_THIS_IN_INITIALIZER_LIST(this))) {
374 RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
377 void RenderWidgetFullscreenPepper::Invalidate() {
378 InvalidateRect(gfx::Rect(size_.width(), size_.height()));
381 void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
382 didInvalidateRect(rect);
385 void RenderWidgetFullscreenPepper::ScrollRect(
386 int dx, int dy, const WebKit::WebRect& rect) {
387 didScrollRect(dx, dy, rect);
390 void RenderWidgetFullscreenPepper::Destroy() {
391 // This function is called by the plugin instance as it's going away, so reset
392 // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
393 plugin_ = NULL;
394 Send(new ViewHostMsg_Close(routing_id_));
395 Release();
398 void RenderWidgetFullscreenPepper::DidChangeCursor(
399 const WebKit::WebCursorInfo& cursor) {
400 didChangeCursor(cursor);
403 webkit::ppapi::PluginDelegate::PlatformContext3D*
404 RenderWidgetFullscreenPepper::CreateContext3D() {
405 CommandLine* command_line = CommandLine::ForCurrentProcess();
406 if (command_line->HasSwitch(switches::kDisableFlashFullscreen3d))
407 return NULL;
408 return new PlatformContext3DImpl;
411 void RenderWidgetFullscreenPepper::ReparentContext(
412 webkit::ppapi::PluginDelegate::PlatformContext3D* context) {
413 PlatformContext3DImpl* context_impl =
414 static_cast<PlatformContext3DImpl*>(context);
416 CommandLine* command_line = CommandLine::ForCurrentProcess();
417 if (command_line->HasSwitch(switches::kDisableFlashFullscreen3d))
418 context_impl->DestroyParentContextProviderAndBackingTexture();
419 else
420 context_impl->SetParentAndCreateBackingTextureIfNeeded();
423 void RenderWidgetFullscreenPepper::SetLayer(WebKit::WebLayer* layer) {
424 layer_ = layer;
425 bool compositing = !!layer_;
426 if (compositing != is_accelerated_compositing_active_) {
427 if (compositing) {
428 initializeLayerTreeView();
429 if (!layerTreeView())
430 return;
431 layer_->setBounds(WebKit::WebSize(size()));
432 layer_->setDrawsContent(true);
433 compositor_->setDeviceScaleFactor(device_scale_factor_);
434 compositor_->setRootLayer(*layer_);
435 didActivateCompositor(-1);
436 } else {
437 didDeactivateCompositor();
442 bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) {
443 bool handled = true;
444 IPC_BEGIN_MESSAGE_MAP(RenderWidgetFullscreenPepper, msg)
445 IPC_MESSAGE_FORWARD(ViewMsg_LockMouse_ACK,
446 mouse_lock_dispatcher_.get(),
447 MouseLockDispatcher::OnLockMouseACK)
448 IPC_MESSAGE_FORWARD(ViewMsg_MouseLockLost,
449 mouse_lock_dispatcher_.get(),
450 MouseLockDispatcher::OnMouseLockLost)
451 IPC_MESSAGE_UNHANDLED(handled = false)
452 IPC_END_MESSAGE_MAP()
453 if (handled)
454 return true;
456 return RenderWidgetFullscreen::OnMessageReceived(msg);
459 void RenderWidgetFullscreenPepper::WillInitiatePaint() {
460 if (plugin_)
461 plugin_->ViewWillInitiatePaint();
464 void RenderWidgetFullscreenPepper::DidInitiatePaint() {
465 if (plugin_)
466 plugin_->ViewInitiatedPaint();
469 void RenderWidgetFullscreenPepper::DidFlushPaint() {
470 if (plugin_)
471 plugin_->ViewFlushedPaint();
474 void RenderWidgetFullscreenPepper::Close() {
475 // If the fullscreen window is closed (e.g. user pressed escape), reset to
476 // normal mode.
477 if (plugin_)
478 plugin_->FlashSetFullscreen(false, false);
480 // Call Close on the base class to destroy the WebWidget instance.
481 RenderWidget::Close();
484 webkit::ppapi::PluginInstance*
485 RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint(
486 const gfx::Rect& paint_bounds,
487 TransportDIB** dib,
488 gfx::Rect* location,
489 gfx::Rect* clip,
490 float* scale_factor) {
491 if (plugin_ && plugin_->GetBitmapForOptimizedPluginPaint(
492 paint_bounds, dib, location, clip, scale_factor)) {
493 return plugin_;
495 return NULL;
498 void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size,
499 const gfx::Size& physical_backing_size,
500 float overdraw_bottom_height,
501 const gfx::Rect& resizer_rect,
502 bool is_fullscreen) {
503 if (layer_)
504 layer_->setBounds(WebKit::WebSize(size));
505 RenderWidget::OnResize(size, physical_backing_size, overdraw_bottom_height,
506 resizer_rect, is_fullscreen);
509 WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
510 return new PepperWidget(this);
513 GURL RenderWidgetFullscreenPepper::GetURLForGraphicsContext3D() {
514 return active_url_;
517 void RenderWidgetFullscreenPepper::SetDeviceScaleFactor(
518 float device_scale_factor) {
519 RenderWidget::SetDeviceScaleFactor(device_scale_factor);
520 if (compositor_)
521 compositor_->setDeviceScaleFactor(device_scale_factor);
524 } // namespace content