summaryrefslogtreecommitdiffstats
path: root/kicker/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'kicker/proxy')
-rw-r--r--kicker/proxy/Makefile.am24
-rw-r--r--kicker/proxy/appletproxy.cpp516
-rw-r--r--kicker/proxy/appletproxy.h67
-rw-r--r--kicker/proxy/extensiondebugger.cpp160
-rw-r--r--kicker/proxy/extensiondebugger.h47
-rw-r--r--kicker/proxy/extensionproxy.cpp401
-rw-r--r--kicker/proxy/extensionproxy.h61
7 files changed, 1276 insertions, 0 deletions
diff --git a/kicker/proxy/Makefile.am b/kicker/proxy/Makefile.am
new file mode 100644
index 000000000..b63535490
--- /dev/null
+++ b/kicker/proxy/Makefile.am
@@ -0,0 +1,24 @@
+INCLUDES = -I$(srcdir)/../libkicker $(all_includes)
+
+bin_PROGRAMS =
+noinst_PROGRAMS = extensiondebugger
+lib_LTLIBRARIES =
+kdeinit_LTLIBRARIES = appletproxy.la extensionproxy.la
+
+METASOURCES = AUTO
+
+appletproxy_la_LIBADD = $(LIB_KDEUI) ../libkicker/libkickermain.la
+appletproxy_la_SOURCES = appletproxy.cpp
+appletproxy_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -module -avoid-version
+
+extensionproxy_la_LIBADD = $(LIB_KDEUI) ../libkicker/libkickermain.la
+extensionproxy_la_SOURCES = extensionproxy.cpp
+extensionproxy_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -module -avoid-version
+
+extensiondebugger_SOURCES = extensiondebugger.cpp
+extensiondebugger_LDADD = ../libkicker/libkickermain.la
+extensiondebugger_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+messages:
+ $(XGETTEXT) appletproxy.cpp -o $(podir)/appletproxy.pot
+ $(XGETTEXT) extensionproxy.cpp -o $(podir)/extensionproxy.pot
diff --git a/kicker/proxy/appletproxy.cpp b/kicker/proxy/appletproxy.cpp
new file mode 100644
index 000000000..d9ac588d5
--- /dev/null
+++ b/kicker/proxy/appletproxy.cpp
@@ -0,0 +1,516 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTDHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <stdlib.h>
+
+#include <qstring.h>
+#include <qfile.h>
+#include <qobjectlist.h>
+#include <qxembed.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kpanelapplet.h>
+#include <kaboutdata.h>
+#include <qfileinfo.h>
+#include <dcopclient.h>
+#include <kwin.h>
+
+#include "appletinfo.h"
+
+#include "appletproxy.h"
+#include "appletproxy.moc"
+
+#include <X11/Xlib.h>
+
+KPanelApplet::Position directionToPosition( int d )
+{
+ switch( d ) {
+ case 1: return KPanelApplet::pTop;
+ case 2: return KPanelApplet::pRight;
+ case 3: return KPanelApplet::pLeft;
+ default:
+ case 0: return KPanelApplet::pBottom;
+ }
+}
+
+static KCmdLineOptions options[] =
+{
+ { "+desktopfile", I18N_NOOP("The applet's desktop file"), 0 },
+ { "configfile <file>", I18N_NOOP("The config file to be used"), 0 },
+ { "callbackid <id>", I18N_NOOP("DCOP callback id of the applet container"), 0 },
+ KCmdLineLastOption
+};
+
+extern "C" KDE_EXPORT int kdemain( int argc, char ** argv )
+{
+ KAboutData aboutData( "kicker", I18N_NOOP("Panel applet proxy.")
+ , "v0.1.0"
+ ,I18N_NOOP("Panel applet proxy.")
+ , KAboutData::License_BSD
+ , "(c) 2000, The KDE Developers");
+ KCmdLineArgs::init(argc, argv, &aboutData );
+ aboutData.addAuthor("Matthias Elter",0, "[email protected]");
+ aboutData.addAuthor("Matthias Ettrich",0, "[email protected]");
+ KApplication::addCmdLineOptions();
+ KCmdLineArgs::addCmdLineOptions(options); // Add our own options.
+
+ KApplication a;
+ a.disableSessionManagement();
+
+ KGlobal::dirs()->addResourceType("applets", KStandardDirs::kde_default("data") +
+ "kicker/applets");
+
+ // setup proxy object
+ AppletProxy proxy(0, "appletproxywidget");
+
+ // parse cmdline args
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ if ( args->count() == 0 )
+ KCmdLineArgs::usage(i18n("No desktop file specified") );
+
+ // Perhaps we should use a konsole-like solution here (shell, list of args...)
+ QString desktopfile( args->arg(0) );
+
+ // load applet DSO
+ if ( !QFile::exists( desktopfile ) &&
+ !desktopfile.endsWith( ".desktop" ) )
+ desktopfile.append( ".desktop" );
+
+ if ( !QFile::exists( desktopfile ) )
+ desktopfile = locate( "applets", desktopfile ).latin1();
+
+ proxy.loadApplet( desktopfile, args->getOption("configfile"));
+
+ // dock into our applet container
+ QCString callbackid = args->getOption( "callbackid");
+ if ( callbackid.isEmpty() )
+ proxy.showStandalone();
+ else
+ proxy.dock(args->getOption("callbackid"));
+
+ return a.exec();
+}
+
+AppletProxy::AppletProxy(QObject* parent, const char* name)
+ : QObject(parent, name)
+ , DCOPObject("AppletProxy")
+ , _info(0)
+ , _applet(0)
+{
+ // try to attach to DCOP server
+ if (!kapp->dcopClient()->attach()) {
+ kdError() << "Failed to attach to DCOP server." << endl;
+ KMessageBox::error(0,
+ i18n("The applet proxy could not be started due to DCOP communication problems."),
+ i18n("Applet Loading Error"));
+ exit(0);
+ }
+
+ if (!kapp->dcopClient()->registerAs("applet_proxy", true)) {
+ kdError() << "Failed to register at DCOP server." << endl;
+ KMessageBox::error(0,
+ i18n("The applet proxy could not be started due to DCOP registration problems."),
+ i18n("Applet Loading Error"));
+ exit(0);
+ }
+
+ _bg = QPixmap();
+}
+
+AppletProxy::~AppletProxy()
+{
+ kapp->dcopClient()->detach();
+ delete _info;
+ delete _applet;
+}
+
+void AppletProxy::loadApplet(const QString& desktopFile, const QString& configFile)
+{
+ QString df;
+
+ // try simple path first
+ QFileInfo finfo( desktopFile );
+ if ( finfo.exists() ) {
+ df = finfo.absFilePath();
+ } else {
+ // locate desktop file
+ df = KGlobal::dirs()->findResource("applets", desktopFile);
+ }
+
+ QFile file(df);
+ // does the config file exist?
+ if (df.isNull() || !file.exists()) {
+ kdError() << "Failed to locate applet desktop file: " << desktopFile << endl;
+ KMessageBox::error(0,
+ i18n("The applet proxy could not load the applet information from %1.").arg(desktopFile),
+ i18n("Applet Loading Error"));
+ exit(0);
+ }
+
+ // create AppletInfo instance
+ delete _info;
+ _info = new AppletInfo(df);
+
+ // set the config file
+ if (!configFile.isNull())
+ _info->setConfigFile(configFile);
+
+ // load applet DSO
+ _applet = loadApplet(*_info);
+
+ // sanity check
+ if (!_applet)
+ {
+ kdError() << "Failed to load applet: " << _info->library() << endl;
+ KMessageBox::error(0,
+ i18n("The applet %1 could not be loaded via the applet proxy.").arg(_info->name()),
+ i18n("Applet Loading Error"));
+ exit(0);
+ }
+
+ // connect updateLayout signal
+ connect(_applet, SIGNAL(updateLayout()), SLOT(slotUpdateLayout()));
+ // connect requestFocus signal
+ connect(_applet, SIGNAL(requestFocus()), SLOT(slotRequestFocus()));
+}
+
+KPanelApplet* AppletProxy::loadApplet(const AppletInfo& info)
+{
+ KLibLoader* loader = KLibLoader::self();
+ KLibrary* lib = loader->library(QFile::encodeName(info.library()));
+
+ if (!lib)
+ {
+ kdWarning() << "cannot open applet: " << info.library()
+ << " because of " << loader->lastErrorMessage() << endl;
+ return 0;
+ }
+
+ KPanelApplet* (*init_ptr)(QWidget *, const QString&);
+ init_ptr = (KPanelApplet* (*)(QWidget *, const QString&))lib->symbol( "init" );
+
+ if (!init_ptr)
+ {
+ kdWarning() << info.library() << " is not a kicker plugin!" << endl;
+ return 0;
+ }
+
+ return init_ptr(0, info.configFile());
+}
+
+void AppletProxy::repaintApplet(QWidget* widget)
+{
+ widget->repaint();
+
+ const QObjectList* children = widget->children();
+
+ if (!children)
+ {
+ return;
+ }
+
+ QObjectList::iterator it = children->begin();
+ for (; it != children->end(); ++it)
+ {
+ QWidget *w = dynamic_cast<QWidget*>(*it);
+ if (w)
+ {
+ repaintApplet(w);
+ }
+ }
+}
+
+void AppletProxy::dock(const QCString& callbackID)
+{
+ kdDebug(1210) << "Callback ID: " << callbackID << endl;
+
+ _callbackID = callbackID;
+
+ // try to attach to DCOP server
+ DCOPClient* dcop = kapp->dcopClient();
+
+ dcop->setNotifications(true);
+ connect(dcop, SIGNAL(applicationRemoved(const QCString&)),
+ SLOT(slotApplicationRemoved(const QCString&)));
+
+ WId win;
+
+ // get docked
+ {
+ QCString replyType;
+ QByteArray data, replyData;
+ QDataStream dataStream( data, IO_WriteOnly );
+
+ int actions = 0;
+ if (_applet) actions = _applet->actions();
+ dataStream << actions;
+
+ int type = 0;
+ if (_applet) type = static_cast<int>(_applet->type());
+ dataStream << type;
+
+ // we use "call" to know whether it was sucessful
+
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ if ( !dcop->call(appname, _callbackID, "dockRequest(int,int)",
+ data, replyType, replyData ) )
+ {
+ kdError() << "Failed to dock into the panel." << endl;
+ KMessageBox::error(0,
+ i18n("The applet proxy could not dock into the panel due to DCOP communication problems."),
+ i18n("Applet Loading Error"));
+ exit(0);
+ }
+
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> win;
+
+ // request background
+ dcop->send(appname, _callbackID, "getBackground()", data);
+ }
+
+ if (win)
+ {
+ if (_applet)
+ {
+ _applet->hide();
+ }
+ QXEmbed::initialize();
+ QXEmbed::embedClientIntoWindow(_applet, win);
+ }
+ else
+ {
+ kdError() << "Failed to dock into the panel." << endl;
+ KMessageBox::error(0,
+ i18n("The applet proxy could not dock into the panel."),
+ i18n("Applet Loading Error"));
+ delete _applet;
+ _applet = 0;
+
+ exit(0);
+ }
+
+}
+
+bool AppletProxy::process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ if ( fun == "widthForHeight(int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int height;
+ dataStream >> height;
+ QDataStream reply( replyData, IO_WriteOnly );
+ replyType = "int";
+
+ if (!_applet)
+ reply << height;
+ else
+ reply << _applet->widthForHeight(height);
+
+ return true;
+ }
+ else if ( fun == "heightForWidth(int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int width;
+ dataStream >> width;
+ QDataStream reply( replyData, IO_WriteOnly );
+ replyType = "int";
+
+ if(!_applet)
+ reply << width;
+ else
+ reply << _applet->heightForWidth(width);
+
+ return true;
+ }
+ else if ( fun == "setDirection(int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int dir;
+ dataStream >> dir;
+
+ if(_applet) {
+ _applet->setPosition(directionToPosition(dir));
+ }
+ return true;
+ }
+ else if ( fun == "setAlignment(int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int alignment;
+ dataStream >> alignment;
+
+ if(_applet) {
+ _applet->setAlignment( (KPanelApplet::Alignment)alignment );
+ }
+ return true;
+ }
+ else if ( fun == "removedFromPanel()" )
+ {
+ delete _applet;
+ _applet = 0;
+ exit(0);
+ return true;
+ }
+ else if ( fun == "about()" )
+ {
+ if(_applet) _applet->action( KPanelApplet::About );
+ return true;
+ }
+ else if ( fun == "help()" )
+ {
+ if(_applet) _applet->action( KPanelApplet::Help );
+ return true;
+ }
+ else if ( fun == "preferences()" )
+ {
+ if(_applet) _applet->action( KPanelApplet::Preferences );
+ return true;
+ }
+ else if (fun == "reportBug()" )
+ {
+ if(_applet) _applet->action( KPanelApplet::ReportBug );
+ return true;
+ }
+ else if ( fun == "actions()" )
+ {
+ QDataStream reply( replyData, IO_WriteOnly );
+ int actions = 0;
+ if(_applet) actions = _applet->actions();
+ reply << actions;
+ replyType = "int";
+ return true;
+ }
+ else if ( fun == "type()" )
+ {
+ QDataStream reply( replyData, IO_WriteOnly );
+ int type = 0;
+ if (_applet) type = static_cast<int>(_applet->type());
+ reply << type;
+ replyType = "int";
+ return true;
+ }
+ else if ( fun == "setBackground(QPixmap)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ dataStream >> _bg;
+ if(_applet)
+ if ( _bg.isNull() ) { // no transparency
+ _applet->unsetPalette();
+ _applet->repaint();
+ }
+ else { //transparency
+ _applet->blockSignals(true);
+ _applet->setBackgroundMode(Qt::FixedPixmap);
+ _applet->setPaletteBackgroundPixmap(_bg);
+ repaintApplet(_applet);
+ _applet->blockSignals(false);
+ }
+ return true;
+ }
+ return false;
+}
+
+void AppletProxy::slotUpdateLayout()
+{
+ if(_callbackID.isNull()) return;
+
+ QByteArray data;
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ kapp->dcopClient()->send(appname, _callbackID, "updateLayout()", data);
+}
+
+void AppletProxy::slotRequestFocus()
+{
+ if(_callbackID.isNull()) return;
+
+ QByteArray data;
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ kapp->dcopClient()->send(appname, _callbackID, "requestFocus()", data);
+}
+
+void AppletProxy::slotApplicationRemoved(const QCString& appId)
+{
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ if(appId == appname) {
+ kdDebug(1210) << "Connection to kicker lost, shutting down" << endl;
+ kapp->quit();
+ }
+}
+
+void AppletProxy::showStandalone()
+{
+ if (!_applet)
+ {
+ return;
+ }
+
+ _applet->resize( _applet->widthForHeight( 48 ), 48 );
+ _applet->setMinimumSize( _applet->size() );
+ _applet->setCaption( _info->name() );
+ kapp->setMainWidget( _applet );
+ _applet->show();
+}
+
diff --git a/kicker/proxy/appletproxy.h b/kicker/proxy/appletproxy.h
new file mode 100644
index 000000000..182280193
--- /dev/null
+++ b/kicker/proxy/appletproxy.h
@@ -0,0 +1,67 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __appletproxy_h__
+#define __appletproxy_h__
+
+#include <qcstring.h>
+#include <qobject.h>
+
+#include <dcopobject.h>
+
+#include "appletinfo.h"
+
+class KPanelApplet;
+class KickerPluginManager;
+
+class AppletProxy : public QObject, DCOPObject
+{
+ Q_OBJECT
+
+public:
+ AppletProxy(QObject* parent, const char* name = 0);
+ ~AppletProxy();
+
+ void loadApplet(const QString& desktopFile, const QString& configFile);
+ KPanelApplet* loadApplet(const AppletInfo& info);
+ void dock(const QCString& callbackID);
+ void showStandalone();
+
+ bool process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+
+protected slots:
+ void slotUpdateLayout();
+ void slotRequestFocus();
+ void slotApplicationRemoved(const QCString&);
+
+private:
+ void repaintApplet(QWidget* widget);
+
+ AppletInfo *_info;
+ KPanelApplet *_applet;
+ QCString _callbackID;
+ QPixmap _bg;
+};
+
+#endif
diff --git a/kicker/proxy/extensiondebugger.cpp b/kicker/proxy/extensiondebugger.cpp
new file mode 100644
index 000000000..f7c3309c4
--- /dev/null
+++ b/kicker/proxy/extensiondebugger.cpp
@@ -0,0 +1,160 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTDHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <qfile.h>
+#include <qlayout.h>
+#include <qpushbutton.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kpanelextension.h>
+#include <kaboutdata.h>
+#include <qfileinfo.h>
+
+#include "appletinfo.h"
+#include "extensiondebugger.h"
+#include "extensiondebugger.moc"
+
+
+
+static KCmdLineOptions options[] =
+{
+ { "+desktopfile", I18N_NOOP("The extensions desktop file"), 0 },
+ KCmdLineLastOption
+};
+
+KPanelExtension* loadExtension(const AppletInfo& info)
+{
+ KLibLoader* loader = KLibLoader::self();
+ KLibrary* lib = loader->library(QFile::encodeName(info.library()));
+
+ if (!lib)
+ {
+ kdWarning() << "cannot open extension: " << info.library()
+ << " because of " << loader->lastErrorMessage() << endl;
+ return 0;
+ }
+
+ KPanelExtension* (*init_ptr)(QWidget *, const QString&);
+ init_ptr = (KPanelExtension* (*)(QWidget *, const QString&))lib->symbol( "init" );
+
+ if (!init_ptr)
+ {
+ kdWarning() << info.library() << " is not a kicker extension!" << endl;
+ return 0;
+ }
+
+ return init_ptr(0, info.configFile());
+}
+
+int main( int argc, char ** argv )
+{
+ KAboutData aboutData( "extensionproxy", I18N_NOOP("Panel extension proxy.")
+ , "v0.1.0"
+ ,I18N_NOOP("Panel extension proxy.")
+ , KAboutData::License_BSD
+ , "(c) 2000, The KDE Developers");
+ KCmdLineArgs::init(argc, argv, &aboutData );
+ aboutData.addAuthor("Matthias Elter",0, "[email protected]");
+ aboutData.addAuthor("Matthias Ettrich",0, "[email protected]");
+ KApplication::addCmdLineOptions();
+ KCmdLineArgs::addCmdLineOptions(options); // Add our own options.
+
+ KApplication a;
+ a.disableSessionManagement();
+
+ KGlobal::dirs()->addResourceType("extensions", KStandardDirs::kde_default("data") +
+ "kicker/extensions");
+
+ QString df;
+
+ // parse cmdline args
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ // sanity check
+ if ( args->count() == 0 )
+ KCmdLineArgs::usage(i18n("No desktop file specified") );
+
+
+ QCString desktopFile = QCString( args->arg(0) );
+
+ // try simple path first
+ QFileInfo finfo( desktopFile );
+ if ( finfo.exists() ) {
+ df = finfo.absFilePath();
+ } else {
+ // locate desktop file
+ df = KGlobal::dirs()->findResource("extensions", QString(desktopFile));
+ }
+
+ // does the config file exist?
+ if (!QFile::exists(df)) {
+ kdError() << "Failed to locate extension desktop file: " << desktopFile << endl;
+ return 1;
+ }
+
+ AppletInfo info( df );
+
+ KPanelExtension *extension = loadExtension(info);
+ if ( !extension ) {
+ kdError() << "Failed to load extension: " << info.library() << endl;
+ return 1;
+ }
+
+ ExtensionContainer *container = new ExtensionContainer( extension );
+ container->show();
+
+ QObject::connect( &a, SIGNAL( lastWindowClosed() ), &a, SLOT( quit() ) );
+
+ int result = a.exec();
+
+ delete extension;
+ return result;
+}
+
+ExtensionContainer::ExtensionContainer( KPanelExtension *extension, QWidget *parent, const char *name )
+ : QWidget( parent, name ), m_extension( extension )
+{
+ ( new QVBoxLayout( this ) )->setAutoAdd( true );
+
+ QPushButton *configButton = new QPushButton( i18n( "Configure..." ), this );
+ connect( configButton, SIGNAL( clicked() ),
+ this, SLOT( showPreferences() ) );
+
+ m_extension->reparent( this, QPoint( 0, 0 ) );
+}
+
+void ExtensionContainer::resizeEvent( QResizeEvent * )
+{
+ m_extension->setGeometry( 0, 0, width(), height() );
+}
+
+void ExtensionContainer::showPreferences()
+{
+ m_extension->action( KPanelExtension::Preferences );
+}
diff --git a/kicker/proxy/extensiondebugger.h b/kicker/proxy/extensiondebugger.h
new file mode 100644
index 000000000..36745ae90
--- /dev/null
+++ b/kicker/proxy/extensiondebugger.h
@@ -0,0 +1,47 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __extensiondebugger_h__
+#define __extensiondebugger_h__
+
+class AppletInfo;
+class KPanelExtension;
+
+class ExtensionContainer : public QWidget
+{
+ Q_OBJECT
+
+public:
+ ExtensionContainer(KPanelExtension *extension, QWidget* parent = 0, const char* name = 0);
+
+protected:
+ void resizeEvent( QResizeEvent *ev );
+
+private slots:
+ void showPreferences();
+
+private:
+ KPanelExtension *m_extension;
+};
+
+#endif
diff --git a/kicker/proxy/extensionproxy.cpp b/kicker/proxy/extensionproxy.cpp
new file mode 100644
index 000000000..0fbb341e5
--- /dev/null
+++ b/kicker/proxy/extensionproxy.cpp
@@ -0,0 +1,401 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTDHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#include <stdlib.h>
+
+#include <qstring.h>
+#include <qfile.h>
+#include <qxembed.h>
+
+#include <kapplication.h>
+#include <kglobal.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kcmdlineargs.h>
+#include <kdebug.h>
+#include <kpanelextension.h>
+#include <kaboutdata.h>
+#include <qfileinfo.h>
+#include <dcopclient.h>
+
+#include "appletinfo.h"
+#include "extensionproxy.h"
+#include "extensionproxy.moc"
+
+#include <X11/Xlib.h>
+
+
+static KCmdLineOptions options[] =
+{
+ { "+desktopfile", I18N_NOOP("The extension's desktop file"), 0 },
+ { "configfile <file>", I18N_NOOP("The config file to be used"), 0 },
+ { "callbackid <id>", I18N_NOOP("DCOP callback id of the extension container"), 0 },
+ KCmdLineLastOption
+};
+
+extern "C" KDE_EXPORT int kdemain( int argc, char ** argv )
+{
+ KAboutData aboutData( "extensionproxy", I18N_NOOP("Panel Extension Proxy")
+ , "v0.1.0"
+ ,I18N_NOOP("Panel extension proxy")
+ , KAboutData::License_BSD
+ , "(c) 2000, The KDE Developers");
+ KCmdLineArgs::init(argc, argv, &aboutData );
+ aboutData.addAuthor("Matthias Elter",0, "[email protected]");
+ aboutData.addAuthor("Matthias Ettrich",0, "[email protected]");
+ KApplication::addCmdLineOptions();
+ KCmdLineArgs::addCmdLineOptions(options); // Add our own options.
+
+ KApplication a;
+ a.disableSessionManagement();
+
+ KGlobal::dirs()->addResourceType("extensions", KStandardDirs::kde_default("data") +
+ "kicker/extensions");
+
+ // setup proxy object
+ ExtensionProxy proxy(0, "extensionproxywidget");
+
+ // parse cmdline args
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ // sanity check
+ if ( args->count() == 0 )
+ KCmdLineArgs::usage(i18n("No desktop file specified") );
+
+ // do we have a callback id?
+ if (args->getOption("callbackid").isNull()) {
+ kdError() << "Callback ID is null. " << endl;
+ exit(0);
+ }
+
+ // Perhaps we should use a konsole-like solution here (shell, list of args...)
+ QCString desktopfile = QCString( args->arg(0) );
+
+ // load extension DSO
+ proxy.loadExtension( desktopfile, args->getOption("configfile"));
+
+ // dock into our extension container
+ proxy.dock(args->getOption("callbackid"));
+
+ return a.exec();
+}
+
+ExtensionProxy::ExtensionProxy(QObject* parent, const char* name)
+ : QObject(parent, name)
+ , DCOPObject("ExtensionProxy")
+ , _info(0)
+ , _extension(0)
+{
+ // try to attach to DCOP server
+ if (!kapp->dcopClient()->attach()) {
+ kdError() << "Failed to attach to DCOP server." << endl;
+ exit(0);
+ }
+
+ if (!kapp->dcopClient()->registerAs("extension_proxy", true)) {
+ kdError() << "Failed to register at DCOP server." << endl;
+ exit(0);
+ }
+}
+
+ExtensionProxy::~ExtensionProxy()
+{
+ kapp->dcopClient()->detach();
+}
+
+void ExtensionProxy::loadExtension(const QCString& desktopFile, const QCString& configFile)
+{
+ QString df;
+
+ // try simple path first
+ QFileInfo finfo( desktopFile );
+ if ( finfo.exists() ) {
+ df = finfo.absFilePath();
+ } else {
+ // locate desktop file
+ df = KGlobal::dirs()->findResource("extensions", QString(desktopFile));
+ }
+
+ QFile file(df);
+ // does the config file exist?
+ if (df.isNull() || !file.exists()) {
+ kdError() << "Failed to locate extension desktop file: " << desktopFile << endl;
+ exit(0);
+ }
+
+ // create AppletInfo instance
+ _info = new AppletInfo(df);
+
+ // set the config file
+ if (!configFile.isNull())
+ _info->setConfigFile(configFile);
+
+ // load extension DSO
+ _extension = loadExtension(*_info);
+
+ // sanity check
+ if (!_extension) {
+ kdError() << "Failed to load extension: " << _info->library() << endl;
+ exit(0);
+ }
+
+ // connect updateLayout signal
+ connect(_extension, SIGNAL(updateLayout()), SLOT(slotUpdateLayout()));
+}
+
+KPanelExtension* ExtensionProxy::loadExtension(const AppletInfo& info)
+{
+ KLibLoader* loader = KLibLoader::self();
+ KLibrary* lib = loader->library(QFile::encodeName(info.library()));
+
+ if (!lib)
+ {
+ kdWarning() << "cannot open extension: " << info.library()
+ << " because of " << loader->lastErrorMessage() << endl;
+ return 0;
+ }
+
+ KPanelExtension* (*init_ptr)(QWidget *, const QString&);
+ init_ptr = (KPanelExtension* (*)(QWidget *, const QString&))lib->symbol( "init" );
+
+ if (!init_ptr)
+ {
+ kdWarning() << info.library() << " is not a kicker extension!" << endl;
+ return 0;
+ }
+
+ return init_ptr(0, info.configFile());
+}
+
+void ExtensionProxy::dock(const QCString& callbackID)
+{
+ kdDebug(1210) << "Callback ID: " << callbackID << endl;
+
+ _callbackID = callbackID;
+
+ // try to attach to DCOP server
+ DCOPClient* dcop = kapp->dcopClient();
+
+ dcop->setNotifications(true);
+ connect(dcop, SIGNAL(applicationRemoved(const QCString&)),
+ SLOT(slotApplicationRemoved(const QCString&)));
+
+ WId win;
+
+ // get docked
+ {
+ QCString replyType;
+ QByteArray data, replyData;
+ QDataStream dataStream( data, IO_WriteOnly );
+
+ int actions = 0;
+ if(_extension) actions = _extension->actions();
+ dataStream << actions;
+
+ int type = 0;
+ if (_extension) type = static_cast<int>(_extension->type());
+ dataStream << type;
+
+ // we use "call" to know whether it was sucessful
+
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ if ( !dcop->call(appname, _callbackID, "dockRequest(int,int)",
+ data, replyType, replyData ) )
+ {
+ kdError() << "Failed to dock into the panel." << endl;
+ exit(0);
+ }
+
+ QDataStream reply( replyData, IO_ReadOnly );
+ reply >> win;
+
+ }
+
+ if (win) {
+ if (_extension)
+ {
+ _extension->hide();
+ }
+ QXEmbed::initialize();
+ QXEmbed::embedClientIntoWindow( _extension, win );
+ }
+ else {
+ kdError() << "Failed to dock into the panel." << endl;
+ if(_extension) delete _extension;
+ exit(0);
+ }
+}
+
+bool ExtensionProxy::process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+{
+ if ( fun == "sizeHint(int,QSize)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int pos;
+ QSize maxSize;
+ dataStream >> pos;
+ dataStream >> maxSize;
+
+ QDataStream reply( replyData, IO_WriteOnly );
+ replyType = "QSize";
+
+ if(!_extension)
+ reply << maxSize;
+ else
+ reply << _extension->sizeHint((KPanelExtension::Position)pos, maxSize);
+
+ return true;
+ }
+ else if ( fun == "setPosition(int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int pos;
+ dataStream >> pos;
+
+ if(_extension) {
+ _extension->setPosition( (KPanelExtension::Position)pos );
+ }
+ return true;
+ }
+ else if ( fun == "setAlignment(int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int alignment;
+ dataStream >> alignment;
+
+ if(_extension) {
+ _extension->setAlignment( (KPanelExtension::Alignment)alignment );
+ }
+ return true;
+ }
+ else if ( fun == "setSize(int,int)" )
+ {
+ QDataStream dataStream( data, IO_ReadOnly );
+ int serializedSize;
+ int custom;
+ dataStream >> serializedSize;
+ dataStream >> custom;
+
+ if (_extension)
+ _extension->setSize(KPanelExtension::Size(serializedSize), custom);
+ return true;
+ }
+ else if ( fun == "removedFromPanel()" )
+ {
+ if(_extension) delete _extension;
+ exit(0);
+ return true;
+ }
+ else if ( fun == "about()" )
+ {
+ if(_extension) _extension->action( KPanelExtension::About );
+ return true;
+ }
+ else if ( fun == "help()" )
+ {
+ if(_extension) _extension->action( KPanelExtension::Help );
+ return true;
+ }
+ else if ( fun == "preferences()" )
+ {
+ if(_extension) _extension->action( KPanelExtension::Preferences );
+ return true;
+ }
+ else if ( fun == "reportBug()" )
+ {
+ if(_extension) _extension->action( KPanelExtension::ReportBug );
+ return true;
+ }
+ else if ( fun == "actions()" )
+ {
+ QDataStream reply( replyData, IO_WriteOnly );
+ int actions = 0;
+ if(_extension) actions = _extension->actions();
+ reply << actions;
+ replyType = "int";
+ return true;
+ }
+ else if ( fun == "preferedPosition()" )
+ {
+ QDataStream reply( replyData, IO_WriteOnly );
+ int pos = static_cast<int>(KPanelExtension::Bottom);
+ if(_extension) pos = static_cast<int>(_extension->preferedPosition());
+ reply << pos;
+ replyType = "int";
+ return true;
+ }
+ else if ( fun == "type()" )
+ {
+ QDataStream reply( replyData, IO_WriteOnly );
+ int type = 0;
+ if (_extension) type = static_cast<int>(_extension->type());
+ reply << type;
+ replyType = "int";
+ return true;
+ }
+ return false;
+}
+
+void ExtensionProxy::slotUpdateLayout()
+{
+ if(_callbackID.isNull()) return;
+
+ QByteArray data;
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ kapp->dcopClient()->send(appname, _callbackID, "updateLayout()", data);
+}
+
+void ExtensionProxy::slotApplicationRemoved(const QCString& appId)
+{
+ int screen_number = 0;
+ if (qt_xdisplay())
+ screen_number = DefaultScreen(qt_xdisplay());
+ QCString appname;
+ if (screen_number == 0)
+ appname = "kicker";
+ else
+ appname.sprintf("kicker-screen-%d", screen_number);
+
+ if(appId == appname) {
+ kdDebug(1210) << "Connection to kicker lost, shutting down" << endl;
+ kapp->quit();
+ }
+}
diff --git a/kicker/proxy/extensionproxy.h b/kicker/proxy/extensionproxy.h
new file mode 100644
index 000000000..e5b8ca96d
--- /dev/null
+++ b/kicker/proxy/extensionproxy.h
@@ -0,0 +1,61 @@
+/*****************************************************************
+
+Copyright (c) 2000 Matthias Elter <[email protected]>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+******************************************************************/
+
+#ifndef __extensionproxy_h__
+#define __extensionproxy_h__
+
+#include <qcstring.h>
+#include <qobject.h>
+
+#include <dcopobject.h>
+
+#include "appletinfo.h"
+
+class KPanelExtension;
+
+class ExtensionProxy : public QObject, DCOPObject
+{
+ Q_OBJECT
+
+public:
+ ExtensionProxy(QObject* parent, const char* name = 0);
+ ~ExtensionProxy();
+
+ void loadExtension(const QCString& desktopFile, const QCString& configFile);
+ KPanelExtension* loadExtension(const AppletInfo& info);
+ void dock(const QCString& callbackID);
+
+ bool process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData);
+
+protected slots:
+ void slotUpdateLayout();
+ void slotApplicationRemoved(const QCString&);
+
+private:
+ AppletInfo *_info;
+ KPanelExtension *_extension;
+ QCString _callbackID;
+};
+
+#endif