diff options
Diffstat (limited to 'kicker/proxy')
-rw-r--r-- | kicker/proxy/CMakeLists.txt | 41 | ||||
-rw-r--r-- | kicker/proxy/Makefile.am | 24 | ||||
-rw-r--r-- | kicker/proxy/appletproxy.cpp | 516 | ||||
-rw-r--r-- | kicker/proxy/appletproxy.h | 67 | ||||
-rw-r--r-- | kicker/proxy/extensiondebugger.cpp | 160 | ||||
-rw-r--r-- | kicker/proxy/extensiondebugger.h | 47 | ||||
-rw-r--r-- | kicker/proxy/extensionproxy.cpp | 401 | ||||
-rw-r--r-- | kicker/proxy/extensionproxy.h | 61 |
8 files changed, 1317 insertions, 0 deletions
diff --git a/kicker/proxy/CMakeLists.txt b/kicker/proxy/CMakeLists.txt new file mode 100644 index 000000000..a637d141e --- /dev/null +++ b/kicker/proxy/CMakeLists.txt @@ -0,0 +1,41 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/kicker/libkicker + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + +##### other data ################################ + +install( FILES DESTINATION ${DATA_INSTALL_DIR}/kicker/menuext ) + + +##### appletproxy (tdeinit) ##################### + +tde_add_tdeinit_executable( appletproxy AUTOMOC + SOURCES appletproxy.cpp + LINK kickermain-shared +) + + +##### extensionproxy (tdeinit) ################## + +tde_add_tdeinit_executable( extensionproxy AUTOMOC + SOURCES extensionproxy.cpp + LINK kickermain-shared +) diff --git a/kicker/proxy/Makefile.am b/kicker/proxy/Makefile.am new file mode 100644 index 000000000..0ed35216d --- /dev/null +++ b/kicker/proxy/Makefile.am @@ -0,0 +1,24 @@ +INCLUDES = -I$(srcdir)/../libkicker $(all_includes) + +bin_PROGRAMS = +noinst_PROGRAMS = extensiondebugger +lib_LTLIBRARIES = +tdeinit_LTLIBRARIES = appletproxy.la extensionproxy.la + +METASOURCES = AUTO + +appletproxy_la_LIBADD = $(LIB_TDEUI) ../libkicker/libkickermain.la +appletproxy_la_SOURCES = appletproxy.cpp +appletproxy_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) -module -avoid-version + +extensionproxy_la_LIBADD = $(LIB_TDEUI) ../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) $(LIB_QT) -lDCOP $(LIB_TDECORE) $(LIB_TDEUI) -ltdefx $(LIB_TDEIO) -ltdetexteditor + +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..ac2f969d8 --- /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 <tqstring.h> +#include <tqfile.h> +#include <tqobjectlist.h> +#include <qxembed.h> + +#include <tdeapplication.h> +#include <tdeglobal.h> +#include <klibloader.h> +#include <tdelocale.h> +#include <kstandarddirs.h> +#include <tdecmdlineargs.h> +#include <kdebug.h> +#include <tdemessagebox.h> +#include <kpanelapplet.h> +#include <tdeaboutdata.h> +#include <tqfileinfo.h> +#include <dcopclient.h> +#include <twin.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 TDECmdLineOptions 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 }, + TDECmdLineLastOption +}; + +extern "C" KDE_EXPORT int kdemain( int argc, char ** argv ) +{ + TDEAboutData aboutData( "kicker", I18N_NOOP("Panel applet proxy.") + , "v0.1.0" + ,I18N_NOOP("Panel applet proxy.") + , TDEAboutData::License_BSD + , "(c) 2000, The KDE Developers"); + TDECmdLineArgs::init(argc, argv, &aboutData ); + aboutData.addAuthor("Matthias Elter",0, "[email protected]"); + aboutData.addAuthor("Matthias Ettrich",0, "[email protected]"); + TDEApplication::addCmdLineOptions(); + TDECmdLineArgs::addCmdLineOptions(options); // Add our own options. + + TDEApplication a; + a.disableSessionManagement(); + + TDEGlobal::dirs()->addResourceType("applets", TDEStandardDirs::kde_default("data") + + "kicker/applets"); + + // setup proxy object + AppletProxy proxy(0, "appletproxywidget"); + + // parse cmdline args + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + if ( args->count() == 0 ) + TDECmdLineArgs::usage(i18n("No desktop file specified") ); + + // Perhaps we should use a konsole-like solution here (shell, list of args...) + TQString desktopfile( args->arg(0) ); + + // load applet DSO + if ( !TQFile::exists( desktopfile ) && + !desktopfile.endsWith( ".desktop" ) ) + desktopfile.append( ".desktop" ); + + if ( !TQFile::exists( desktopfile ) ) + desktopfile = locate( "applets", desktopfile ).latin1(); + + proxy.loadApplet( desktopfile, args->getOption("configfile")); + + // dock into our applet container + TQCString callbackid = args->getOption( "callbackid"); + if ( callbackid.isEmpty() ) + proxy.showStandalone(); + else + proxy.dock(args->getOption("callbackid")); + + return a.exec(); +} + +AppletProxy::AppletProxy(TQObject* parent, const char* name) + : TQObject(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) == 0) { + 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 = TQPixmap(); +} + +AppletProxy::~AppletProxy() +{ + kapp->dcopClient()->detach(); + delete _info; + delete _applet; +} + +void AppletProxy::loadApplet(const TQString& desktopFile, const TQString& configFile) +{ + TQString df; + + // try simple path first + TQFileInfo finfo( desktopFile ); + if ( finfo.exists() ) { + df = finfo.absFilePath(); + } else { + // locate desktop file + df = TDEGlobal::dirs()->findResource("applets", desktopFile); + } + + TQFile 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, TQT_SIGNAL(updateLayout()), TQT_SLOT(slotUpdateLayout())); + // connect requestFocus signal + connect(_applet, TQT_SIGNAL(requestFocus()), TQT_SLOT(slotRequestFocus())); +} + +KPanelApplet* AppletProxy::loadApplet(const AppletInfo& info) +{ + KLibLoader* loader = KLibLoader::self(); + KLibrary* lib = loader->library(TQFile::encodeName(info.library())); + + if (!lib) + { + kdWarning() << "cannot open applet: " << info.library() + << " because of " << loader->lastErrorMessage() << endl; + return 0; + } + + KPanelApplet* (*init_ptr)(TQWidget *, const TQString&); + init_ptr = (KPanelApplet* (*)(TQWidget *, const TQString&))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(TQWidget* widget) +{ + widget->repaint(); + + const TQObjectList children = widget->childrenListObject(); + + if (children.isEmpty()) + { + return; + } + + TQObjectList::iterator it = children.begin(); + for (; it != children.end(); ++it) + { + TQWidget *w = dynamic_cast<TQWidget*>(*it); + if (w) + { + repaintApplet(w); + } + } +} + +void AppletProxy::dock(const TQCString& callbackID) +{ + kdDebug(1210) << "Callback ID: " << callbackID << endl; + + _callbackID = callbackID; + + // try to attach to DCOP server + DCOPClient* dcop = kapp->dcopClient(); + + dcop->setNotifications(true); + connect(dcop, TQT_SIGNAL(applicationRemoved(const TQCString&)), + TQT_SLOT(slotApplicationRemoved(const TQCString&))); + + WId win; + + // get docked + { + TQCString replyType; + TQByteArray data, replyData; + TQDataStream 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 (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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); + } + + TQDataStream 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 TQCString &fun, const TQByteArray &data, + TQCString& replyType, TQByteArray &replyData) +{ + if ( fun == "widthForHeight(int)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + int height; + dataStream >> height; + TQDataStream reply( replyData, IO_WriteOnly ); + replyType = "int"; + + if (!_applet) + reply << height; + else + reply << _applet->widthForHeight(height); + + return true; + } + else if ( fun == "heightForWidth(int)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + int width; + dataStream >> width; + TQDataStream reply( replyData, IO_WriteOnly ); + replyType = "int"; + + if(!_applet) + reply << width; + else + reply << _applet->heightForWidth(width); + + return true; + } + else if ( fun == "setDirection(int)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + int dir; + dataStream >> dir; + + if(_applet) { + _applet->setPosition(directionToPosition(dir)); + } + return true; + } + else if ( fun == "setAlignment(int)" ) + { + TQDataStream 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()" ) + { + TQDataStream reply( replyData, IO_WriteOnly ); + int actions = 0; + if(_applet) actions = _applet->actions(); + reply << actions; + replyType = "int"; + return true; + } + else if ( fun == "type()" ) + { + TQDataStream 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(TQPixmap)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + dataStream >> _bg; + if(_applet) + if ( _bg.isNull() ) { // no transparency + _applet->unsetPalette(); + _applet->repaint(); + } + else { //transparency + _applet->blockSignals(true); + _applet->setBackgroundMode(TQt::FixedPixmap); + _applet->setPaletteBackgroundPixmap(_bg); + repaintApplet(_applet); + _applet->blockSignals(false); + } + return true; + } + return false; +} + +void AppletProxy::slotUpdateLayout() +{ + if(_callbackID.isNull()) return; + + TQByteArray data; + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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; + + TQByteArray data; + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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 TQCString& appId) +{ + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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..4c504022f --- /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 <tqcstring.h> +#include <tqobject.h> + +#include <dcopobject.h> + +#include "appletinfo.h" + +class KPanelApplet; +class KickerPluginManager; + +class AppletProxy : public TQObject, DCOPObject +{ + Q_OBJECT + +public: + AppletProxy(TQObject* parent, const char* name = 0); + ~AppletProxy(); + + void loadApplet(const TQString& desktopFile, const TQString& configFile); + KPanelApplet* loadApplet(const AppletInfo& info); + void dock(const TQCString& callbackID); + void showStandalone(); + + bool process(const TQCString &fun, const TQByteArray &data, + TQCString& replyType, TQByteArray &replyData); + +protected slots: + void slotUpdateLayout(); + void slotRequestFocus(); + void slotApplicationRemoved(const TQCString&); + +private: + void repaintApplet(TQWidget* widget); + + AppletInfo *_info; + KPanelApplet *_applet; + TQCString _callbackID; + TQPixmap _bg; +}; + +#endif diff --git a/kicker/proxy/extensiondebugger.cpp b/kicker/proxy/extensiondebugger.cpp new file mode 100644 index 000000000..c210e7b9e --- /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 <tqfile.h> +#include <tqlayout.h> +#include <tqpushbutton.h> + +#include <tdeapplication.h> +#include <tdeglobal.h> +#include <klibloader.h> +#include <tdelocale.h> +#include <kstandarddirs.h> +#include <tdecmdlineargs.h> +#include <kdebug.h> +#include <kpanelextension.h> +#include <tdeaboutdata.h> +#include <tqfileinfo.h> + +#include "appletinfo.h" +#include "extensiondebugger.h" +#include "extensiondebugger.moc" + + + +static TDECmdLineOptions options[] = +{ + { "+desktopfile", I18N_NOOP("The extensions desktop file"), 0 }, + TDECmdLineLastOption +}; + +KPanelExtension* loadExtension(const AppletInfo& info) +{ + KLibLoader* loader = KLibLoader::self(); + KLibrary* lib = loader->library(TQFile::encodeName(info.library())); + + if (!lib) + { + kdWarning() << "cannot open extension: " << info.library() + << " because of " << loader->lastErrorMessage() << endl; + return 0; + } + + KPanelExtension* (*init_ptr)(TQWidget *, const TQString&); + init_ptr = (KPanelExtension* (*)(TQWidget *, const TQString&))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 ) +{ + TDEAboutData aboutData( "extensionproxy", I18N_NOOP("Panel extension proxy.") + , "v0.1.0" + ,I18N_NOOP("Panel extension proxy.") + , TDEAboutData::License_BSD + , "(c) 2000, The KDE Developers"); + TDECmdLineArgs::init(argc, argv, &aboutData ); + aboutData.addAuthor("Matthias Elter",0, "[email protected]"); + aboutData.addAuthor("Matthias Ettrich",0, "[email protected]"); + TDEApplication::addCmdLineOptions(); + TDECmdLineArgs::addCmdLineOptions(options); // Add our own options. + + TDEApplication a; + a.disableSessionManagement(); + + TDEGlobal::dirs()->addResourceType("extensions", TDEStandardDirs::kde_default("data") + + "kicker/extensions"); + + TQString df; + + // parse cmdline args + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + // sanity check + if ( args->count() == 0 ) + TDECmdLineArgs::usage(i18n("No desktop file specified") ); + + + TQCString desktopFile = TQCString( args->arg(0) ); + + // try simple path first + TQFileInfo finfo( desktopFile ); + if ( finfo.exists() ) { + df = finfo.absFilePath(); + } else { + // locate desktop file + df = TDEGlobal::dirs()->findResource("extensions", TQString(desktopFile)); + } + + // does the config file exist? + if (!TQFile::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(); + + TQObject::connect( &a, TQT_SIGNAL( lastWindowClosed() ), &a, TQT_SLOT( quit() ) ); + + int result = a.exec(); + + delete extension; + return result; +} + +ExtensionContainer::ExtensionContainer( KPanelExtension *extension, TQWidget *parent, const char *name ) + : TQWidget( parent, name ), m_extension( extension ) +{ + ( new TQVBoxLayout( this ) )->setAutoAdd( true ); + + TQPushButton *configButton = new TQPushButton( i18n( "Configure..." ), this ); + connect( configButton, TQT_SIGNAL( clicked() ), + this, TQT_SLOT( showPreferences() ) ); + + m_extension->reparent( this, TQPoint( 0, 0 ) ); +} + +void ExtensionContainer::resizeEvent( TQResizeEvent * ) +{ + 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..0f4719b9f --- /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 TQWidget +{ + Q_OBJECT + +public: + ExtensionContainer(KPanelExtension *extension, TQWidget* parent = 0, const char* name = 0); + +protected: + void resizeEvent( TQResizeEvent *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..13c40e67b --- /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 <tqstring.h> +#include <tqfile.h> +#include <qxembed.h> + +#include <tdeapplication.h> +#include <tdeglobal.h> +#include <klibloader.h> +#include <tdelocale.h> +#include <kstandarddirs.h> +#include <tdecmdlineargs.h> +#include <kdebug.h> +#include <kpanelextension.h> +#include <tdeaboutdata.h> +#include <tqfileinfo.h> +#include <dcopclient.h> + +#include "appletinfo.h" +#include "extensionproxy.h" +#include "extensionproxy.moc" + +#include <X11/Xlib.h> + + +static TDECmdLineOptions 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 }, + TDECmdLineLastOption +}; + +extern "C" KDE_EXPORT int kdemain( int argc, char ** argv ) +{ + TDEAboutData aboutData( "extensionproxy", I18N_NOOP("Panel Extension Proxy") + , "v0.1.0" + ,I18N_NOOP("Panel extension proxy") + , TDEAboutData::License_BSD + , "(c) 2000, The KDE Developers"); + TDECmdLineArgs::init(argc, argv, &aboutData ); + aboutData.addAuthor("Matthias Elter",0, "[email protected]"); + aboutData.addAuthor("Matthias Ettrich",0, "[email protected]"); + TDEApplication::addCmdLineOptions(); + TDECmdLineArgs::addCmdLineOptions(options); // Add our own options. + + TDEApplication a; + a.disableSessionManagement(); + + TDEGlobal::dirs()->addResourceType("extensions", TDEStandardDirs::kde_default("data") + + "kicker/extensions"); + + // setup proxy object + ExtensionProxy proxy(0, "extensionproxywidget"); + + // parse cmdline args + TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(); + + // sanity check + if ( args->count() == 0 ) + TDECmdLineArgs::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...) + TQCString desktopfile = TQCString( 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(TQObject* parent, const char* name) + : TQObject(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) == 0) { + kdError() << "Failed to register at DCOP server." << endl; + exit(0); + } +} + +ExtensionProxy::~ExtensionProxy() +{ + kapp->dcopClient()->detach(); +} + +void ExtensionProxy::loadExtension(const TQCString& desktopFile, const TQCString& configFile) +{ + TQString df; + + // try simple path first + TQFileInfo finfo( desktopFile ); + if ( finfo.exists() ) { + df = finfo.absFilePath(); + } else { + // locate desktop file + df = TDEGlobal::dirs()->findResource("extensions", TQString(desktopFile)); + } + + TQFile 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, TQT_SIGNAL(updateLayout()), TQT_SLOT(slotUpdateLayout())); +} + +KPanelExtension* ExtensionProxy::loadExtension(const AppletInfo& info) +{ + KLibLoader* loader = KLibLoader::self(); + KLibrary* lib = loader->library(TQFile::encodeName(info.library())); + + if (!lib) + { + kdWarning() << "cannot open extension: " << info.library() + << " because of " << loader->lastErrorMessage() << endl; + return 0; + } + + KPanelExtension* (*init_ptr)(TQWidget *, const TQString&); + init_ptr = (KPanelExtension* (*)(TQWidget *, const TQString&))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 TQCString& callbackID) +{ + kdDebug(1210) << "Callback ID: " << callbackID << endl; + + _callbackID = callbackID; + + // try to attach to DCOP server + DCOPClient* dcop = kapp->dcopClient(); + + dcop->setNotifications(true); + connect(dcop, TQT_SIGNAL(applicationRemoved(const TQCString&)), + TQT_SLOT(slotApplicationRemoved(const TQCString&))); + + WId win; + + // get docked + { + TQCString replyType; + TQByteArray data, replyData; + TQDataStream 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 (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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); + } + + TQDataStream 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 TQCString &fun, const TQByteArray &data, + TQCString& replyType, TQByteArray &replyData) +{ + if ( fun == "sizeHint(int,TQSize)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + int pos; + TQSize maxSize; + dataStream >> pos; + dataStream >> maxSize; + + TQDataStream reply( replyData, IO_WriteOnly ); + replyType = "TQSize"; + + if(!_extension) + reply << maxSize; + else + reply << _extension->sizeHint((KPanelExtension::Position)pos, maxSize); + + return true; + } + else if ( fun == "setPosition(int)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + int pos; + dataStream >> pos; + + if(_extension) { + _extension->setPosition( (KPanelExtension::Position)pos ); + } + return true; + } + else if ( fun == "setAlignment(int)" ) + { + TQDataStream dataStream( data, IO_ReadOnly ); + int alignment; + dataStream >> alignment; + + if(_extension) { + _extension->setAlignment( (KPanelExtension::Alignment)alignment ); + } + return true; + } + else if ( fun == "setSize(int,int)" ) + { + TQDataStream 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()" ) + { + TQDataStream reply( replyData, IO_WriteOnly ); + int actions = 0; + if(_extension) actions = _extension->actions(); + reply << actions; + replyType = "int"; + return true; + } + else if ( fun == "preferedPosition()" ) + { + TQDataStream 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()" ) + { + TQDataStream 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; + + TQByteArray data; + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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 TQCString& appId) +{ + int screen_number = 0; + if (tqt_xdisplay()) + screen_number = DefaultScreen(tqt_xdisplay()); + TQCString 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..88bc0a325 --- /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 <tqcstring.h> +#include <tqobject.h> + +#include <dcopobject.h> + +#include "appletinfo.h" + +class KPanelExtension; + +class ExtensionProxy : public TQObject, DCOPObject +{ + Q_OBJECT + +public: + ExtensionProxy(TQObject* parent, const char* name = 0); + ~ExtensionProxy(); + + void loadExtension(const TQCString& desktopFile, const TQCString& configFile); + KPanelExtension* loadExtension(const AppletInfo& info); + void dock(const TQCString& callbackID); + + bool process(const TQCString &fun, const TQByteArray &data, + TQCString& replyType, TQByteArray &replyData); + +protected slots: + void slotUpdateLayout(); + void slotApplicationRemoved(const TQCString&); + +private: + AppletInfo *_info; + KPanelExtension *_extension; + TQCString _callbackID; +}; + +#endif |