Commit eb7aefb1 authored by kbalazs@webkit.org's avatar kbalazs@webkit.org

2011-03-10 Balazs Kelemen <kbalazs@webkit.org>

        Reviewed by Andreas Kling.

        [WK2] Make non-transparent windowless plugins paint on X11
        https://bugs.webkit.org/show_bug.cgi?id=55660

        Implement painting for non-transparent windowless X11 plugins.
        The essence of the logic has been adapted from WebCore.
        The implementation is stubbed for GTK and working only on Qt
        but it should be really easy to finish it for GTK.

        * WebKit2.pro:
        * WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp:
        (WebKit::NPN_GetValue): Handle X11 specific values that are necessary.
        * WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
        (WebKit::NetscapePlugin::NetscapePlugin): Initialize the X11 specific
        members that has been added.
        (WebKit::NetscapePlugin::callSetWindow): Always set the x and y coordinates
        of the NP_Window to 0 on X11 since we are using a backings store as the
        painting area for the plugin.
        * WebProcess/Plugins/Netscape/NetscapePlugin.h:
        * WebProcess/Plugins/Netscape/gtk/NetscapePluginGtk.cpp: Removed in favour
        of a common implementation for X11.
        * WebProcess/Plugins/Netscape/qt/NetscapePluginQt.cpp: Ditto.
        * WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp: Added.
        (WebKit::getPluginDisplay):

        Platform specific static getters.
        (WebKit::x11Display):
        (WebKit::displayDepth):
        (WebKit::rootWindowID):
        (WebKit::x11Screen):

        (WebKit::NetscapePlugin::platformPostInitialize): Set up the visual
        settings and the colormap for the plugin.
        (WebKit::NetscapePlugin::platformDestroy):
        (WebKit::NetscapePlugin::platformInvalidate): Remained stub.
        (WebKit::NetscapePlugin::platformGeometryDidChange): Create a new
        pixmap that fits the geometry.
        (WebKit::NetscapePlugin::platformPaint): Propagate a paint event
        to the plugin, sync with it if necessary and draw the pixmap to
        the screen.
        (WebKit::toNP): Remained stub.
        (WebKit::NetscapePlugin::platformHandleMouseEvent): Remained stub.
        (WebKit::NetscapePlugin::platformHandleWheelEvent): Remained stub.
        (WebKit::NetscapePlugin::platformSetFocus): Remained stub.
        (WebKit::NetscapePlugin::platformHandleMouseEnterEvent): Remained stub.
        (WebKit::NetscapePlugin::platformHandleMouseLeaveEvent): Remained stub.
        (WebKit::NetscapePlugin::platformHandleKeyboardEvent): Remained stub.
        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
        (WebKit::WebFrameLoaderClient::createPlugin): Hack. Inject wmode=opaque
        key-value pair to the plugin parameters to force Flash to act in
        non-transparent windowless mode. Qt also doing this in WebCore.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@80714 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 83de0c7c
2011-03-10 Balazs Kelemen <kbalazs@webkit.org>
Reviewed by Andreas Kling.
[WK2] Make non-transparent windowless plugins paint on X11
https://bugs.webkit.org/show_bug.cgi?id=55660
Implement painting for non-transparent windowless X11 plugins.
The essence of the logic has been adapted from WebCore.
The implementation is stubbed for GTK and working only on Qt
but it should be really easy to finish it for GTK.
* WebKit2.pro:
* WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp:
(WebKit::NPN_GetValue): Handle X11 specific values that are necessary.
* WebProcess/Plugins/Netscape/NetscapePlugin.cpp:
(WebKit::NetscapePlugin::NetscapePlugin): Initialize the X11 specific
members that has been added.
(WebKit::NetscapePlugin::callSetWindow): Always set the x and y coordinates
of the NP_Window to 0 on X11 since we are using a backings store as the
painting area for the plugin.
* WebProcess/Plugins/Netscape/NetscapePlugin.h:
* WebProcess/Plugins/Netscape/gtk/NetscapePluginGtk.cpp: Removed in favour
of a common implementation for X11.
* WebProcess/Plugins/Netscape/qt/NetscapePluginQt.cpp: Ditto.
* WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp: Added.
(WebKit::getPluginDisplay):
Platform specific static getters.
(WebKit::x11Display):
(WebKit::displayDepth):
(WebKit::rootWindowID):
(WebKit::x11Screen):
(WebKit::NetscapePlugin::platformPostInitialize): Set up the visual
settings and the colormap for the plugin.
(WebKit::NetscapePlugin::platformDestroy):
(WebKit::NetscapePlugin::platformInvalidate): Remained stub.
(WebKit::NetscapePlugin::platformGeometryDidChange): Create a new
pixmap that fits the geometry.
(WebKit::NetscapePlugin::platformPaint): Propagate a paint event
to the plugin, sync with it if necessary and draw the pixmap to
the screen.
(WebKit::toNP): Remained stub.
(WebKit::NetscapePlugin::platformHandleMouseEvent): Remained stub.
(WebKit::NetscapePlugin::platformHandleWheelEvent): Remained stub.
(WebKit::NetscapePlugin::platformSetFocus): Remained stub.
(WebKit::NetscapePlugin::platformHandleMouseEnterEvent): Remained stub.
(WebKit::NetscapePlugin::platformHandleMouseLeaveEvent): Remained stub.
(WebKit::NetscapePlugin::platformHandleKeyboardEvent): Remained stub.
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::createPlugin): Hack. Inject wmode=opaque
key-value pair to the plugin parameters to force Flash to act in
non-transparent windowless mode. Qt also doing this in WebCore.
2011-03-09 Peter Kasting <pkasting@google.com>
Reviewed by Mihai Parparita.
......
......@@ -450,7 +450,7 @@ SOURCES += \
WebProcess/Plugins/Netscape/NetscapeBrowserFuncs.cpp \
WebProcess/Plugins/Netscape/NetscapePlugin.cpp \
WebProcess/Plugins/Netscape/NetscapePluginStream.cpp \
WebProcess/Plugins/Netscape/qt/NetscapePluginQt.cpp \
WebProcess/Plugins/Netscape/x11/NetscapePluginX11.cpp \
WebProcess/Plugins/Netscape/qt/PluginProxyQt.cpp \
WebProcess/Plugins/Plugin.cpp \
WebProcess/Plugins/PluginView.cpp \
......
......@@ -35,6 +35,12 @@
#include <WebCore/SharedBuffer.h>
#include <utility>
#if PLATFORM(QT)
#include <QX11Info>
#elif PLATFORM(GTK)
#include <gdk/gdkx.h>
#endif
using namespace WebCore;
using namespace std;
......@@ -484,17 +490,33 @@ static NPError NPN_GetValue(NPP npp, NPNVariable variable, void *value)
*(NPBool*)value = true;
break;
#elif PLUGIN_ARCHITECTURE(X11)
case NPNVxDisplay:
#if PLATFORM(QT)
*reinterpret_cast<Display**>(value) = QX11Info::display();
break;
#elif PLATFORM(GTK)
*reinterpret_cast<Display**>(value) = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
break;
#else
goto default;
#endif
case NPNVSupportsXEmbedBool:
*static_cast<NPBool*>(value) = true;
break;
case NPNVSupportsWindowless:
*static_cast<NPBool*>(value) = true;
break;
case NPNVToolkit: {
const uint32_t expectedGTKToolKitVersion = 2;
RefPtr<NetscapePlugin> plugin = NetscapePlugin::fromNPP(npp);
if (plugin->quirks().contains(PluginQuirks::RequiresGTKToolKit)) {
*reinterpret_cast<uint32_t*>(value) = expectedGTKToolKitVersion;
break;
}
return NPERR_GENERIC_ERROR;
*reinterpret_cast<uint32_t*>(value) = plugin->quirks().contains(PluginQuirks::RequiresGTKToolKit) ?
expectedGTKToolKitVersion : 0;
break;
}
// TODO: implement NPNVnetscapeWindow once we want to support windowed plugins.
#endif
default:
notImplemented();
......
......@@ -75,7 +75,10 @@ NetscapePlugin::NetscapePlugin(PassRefPtr<NetscapePluginModule> pluginModule)
#ifndef NP_NO_CARBON
, m_nullEventTimer(RunLoop::main(), this, &NetscapePlugin::nullEventTimerFired)
, m_npCGContext()
#endif
#endif
#elif PLUGIN_ARCHITECTURE(X11)
, m_drawable(0)
, m_pluginDisplay(0)
#endif
{
m_npp.ndata = this;
......@@ -347,8 +350,14 @@ NPError NetscapePlugin::NPP_SetValue(NPNVariable variable, void *value)
void NetscapePlugin::callSetWindow()
{
#if PLUGIN_ARCHITECTURE(X11)
// We use a backing store as the painting area for the plugin.
m_npWindow.x = 0;
m_npWindow.y = 0;
#else
m_npWindow.x = m_frameRect.x();
m_npWindow.y = m_frameRect.y();
#endif
m_npWindow.width = m_frameRect.width();
m_npWindow.height = m_frameRect.height();
m_npWindow.clipRect.top = m_clipRect.y();
......
......@@ -208,7 +208,7 @@ private:
RefPtr<NetscapePluginStream> m_manualStream;
Vector<bool, 8> m_popupEnabledStates;
#if PLATFORM(MAC)
#if PLUGIN_ARCHITECTURE(MAC)
NPDrawingModel m_drawingModel;
NPEventModel m_eventModel;
RetainPtr<PlatformLayer> m_pluginLayer;
......@@ -229,8 +229,11 @@ private:
RunLoop::Timer<NetscapePlugin> m_nullEventTimer;
NP_CGContext m_npCGContext;
#endif
#elif PLATFORM(WIN)
#elif PLUGIN_ARCHITECTURE(WIN)
HWND m_window;
#elif PLUGIN_ARCHITECTURE(X11)
Pixmap m_drawable;
Display* m_pluginDisplay;
#endif
};
......
/*
* Copyright (C) 2010 Apple Inc. All rights reserved.
* Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "NetscapePlugin.h"
#include <WebCore/NotImplemented.h>
using namespace WebCore;
namespace WebKit {
bool NetscapePlugin::platformPostInitialize()
{
notImplemented();
return true;
}
void NetscapePlugin::platformDestroy()
{
notImplemented();
}
bool NetscapePlugin::platformInvalidate(const IntRect&)
{
notImplemented();
return false;
}
void NetscapePlugin::platformGeometryDidChange()
{
notImplemented();
}
void NetscapePlugin::platformPaint(GraphicsContext* context, const IntRect& dirtyRect, bool)
{
notImplemented();
}
NPEvent toNP(const WebMouseEvent& event)
{
NPEvent npEvent = NPEvent();
notImplemented();
return npEvent;
}
bool NetscapePlugin::platformHandleMouseEvent(const WebMouseEvent& event)
{
notImplemented();
return true;
}
bool NetscapePlugin::platformHandleWheelEvent(const WebWheelEvent&)
{
notImplemented();
return false;
}
void NetscapePlugin::platformSetFocus(bool)
{
notImplemented();
}
bool NetscapePlugin::platformHandleMouseEnterEvent(const WebMouseEvent& event)
{
notImplemented();
return true;
}
bool NetscapePlugin::platformHandleMouseLeaveEvent(const WebMouseEvent& event)
{
notImplemented();
return true;
}
bool NetscapePlugin::platformHandleKeyboardEvent(const WebKeyboardEvent&)
{
notImplemented();
return false;
}
} // namespace WebKit
......@@ -31,19 +31,141 @@
#include <WebCore/GraphicsContext.h>
#include <WebCore/NotImplemented.h>
#if PLATFORM(QT)
#include <QApplication>
#include <QDesktopWidget>
#include <QPixmap>
#include <QX11Info>
#elif PLATFORM(GTK)
#include <gdk/gdkx.h>
#endif
using namespace WebCore;
namespace WebKit {
static Display *getPluginDisplay()
{
#if PLATFORM(QT)
// At the moment, we only support gdk based plugins (like Flash) that use a different X connection.
// The code below has the same effect as this one:
// Display *gdkDisplay = gdk_x11_display_get_xdisplay(gdk_display_get_default());
QLibrary library("libgdk-x11-2.0", 0);
if (!library.load())
return 0;
typedef void *(*gdk_display_get_default_ptr)();
gdk_display_get_default_ptr gdk_display_get_default = (gdk_display_get_default_ptr)library.resolve("gdk_display_get_default");
if (!gdk_display_get_default)
return 0;
typedef void *(*gdk_x11_display_get_xdisplay_ptr)(void *);
gdk_x11_display_get_xdisplay_ptr gdk_x11_display_get_xdisplay = (gdk_x11_display_get_xdisplay_ptr)library.resolve("gdk_x11_display_get_xdisplay");
if (!gdk_x11_display_get_xdisplay)
return 0;
return (Display*)gdk_x11_display_get_xdisplay(gdk_display_get_default());
#elif PLATFORM(GTK)
// Since we're a gdk/gtk app, we'll (probably?) have the same X connection as any gdk-based
// plugins, so we can return that. We might want to add other implementations here later.
return GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
#else
return 0;
#endif
}
static inline Display* x11Display()
{
#if PLATFORM(QT)
return QX11Info::display();
#elif PLATFORM(GTK)
return GDK_DISPLAY_XDISPLAY(gdk_display_get_default())
#else
return 0;
#endif
}
static inline int displayDepth()
{
#if PLATFORM(QT)
return QApplication::desktop()->x11Info().depth();
#elif PLATFORM(GTK)
return gdk_visual_get_depth(gdk_screen_get_system_visual(gdk_screen_get_default()));
#else
return 0;
#endif
}
static inline unsigned long rootWindowID()
{
#if PLATFORM(QT)
return QX11Info::appRootWindow();
#elif PLATFORM(GTK)
return GDK_ROOT_WINDOW();
#else
return 0;
#endif
}
static inline int x11Screen()
{
#if PLATFORM(QT)
return QX11Info::appScreen();
#elif PLATFORM(GTK)
return gdk_screen_get_number(gdk_screen_get_default());
#else
return 0;
#endif
}
bool NetscapePlugin::platformPostInitialize()
{
notImplemented();
if (m_isWindowed)
return false;
if (!(m_pluginDisplay = getPluginDisplay()))
return false;
NPSetWindowCallbackStruct* callbackStruct = new NPSetWindowCallbackStruct;
callbackStruct->type = 0;
Display* display = x11Display();
int depth = displayDepth();
callbackStruct->display = display;
callbackStruct->depth = depth;
XVisualInfo visualTemplate;
visualTemplate.screen = x11Screen();
visualTemplate.depth = depth;
visualTemplate.c_class = TrueColor;
int numMatching;
XVisualInfo* visualInfo = XGetVisualInfo(display, VisualScreenMask | VisualDepthMask | VisualClassMask,
&visualTemplate, &numMatching);
ASSERT(visualInfo);
Visual* visual = visualInfo[0].visual;
ASSERT(visual);
XFree(visualInfo);
callbackStruct->visual = visual;
callbackStruct->colormap = XCreateColormap(display, rootWindowID(), visual, AllocNone);
m_npWindow.type = NPWindowTypeDrawable;
m_npWindow.window = 0;
m_npWindow.ws_info = callbackStruct;
callSetWindow();
return true;
}
void NetscapePlugin::platformDestroy()
{
notImplemented();
delete static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info);
if (m_drawable) {
XFreePixmap(x11Display(), m_drawable);
m_drawable = 0;
}
}
bool NetscapePlugin::platformInvalidate(const IntRect&)
......@@ -54,12 +176,75 @@ bool NetscapePlugin::platformInvalidate(const IntRect&)
void NetscapePlugin::platformGeometryDidChange()
{
notImplemented();
if (m_isWindowed) {
notImplemented();
return;
}
Display* display = x11Display();
if (m_drawable)
XFreePixmap(display, m_drawable);
m_drawable = XCreatePixmap(display, rootWindowID(), m_frameRect.width(), m_frameRect.height(), displayDepth());
XSync(display, false); // Make sure that the server knows about the Drawable.
}
void NetscapePlugin::platformPaint(GraphicsContext* context, const IntRect& dirtyRect, bool)
void NetscapePlugin::platformPaint(GraphicsContext* context, const IntRect& dirtyRect, bool /*isSnapshot*/)
{
if (m_isWindowed) {
notImplemented();
return;
}
if (!m_isStarted) {
// FIXME: we should paint a missing plugin icon.
return;
}
if (context->paintingDisabled())
return;
ASSERT(m_drawable);
#if PLATFORM(QT)
QPainter* painter = context->platformContext();
painter->translate(m_frameRect.x(), m_frameRect.y());
#else
notImplemented();
return;
#endif
XEvent xevent;
memset(&xevent, 0, sizeof(XEvent));
XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose;
exposeEvent.type = GraphicsExpose;
exposeEvent.display = x11Display();
exposeEvent.drawable = m_drawable;
IntRect exposedRect(dirtyRect);
exposedRect.intersect(m_frameRect);
exposedRect.move(-m_frameRect.x(), -m_frameRect.y());
exposeEvent.x = exposedRect.x();
exposeEvent.y = exposedRect.y();
// Note: in transparent mode Flash thinks width is the right and height is the bottom.
// We should take it into account if we want to support transparency.
exposeEvent.width = exposedRect.width();
exposeEvent.height = exposedRect.height();
NPP_HandleEvent(&xevent);
if (m_pluginDisplay != x11Display())
XSync(m_pluginDisplay, false);
#if PLATFORM(QT)
QPixmap qtDrawable = QPixmap::fromX11Pixmap(m_drawable, QPixmap::ExplicitlyShared);
ASSERT(qtDrawable.depth() == static_cast<NPSetWindowCallbackStruct*>(m_npWindow.ws_info)->depth);
painter->drawPixmap(QPoint(exposedRect.x(), exposedRect.y()), qtDrawable, exposedRect);
painter->translate(-m_frameRect.x(), -m_frameRect.y());
#endif
}
NPEvent toNP(const WebMouseEvent& event)
......
......@@ -1217,6 +1217,19 @@ PassRefPtr<Widget> WebFrameLoaderClient::createPlugin(const IntSize&, HTMLPlugIn
parameters.names[i] = paramNames[i].lower();
}
#if PLUGIN_ARCHITECTURE(X11)
if (equalIgnoringCase(mimeType, "application/x-shockwave-flash")) {
// Currently we don't support transparency and windowed mode.
// Inject wmode=opaque to make Flash work in these conditions.
size_t wmodeIndex = parameters.names.find("wmode");
if (wmodeIndex == -1) {
parameters.names.append("wmode");
parameters.values.append("opaque");
} else if (equalIgnoringCase(parameters.values[wmodeIndex], "window"))
parameters.values[wmodeIndex] = "opaque";
}
#endif
RefPtr<Plugin> plugin = webPage->createPlugin(parameters);
if (!plugin)
return 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment