summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/plugins/qt
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/plugins/qt
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_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.cpp150
-rw-r--r--Source/WebCore/plugins/qt/PluginContainerQt.h63
-rw-r--r--Source/WebCore/plugins/qt/PluginPackageQt.cpp199
-rw-r--r--Source/WebCore/plugins/qt/PluginViewQt.cpp1011
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