diff --git a/nsplugins/nspluginloader.cpp b/nsplugins/nspluginloader.cpp index 0e9c2507fc..96bfba769a 100644 --- a/nsplugins/nspluginloader.cpp +++ b/nsplugins/nspluginloader.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include "nsplugins_class_interface.h" #include "nsplugins_instance_interface.h" @@ -52,6 +53,8 @@ #include +#include + NSPluginLoader *NSPluginLoader::s_instance = 0; int NSPluginLoader::s_refCount = 0; @@ -59,10 +62,14 @@ int NSPluginLoader::s_refCount = 0; NSPluginInstance::NSPluginInstance(QWidget *parent, const QString& viewerDBusId, const QString& id) : EMBEDCLASS(parent) { + setWindowTitle("nsp.host"); // for debugging.. _instanceInterface = new org::kde::nsplugins::Instance( viewerDBusId, id, QDBusConnection::sessionBus() ); _loader = 0; - shown = false; + shown = false; + embedded = false; + resizedAfterShow = false; + QGridLayout *_layout = new QGridLayout(this); _layout->setMargin(1); _layout->setSpacing(1); @@ -85,12 +92,6 @@ void NSPluginInstance::doLoadPlugin() { delete _button; _button = 0L; _loader = NSPluginLoader::instance(); - - kDebug() << _instanceInterface->winId(); - embedClient( _instanceInterface->winId() ); - - show(); - shown = true; } } @@ -114,16 +115,46 @@ void NSPluginInstance::windowChanged(WId w) } + +/* + Flash 9.0r115 is picky, and only wants to be sized once, + so we want to do it when we're ready. For that, we wait + until we get the 2nd resize from khtml (and not the original + Qt default) +*/ + + void NSPluginInstance::resizeEvent(QResizeEvent *event) { - kDebug() << "NSPluginInstance(client)::resizeEvent" << shown << event->size(); - if (shown == false) - return; - EMBEDCLASS::resizeEvent(event); - if (isVisible()) { - _instanceInterface->resizePlugin(width(), height()); - } - kDebug() << "NSPluginInstance(client)::resizeEvent"; + if (shown) + resizedAfterShow = true; + + kDebug() << this << shown << resizedAfterShow; + EMBEDCLASS::resizeEvent(event); + QTimer::singleShot(10, this, SLOT(embedIfNeeded())); +} + +void NSPluginInstance::showEvent(QShowEvent *event) +{ + shown = true; + + kDebug() << this << shown << resizedAfterShow; + EMBEDCLASS::showEvent(event); + QTimer::singleShot(10, this, SLOT(embedIfNeeded())); +} + +void NSPluginInstance::embedIfNeeded() +{ + if (embedded) + return; + if (shown && resizedAfterShow) { + kDebug() << isVisible() << width() << height() << winId() << internalWinId(); + show(); + qApp->syncX(); + embedded = true; + _instanceInterface->setupWindow(winId(), width(), height()); + qApp->syncX(); + } } void NSPluginInstance::javascriptResult(int id, const QString &result) @@ -391,7 +422,7 @@ NSPluginInstance *NSPluginLoader::newInstance(QWidget *parent, const QString& ur return 0; } } - + kDebug() << "-> ownID" << ownDBusId << " viewer ID:" << _viewerDBusId; QStringList argn( _argn ); @@ -426,7 +457,7 @@ NSPluginInstance *NSPluginLoader::newInstance(QWidget *parent, const QString& ur kDebug() << "Couldn't create plugin class"; return 0; } - + org::kde::nsplugins::Class* cls = new org::kde::nsplugins::Class( _viewerDBusId, cls_ref.path(), QDBusConnection::sessionBus() ); // handle special plugin cases diff --git a/nsplugins/nspluginloader.h b/nsplugins/nspluginloader.h index b58dd6e898..f638b95b35 100644 --- a/nsplugins/nspluginloader.h +++ b/nsplugins/nspluginloader.h @@ -58,9 +58,10 @@ public: private Q_SLOTS: void doLoadPlugin(); - + void embedIfNeeded(); protected: void resizeEvent(QResizeEvent *event); + void showEvent(QShowEvent *event); void windowChanged(WId w); virtual void focusInEvent( QFocusEvent* event ); virtual void focusOutEvent( QFocusEvent* event ); @@ -68,6 +69,8 @@ private: class NSPluginLoader *_loader; OrgKdeNspluginsInstanceInterface *_instanceInterface; bool shown; + bool embedded; // if embedding was complete + bool resizedAfterShow; QPushButton *_button; QGridLayout *_layout; }; diff --git a/nsplugins/viewer/nsplugin.cpp b/nsplugins/viewer/nsplugin.cpp index 96d353b0eb..9cb4c9a27c 100644 --- a/nsplugins/viewer/nsplugin.cpp +++ b/nsplugins/viewer/nsplugin.cpp @@ -192,7 +192,7 @@ NPError g_NPN_GetValue(NPP /*instance*/, NPNVariable variable, void *value) case NPNVToolkit: // This is messy. OSS things want to see "Gtk2" here; // but commercial flash works better if we return something else. - // So we return a KHTML classic, since we can work with + // So we return a KHTML classic, since we can work with // the community members far easier. *(NPNToolkitType*)value = (NPNToolkitType)0xFEEDABEE; return NPERR_NO_ERROR; @@ -593,7 +593,7 @@ NPError g_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void* /*value*/) static int s_instanceCounter = 0; NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs, - KLibrary *handle, int width, int height, + KLibrary *handle, const QString &src, const QString &/*mime*/, const QString &appId, const QString &callbackId, bool embed, @@ -606,14 +606,11 @@ NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs, QDBusConnection::sessionBus().registerObject( objectName(), this ); Q_UNUSED(embed); - _firstResize = true; _embedded = false; _npp = privateData; _npp->ndata = this; _destroyed = false; _handle = handle; - _width = width; - _height = height; _tempFiles.setAutoDelete( true ); _streams.setAutoDelete( true ); _waitingRequests.setAutoDelete( true ); @@ -632,33 +629,18 @@ NSPluginInstance::NSPluginInstance(NPP privateData, NPPluginFuncs *pluginFuncs, kDebug(1431) << "pdata = " << _npp->pdata; kDebug(1431) << "ndata = " << _npp->ndata; - if (width == 0) - width = 1600; - - if (height == 0) - height = 1200; - - // Create our XEmbed peer with the part. - _outside = new QX11EmbedWidget(); - _outside->hide(); - _outside->setWindowTitle("nspluginviewer.outside"); - - // We need to wait until we're embedded before being able to - // do things. - connect(_outside, SIGNAL(embedded()), this, SLOT(embeddedIntoHost())); - // Create the appropriate host for the plugin type. _pluginHost = 0; int result = PR_FALSE; - + //### iceweasel does something odd here --- it enabled XEmbed for swfdec, // even though that doesn't provide GetValue at all(!) if (NPGetValue(NPPVpluginNeedsXEmbed, &result) == NPERR_NO_ERROR && result) { kDebug(1431) << "plugin reqests XEmbed"; - _pluginHost = new PluginHostXEmbed(this, _outside); + _pluginHost = new PluginHostXEmbed(this); } else { kDebug(1431) << "plugin requests Xt"; - _pluginHost = new PluginHostXt(this, _outside, width, height); + _pluginHost = new PluginHostXt(this); } XSync(QX11Info::display(), false); @@ -714,9 +696,6 @@ void NSPluginInstance::destroy() delete _pluginHost; _pluginHost = 0; - - delete _outside; - _outside = 0; if (_npp) { ::free(_npp); // matched with malloc() in newInstance @@ -831,7 +810,7 @@ void NSPluginInstance::timer() QString NSPluginInstance::normalizedURL(const QString& url) const { // ### for dfaure: KUrl(KUrl("http://www.youtube.com/?v=JvOSnRD5aNk"), KUrl("javascript:window.location+"__flashplugin_unique__")); - + //### hack, prolly evil, etc. if (url.startsWith("javascript:")) return url; @@ -909,45 +888,16 @@ void NSPluginInstance::streamFinished( NSPluginStreamBase* strm ) _timer->start( 100 ); } -void NSPluginInstance::embeddedIntoHost() -{ - _outside->show(); - setupWindow(); - _embedded = true; -} - -void NSPluginInstance::setupWindow() +void NSPluginInstance::setupWindow(int winId, int w, int h) { + kDebug(1431) << "-> NSPluginInstance::setupWindow( winid =" << winId << " w=" << w << ", h=" << h << " ) "; if (_pluginHost) - _pluginHost->setupWindow(_width, _height); -} - - -void NSPluginInstance::resizePlugin(int w, int h) -{ - kDebug(1431) << "-> NSPluginInstance::resizePlugin( w=" << w << ", h=" << h << " ) "; - if (!_embedded) { - _width = w; - _height = h; - return; - } - - if (w == _width && h == _height) - return; - - _width = w; - _height = h; - - _outside->resize(w, h); - if (_pluginHost) - _pluginHost->resizePlugin(w, h); - - if (_firstResize) { - _firstResize = false; - setupWindow(); - } + _pluginHost->setupWindow(winId, w, h); + else + kWarning(1431) << "No plugin host!"; kDebug(1431) << "<- NSPluginInstance::resizePlugin"; + _embedded = true; } @@ -1292,7 +1242,7 @@ NSPluginClass::NSPluginClass( const QString &library, // initialize plugin kDebug(1431) << "Plugin library " << library << " loaded!"; - + // see if it uses gtk if (!s_initedGTK) { gtkInitFunc* gtkInit = (gtkInitFunc*)_handle->resolveFunction("gtk_init"); @@ -1302,7 +1252,7 @@ NSPluginClass::NSPluginClass( const QString &library, s_initedGTK = true; } } - + _constructed = true; _error = initialize()!=NPERR_NO_ERROR; } @@ -1338,7 +1288,7 @@ int NSPluginClass::initialize() // initialize nescape exported functions memset(&_pluginFuncs, 0, sizeof(_pluginFuncs)); memset(&_nsFuncs, 0, sizeof(_nsFuncs)); - + _pluginFuncs.size = sizeof(_pluginFuncs); _nsFuncs.size = sizeof(_nsFuncs); _nsFuncs.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; @@ -1399,8 +1349,6 @@ QDBusObjectPath NSPluginClass::newInstance( const QString &url, const QString &m char **_argn = new char*[argc]; char **_argv = new char*[argc]; QString src = url; - int width = 0; - int height = 0; QString baseURL = url; for (unsigned int i=0; i - - - - + + diff --git a/nsplugins/viewer/pluginhost.h b/nsplugins/viewer/pluginhost.h index dac4b40d31..0aa8b98386 100644 --- a/nsplugins/viewer/pluginhost.h +++ b/nsplugins/viewer/pluginhost.h @@ -1,6 +1,6 @@ /* - This class abstracts away various ways one can embed plugins + This class abstracts away various ways one can embed plugins Copyright (c) 2007 Maksim Orlovich @@ -29,10 +29,9 @@ class PluginHost { public: - virtual void setupWindow (int width, int height) = 0; - virtual void resizePlugin(int width, int height) = 0; + virtual void setupWindow (int winId, int width, int height) = 0; virtual ~PluginHost() {}; - + void setupPluginWindow(NSPluginInstance* instance, void* winID, int width, int height); }; diff --git a/nsplugins/viewer/pluginhost_xembed.cpp b/nsplugins/viewer/pluginhost_xembed.cpp index 25232a9eb4..58673eed31 100644 --- a/nsplugins/viewer/pluginhost_xembed.cpp +++ b/nsplugins/viewer/pluginhost_xembed.cpp @@ -28,49 +28,18 @@ #include #include -PluginHostXEmbed::PluginHostXEmbed(NSPluginInstance* plugin, QX11EmbedWidget* outside): - _plugin(plugin), _outside(outside), _container(0) -{ - // Nothing here yet --- will do once embedded, inside setupWindow -} +PluginHostXEmbed::PluginHostXEmbed(NSPluginInstance* plugin): + _plugin(plugin) +{} PluginHostXEmbed::~PluginHostXEmbed() +{} + + +void PluginHostXEmbed::setupWindow(int winId, int width, int height) { -/* delete _inside; - _inside = 0;*/ -} - - -void PluginHostXEmbed::resizePlugin(int width, int height) -{ -// return; - kDebug(1431) << _container->geometry() << _outside->geometry(); -/* _inside->setGeometry(0, 0, width, height);*/ -} - -void PluginHostXEmbed::setupWindow(int width, int height) -{ - if (!_container) { - QVBoxLayout* outsideLayout = new QVBoxLayout(_outside); - outsideLayout->setMargin(0); - _outside->setLayout(outsideLayout); - - _container = new QX11EmbedContainer(_outside); - _container->setWindowTitle("_inner"); - outsideLayout->addWidget(_container); - -// QPalette p = _container->palette(); -// p.setColor(_container->backgroundRole(), Qt::green); -// _container->setPalette(p); -// _container->setAutoFillBackground(true); - - _container->show(); - outsideLayout->update(); - } - kDebug() << _outside->geometry() << _container->geometry() << - _outside->isVisible() << _container->isVisible(); - - setupPluginWindow(_plugin, (void*)_container->winId(), width, height); + kDebug() << winId << width << height; + setupPluginWindow(_plugin, (void*)winId, width, height); } // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; diff --git a/nsplugins/viewer/pluginhost_xembed.h b/nsplugins/viewer/pluginhost_xembed.h index 696e4a11b9..2bd19e0fd3 100644 --- a/nsplugins/viewer/pluginhost_xembed.h +++ b/nsplugins/viewer/pluginhost_xembed.h @@ -29,14 +29,11 @@ class PluginHostXEmbed : public PluginHost { public: - PluginHostXEmbed(NSPluginInstance* plugin, QX11EmbedWidget* outside); - virtual void setupWindow(int width, int height); - virtual void resizePlugin(int width, int height); + PluginHostXEmbed(NSPluginInstance* plugin); + virtual void setupWindow(int winId, int width, int height); virtual ~PluginHostXEmbed(); private: NSPluginInstance* _plugin; - QX11EmbedWidget* _outside; - QX11EmbedContainer* _container; }; diff --git a/nsplugins/viewer/pluginhost_xt.cpp b/nsplugins/viewer/pluginhost_xt.cpp index 5e3e7befdf..1027f4215d 100644 --- a/nsplugins/viewer/pluginhost_xt.cpp +++ b/nsplugins/viewer/pluginhost_xt.cpp @@ -28,25 +28,54 @@ #include #include -PluginHostXt::PluginHostXt(NSPluginInstance* plugin, QX11EmbedWidget* outside, - int width, int height): - _plugin(plugin), _outside(outside) +// BEGIN Workaround for QX11EmbedWidget silliness --- it maps widgets by default +// Most of the code is from Qt 4.3.3, Copyright (C) 1992-2007 Trolltech ASA +static unsigned int XEMBED_VERSION = 0; +static Atom _XEMBED_INFO = None; +static void initXEmbedAtoms(Display *d) { + if (_XEMBED_INFO == None) + _XEMBED_INFO = XInternAtom(d, "_XEMBED_INFO", false); +} + +static void doNotAskForXEmbedMapping(QX11EmbedWidget* widget) +{ + initXEmbedAtoms(widget->x11Info().display()); + unsigned int data[] = {XEMBED_VERSION, 0 /* e.g. not XEMBED_MAPPED*/}; + XChangeProperty(widget->x11Info().display(), widget->winId(), _XEMBED_INFO, + _XEMBED_INFO, 32, PropModeReplace, + (unsigned char*) data, 2); +} + +// END Workaround for QX11EmbedWidget silliness. + + +PluginHostXt::PluginHostXt(NSPluginInstance* plugin): + _plugin(plugin), _outside(0), _toplevel(0), _form(0) +{} + + +void PluginHostXt::setupWindow(int winId, int width, int height) +{ + _outside = new QX11EmbedWidget(); + doNotAskForXEmbedMapping(_outside); + _outside->embedInto(winId); + Arg args[7]; Cardinal nargs = 0; XtSetArg(args[nargs], XtNwidth, width); nargs++; XtSetArg(args[nargs], XtNheight, height); nargs++; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; - + String n, c; XtGetApplicationNameAndClass(QX11Info::display(), &n, &c); _toplevel = XtAppCreateShell("drawingArea", c, applicationShellWidgetClass, QX11Info::display(), args, nargs); - + //if (embed) XtSetMappedWhenManaged(_toplevel, False); XtRealizeWidget(_toplevel); - + // Create form window that is searched for by flash plugin _form = XtVaCreateWidget("form", compositeWidgetClass, _toplevel, NULL); XtSetArg(args[nargs], XtNvisual, QX11Info::appVisual()); nargs++; @@ -66,24 +95,32 @@ PluginHostXt::PluginHostXt(NSPluginInstance* plugin, QX11EmbedWidget* outside, #endif XtRealizeWidget(_form); XtManageChild(_form); - + // Register forwarder XtAddEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), False, forwarder, (XtPointer)this ); XtAddEventHandler(_form, (KeyPressMask|KeyReleaseMask), False, forwarder, (XtPointer)this ); + + // Embed the Xt widget into the Qt widget + XReparentWindow(QX11Info::display(), XtWindow(_toplevel), _outside->winId(), 0, 0); + XtMapWidget(_toplevel); + setupPluginWindow(_plugin, (void*) XtWindow(_form), width, height); } PluginHostXt::~PluginHostXt() { - XtRemoveEventHandler(_form, (KeyPressMask|KeyReleaseMask), - False, forwarder, (XtPointer)this); - XtRemoveEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), - False, forwarder, (XtPointer)this); - XtDestroyWidget(_form); - XtDestroyWidget(_toplevel); - _form = 0; - _toplevel = 0; + if (_form) { + XtRemoveEventHandler(_form, (KeyPressMask|KeyReleaseMask), + False, forwarder, (XtPointer)this); + XtRemoveEventHandler(_toplevel, (KeyPressMask|KeyReleaseMask), + False, forwarder, (XtPointer)this); + XtDestroyWidget(_form); + XtDestroyWidget(_toplevel); + _form = 0; + _toplevel = 0; + } + delete _outside; } void PluginHostXt::forwarder(Widget w, XtPointer cl_data, XEvent * event, Boolean * cont) @@ -112,14 +149,14 @@ static void resizeWidgets(Window w, int width, int height) { } } - + #if 0 void PluginHostXt::resizePlugin(int w, int h) { kDebug(1431) << w << h; XResizeWindow(QX11Info::display(), XtWindow(_form), w, h); XResizeWindow(QX11Info::display(), XtWindow(_toplevel), w, h); - + Arg args[7]; Cardinal nargs = 0; XtSetArg(args[nargs], XtNwidth, w); nargs++; @@ -128,18 +165,12 @@ void PluginHostXt::resizePlugin(int w, int h) XtSetArg(args[nargs], XtNdepth, QX11Info::appDepth()); nargs++; XtSetArg(args[nargs], XtNcolormap, QX11Info::appColormap()); nargs++; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; - + XtSetValues(_form, args, nargs); - + resizeWidgets(XtWindow(_form), w, h); } -void PluginHostXt::setupWindow(int width, int height) -{ - // Embed the Xt widget into the Qt widget - XReparentWindow(QX11Info::display(), XtWindow(_toplevel), _outside->winId(), 0, 0); - XtMapWidget(_toplevel); - setupPluginWindow(_plugin, (void*) XtWindow(_form), width, height); -} +#endif // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; diff --git a/nsplugins/viewer/pluginhost_xt.h b/nsplugins/viewer/pluginhost_xt.h index fd9388d58d..a53931d2ac 100644 --- a/nsplugins/viewer/pluginhost_xt.h +++ b/nsplugins/viewer/pluginhost_xt.h @@ -39,9 +39,8 @@ class PluginHostXt : public PluginHost { public: - PluginHostXt(NSPluginInstance* plugin, QX11EmbedWidget* outside, int w, int h); - virtual void setupWindow(int width, int height); - virtual void resizePlugin(int width, int height); + PluginHostXt(NSPluginInstance* plugin); + virtual void setupWindow(int winId, int width, int height); virtual ~PluginHostXt(); private: static void forwarder(Widget w, XtPointer cl_data, XEvent * event, Boolean * cont);