Index: webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
index 2e2058163107b00a78e897e979496e4d3ddb1164..c77b61bbae1d24d39da1eaa066a899238833ec88 100644 |
--- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
+++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
@@ -64,6 +64,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( |
windowless_(false), |
plugin_(NULL), |
instance_(instance), |
+ pixmap_(NULL), |
parent_(containing_view), |
quirks_(0) |
{ |
@@ -76,6 +77,17 @@ WebPluginDelegateImpl::~WebPluginDelegateImpl() { |
if (!windowless_) |
WindowedDestroyWindow(); |
+ |
+ if (window_.ws_info) { |
+ // We only ever use ws_info as an NPSetWindowCallbackStruct. |
+ delete static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); |
+ } |
+ |
+ if (pixmap_) { |
+ g_object_unref(gdk_drawable_get_colormap(pixmap_)); |
+ g_object_unref(pixmap_); |
+ pixmap_ = NULL; |
+ } |
} |
void WebPluginDelegateImpl::PluginDestroyed() { |
@@ -108,8 +120,6 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url, |
// a valid window handle causes subtle bugs with plugins which retreive |
// the window handle and validate the same. The window handle can be |
// retreived via NPN_GetValue of NPNVnetscapeWindow. |
- NOTIMPLEMENTED() << "windowless not implemented"; |
- return false; |
// instance_->set_window_handle(parent_); |
// CreateDummyWindowForActivation(); |
// handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); |
@@ -159,14 +169,14 @@ void WebPluginDelegateImpl::UpdateGeometry( |
} |
} |
-void WebPluginDelegateImpl::Paint(void* dc, const gfx::Rect& rect) { |
+void WebPluginDelegateImpl::Paint(cairo_surface_t* context, |
+ const gfx::Rect& rect) { |
if (windowless_) { |
- // TODO(port): windowless painting. |
- // WindowlessPaint(dc, rect); |
+ WindowlessPaint(context, rect); |
} |
} |
-void WebPluginDelegateImpl::Print(void* dc) { |
+void WebPluginDelegateImpl::Print(cairo_surface_t* context) { |
NOTIMPLEMENTED(); |
} |
@@ -321,13 +331,15 @@ bool WebPluginDelegateImpl::WindowedCreatePlugin() { |
window_.window = GINT_TO_POINTER( |
gtk_socket_get_id(GTK_SOCKET(windowed_handle_))); |
- NPSetWindowCallbackStruct* extra = new NPSetWindowCallbackStruct; |
+ if (!window_.ws_info) |
+ window_.ws_info = new NPSetWindowCallbackStruct; |
+ NPSetWindowCallbackStruct* extra = |
+ static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); |
extra->display = GDK_WINDOW_XDISPLAY(windowed_handle_->window); |
GdkVisual* visual = gdk_drawable_get_visual(windowed_handle_->window); |
extra->visual = GDK_VISUAL_XVISUAL(visual); |
extra->depth = visual->depth; |
extra->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(windowed_handle_->window)); |
- window_.ws_info = extra; |
return true; |
} |
@@ -411,7 +423,7 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
// Only resend to the instance if the geometry has changed. |
if (window_rect == window_rect_ && clip_rect == clip_rect_) |
return; |
- /* |
+ |
// Set this flag before entering the instance in case of side-effects. |
windowless_needs_set_window_ = true; |
@@ -423,40 +435,45 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
window_rect_ = window_rect; |
WindowlessSetWindow(true); |
+ } |
+} |
- WINDOWPOS win_pos = {0}; |
- win_pos.x = window_rect_.x(); |
- win_pos.y = window_rect_.y(); |
- win_pos.cx = window_rect_.width(); |
- win_pos.cy = window_rect_.height(); |
- |
- NPEvent pos_changed_event; |
- pos_changed_event.event = WM_WINDOWPOSCHANGED; |
- pos_changed_event.wParam = 0; |
- pos_changed_event.lParam = PtrToUlong(&win_pos); |
+void WebPluginDelegateImpl::EnsurePixmapAtLeastSize(int width, int height) { |
+ if (pixmap_) { |
+ gint cur_width, cur_height; |
+ gdk_drawable_get_size(pixmap_, &cur_width, &cur_height); |
+ if (cur_width >= width && cur_height >= height) |
+ return; // We are already the appropriate size. |
- instance()->NPP_HandleEvent(&pos_changed_event); |
+ // Otherwise, we need to recreate ourselves. |
+ g_object_unref(gdk_drawable_get_colormap(pixmap_)); |
+ g_object_unref(pixmap_); |
+ pixmap_ = NULL; |
} |
- */ |
+ |
+ // |sys_visual| is owned by gdk; we shouldn't free it. |
+ GdkVisual* sys_visual = gdk_visual_get_system(); |
+ pixmap_ = gdk_pixmap_new(NULL, // use width/height/depth params |
+ width, height, sys_visual->depth); |
+ GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(), |
+ FALSE); |
+ gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap_), colormap); |
} |
-#if 0 |
-void WebPluginDelegateImpl::WindowlessPaint(HDC hdc, |
+void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, |
const gfx::Rect& damage_rect) { |
- DCHECK(hdc); |
+ // Compare to: |
+ // http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp: |
+ // nsPluginInstanceOwner::Renderer::NativeDraw(). |
- RECT damage_rect_win; |
- damage_rect_win.left = damage_rect.x(); // + window_rect_.x(); |
- damage_rect_win.top = damage_rect.y(); // + window_rect_.y(); |
- damage_rect_win.right = damage_rect_win.left + damage_rect.width(); |
- damage_rect_win.bottom = damage_rect_win.top + damage_rect.height(); |
+ DCHECK(context); |
- // We need to pass the HDC to the plugin via NPP_SetWindow in the |
+ // We need to pass the DC to the plugin via NPP_SetWindow in the |
// first paint to ensure that it initiates rect invalidations. |
- if (window_.window == NULL) |
+ // TODO(evanm): for now, it appears we always need to do this. |
+ if (true) |
windowless_needs_set_window_ = true; |
- window_.window = hdc; |
// TODO(darin): we should avoid calling NPP_SetWindow here since it may |
// cause page layout to be invalidated. |
@@ -465,16 +482,37 @@ void WebPluginDelegateImpl::WindowlessPaint(HDC hdc, |
if (windowless_needs_set_window_) |
WindowlessSetWindow(false); |
- NPEvent paint_event; |
- paint_event.event = WM_PAINT; |
- // NOTE: NPAPI is not 64bit safe. It puts pointers into 32bit values. |
- paint_event.wParam = PtrToUlong(hdc); |
- paint_event.lParam = PtrToUlong(&damage_rect_win); |
+ EnsurePixmapAtLeastSize(damage_rect.width(), damage_rect.height()); |
+ |
+ // Copy the current image into the pixmap, so the plugin can draw over |
+ // this background. |
+ cairo_t* cairo = gdk_cairo_create(pixmap_); |
+ cairo_set_source_surface(cairo, context, 0, 0); |
+ cairo_paint(cairo); |
+ cairo_destroy(cairo); |
+ |
+ // Construct the paint message, targeting the pixmap. |
+ XGraphicsExposeEvent event = {0}; |
+ event.type = GraphicsExpose; |
+ event.display = GDK_DISPLAY(); |
+ event.drawable = GDK_PIXMAP_XID(pixmap_); |
+ event.x = damage_rect.x(); |
+ event.y = damage_rect.y(); |
+ event.width = damage_rect.width(); |
+ event.height = damage_rect.height(); |
+ |
+ // Tell the plugin to paint into the pixmap. |
static StatsRate plugin_paint("Plugin.Paint"); |
StatsScope<StatsRate> scope(plugin_paint); |
- instance()->NPP_HandleEvent(&paint_event); |
+ NPError err = instance()->NPP_HandleEvent(reinterpret_cast<XEvent*>(&event)); |
+ DCHECK_EQ(err, NPERR_NO_ERROR); |
+ |
+ // Now copy the rendered image pixmap back into the drawing buffer. |
+ cairo = cairo_create(context); |
+ gdk_cairo_set_source_pixmap(cairo, pixmap_, 0, 0); |
+ cairo_paint(cairo); |
+ cairo_destroy(cairo); |
} |
-#endif |
void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { |
if (!instance()) |
@@ -484,6 +522,9 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { |
return; |
DCHECK(instance()->windowless()); |
+ // Mozilla docs say that this window param is not used for windowless |
+ // plugins; rather, the window is passed during the GraphicsExpose event. |
+ DCHECK(window_.window == 0); |
window_.clipRect.top = clip_rect_.y(); |
window_.clipRect.left = clip_rect_.x(); |
@@ -495,6 +536,20 @@ void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { |
window_.y = window_rect_.y(); |
window_.type = NPWindowTypeDrawable; |
+ if (!window_.ws_info) |
+ window_.ws_info = new NPSetWindowCallbackStruct; |
+ NPSetWindowCallbackStruct* extra = |
+ static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); |
+ extra->display = GDK_DISPLAY(); |
+ GdkVisual* visual = gdk_visual_get_system(); |
+ extra->visual = GDK_VISUAL_XVISUAL(visual); |
+ extra->depth = visual->depth; |
+ GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(), FALSE); |
+ extra->colormap = GDK_COLORMAP_XCOLORMAP(colormap); |
+ |
+ if (!force_set_window) |
+ windowless_needs_set_window_ = false; |
+ |
NPError err = instance()->NPP_SetWindow(&window_); |
DCHECK(err == NPERR_NO_ERROR); |
} |