Refactor management of overview window copy lifetime into a separate class.
[chromium-blink-merge.git] / content / renderer / render_widget_fullscreen_pepper.cc
blob30f2ed9d5d0b4e1ef49c31930e7941cca1008936
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/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.h"
17 #include "content/renderer/pepper/pepper_plugin_instance_impl.h"
18 #include "content/renderer/render_thread_impl.h"
19 #include "gpu/command_buffer/client/gles2_implementation.h"
20 #include "skia/ext/platform_canvas.h"
21 #include "third_party/WebKit/public/platform/WebCanvas.h"
22 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
23 #include "third_party/WebKit/public/platform/WebLayer.h"
24 #include "third_party/WebKit/public/platform/WebSize.h"
25 #include "third_party/WebKit/public/web/WebCursorInfo.h"
26 #include "third_party/WebKit/public/web/WebWidget.h"
27 #include "ui/gfx/size_conversions.h"
28 #include "ui/gl/gpu_preference.h"
30 using WebKit::WebCanvas;
31 using WebKit::WebCompositionUnderline;
32 using WebKit::WebCursorInfo;
33 using WebKit::WebGestureEvent;
34 using WebKit::WebInputEvent;
35 using WebKit::WebMouseEvent;
36 using WebKit::WebMouseWheelEvent;
37 using WebKit::WebPoint;
38 using WebKit::WebRect;
39 using WebKit::WebSize;
40 using WebKit::WebString;
41 using WebKit::WebTextDirection;
42 using WebKit::WebTextInputType;
43 using WebKit::WebVector;
44 using WebKit::WebWidget;
45 using WebKit::WGC3Dintptr;
47 namespace content {
49 namespace {
51 class FullscreenMouseLockDispatcher : public MouseLockDispatcher {
52 public:
53 explicit FullscreenMouseLockDispatcher(RenderWidgetFullscreenPepper* widget);
54 virtual ~FullscreenMouseLockDispatcher();
56 private:
57 // MouseLockDispatcher implementation.
58 virtual void SendLockMouseRequest(bool unlocked_by_target) OVERRIDE;
59 virtual void SendUnlockMouseRequest() OVERRIDE;
61 RenderWidgetFullscreenPepper* widget_;
63 DISALLOW_COPY_AND_ASSIGN(FullscreenMouseLockDispatcher);
66 WebMouseEvent WebMouseEventFromGestureEvent(const WebGestureEvent& gesture) {
67 WebMouseEvent mouse;
69 switch (gesture.type) {
70 case WebInputEvent::GestureScrollBegin:
71 mouse.type = WebInputEvent::MouseDown;
72 break;
74 case WebInputEvent::GestureScrollUpdate:
75 mouse.type = WebInputEvent::MouseMove;
76 break;
78 case WebInputEvent::GestureFlingStart:
79 if (gesture.sourceDevice == WebGestureEvent::Touchscreen) {
80 // A scroll gesture on the touchscreen may end with a GestureScrollEnd
81 // when there is no velocity, or a GestureFlingStart when it has a
82 // velocity. In both cases, it should end the drag that was initiated by
83 // the GestureScrollBegin (and subsequent GestureScrollUpdate) events.
84 mouse.type = WebInputEvent::MouseUp;
85 break;
86 } else {
87 return mouse;
89 case WebInputEvent::GestureScrollEnd:
90 mouse.type = WebInputEvent::MouseUp;
91 break;
93 default:
94 break;
97 if (mouse.type == WebInputEvent::Undefined)
98 return mouse;
100 mouse.timeStampSeconds = gesture.timeStampSeconds;
101 mouse.modifiers = gesture.modifiers | WebInputEvent::LeftButtonDown;
102 mouse.button = WebMouseEvent::ButtonLeft;
103 mouse.clickCount = (mouse.type == WebInputEvent::MouseDown ||
104 mouse.type == WebInputEvent::MouseUp);
106 mouse.x = gesture.x;
107 mouse.y = gesture.y;
108 mouse.windowX = gesture.globalX;
109 mouse.windowY = gesture.globalY;
110 mouse.globalX = gesture.globalX;
111 mouse.globalY = gesture.globalY;
113 return mouse;
116 FullscreenMouseLockDispatcher::FullscreenMouseLockDispatcher(
117 RenderWidgetFullscreenPepper* widget) : widget_(widget) {
120 FullscreenMouseLockDispatcher::~FullscreenMouseLockDispatcher() {
123 void FullscreenMouseLockDispatcher::SendLockMouseRequest(
124 bool unlocked_by_target) {
125 widget_->Send(new ViewHostMsg_LockMouse(widget_->routing_id(), false,
126 unlocked_by_target, true));
129 void FullscreenMouseLockDispatcher::SendUnlockMouseRequest() {
130 widget_->Send(new ViewHostMsg_UnlockMouse(widget_->routing_id()));
133 // WebWidget that simply wraps the pepper plugin.
134 class PepperWidget : public WebWidget {
135 public:
136 explicit PepperWidget(RenderWidgetFullscreenPepper* widget)
137 : widget_(widget) {
140 virtual ~PepperWidget() {}
142 // WebWidget API
143 virtual void close() {
144 delete this;
147 virtual WebSize size() {
148 return size_;
151 virtual void willStartLiveResize() {
154 virtual void resize(const WebSize& size) {
155 if (!widget_->plugin())
156 return;
158 size_ = size;
159 WebRect plugin_rect(0, 0, size_.width, size_.height);
160 widget_->plugin()->ViewChanged(plugin_rect, plugin_rect,
161 std::vector<gfx::Rect>());
162 widget_->Invalidate();
165 virtual void willEndLiveResize() {
168 virtual void animate(double frameBeginTime) {
171 virtual void layout() {
174 virtual void paint(WebCanvas* canvas, const WebRect& rect, PaintOptions) {
175 if (!widget_->plugin())
176 return;
178 SkAutoCanvasRestore auto_restore(canvas, true);
179 float canvas_scale = widget_->deviceScaleFactor();
180 canvas->scale(canvas_scale, canvas_scale);
182 WebRect plugin_rect(0, 0, size_.width, size_.height);
183 widget_->plugin()->Paint(canvas, plugin_rect, rect);
186 virtual void setCompositorSurfaceReady() {
189 virtual void composite(bool finish) {
192 virtual void themeChanged() {
193 NOTIMPLEMENTED();
196 virtual bool handleInputEvent(const WebInputEvent& event) {
197 if (!widget_->plugin())
198 return false;
200 // This cursor info is ignored, we always set the cursor directly from
201 // RenderWidgetFullscreenPepper::DidChangeCursor.
202 WebCursorInfo cursor;
204 // Pepper plugins do not accept gesture events. So do not send the gesture
205 // events directly to the plugin. Instead, try to convert them to equivalent
206 // mouse events, and then send to the plugin.
207 if (WebInputEvent::isGestureEventType(event.type)) {
208 bool result = false;
209 const WebGestureEvent* gesture_event =
210 static_cast<const WebGestureEvent*>(&event);
211 switch (event.type) {
212 case WebInputEvent::GestureTap: {
213 WebMouseEvent mouse;
215 mouse.timeStampSeconds = gesture_event->timeStampSeconds;
216 mouse.type = WebInputEvent::MouseMove;
217 mouse.modifiers = gesture_event->modifiers;
219 mouse.x = gesture_event->x;
220 mouse.y = gesture_event->y;
221 mouse.windowX = gesture_event->globalX;
222 mouse.windowY = gesture_event->globalY;
223 mouse.globalX = gesture_event->globalX;
224 mouse.globalY = gesture_event->globalY;
225 mouse.movementX = 0;
226 mouse.movementY = 0;
227 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
229 mouse.type = WebInputEvent::MouseDown;
230 mouse.button = WebMouseEvent::ButtonLeft;
231 mouse.clickCount = gesture_event->data.tap.tapCount;
232 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
234 mouse.type = WebInputEvent::MouseUp;
235 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
236 break;
239 default: {
240 WebMouseEvent mouse = WebMouseEventFromGestureEvent(*gesture_event);
241 if (mouse.type != WebInputEvent::Undefined)
242 result |= widget_->plugin()->HandleInputEvent(mouse, &cursor);
243 break;
246 return result;
249 bool result = widget_->plugin()->HandleInputEvent(event, &cursor);
251 // For normal web pages, WebViewImpl does input event translations and
252 // generates context menu events. Since we don't have a WebView, we need to
253 // do the necessary translation ourselves.
254 if (WebInputEvent::isMouseEventType(event.type)) {
255 const WebMouseEvent& mouse_event =
256 reinterpret_cast<const WebMouseEvent&>(event);
257 bool send_context_menu_event = false;
258 // On Mac/Linux, we handle it on mouse down.
259 // On Windows, we handle it on mouse up.
260 #if defined(OS_WIN)
261 send_context_menu_event =
262 mouse_event.type == WebInputEvent::MouseUp &&
263 mouse_event.button == WebMouseEvent::ButtonRight;
264 #elif defined(OS_MACOSX)
265 send_context_menu_event =
266 mouse_event.type == WebInputEvent::MouseDown &&
267 (mouse_event.button == WebMouseEvent::ButtonRight ||
268 (mouse_event.button == WebMouseEvent::ButtonLeft &&
269 mouse_event.modifiers & WebMouseEvent::ControlKey));
270 #else
271 send_context_menu_event =
272 mouse_event.type == WebInputEvent::MouseDown &&
273 mouse_event.button == WebMouseEvent::ButtonRight;
274 #endif
275 if (send_context_menu_event) {
276 WebMouseEvent context_menu_event(mouse_event);
277 context_menu_event.type = WebInputEvent::ContextMenu;
278 widget_->plugin()->HandleInputEvent(context_menu_event, &cursor);
281 return result;
284 virtual void mouseCaptureLost() {
287 virtual void setFocus(bool focus) {
290 // TODO(piman): figure out IME and implement these if necessary.
291 virtual bool setComposition(
292 const WebString& text,
293 const WebVector<WebCompositionUnderline>& underlines,
294 int selectionStart,
295 int selectionEnd) {
296 return false;
299 virtual bool confirmComposition() {
300 return false;
303 virtual bool compositionRange(size_t* location, size_t* length) {
304 return false;
307 virtual bool confirmComposition(const WebString& text) {
308 return false;
311 virtual WebTextInputType textInputType() {
312 return WebKit::WebTextInputTypeNone;
315 virtual WebRect caretOrSelectionBounds() {
316 return WebRect();
319 virtual bool selectionRange(WebPoint& start, WebPoint& end) const {
320 return false;
323 virtual bool caretOrSelectionRange(size_t* location, size_t* length) {
324 return false;
327 virtual void setTextDirection(WebTextDirection) {
330 virtual bool isAcceleratedCompositingActive() const {
331 return widget_->plugin() && widget_->is_compositing();
334 private:
335 RenderWidgetFullscreenPepper* widget_;
336 WebSize size_;
338 DISALLOW_COPY_AND_ASSIGN(PepperWidget);
341 } // anonymous namespace
343 // static
344 RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
345 int32 opener_id,
346 PepperPluginInstanceImpl* plugin,
347 const GURL& active_url,
348 const WebKit::WebScreenInfo& screen_info) {
349 DCHECK_NE(MSG_ROUTING_NONE, opener_id);
350 scoped_refptr<RenderWidgetFullscreenPepper> widget(
351 new RenderWidgetFullscreenPepper(plugin, active_url, screen_info));
352 widget->Init(opener_id);
353 widget->AddRef();
354 return widget.get();
357 RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
358 PepperPluginInstanceImpl* plugin,
359 const GURL& active_url,
360 const WebKit::WebScreenInfo& screen_info)
361 : RenderWidgetFullscreen(screen_info),
362 active_url_(active_url),
363 plugin_(plugin),
364 layer_(NULL),
365 mouse_lock_dispatcher_(new FullscreenMouseLockDispatcher(
366 this)) {
369 RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
372 void RenderWidgetFullscreenPepper::Invalidate() {
373 InvalidateRect(gfx::Rect(size_.width(), size_.height()));
376 void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
377 didInvalidateRect(rect);
380 void RenderWidgetFullscreenPepper::ScrollRect(
381 int dx, int dy, const WebKit::WebRect& rect) {
382 didScrollRect(dx, dy, rect);
385 void RenderWidgetFullscreenPepper::Destroy() {
386 // This function is called by the plugin instance as it's going away, so reset
387 // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
388 plugin_ = NULL;
390 // After calling Destroy(), the plugin instance assumes that the layer is not
391 // used by us anymore, so it may destroy the layer before this object goes
392 // away.
393 SetLayer(NULL);
395 Send(new ViewHostMsg_Close(routing_id_));
396 Release();
399 void RenderWidgetFullscreenPepper::DidChangeCursor(
400 const WebKit::WebCursorInfo& cursor) {
401 didChangeCursor(cursor);
404 void RenderWidgetFullscreenPepper::SetLayer(WebKit::WebLayer* layer) {
405 layer_ = layer;
406 bool compositing = !!layer_;
407 if (compositing != is_accelerated_compositing_active_) {
408 if (compositing) {
409 initializeLayerTreeView();
410 if (!layerTreeView())
411 return;
412 layer_->setBounds(WebKit::WebSize(size()));
413 layer_->setDrawsContent(true);
414 compositor_->setDeviceScaleFactor(device_scale_factor_);
415 compositor_->setRootLayer(*layer_);
416 didActivateCompositor(-1);
417 } else {
418 didDeactivateCompositor();
423 bool RenderWidgetFullscreenPepper::OnMessageReceived(const IPC::Message& msg) {
424 bool handled = true;
425 IPC_BEGIN_MESSAGE_MAP(RenderWidgetFullscreenPepper, msg)
426 IPC_MESSAGE_FORWARD(ViewMsg_LockMouse_ACK,
427 mouse_lock_dispatcher_.get(),
428 MouseLockDispatcher::OnLockMouseACK)
429 IPC_MESSAGE_FORWARD(ViewMsg_MouseLockLost,
430 mouse_lock_dispatcher_.get(),
431 MouseLockDispatcher::OnMouseLockLost)
432 IPC_MESSAGE_UNHANDLED(handled = false)
433 IPC_END_MESSAGE_MAP()
434 if (handled)
435 return true;
437 return RenderWidgetFullscreen::OnMessageReceived(msg);
440 void RenderWidgetFullscreenPepper::DidInitiatePaint() {
441 if (plugin_)
442 plugin_->ViewInitiatedPaint();
445 void RenderWidgetFullscreenPepper::DidFlushPaint() {
446 if (plugin_)
447 plugin_->ViewFlushedPaint();
450 void RenderWidgetFullscreenPepper::Close() {
451 // If the fullscreen window is closed (e.g. user pressed escape), reset to
452 // normal mode.
453 if (plugin_)
454 plugin_->FlashSetFullscreen(false, false);
456 // Call Close on the base class to destroy the WebWidget instance.
457 RenderWidget::Close();
460 PepperPluginInstanceImpl*
461 RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint(
462 const gfx::Rect& paint_bounds,
463 TransportDIB** dib,
464 gfx::Rect* location,
465 gfx::Rect* clip,
466 float* scale_factor) {
467 if (plugin_ && plugin_->GetBitmapForOptimizedPluginPaint(
468 paint_bounds, dib, location, clip, scale_factor)) {
469 return plugin_;
471 return NULL;
474 void RenderWidgetFullscreenPepper::OnResize(
475 const ViewMsg_Resize_Params& params) {
476 if (layer_)
477 layer_->setBounds(WebKit::WebSize(params.new_size));
478 RenderWidget::OnResize(params);
481 WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
482 return new PepperWidget(this);
485 GURL RenderWidgetFullscreenPepper::GetURLForGraphicsContext3D() {
486 return active_url_;
489 void RenderWidgetFullscreenPepper::SetDeviceScaleFactor(
490 float device_scale_factor) {
491 RenderWidget::SetDeviceScaleFactor(device_scale_factor);
492 if (compositor_)
493 compositor_->setDeviceScaleFactor(device_scale_factor);
496 } // namespace content