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 8d20186f23feb958b3602b50b41f669d36905228..4922bf48a054e8f0c229d786ba4c09bce1384baa 100644 |
--- a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
+++ b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc |
@@ -171,9 +171,8 @@ void WebPluginDelegateImpl::UpdateGeometry( |
void WebPluginDelegateImpl::Paint(cairo_surface_t* context, |
const gfx::Rect& rect) { |
- if (windowless_) { |
+ if (windowless_) |
WindowlessPaint(context, rect); |
- } |
} |
void WebPluginDelegateImpl::Print(cairo_surface_t* context) { |
@@ -460,6 +459,25 @@ void WebPluginDelegateImpl::EnsurePixmapAtLeastSize(int width, int height) { |
gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap_), colormap); |
} |
+#ifdef DEBUG_RECTANGLES |
+namespace { |
+ |
+// Draw a rectangle on a Cairo surface. |
+// Useful for debugging various rectangles involved in drawing plugins. |
+void DrawDebugRectangle(cairo_surface_t* surface, |
+ const gfx::Rect& rect, |
+ float r, float g, float b) { |
+ cairo_t* cairo = cairo_create(surface); |
+ cairo_set_source_rgba(cairo, r, g, b, 0.5); |
+ cairo_rectangle(cairo, rect.x(), rect.y(), |
+ rect.width(), rect.height()); |
+ cairo_stroke(cairo); |
+ cairo_destroy(cairo); |
+} |
+ |
+} // namespace |
+#endif |
+ |
void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, |
const gfx::Rect& damage_rect) { |
// Compare to: |
@@ -482,12 +500,47 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, |
if (windowless_needs_set_window_) |
WindowlessSetWindow(false); |
- EnsurePixmapAtLeastSize(damage_rect.width(), damage_rect.height()); |
+ // The actual dirty region is just the intersection of the plugin |
+ // window with the damage region. However, the plugin wants to draw |
+ // relative to the containing window's origin, so our pixmap must be |
+ // from the window's origin down to the bottom-right edge of the |
+ // dirty region. |
+ // |
+ // +-----------------------------+-----------------------------+ |
+ // | | | |
+ // | pixmap +-------------+ | |
+ // | | damage | window | |
+ // | | | | |
+ // | +-------+-------------+----------+ | |
+ // | | | draw | | | |
+ // +-------+-------+-------------+ | | |
+ // | | | | |
+ // | | plugin | | |
+ // | +--------------------------------+ | |
+ // | | |
+ // | | |
+ // +-----------------------------------------------------------+ |
+ // |
+ // TOOD(evanm): on Windows, we instead just translate the origin of |
+ // the DC that we hand to the plugin. Does such a thing exist on X? |
+ // TODO(evanm): make use of the clip rect as well. |
+ |
+ gfx::Rect plugin_rect(window_.x, window_.y, window_.width, window_.height); |
+ gfx::Rect draw_rect = plugin_rect.Intersect(damage_rect); |
+ |
+ gfx::Rect pixmap_rect(0, 0, |
+ draw_rect.x() + draw_rect.width(), |
+ draw_rect.y() + draw_rect.height()); |
+ |
+ 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_); |
cairo_set_source_surface(cairo, context, 0, 0); |
+ cairo_rectangle(cairo, draw_rect.x(), draw_rect.y(), |
+ draw_rect.width(), draw_rect.height()); |
+ cairo_clip(cairo); |
cairo_paint(cairo); |
cairo_destroy(cairo); |
@@ -496,10 +549,10 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, |
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(); |
+ event.x = draw_rect.x(); |
+ event.y = draw_rect.y(); |
+ event.width = draw_rect.width(); |
+ event.height = draw_rect.height(); |
// Tell the plugin to paint into the pixmap. |
static StatsRate plugin_paint("Plugin.Paint"); |
@@ -510,8 +563,19 @@ void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, |
// 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_rectangle(cairo, draw_rect.x(), draw_rect.y(), |
+ draw_rect.width(), draw_rect.height()); |
+ cairo_clip(cairo); |
cairo_paint(cairo); |
cairo_destroy(cairo); |
+ |
+#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); |
+#endif |
} |
void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { |
@@ -568,87 +632,18 @@ void WebPluginDelegateImpl::SetFocus() { |
bool WebPluginDelegateImpl::HandleEvent(NPEvent* event, |
WebCursor* cursor) { |
- NOTIMPLEMENTED(); |
-#if 0 |
- DCHECK(windowless_) << "events should only be received in windowless mode"; |
- DCHECK(cursor != NULL); |
- |
- // To ensure that the plugin receives keyboard events we set focus to the |
- // dummy window. |
- // TODO(iyengar) We need a framework in the renderer to identify which |
- // windowless plugin is under the mouse and to handle this. This would |
- // also require some changes in RenderWidgetHost to detect this in the |
- // WM_MOUSEACTIVATE handler and inform the renderer accordingly. |
- HWND prev_focus_window = NULL; |
- if (event->event == WM_RBUTTONDOWN) { |
- prev_focus_window = ::SetFocus(dummy_window_for_activation_); |
- } |
- |
- if (ShouldTrackEventForModalLoops(event)) { |
- // A windowless plugin can enter a modal loop in a NPP_HandleEvent call. |
- // For e.g. Flash puts up a context menu when we right click on the |
- // windowless plugin area. We detect this by setting up a message filter |
- // hook pror to calling NPP_HandleEvent on the plugin and unhook on |
- // return from NPP_HandleEvent. If the plugin does enter a modal loop |
- // in that context we unhook on receiving the first notification in |
- // the message filter hook. |
- handle_event_message_filter_hook_ = |
- SetWindowsHookEx(WH_MSGFILTER, HandleEventMessageFilterHook, NULL, |
- GetCurrentThreadId()); |
- } |
- |
- bool old_task_reentrancy_state = |
- MessageLoop::current()->NestableTasksAllowed(); |
- |
- current_plugin_instance_ = this; |
- |
- handle_event_depth_++; |
- |
- bool pop_user_gesture = false; |
- |
- if (IsUserGestureMessage(event->event)) { |
- pop_user_gesture = true; |
- instance()->PushPopupsEnabledState(true); |
- } |
- |
bool ret = instance()->NPP_HandleEvent(event) != 0; |
+#if 0 |
if (event->event == WM_MOUSEMOVE) { |
// Snag a reference to the current cursor ASAP in case the plugin modified |
// it. There is a nasty race condition here with the multiprocess browser |
// as someone might be setting the cursor in the main process as well. |
*cursor = current_windowless_cursor_; |
} |
- |
- if (pop_user_gesture) { |
- instance()->PopPopupsEnabledState(); |
- } |
- |
- handle_event_depth_--; |
- |
- current_plugin_instance_ = NULL; |
- |
- MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); |
- |
- if (handle_event_message_filter_hook_) { |
- UnhookWindowsHookEx(handle_event_message_filter_hook_); |
- handle_event_message_filter_hook_ = NULL; |
- } |
- |
- // We could have multiple NPP_HandleEvent calls nested together in case |
- // the plugin enters a modal loop. Reset the pump messages event when |
- // the outermost NPP_HandleEvent call unwinds. |
- if (handle_event_depth_ == 0) { |
- ResetEvent(handle_event_pump_messages_event_); |
- } |
- |
- if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { |
- ::SetFocus(prev_focus_window); |
- } |
+#endif |
return ret; |
-#endif |
- return 0; |
} |
WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( |