OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/glue/plugins/webplugin_delegate_impl.h" | 5 #include "webkit/glue/plugins/webplugin_delegate_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include <gtk/gtk.h> | 10 #include <gtk/gtk.h> |
(...skipping 26 matching lines...) Expand all Loading... |
37 using WebKit::WebMouseEvent; | 37 using WebKit::WebMouseEvent; |
38 | 38 |
39 WebPluginDelegateImpl::WebPluginDelegateImpl( | 39 WebPluginDelegateImpl::WebPluginDelegateImpl( |
40 gfx::PluginWindowHandle containing_view, | 40 gfx::PluginWindowHandle containing_view, |
41 NPAPI::PluginInstance *instance) | 41 NPAPI::PluginInstance *instance) |
42 : windowed_handle_(0), | 42 : windowed_handle_(0), |
43 windowed_did_set_window_(false), | 43 windowed_did_set_window_(false), |
44 windowless_(false), | 44 windowless_(false), |
45 plugin_(NULL), | 45 plugin_(NULL), |
46 instance_(instance), | 46 instance_(instance), |
| 47 windowless_shm_pixmap_(None), |
47 pixmap_(NULL), | 48 pixmap_(NULL), |
48 first_event_time_(-1.0), | 49 first_event_time_(-1.0), |
49 plug_(NULL), | 50 plug_(NULL), |
50 socket_(NULL), | 51 socket_(NULL), |
51 parent_(containing_view), | 52 parent_(containing_view), |
52 quirks_(0), | 53 quirks_(0), |
53 handle_event_depth_(0), | 54 handle_event_depth_(0), |
54 first_set_window_call_(true) { | 55 first_set_window_call_(true) { |
55 memset(&window_, 0, sizeof(window_)); | 56 memset(&window_, 0, sizeof(window_)); |
56 if (instance_->mime_type() == "application/x-shockwave-flash") { | 57 if (instance_->mime_type() == "application/x-shockwave-flash") { |
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 DCHECK_EQ(err, NPERR_NO_ERROR); | 393 DCHECK_EQ(err, NPERR_NO_ERROR); |
393 } | 394 } |
394 | 395 |
395 gfx::Rect pixmap_draw_rect = draw_rect; | 396 gfx::Rect pixmap_draw_rect = draw_rect; |
396 pixmap_draw_rect.Offset(offset_x, offset_y); | 397 pixmap_draw_rect.Offset(offset_x, offset_y); |
397 | 398 |
398 gfx::Rect pixmap_rect(0, 0, | 399 gfx::Rect pixmap_rect(0, 0, |
399 pixmap_draw_rect.right(), | 400 pixmap_draw_rect.right(), |
400 pixmap_draw_rect.bottom()); | 401 pixmap_draw_rect.bottom()); |
401 | 402 |
402 EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); | |
403 | |
404 // Copy the current image into the pixmap, so the plugin can draw over | |
405 // this background. | |
406 cairo_t* cairo = gdk_cairo_create(pixmap_); | |
407 BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); | |
408 cairo_destroy(cairo); | |
409 | |
410 // Construct the paint message, targeting the pixmap. | 403 // Construct the paint message, targeting the pixmap. |
411 NPEvent np_event = {0}; | 404 NPEvent np_event = {0}; |
412 XGraphicsExposeEvent &event = np_event.xgraphicsexpose; | 405 XGraphicsExposeEvent &event = np_event.xgraphicsexpose; |
413 event.type = GraphicsExpose; | 406 event.type = GraphicsExpose; |
414 event.display = GDK_DISPLAY(); | |
415 event.drawable = GDK_PIXMAP_XID(pixmap_); | |
416 event.x = pixmap_draw_rect.x(); | 407 event.x = pixmap_draw_rect.x(); |
417 event.y = pixmap_draw_rect.y(); | 408 event.y = pixmap_draw_rect.y(); |
418 event.width = pixmap_draw_rect.width(); | 409 event.width = pixmap_draw_rect.width(); |
419 event.height = pixmap_draw_rect.height(); | 410 event.height = pixmap_draw_rect.height(); |
| 411 event.display = GDK_DISPLAY(); |
420 | 412 |
421 // Tell the plugin to paint into the pixmap. | 413 if (windowless_shm_pixmap_ != None) { |
422 static StatsRate plugin_paint("Plugin.Paint"); | 414 Pixmap pixmap = None; |
423 StatsScope<StatsRate> scope(plugin_paint); | 415 GC xgc = NULL; |
424 NPError err = instance()->NPP_HandleEvent(&np_event); | 416 Display* display = event.display; |
425 DCHECK_EQ(err, NPERR_NO_ERROR); | 417 gfx::Rect plugin_draw_rect = draw_rect; |
426 | 418 |
427 cairo_save(context); | 419 // Make plugin_draw_rect relative to the plugin window. |
428 // Now copy the rendered image pixmap back into the drawing buffer. | 420 plugin_draw_rect.Offset(-window_rect_.x(), -window_rect_.y()); |
429 gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); | 421 |
430 cairo_rectangle(context, draw_rect.x(), draw_rect.y(), | 422 // In case the drawing area does not start with the plugin window origin, |
431 draw_rect.width(), draw_rect.height()); | 423 // we can not let the plugin directly draw over the shared memory pixmap. |
432 cairo_clip(context); | 424 if (plugin_draw_rect.x() != pixmap_draw_rect.x() || |
433 cairo_paint(context); | 425 plugin_draw_rect.y() != pixmap_draw_rect.y()) { |
| 426 pixmap = XCreatePixmap(display, windowless_shm_pixmap_, |
| 427 std::max(1, pixmap_rect.width()), |
| 428 std::max(1, pixmap_rect.height()), |
| 429 DefaultDepth(display, 0)); |
| 430 xgc = XCreateGC(display, windowless_shm_pixmap_, 0, NULL); |
| 431 // Copy the current image into the pixmap, so the plugin can draw over it. |
| 432 XCopyArea(display, windowless_shm_pixmap_, pixmap, xgc, |
| 433 plugin_draw_rect.x(), plugin_draw_rect.y(), |
| 434 pixmap_draw_rect.width(), pixmap_draw_rect.height(), |
| 435 pixmap_draw_rect.x(), pixmap_draw_rect.y()); |
| 436 |
| 437 event.drawable = pixmap; |
| 438 } else { |
| 439 event.drawable = windowless_shm_pixmap_; |
| 440 } |
| 441 |
| 442 // Tell the plugin to paint into the pixmap. |
| 443 static StatsRate plugin_paint("Plugin.Paint"); |
| 444 StatsScope<StatsRate> scope(plugin_paint); |
| 445 NPError err = instance()->NPP_HandleEvent(&np_event); |
| 446 DCHECK_EQ(err, NPERR_NO_ERROR); |
| 447 |
| 448 if (pixmap != None) { |
| 449 // Copy the rendered image pixmap back into the shm pixmap |
| 450 // and thus the drawing buffer. |
| 451 XCopyArea(display, pixmap, windowless_shm_pixmap_, xgc, |
| 452 pixmap_draw_rect.x(), pixmap_draw_rect.y(), |
| 453 pixmap_draw_rect.width(), pixmap_draw_rect.height(), |
| 454 plugin_draw_rect.x(), plugin_draw_rect.y()); |
| 455 XSync(display, FALSE); |
| 456 if (xgc) |
| 457 XFreeGC(display, xgc); |
| 458 XFreePixmap(display, pixmap); |
| 459 } else { |
| 460 XSync(display, FALSE); |
| 461 } |
| 462 } else { |
| 463 EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); |
| 464 |
| 465 // Copy the current image into the pixmap, so the plugin can draw over |
| 466 // this background. |
| 467 cairo_t* cairo = gdk_cairo_create(pixmap_); |
| 468 BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); |
| 469 cairo_destroy(cairo); |
| 470 |
| 471 event.drawable = GDK_PIXMAP_XID(pixmap_); |
| 472 |
| 473 // Tell the plugin to paint into the pixmap. |
| 474 static StatsRate plugin_paint("Plugin.Paint"); |
| 475 StatsScope<StatsRate> scope(plugin_paint); |
| 476 NPError err = instance()->NPP_HandleEvent(&np_event); |
| 477 DCHECK_EQ(err, NPERR_NO_ERROR); |
| 478 |
| 479 cairo_save(context); |
| 480 // Now copy the rendered image pixmap back into the drawing buffer. |
| 481 gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); |
| 482 cairo_rectangle(context, draw_rect.x(), draw_rect.y(), |
| 483 draw_rect.width(), draw_rect.height()); |
| 484 cairo_clip(context); |
| 485 cairo_paint(context); |
434 | 486 |
435 #ifdef DEBUG_RECTANGLES | 487 #ifdef DEBUG_RECTANGLES |
436 // Draw some debugging rectangles. | 488 // Draw some debugging rectangles. |
437 // Pixmap rect = blue. | 489 // Pixmap rect = blue. |
438 DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); | 490 DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); |
439 // Drawing rect = red. | 491 // Drawing rect = red. |
440 DrawDebugRectangle(context, draw_rect, 1, 0, 0); | 492 DrawDebugRectangle(context, draw_rect, 1, 0, 0); |
441 #endif | 493 #endif |
442 cairo_restore(context); | 494 cairo_restore(context); |
| 495 } |
443 } | 496 } |
444 | 497 |
445 void WebPluginDelegateImpl::WindowlessSetWindow() { | 498 void WebPluginDelegateImpl::WindowlessSetWindow() { |
446 if (!instance()) | 499 if (!instance()) |
447 return; | 500 return; |
448 | 501 |
449 if (window_rect_.IsEmpty()) // wait for geometry to be set. | 502 if (window_rect_.IsEmpty()) // wait for geometry to be set. |
450 return; | 503 return; |
451 | 504 |
452 DCHECK(instance()->windowless()); | 505 DCHECK(instance()->windowless()); |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
700 if (event->event == WM_MOUSEMOVE) { | 753 if (event->event == WM_MOUSEMOVE) { |
701 // Snag a reference to the current cursor ASAP in case the plugin modified | 754 // Snag a reference to the current cursor ASAP in case the plugin modified |
702 // it. There is a nasty race condition here with the multiprocess browser | 755 // it. There is a nasty race condition here with the multiprocess browser |
703 // as someone might be setting the cursor in the main process as well. | 756 // as someone might be setting the cursor in the main process as well. |
704 *cursor = current_windowless_cursor_; | 757 *cursor = current_windowless_cursor_; |
705 } | 758 } |
706 #endif | 759 #endif |
707 | 760 |
708 return ret; | 761 return ret; |
709 } | 762 } |
OLD | NEW |