diff options
| author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
|---|---|---|
| committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
| commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
| tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/plugins/qt | |
| parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
| download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 | |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/plugins/qt')
| -rw-r--r-- | Source/WebCore/plugins/qt/PluginContainerQt.cpp | 150 | ||||
| -rw-r--r-- | Source/WebCore/plugins/qt/PluginContainerQt.h | 63 | ||||
| -rw-r--r-- | Source/WebCore/plugins/qt/PluginPackageQt.cpp | 199 | ||||
| -rw-r--r-- | Source/WebCore/plugins/qt/PluginViewQt.cpp | 1011 |
4 files changed, 1423 insertions, 0 deletions
diff --git a/Source/WebCore/plugins/qt/PluginContainerQt.cpp b/Source/WebCore/plugins/qt/PluginContainerQt.cpp new file mode 100644 index 0000000..8486180 --- /dev/null +++ b/Source/WebCore/plugins/qt/PluginContainerQt.cpp @@ -0,0 +1,150 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "PluginContainerQt.h" + +#include "FocusController.h" +#include "Frame.h" +#include "FrameView.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformWheelEvent.h" +#include "PluginView.h" +#include <QApplication> +#include <QX11Info> + +using namespace WebCore; + +PluginClientWrapper::PluginClientWrapper(QWidget* parent, WId client) + : QWidget(0, Qt::Popup) +{ + // create a QWidget that adopts the plugin window id, do not give it + // a parent so that we don't end up handling events supposed to be + // handled by the QX11EmbedContainer. + + // without the parent this will be considered a toplevel widget, + // and thus make Qt not quit the event loop after the last window + // has been closed. In order to work around this, we set the window + // type to Qt::Popup. + + create(client, false, true); + m_parent = parent; +} + +PluginClientWrapper::~PluginClientWrapper() +{ + destroy(false, false); +} + +bool PluginClientWrapper::x11Event(XEvent* event) +{ + // modify the event window id and insert it into the Qt event system. + event->xany.window = m_parent->effectiveWinId(); + static_cast<QApplication*>(QApplication::instance())->x11ProcessEvent(event); + return true; +} + +PluginContainerQt::PluginContainerQt(PluginView* view, QWidget* parent) + : QX11EmbedContainer(parent) + , m_pluginView(view) + , m_clientWrapper(0) +{ + connect(this, SIGNAL(clientClosed()), this, SLOT(on_clientClosed())); + connect(this, SIGNAL(clientIsEmbedded()), this, SLOT(on_clientIsEmbedded())); +} + +PluginContainerQt::~PluginContainerQt() +{ + delete m_clientWrapper; + m_pluginView->setPlatformPluginWidget(0); +} + +void PluginContainerQt::on_clientClosed() +{ + delete m_clientWrapper; + m_clientWrapper = 0; +} + +void PluginContainerQt::on_clientIsEmbedded() +{ + delete m_clientWrapper; + m_clientWrapper = 0; + + // Only create a QWidget wrapper for the plugin in the case it isn't in the + // Qt window mapper, and thus receiving events from the Qt event system. + // This way the PluginClientWrapper receives the scroll events and passes + // them to the parent. NOTICE: Native Qt based plugins running in process, + // will already be in the window mapper, and thus creating a wrapper, stops + // them from getting events from Qt, as they are redirected to the wrapper. + if (!QWidget::find(clientWinId())) + m_clientWrapper = new PluginClientWrapper(this, clientWinId()); +} + +void PluginContainerQt::redirectWheelEventsToParent(bool enable) +{ + // steal wheel events from the plugin as we want to handle it. When doing this + // all button 4, 5, 6, and 7, ButtonPress and ButtonRelease events are passed + // to the x11Event handler of the PluginClientWrapper, which then changes the + // window id of the event to the parent of PluginContainer and puts the event + // back into the Qt event loop, so that we will actually scroll the parent + // frame. + for (int buttonNo = 4; buttonNo < 8; buttonNo++) { + if (enable) + XGrabButton(x11Info().display(), buttonNo, AnyModifier, clientWinId(), + false, ButtonPressMask, GrabModeAsync, GrabModeAsync, 0L, 0L); + else + XUngrabButton(x11Info().display(), buttonNo, AnyModifier, clientWinId()); + } +} + +bool PluginContainerQt::x11Event(XEvent* event) +{ + switch (event->type) { + case EnterNotify: + // if the plugin window doesn't have focus we do not want to send wheel + // events to it, but to the parent frame, so let's redirect here. + redirectWheelEventsToParent(!hasFocus()); + break; + case LeaveNotify: + // it is always safe to ungrab wheel events when the mouse leaves the + // plugin window. + redirectWheelEventsToParent(false); + break; + } + + return QX11EmbedContainer::x11Event(event); +} + +void PluginContainerQt::focusInEvent(QFocusEvent* event) +{ + // we got focus, stop redirecting the wheel events + redirectWheelEventsToParent(false); + + if (Page* page = m_pluginView->parentFrame()->page()) + page->focusController()->setActive(true); + + m_pluginView->focusPluginElement(); +} + +void PluginContainerQt::focusOutEvent(QFocusEvent*) +{ + if (Page* page = m_pluginView->parentFrame()->page()) + page->focusController()->setActive(false); +} diff --git a/Source/WebCore/plugins/qt/PluginContainerQt.h b/Source/WebCore/plugins/qt/PluginContainerQt.h new file mode 100644 index 0000000..3a2896d --- /dev/null +++ b/Source/WebCore/plugins/qt/PluginContainerQt.h @@ -0,0 +1,63 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef PluginContainerQt_h +#define PluginContainerQt_h + +#include <QX11EmbedContainer> + +namespace WebCore { + + class PluginView; + + class PluginContainerQt : public QX11EmbedContainer + { + Q_OBJECT + public: + PluginContainerQt(PluginView*, QWidget* parent); + ~PluginContainerQt(); + + void redirectWheelEventsToParent(bool enable = true); + + protected: + virtual bool x11Event(XEvent*); + virtual void focusInEvent(QFocusEvent*); + virtual void focusOutEvent(QFocusEvent*); + + public slots: + void on_clientClosed(); + void on_clientIsEmbedded(); + + private: + PluginView* m_pluginView; + QWidget* m_clientWrapper; + }; + + class PluginClientWrapper : public QWidget + { + public: + PluginClientWrapper(QWidget* parent, WId client); + ~PluginClientWrapper(); + bool x11Event(XEvent*); + + private: + QWidget* m_parent; + }; +} + +#endif // PluginContainerQt_h diff --git a/Source/WebCore/plugins/qt/PluginPackageQt.cpp b/Source/WebCore/plugins/qt/PluginPackageQt.cpp new file mode 100644 index 0000000..ce07faf --- /dev/null +++ b/Source/WebCore/plugins/qt/PluginPackageQt.cpp @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Collabora Ltd. 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "PluginPackage.h" + +#include "MIMETypeRegistry.h" +#include "npruntime_impl.h" +#include "PluginDatabase.h" +#include "PluginDebug.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +bool PluginPackage::fetchInfo() +{ + if (!load()) + return false; + + NPP_GetValueProcPtr gv = (NPP_GetValueProcPtr)m_module->resolve("NP_GetValue"); + typedef char *(*NPP_GetMIMEDescriptionProcPtr)(); + NPP_GetMIMEDescriptionProcPtr gm = + (NPP_GetMIMEDescriptionProcPtr)m_module->resolve("NP_GetMIMEDescription"); + if (!gm || !gv) + return false; + + char *buf = 0; + NPError err = gv(0, NPPVpluginNameString, (void*) &buf); + if (err != NPERR_NO_ERROR) + return false; + + m_name = buf; + err = gv(0, NPPVpluginDescriptionString, (void*) &buf); + if (err != NPERR_NO_ERROR) + return false; + + m_description = buf; + determineModuleVersionFromDescription(); + + String mimeDescription = gm(); + setMIMEDescription(mimeDescription); + m_infoIsFromCache = false; + + return true; +} + +void PluginPackage::setMIMEDescription(const String& mimeDescription) +{ + m_fullMIMEDescription = mimeDescription.lower(); + + Vector<String> types; + mimeDescription.lower().split(UChar(';'), false, types); + for (unsigned i = 0; i < types.size(); ++i) { + Vector<String> mime; + types[i].split(UChar(':'), true, mime); + if (mime.size() > 0) { + Vector<String> exts; + if (mime.size() > 1) + mime[1].split(UChar(','), false, exts); + determineQuirks(mime[0]); + m_mimeToExtensions.add(mime[0], exts); + if (mime.size() > 2) + m_mimeToDescriptions.add(mime[0], mime[2]); + } + } +} + +static NPError staticPluginQuirkRequiresGtkToolKit_NPN_GetValue(NPP instance, NPNVariable variable, void* value) +{ + if (variable == NPNVToolkit) { + *static_cast<uint32_t*>(value) = 2; + return NPERR_NO_ERROR; + } + + return NPN_GetValue(instance, variable, value); +} + +static void initializeGtk(QLibrary* module = 0) +{ + // Ensures missing Gtk initialization in some versions of Adobe's flash player + // plugin do not cause crashes. See BR# 40567, 44324, and 44405 for details. + if (module) { + typedef void *(*gtk_init_ptr)(int*, char***); + gtk_init_ptr gtkInit = (gtk_init_ptr)module->resolve("gtk_init"); + if (gtkInit) { + // Prevent gtk_init() from replacing the X error handlers, since the Gtk + // handlers abort when they receive an X error, thus killing the viewer. +#ifdef Q_WS_X11 + int (*old_error_handler)(Display*, XErrorEvent*) = XSetErrorHandler(0); + int (*old_io_error_handler)(Display*) = XSetIOErrorHandler(0); +#endif + gtkInit(0, 0); +#ifdef Q_WS_X11 + XSetErrorHandler(old_error_handler); + XSetIOErrorHandler(old_io_error_handler); +#endif + return; + } + } + + QLibrary library("libgtk-x11-2.0.so.0"); + if (library.load()) { + typedef void *(*gtk_init_check_ptr)(int*, char***); + gtk_init_check_ptr gtkInitCheck = (gtk_init_check_ptr)library.resolve("gtk_init_check"); + // NOTE: We're using gtk_init_check() since gtk_init() calls exit() on failure. + if (gtkInitCheck) + (void) gtkInitCheck(0, 0); + } +} + +bool PluginPackage::load() +{ + if (m_isLoaded) { + m_loadCount++; + return true; + } + + m_module = new QLibrary((QString)m_path); + m_module->setLoadHints(QLibrary::ResolveAllSymbolsHint); + if (!m_module->load()) { + LOG(Plugins, "%s not loaded (%s)", m_path.utf8().data(), + m_module->errorString().toLatin1().constData()); + return false; + } + + m_isLoaded = true; + + NP_InitializeFuncPtr NP_Initialize; + NPError npErr; + + NP_Initialize = (NP_InitializeFuncPtr)m_module->resolve("NP_Initialize"); + m_NPP_Shutdown = (NPP_ShutdownProcPtr)m_module->resolve("NP_Shutdown"); + + if (!NP_Initialize || !m_NPP_Shutdown) + goto abort; + + memset(&m_pluginFuncs, 0, sizeof(m_pluginFuncs)); + m_pluginFuncs.size = sizeof(m_pluginFuncs); + + initializeBrowserFuncs(); + + if (m_path.contains("npwrapper.")) { + // nspluginwrapper relies on the toolkit value to know if glib is available + // It does so in NP_Initialize with a null instance, therefore it is done this way: + m_browserFuncs.getvalue = staticPluginQuirkRequiresGtkToolKit_NPN_GetValue; + // Workaround Adobe's failure to properly initialize Gtk in some versions + // of their flash player plugin. + initializeGtk(); + } else if (m_path.contains("flashplayer")) { + // Workaround Adobe's failure to properly initialize Gtk in some versions + // of their flash player plugin. + initializeGtk(m_module); + } + +#if defined(XP_UNIX) + npErr = NP_Initialize(&m_browserFuncs, &m_pluginFuncs); +#else + npErr = NP_Initialize(&m_browserFuncs); +#endif + if (npErr != NPERR_NO_ERROR) + goto abort; + + m_loadCount++; + return true; + +abort: + unloadWithoutShutdown(); + return false; +} + +uint16_t PluginPackage::NPVersion() const +{ + return NP_VERSION_MINOR; +} + +} diff --git a/Source/WebCore/plugins/qt/PluginViewQt.cpp b/Source/WebCore/plugins/qt/PluginViewQt.cpp new file mode 100644 index 0000000..fdbe552 --- /dev/null +++ b/Source/WebCore/plugins/qt/PluginViewQt.cpp @@ -0,0 +1,1011 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * Copyright (C) 2008 Collabora Ltd. All rights reserved. + * Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in> + * + * 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 COMPUTER, INC. ``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 COMPUTER, INC. OR + * 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 "PluginView.h" + +#if USE(JSC) +#include "Bridge.h" +#endif +#include "Chrome.h" +#include "ChromeClient.h" +#include "Document.h" +#include "DocumentLoader.h" +#include "Element.h" +#include "FloatPoint.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoadRequest.h" +#include "FrameLoader.h" +#include "FrameTree.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HTMLNames.h" +#include "HTMLPlugInElement.h" +#include "HostWindow.h" +#include "Image.h" +#if USE(JSC) +#include "JSDOMBinding.h" +#endif +#include "KeyboardEvent.h" +#include "MouseEvent.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PlatformMouseEvent.h" +#include "PlatformKeyboardEvent.h" +#include "PluginContainerQt.h" +#include "PluginDebug.h" +#include "PluginPackage.h" +#include "PluginMainThreadScheduler.h" +#include "QWebPageClient.h" +#include "RenderLayer.h" +#include "ScriptController.h" +#include "Settings.h" +#include "npruntime_impl.h" +#include "qwebpage_p.h" +#include "runtime_root.h" + +#include <QApplication> +#include <QDesktopWidget> +#include <QGraphicsWidget> +#include <QKeyEvent> +#include <QPainter> +#include <QStyleOptionGraphicsItem> +#include <QWidget> +#include <QX11Info> +#include <X11/X.h> +#ifndef QT_NO_XRENDER +#define Bool int +#define Status int +#include <X11/extensions/Xrender.h> +#endif +#include <runtime/JSLock.h> +#include <runtime/JSValue.h> + +using JSC::ExecState; +using JSC::Interpreter; +using JSC::JSLock; +using JSC::JSObject; +using JSC::UString; + +using std::min; + +using namespace WTF; + +namespace WebCore { + +using namespace HTMLNames; + +#if USE(ACCELERATED_COMPOSITING) +// Qt's GraphicsLayer (GraphicsLayerQt) requires layers to be QGraphicsWidgets +class PluginGraphicsLayerQt : public QGraphicsWidget { +public: + PluginGraphicsLayerQt(PluginView* view) : m_view(view) { } + ~PluginGraphicsLayerQt() { } + + void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0) + { + Q_UNUSED(widget); + m_view->paintUsingXPixmap(painter, option->exposedRect.toRect()); + } + +private: + PluginView* m_view; +}; +#endif + +void PluginView::updatePluginWidget() +{ + if (!parent()) + return; + + ASSERT(parent()->isFrameView()); + FrameView* frameView = static_cast<FrameView*>(parent()); + + IntRect oldWindowRect = m_windowRect; + IntRect oldClipRect = m_clipRect; + + m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size()); + m_clipRect = windowClipRect(); + m_clipRect.move(-m_windowRect.x(), -m_windowRect.y()); + + if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect) + return; + + if (!m_isWindowed && m_windowRect.size() != oldWindowRect.size()) { +#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5) + // On Maemo5, Flash always renders to 16-bit buffer + if (m_renderToImage) + m_image = QImage(m_windowRect.width(), m_windowRect.height(), QImage::Format_RGB16); + else +#endif + { + if (m_drawable) + XFreePixmap(QX11Info::display(), m_drawable); + + m_drawable = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), m_windowRect.width(), m_windowRect.height(), + ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth); + QApplication::syncX(); // make sure that the server knows about the Drawable + } + } + + // do not call setNPWindowIfNeeded immediately, will be called on paint() + m_hasPendingGeometryChange = true; + + // (i) in order to move/resize the plugin window at the same time as the + // rest of frame during e.g. scrolling, we set the window geometry + // in the paint() function, but as paint() isn't called when the + // plugin window is outside the frame which can be caused by a + // scroll, we need to move/resize immediately. + // (ii) if we are running layout tests from DRT, paint() won't ever get called + // so we need to call setNPWindowIfNeeded() if window geometry has changed + if (!m_windowRect.intersects(frameView->frameRect()) + || (QWebPagePrivate::drtRun && platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect))) + setNPWindowIfNeeded(); + + if (!m_platformLayer) { + // Make sure we get repainted afterwards. This is necessary for downward + // scrolling to move the plugin widget properly. + invalidate(); + } +} + +void PluginView::setFocus(bool focused) +{ + if (platformPluginWidget()) { + if (focused) + platformPluginWidget()->setFocus(Qt::OtherFocusReason); + } else { + Widget::setFocus(focused); + } +} + +void PluginView::show() +{ + Q_ASSERT(platformPluginWidget() == platformWidget()); + Widget::show(); +} + +void PluginView::hide() +{ + Q_ASSERT(platformPluginWidget() == platformWidget()); + Widget::hide(); +} + +#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5) +void PluginView::paintUsingImageSurfaceExtension(QPainter* painter, const IntRect& exposedRect) +{ + NPImageExpose imageExpose; + QPoint offset; + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + const bool surfaceHasUntransformedContents = client && qobject_cast<QWidget*>(client->pluginParent()); + + QPaintDevice* surface = QPainter::redirected(painter->device(), &offset); + + // If the surface is a QImage, we can render directly into it + if (surfaceHasUntransformedContents && surface && surface->devType() == QInternal::Image) { + QImage* image = static_cast<QImage*>(surface); + offset = -offset; // negating the offset gives us the offset of the view within the surface + imageExpose.data = reinterpret_cast<char*>(image->bits()); + imageExpose.dataSize.width = image->width(); + imageExpose.dataSize.height = image->height(); + imageExpose.stride = image->bytesPerLine(); + imageExpose.depth = image->depth(); // this is guaranteed to be 16 on Maemo5 + imageExpose.translateX = offset.x() + m_windowRect.x(); + imageExpose.translateY = offset.y() + m_windowRect.y(); + imageExpose.scaleX = 1; + imageExpose.scaleY = 1; + } else { + if (m_isTransparent) { + // On Maemo5, Flash expects the buffer to contain the contents that are below it. + // We don't support transparency for non-raster graphicssystem, so clean the image + // before giving to Flash. + QPainter imagePainter(&m_image); + imagePainter.fillRect(exposedRect, Qt::white); + } + + imageExpose.data = reinterpret_cast<char*>(m_image.bits()); + imageExpose.dataSize.width = m_image.width(); + imageExpose.dataSize.height = m_image.height(); + imageExpose.stride = m_image.bytesPerLine(); + imageExpose.depth = m_image.depth(); + imageExpose.translateX = 0; + imageExpose.translateY = 0; + imageExpose.scaleX = 1; + imageExpose.scaleY = 1; + } + imageExpose.x = exposedRect.x(); + imageExpose.y = exposedRect.y(); + imageExpose.width = exposedRect.width(); + imageExpose.height = exposedRect.height(); + + XEvent xevent; + memset(&xevent, 0, sizeof(XEvent)); + XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose; + exposeEvent.type = GraphicsExpose; + exposeEvent.display = 0; + exposeEvent.drawable = reinterpret_cast<XID>(&imageExpose); + exposeEvent.x = exposedRect.x(); + exposeEvent.y = exposedRect.y(); + exposeEvent.width = exposedRect.width(); + exposeEvent.height = exposedRect.height(); + + dispatchNPEvent(xevent); + + if (!surfaceHasUntransformedContents || !surface || surface->devType() != QInternal::Image) + painter->drawImage(QPoint(frameRect().x() + exposedRect.x(), frameRect().y() + exposedRect.y()), m_image, exposedRect); +} +#endif + +void PluginView::paintUsingXPixmap(QPainter* painter, const QRect &exposedRect) +{ + QPixmap qtDrawable = QPixmap::fromX11Pixmap(m_drawable, QPixmap::ExplicitlyShared); + const int drawableDepth = ((NPSetWindowCallbackStruct*)m_npWindow.ws_info)->depth; + ASSERT(drawableDepth == qtDrawable.depth()); + const bool syncX = m_pluginDisplay && m_pluginDisplay != QX11Info::display(); + + // When printing, Qt uses a QPicture to capture the output in preview mode. The + // QPicture holds a reference to the X Pixmap. As a result, the print preview would + // update itself when the X Pixmap changes. To prevent this, we create a copy. + if (m_element->document()->printing()) + qtDrawable = qtDrawable.copy(); + + if (m_isTransparent && drawableDepth != 32) { + // Attempt content propagation for drawable with no alpha by copying over from the backing store + QPoint offset; + QPaintDevice* backingStoreDevice = QPainter::redirected(painter->device(), &offset); + offset = -offset; // negating the offset gives us the offset of the view within the backing store pixmap + + const bool hasValidBackingStore = backingStoreDevice && backingStoreDevice->devType() == QInternal::Pixmap; + QPixmap* backingStorePixmap = static_cast<QPixmap*>(backingStoreDevice); + + // We cannot grab contents from the backing store when painting on QGraphicsView items + // (because backing store contents are already transformed). What we really mean to do + // here is to check if we are painting on QWebView, but let's be a little permissive :) + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + const bool backingStoreHasUntransformedContents = client && qobject_cast<QWidget*>(client->pluginParent()); + + if (hasValidBackingStore && backingStorePixmap->depth() == drawableDepth + && backingStoreHasUntransformedContents) { + GC gc = XDefaultGC(QX11Info::display(), QX11Info::appScreen()); + XCopyArea(QX11Info::display(), backingStorePixmap->handle(), m_drawable, gc, + offset.x() + m_windowRect.x() + exposedRect.x(), offset.y() + m_windowRect.y() + exposedRect.y(), + exposedRect.width(), exposedRect.height(), exposedRect.x(), exposedRect.y()); + } else { // no backing store, clean the pixmap because the plugin thinks its transparent + QPainter painter(&qtDrawable); + painter.fillRect(exposedRect, Qt::white); + } + + if (syncX) + QApplication::syncX(); + } + + XEvent xevent; + memset(&xevent, 0, sizeof(XEvent)); + XGraphicsExposeEvent& exposeEvent = xevent.xgraphicsexpose; + exposeEvent.type = GraphicsExpose; + exposeEvent.display = QX11Info::display(); + exposeEvent.drawable = qtDrawable.handle(); + exposeEvent.x = exposedRect.x(); + exposeEvent.y = exposedRect.y(); + exposeEvent.width = exposedRect.x() + exposedRect.width(); // flash bug? it thinks width is the right in transparent mode + exposeEvent.height = exposedRect.y() + exposedRect.height(); // flash bug? it thinks height is the bottom in transparent mode + + dispatchNPEvent(xevent); + + if (syncX) + XSync(m_pluginDisplay, false); // sync changes by plugin + + painter->drawPixmap(QPoint(exposedRect.x(), exposedRect.y()), qtDrawable, exposedRect); +} + +void PluginView::paint(GraphicsContext* context, const IntRect& rect) +{ + if (!m_isStarted) { + paintMissingPluginIcon(context, rect); + return; + } + + if (context->paintingDisabled()) + return; + + setNPWindowIfNeeded(); + + if (m_isWindowed) + return; + +#if USE(ACCELERATED_COMPOSITING) + if (m_platformLayer) + return; +#endif + + if (!m_drawable +#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5) + && m_image.isNull() +#endif + ) + return; + + QPainter* painter = context->platformContext(); + IntRect exposedRect(rect); + exposedRect.intersect(frameRect()); + exposedRect.move(-frameRect().x(), -frameRect().y()); + +#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5) + if (!m_image.isNull()) { + paintUsingImageSurfaceExtension(painter, exposedRect); + return; + } +#endif + + painter->translate(frameRect().x(), frameRect().y()); + paintUsingXPixmap(painter, exposedRect); + painter->translate(-frameRect().x(), -frameRect().y()); +} + +// TODO: Unify across ports. +bool PluginView::dispatchNPEvent(NPEvent& event) +{ + if (!m_plugin->pluginFuncs()->event) + return false; + + PluginView::setCurrentPluginView(this); +#if USE(JSC) + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); +#endif + setCallingPlugin(true); + bool accepted = m_plugin->pluginFuncs()->event(m_instance, &event); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + + return accepted; +} + +void setSharedXEventFields(XEvent* xEvent, QWidget* ownerWidget) +{ + xEvent->xany.serial = 0; // we are unaware of the last request processed by X Server + xEvent->xany.send_event = false; + xEvent->xany.display = QX11Info::display(); + // NOTE: event->xany.window doesn't always respond to the .window property of other XEvent's + // but does in the case of KeyPress, KeyRelease, ButtonPress, ButtonRelease, and MotionNotify + // events; thus, this is right: + xEvent->xany.window = ownerWidget ? ownerWidget->window()->handle() : 0; +} + +void PluginView::initXEvent(XEvent* xEvent) +{ + memset(xEvent, 0, sizeof(XEvent)); + + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + QWidget* ownerWidget = client ? client->ownerWidget() : 0; + setSharedXEventFields(xEvent, ownerWidget); +} + +void setXKeyEventSpecificFields(XEvent* xEvent, KeyboardEvent* event) +{ + const PlatformKeyboardEvent* keyEvent = event->keyEvent(); + + xEvent->type = (event->type() == eventNames().keydownEvent) ? 2 : 3; // ints as Qt unsets KeyPress and KeyRelease + xEvent->xkey.root = QX11Info::appRootWindow(); + xEvent->xkey.subwindow = 0; // we have no child window + xEvent->xkey.time = event->timeStamp(); + xEvent->xkey.state = keyEvent->nativeModifiers(); + xEvent->xkey.keycode = keyEvent->nativeScanCode(); + + // We may not have a nativeScanCode() if the key event is from DRT's eventsender. In that + // case just populate the XEvent's keycode with the Qt platform-independent keycode. The only + // place this keycode will be used is in webkit_test_plugin_handle_event(). + if (QWebPagePrivate::drtRun && !xEvent->xkey.keycode) { + QKeyEvent* qKeyEvent = keyEvent->qtEvent(); + ASSERT(qKeyEvent); + if (!qKeyEvent->text().isEmpty()) + xEvent->xkey.keycode = int(qKeyEvent->text().at(0).unicode() + qKeyEvent->modifiers()); + else if (qKeyEvent->key() && (qKeyEvent->key() != Qt::Key_unknown)) + xEvent->xkey.keycode = int(qKeyEvent->key() + qKeyEvent->modifiers()); + } + + xEvent->xkey.same_screen = true; + + // NOTE: As the XEvents sent to the plug-in are synthesized and there is not a native window + // corresponding to the plug-in rectangle, some of the members of the XEvent structures are not + // set to their normal Xserver values. e.g. Key events don't have a position. + // source: https://developer.mozilla.org/en/NPEvent + xEvent->xkey.x = 0; + xEvent->xkey.y = 0; + xEvent->xkey.x_root = 0; + xEvent->xkey.y_root = 0; +} + +void PluginView::handleKeyboardEvent(KeyboardEvent* event) +{ + if (m_isWindowed) + return; + + if (event->type() != eventNames().keydownEvent && event->type() != eventNames().keyupEvent) + return; + + XEvent npEvent; + initXEvent(&npEvent); + setXKeyEventSpecificFields(&npEvent, event); + + if (!dispatchNPEvent(npEvent)) + event->setDefaultHandled(); +} + +static unsigned int inputEventState(MouseEvent* event) +{ + unsigned int state = 0; + if (event->ctrlKey()) + state |= ControlMask; + if (event->shiftKey()) + state |= ShiftMask; + if (event->altKey()) + state |= Mod1Mask; + if (event->metaKey()) + state |= Mod4Mask; + return state; +} + +static void setXButtonEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos) +{ + XButtonEvent& xbutton = xEvent->xbutton; + xbutton.type = event->type() == eventNames().mousedownEvent ? ButtonPress : ButtonRelease; + xbutton.root = QX11Info::appRootWindow(); + xbutton.subwindow = 0; + xbutton.time = event->timeStamp(); + xbutton.x = postZoomPos.x(); + xbutton.y = postZoomPos.y(); + xbutton.x_root = event->screenX(); + xbutton.y_root = event->screenY(); + xbutton.state = inputEventState(event); + switch (event->button()) { + case MiddleButton: + xbutton.button = Button2; + break; + case RightButton: + xbutton.button = Button3; + break; + case LeftButton: + default: + xbutton.button = Button1; + break; + } + xbutton.same_screen = true; +} + +static void setXMotionEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos) +{ + XMotionEvent& xmotion = xEvent->xmotion; + xmotion.type = MotionNotify; + xmotion.root = QX11Info::appRootWindow(); + xmotion.subwindow = 0; + xmotion.time = event->timeStamp(); + xmotion.x = postZoomPos.x(); + xmotion.y = postZoomPos.y(); + xmotion.x_root = event->screenX(); + xmotion.y_root = event->screenY(); + xmotion.state = inputEventState(event); + xmotion.is_hint = NotifyNormal; + xmotion.same_screen = true; +} + +static void setXCrossingEventSpecificFields(XEvent* xEvent, MouseEvent* event, const IntPoint& postZoomPos) +{ + XCrossingEvent& xcrossing = xEvent->xcrossing; + xcrossing.type = event->type() == eventNames().mouseoverEvent ? EnterNotify : LeaveNotify; + xcrossing.root = QX11Info::appRootWindow(); + xcrossing.subwindow = 0; + xcrossing.time = event->timeStamp(); + xcrossing.x = postZoomPos.y(); + xcrossing.y = postZoomPos.x(); + xcrossing.x_root = event->screenX(); + xcrossing.y_root = event->screenY(); + xcrossing.state = inputEventState(event); + xcrossing.mode = NotifyNormal; + xcrossing.detail = NotifyDetailNone; + xcrossing.same_screen = true; + xcrossing.focus = false; +} + +void PluginView::handleMouseEvent(MouseEvent* event) +{ + if (m_isWindowed) + return; + + if (event->button() == RightButton && m_plugin->quirks().contains(PluginQuirkIgnoreRightClickInWindowlessMode)) + return; + + if (event->type() == eventNames().mousedownEvent) { + // Give focus to the plugin on click + if (Page* page = m_parentFrame->page()) + page->focusController()->setActive(true); + + focusPluginElement(); + } + + XEvent npEvent; + initXEvent(&npEvent); + + IntPoint postZoomPos = roundedIntPoint(m_element->renderer()->absoluteToLocal(event->absoluteLocation())); + + if (event->type() == eventNames().mousedownEvent || event->type() == eventNames().mouseupEvent) + setXButtonEventSpecificFields(&npEvent, event, postZoomPos); + else if (event->type() == eventNames().mousemoveEvent) + setXMotionEventSpecificFields(&npEvent, event, postZoomPos); + else if (event->type() == eventNames().mouseoutEvent || event->type() == eventNames().mouseoverEvent) + setXCrossingEventSpecificFields(&npEvent, event, postZoomPos); + else + return; + + if (!dispatchNPEvent(npEvent)) + event->setDefaultHandled(); +} + +void PluginView::handleFocusInEvent() +{ + XEvent npEvent; + initXEvent(&npEvent); + + XFocusChangeEvent& event = npEvent.xfocus; + event.type = 9; /* int as Qt unsets FocusIn */ + event.mode = NotifyNormal; + event.detail = NotifyDetailNone; + + dispatchNPEvent(npEvent); +} + +void PluginView::handleFocusOutEvent() +{ + XEvent npEvent; + initXEvent(&npEvent); + + XFocusChangeEvent& event = npEvent.xfocus; + event.type = 10; /* int as Qt unsets FocusOut */ + event.mode = NotifyNormal; + event.detail = NotifyDetailNone; + + dispatchNPEvent(npEvent); +} + +void PluginView::setParent(ScrollView* parent) +{ + Widget::setParent(parent); + + if (parent) + init(); +} + +void PluginView::setNPWindowRect(const IntRect&) +{ + if (!m_isWindowed) + setNPWindowIfNeeded(); +} + +void PluginView::setNPWindowIfNeeded() +{ + if (!m_isStarted || !parent() || !m_plugin->pluginFuncs()->setwindow) + return; + + // If the plugin didn't load sucessfully, no point in calling setwindow + if (m_status != PluginStatusLoadedSuccessfully) + return; + + // On Unix, only call plugin if it's full-page or windowed + if (m_mode != NP_FULL && m_mode != NP_EMBED) + return; + + // Check if the platformPluginWidget still exists + if (m_isWindowed && !platformPluginWidget()) + return; + + if (!m_hasPendingGeometryChange) + return; + m_hasPendingGeometryChange = false; + + if (m_isWindowed) { + platformPluginWidget()->setGeometry(m_windowRect); + // if setMask is set with an empty QRegion, no clipping will + // be performed, so in that case we hide the plugin view + platformPluginWidget()->setVisible(!m_clipRect.isEmpty()); + platformPluginWidget()->setMask(QRegion(m_clipRect)); + + m_npWindow.x = m_windowRect.x(); + m_npWindow.y = m_windowRect.y(); + } else { + m_npWindow.x = 0; + m_npWindow.y = 0; + } + + // If the width or height are null, set the clipRect to null, indicating that + // the plugin is not visible/scrolled out. + if (!m_clipRect.width() || !m_clipRect.height()) { + m_npWindow.clipRect.left = 0; + m_npWindow.clipRect.right = 0; + m_npWindow.clipRect.top = 0; + m_npWindow.clipRect.bottom = 0; + } else { + // Clipping rectangle of the plug-in; the origin is the top left corner of the drawable or window. + m_npWindow.clipRect.left = m_npWindow.x + m_clipRect.x(); + m_npWindow.clipRect.top = m_npWindow.y + m_clipRect.y(); + m_npWindow.clipRect.right = m_npWindow.x + m_clipRect.x() + m_clipRect.width(); + m_npWindow.clipRect.bottom = m_npWindow.y + m_clipRect.y() + m_clipRect.height(); + } + + if (m_plugin->quirks().contains(PluginQuirkDontCallSetWindowMoreThanOnce)) { + // FLASH WORKAROUND: Only set initially. Multiple calls to + // setNPWindow() cause the plugin to crash in windowed mode. + if (!m_isWindowed || m_npWindow.width == -1 || m_npWindow.height == -1) { + m_npWindow.width = m_windowRect.width(); + m_npWindow.height = m_windowRect.height(); + } + } else { + m_npWindow.width = m_windowRect.width(); + m_npWindow.height = m_windowRect.height(); + } + + PluginView::setCurrentPluginView(this); +#if USE(JSC) + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); +#endif + setCallingPlugin(true); + m_plugin->pluginFuncs()->setwindow(m_instance, &m_npWindow); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); +} + +void PluginView::setParentVisible(bool visible) +{ + if (isParentVisible() == visible) + return; + + Widget::setParentVisible(visible); + + if (isSelfVisible() && platformPluginWidget()) + platformPluginWidget()->setVisible(visible); +} + +NPError PluginView::handlePostReadFile(Vector<char>& buffer, uint32_t len, const char* buf) +{ + String filename(buf, len); + + if (filename.startsWith("file:///")) + filename = filename.substring(8); + + long long size; + if (!getFileSize(filename, size)) + return NPERR_FILE_NOT_FOUND; + + FILE* fileHandle = fopen((filename.utf8()).data(), "r"); + if (!fileHandle) + return NPERR_FILE_NOT_FOUND; + + buffer.resize(size); + int bytesRead = fread(buffer.data(), 1, size, fileHandle); + + fclose(fileHandle); + + if (bytesRead <= 0) + return NPERR_FILE_NOT_FOUND; + + return NPERR_NO_ERROR; +} + +bool PluginView::platformGetValueStatic(NPNVariable variable, void* value, NPError* result) +{ + switch (variable) { + case NPNVToolkit: + *static_cast<uint32_t*>(value) = 0; + *result = NPERR_NO_ERROR; + return true; + + case NPNVSupportsXEmbedBool: + *static_cast<NPBool*>(value) = true; + *result = NPERR_NO_ERROR; + return true; + + case NPNVjavascriptEnabledBool: + *static_cast<NPBool*>(value) = true; + *result = NPERR_NO_ERROR; + return true; + + case NPNVSupportsWindowless: + *static_cast<NPBool*>(value) = true; + *result = NPERR_NO_ERROR; + return true; + +#if defined(MOZ_PLATFORM_MAEMO) && (MOZ_PLATFORM_MAEMO >= 5) + case NPNVSupportsWindowlessLocal: + *static_cast<NPBool*>(value) = true; + *result = NPERR_NO_ERROR; + return true; +#endif + + default: + return false; + } +} + +bool PluginView::platformGetValue(NPNVariable variable, void* value, NPError* result) +{ + switch (variable) { + case NPNVxDisplay: + *(void **)value = QX11Info::display(); + *result = NPERR_NO_ERROR; + return true; + + case NPNVxtAppContext: + *result = NPERR_GENERIC_ERROR; + return true; + + case NPNVnetscapeWindow: { + void* w = reinterpret_cast<void*>(value); + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + *((XID *)w) = client ? client->ownerWidget()->window()->winId() : 0; + *result = NPERR_NO_ERROR; + return true; + } + + case NPNVToolkit: + if (m_plugin->quirks().contains(PluginQuirkRequiresGtkToolKit)) { + *((uint32_t *)value) = 2; + *result = NPERR_NO_ERROR; + return true; + } + return false; + + default: + return false; + } +} + +void PluginView::invalidateRect(const IntRect& rect) +{ +#if USE(ACCELERATED_COMPOSITING) && !USE(TEXTURE_MAPPER) + if (m_platformLayer) { + m_platformLayer->update(QRectF(rect)); + return; + } +#endif + + if (m_isWindowed) { + if (platformWidget()) + platformWidget()->update(rect); + return; + } + + invalidateWindowlessPluginRect(rect); +} + +void PluginView::invalidateRect(NPRect* rect) +{ + if (!rect) { + invalidate(); + return; + } + IntRect r(rect->left, rect->top, rect->right - rect->left, rect->bottom - rect->top); + invalidateRect(r); +} + +void PluginView::invalidateRegion(NPRegion region) +{ + Q_UNUSED(region); + invalidate(); +} + +void PluginView::forceRedraw() +{ + invalidate(); +} + +static Display *getPluginDisplay() +{ + // The plugin toolkit might run using a different X connection. 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()); +} + +static void getVisualAndColormap(int depth, Visual **visual, Colormap *colormap) +{ + *visual = 0; + *colormap = 0; + +#ifndef QT_NO_XRENDER + static const bool useXRender = qgetenv("QT_X11_NO_XRENDER").isNull(); // Should also check for XRender >= 0.5 +#else + static const bool useXRender = false; +#endif + + if (!useXRender && depth == 32) + return; + + int nvi; + XVisualInfo templ; + templ.screen = QX11Info::appScreen(); + templ.depth = depth; + templ.c_class = TrueColor; + XVisualInfo* xvi = XGetVisualInfo(QX11Info::display(), VisualScreenMask | VisualDepthMask | VisualClassMask, &templ, &nvi); + + if (!xvi) + return; + +#ifndef QT_NO_XRENDER + if (depth == 32) { + for (int idx = 0; idx < nvi; ++idx) { + XRenderPictFormat* format = XRenderFindVisualFormat(QX11Info::display(), xvi[idx].visual); + if (format->type == PictTypeDirect && format->direct.alphaMask) { + *visual = xvi[idx].visual; + break; + } + } + } else +#endif // QT_NO_XRENDER + *visual = xvi[0].visual; + + XFree(xvi); + + if (*visual) + *colormap = XCreateColormap(QX11Info::display(), QX11Info::appRootWindow(), *visual, AllocNone); +} + +bool PluginView::platformStart() +{ + ASSERT(m_isStarted); + ASSERT(m_status == PluginStatusLoadedSuccessfully); + + if (m_plugin->pluginFuncs()->getvalue) { + PluginView::setCurrentPluginView(this); +#if USE(JSC) + JSC::JSLock::DropAllLocks dropAllLocks(JSC::SilenceAssertionsOnly); +#endif + setCallingPlugin(true); + m_plugin->pluginFuncs()->getvalue(m_instance, NPPVpluginNeedsXEmbed, &m_needsXEmbed); + setCallingPlugin(false); + PluginView::setCurrentPluginView(0); + } + + if (m_isWindowed) { + QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient(); + if (m_needsXEmbed && client) { + setPlatformWidget(new PluginContainerQt(this, client->ownerWidget())); + // sync our XEmbed container window creation before sending the xid to plugins. + QApplication::syncX(); + } else { + notImplemented(); + m_status = PluginStatusCanNotLoadPlugin; + return false; + } + } else { + setPlatformWidget(0); + m_pluginDisplay = getPluginDisplay(); + +#if USE(ACCELERATED_COMPOSITING) && !USE(TEXTURE_MAPPER) + if (m_parentFrame->page()->chrome()->client()->allowsAcceleratedCompositing() + && m_parentFrame->page()->settings() + && m_parentFrame->page()->settings()->acceleratedCompositingEnabled()) { + m_platformLayer = new PluginGraphicsLayerQt(this); + // Trigger layer computation in RenderLayerCompositor + m_element->setNeedsStyleRecalc(SyntheticStyleChange); + } +#endif + } + + show(); + + NPSetWindowCallbackStruct* wsi = new NPSetWindowCallbackStruct(); + wsi->type = 0; + + if (m_isWindowed) { + const QX11Info* x11Info = &platformPluginWidget()->x11Info(); + + wsi->display = x11Info->display(); + wsi->visual = (Visual*)x11Info->visual(); + wsi->depth = x11Info->depth(); + wsi->colormap = x11Info->colormap(); + + m_npWindow.type = NPWindowTypeWindow; + m_npWindow.window = (void*)platformPluginWidget()->winId(); + m_npWindow.width = -1; + m_npWindow.height = -1; + } else { + const QX11Info* x11Info = &QApplication::desktop()->x11Info(); + + if (x11Info->depth() == 32 || !m_plugin->quirks().contains(PluginQuirkRequiresDefaultScreenDepth)) { + getVisualAndColormap(32, &m_visual, &m_colormap); + wsi->depth = 32; + } + + if (!m_visual) { + getVisualAndColormap(x11Info->depth(), &m_visual, &m_colormap); + wsi->depth = x11Info->depth(); + } + + wsi->display = x11Info->display(); + wsi->visual = m_visual; + wsi->colormap = m_colormap; + + m_npWindow.type = NPWindowTypeDrawable; + m_npWindow.window = 0; // Not used? + m_npWindow.x = 0; + m_npWindow.y = 0; + m_npWindow.width = -1; + m_npWindow.height = -1; + } + + m_npWindow.ws_info = wsi; + + if (!(m_plugin->quirks().contains(PluginQuirkDeferFirstSetWindowCall))) { + updatePluginWidget(); + setNPWindowIfNeeded(); + } + + return true; +} + +void PluginView::platformDestroy() +{ + if (platformPluginWidget()) + delete platformPluginWidget(); + + if (m_drawable) + XFreePixmap(QX11Info::display(), m_drawable); + + if (m_colormap) + XFreeColormap(QX11Info::display(), m_colormap); +} + +void PluginView::halt() +{ +} + +void PluginView::restart() +{ +} + +#if USE(ACCELERATED_COMPOSITING) +PlatformLayer* PluginView::platformLayer() const +{ + return m_platformLayer.get(); +} +#endif + +} // namespace WebCore |
