Index: webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
=================================================================== |
--- webkit/glue/plugins/webplugin_delegate_impl_gtk.cc (revision 54851) |
+++ webkit/glue/plugins/webplugin_delegate_impl_gtk.cc (working copy) |
@@ -44,6 +44,7 @@ |
windowless_(false), |
plugin_(NULL), |
instance_(instance), |
+ windowless_shm_pixmap_(None), |
pixmap_(NULL), |
first_event_time_(-1.0), |
plug_(NULL), |
@@ -399,47 +400,99 @@ |
pixmap_draw_rect.right(), |
pixmap_draw_rect.bottom()); |
- EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); |
- |
- // Copy the current image into the pixmap, so the plugin can draw over |
- // this background. |
- cairo_t* cairo = gdk_cairo_create(pixmap_); |
- BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); |
- cairo_destroy(cairo); |
- |
// Construct the paint message, targeting the pixmap. |
NPEvent np_event = {0}; |
XGraphicsExposeEvent &event = np_event.xgraphicsexpose; |
event.type = GraphicsExpose; |
- event.display = GDK_DISPLAY(); |
- event.drawable = GDK_PIXMAP_XID(pixmap_); |
event.x = pixmap_draw_rect.x(); |
event.y = pixmap_draw_rect.y(); |
event.width = pixmap_draw_rect.width(); |
event.height = pixmap_draw_rect.height(); |
+ event.display = GDK_DISPLAY(); |
- // Tell the plugin to paint into the pixmap. |
- static StatsRate plugin_paint("Plugin.Paint"); |
- StatsScope<StatsRate> scope(plugin_paint); |
- NPError err = instance()->NPP_HandleEvent(&np_event); |
- DCHECK_EQ(err, NPERR_NO_ERROR); |
+ if (windowless_shm_pixmap_ != None) { |
+ Pixmap pixmap = None; |
+ GC xgc = NULL; |
+ Display* display = event.display; |
+ gfx::Rect plugin_draw_rect = draw_rect; |
- cairo_save(context); |
- // Now copy the rendered image pixmap back into the drawing buffer. |
- gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); |
- cairo_rectangle(context, draw_rect.x(), draw_rect.y(), |
- draw_rect.width(), draw_rect.height()); |
- cairo_clip(context); |
- cairo_paint(context); |
+ // Make plugin_draw_rect relative to the plugin window. |
+ plugin_draw_rect.Offset(-window_rect_.x(), -window_rect_.y()); |
+ // In case the drawing area does not start with the plugin window origin, |
+ // we can not let the plugin directly draw over the shared memory pixmap. |
+ if (plugin_draw_rect.x() != pixmap_draw_rect.x() || |
+ plugin_draw_rect.y() != pixmap_draw_rect.y()) { |
+ pixmap = XCreatePixmap(display, windowless_shm_pixmap_, |
+ std::max(1, pixmap_rect.width()), |
+ std::max(1, pixmap_rect.height()), |
+ DefaultDepth(display, 0)); |
+ xgc = XCreateGC(display, windowless_shm_pixmap_, 0, NULL); |
+ // Copy the current image into the pixmap, so the plugin can draw over it. |
+ XCopyArea(display, windowless_shm_pixmap_, pixmap, xgc, |
+ plugin_draw_rect.x(), plugin_draw_rect.y(), |
+ pixmap_draw_rect.width(), pixmap_draw_rect.height(), |
+ pixmap_draw_rect.x(), pixmap_draw_rect.y()); |
+ |
+ event.drawable = pixmap; |
+ } else { |
+ event.drawable = windowless_shm_pixmap_; |
+ } |
+ |
+ // Tell the plugin to paint into the pixmap. |
+ static StatsRate plugin_paint("Plugin.Paint"); |
+ StatsScope<StatsRate> scope(plugin_paint); |
+ NPError err = instance()->NPP_HandleEvent(&np_event); |
+ DCHECK_EQ(err, NPERR_NO_ERROR); |
+ |
+ if (pixmap != None) { |
+ // Copy the rendered image pixmap back into the shm pixmap |
+ // and thus the drawing buffer. |
+ XCopyArea(display, pixmap, windowless_shm_pixmap_, xgc, |
+ pixmap_draw_rect.x(), pixmap_draw_rect.y(), |
+ pixmap_draw_rect.width(), pixmap_draw_rect.height(), |
+ plugin_draw_rect.x(), plugin_draw_rect.y()); |
+ XSync(display, FALSE); |
+ if (xgc) |
+ XFreeGC(display, xgc); |
+ XFreePixmap(display, pixmap); |
+ } else { |
+ XSync(display, FALSE); |
+ } |
+ } else { |
+ EnsurePixmapAtLeastSize(pixmap_rect.width(), pixmap_rect.height()); |
+ |
+ // Copy the current image into the pixmap, so the plugin can draw over |
+ // this background. |
+ cairo_t* cairo = gdk_cairo_create(pixmap_); |
+ BlitContextToContext(cairo, pixmap_draw_rect, context, draw_rect.origin()); |
+ cairo_destroy(cairo); |
+ |
+ event.drawable = GDK_PIXMAP_XID(pixmap_); |
+ |
+ // Tell the plugin to paint into the pixmap. |
+ static StatsRate plugin_paint("Plugin.Paint"); |
+ StatsScope<StatsRate> scope(plugin_paint); |
+ NPError err = instance()->NPP_HandleEvent(&np_event); |
+ DCHECK_EQ(err, NPERR_NO_ERROR); |
+ |
+ cairo_save(context); |
+ // Now copy the rendered image pixmap back into the drawing buffer. |
+ gdk_cairo_set_source_pixmap(context, pixmap_, -offset_x, -offset_y); |
+ cairo_rectangle(context, draw_rect.x(), draw_rect.y(), |
+ draw_rect.width(), draw_rect.height()); |
+ cairo_clip(context); |
+ cairo_paint(context); |
+ |
#ifdef DEBUG_RECTANGLES |
- // Draw some debugging rectangles. |
- // Pixmap rect = blue. |
- DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); |
- // Drawing rect = red. |
- DrawDebugRectangle(context, draw_rect, 1, 0, 0); |
+ // Draw some debugging rectangles. |
+ // Pixmap rect = blue. |
+ DrawDebugRectangle(context, pixmap_rect, 0, 0, 1); |
+ // Drawing rect = red. |
+ DrawDebugRectangle(context, draw_rect, 1, 0, 0); |
#endif |
- cairo_restore(context); |
+ cairo_restore(context); |
+ } |
} |
void WebPluginDelegateImpl::WindowlessSetWindow() { |