diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-06 20:39:50 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-06 20:39:50 +0000 |
commit | 886a2bf061a5f45c7dbf8d807131e23be17809ac (patch) | |
tree | 7b063ef35c201db659d4ae200f76ffe091fc24bc /webkit/glue/plugins | |
parent | 5af45c4304f4cec5c68d151f7973181e8dcd73c7 (diff) | |
download | chromium_src-886a2bf061a5f45c7dbf8d807131e23be17809ac.zip chromium_src-886a2bf061a5f45c7dbf8d807131e23be17809ac.tar.gz chromium_src-886a2bf061a5f45c7dbf8d807131e23be17809ac.tar.bz2 |
Linux: more windowless plugin work.
- Try not to pass the entire drawing buffer through X and back -- instead,
just the region covered by the windowless plugin.
- Pass through some events (just hits a later NOTIMPLEMENTED()).
Review URL: http://codereview.chromium.org/56160
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13184 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/plugins')
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_gtk.cc | 151 |
1 files changed, 73 insertions, 78 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc b/webkit/glue/plugins/webplugin_delegate_impl_gtk.cc index 8d20186..4922bf4 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( |