kwin/plugins.cpp
Daniel M. Duley de782ec37b Implemented plugins :) This was a huge pain in the arse because a) I am stupid
and it kept segfaulting because I wasn't releasing windows, and b) The plugins
didn't want to resolve anything in the kwin executable, only to the other
libs. I finally solved this by using -rdynamic in kwin's LDFLAGS, which I hope
is okay ;-)

svn path=/trunk/kdebase/kwin/; revision=37234
1999-12-24 01:36:47 +00:00

177 lines
4.7 KiB
C++

#include <kglobal.h>
#include <kconfig.h>
#include <kstddirs.h>
#include <kdesktopfile.h>
#include <ksimpleconfig.h>
#include <klocale.h>
#include <qdir.h>
#include <qfile.h>
#include "plugins.h"
#include "stdclient.h"
PluginMenu::PluginMenu(PluginMgr *manager, QWidget *parent, const char *name)
: QPopupMenu(parent, name)
{
connect(this, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
connect(this, SIGNAL(activated(int)), SLOT(slotActivated(int)));
mgr = manager;
}
void PluginMenu::slotAboutToShow()
{
clear();
fileList.clear();
insertItem(i18n("Standard"), 0);
idCount = 1;
QDir dir;
dir.setFilter(QDir::Files);
const QFileInfoList *list;
int count = KGlobal::dirs()->findDirs("data", "kwin").count();
if(count){
dir.setPath(KGlobal::dirs()->findDirs("data", "kwin")
[count > 1 ? 1 : 0]);
if(dir.exists()){
list = dir.entryInfoList();
if(list){
QFileInfoListIterator it(*list);
QFileInfo *fi;
for(; (fi = it.current()) != NULL; ++it){
if(KDesktopFile::isDesktopFile(fi->absFilePath()))
parseDesktop(fi);
}
}
}
if(count > 1){
dir.setPath(KGlobal::dirs()->findDirs("data", "kwin")[0]);
if(dir.exists()){
list = dir.entryInfoList();
if(list){
QFileInfoListIterator it(*list);
QFileInfo *fi;
for(; (fi = it.current()) != NULL; ++it){
if(KDesktopFile::isDesktopFile(fi->absFilePath()))
parseDesktop(fi);
}
}
}
}
}
}
void PluginMenu::parseDesktop(QFileInfo *fi)
{
QString tmpStr;
KSimpleConfig config(fi->absFilePath(), true);
config.setDesktopGroup();
tmpStr = config.readEntry("X-KDE-Library", "");
if(tmpStr.isEmpty()){
warning("KWin: Invalid plugin: %s", fi->absFilePath().latin1());
return;
}
fileList.append(tmpStr);
tmpStr = config.readEntry("Name", "");
if(tmpStr.isEmpty())
tmpStr = fi->baseName();
insertItem(tmpStr, idCount);
++idCount;
}
void PluginMenu::slotActivated(int id)
{
if(id == 0)
mgr->loadPlugin(QString::null);
else
mgr->loadPlugin(fileList[id-1]);
}
PluginMgr::PluginMgr()
: QObject()
{
alloc_ptr = NULL;
handle = 0;
QString pluginStr;
KConfig *config = KGlobal::config();
config->setGroup("Style");
pluginStr = config->readEntry("PluginLib", "standard");
if(pluginStr.isEmpty() || pluginStr == "standard")
return;
else
loadPlugin(pluginStr);
}
PluginMgr::~PluginMgr()
{
if(handle)
lt_dlclose(handle);
}
Client* PluginMgr::allocateClient(Workspace *ws, WId w)
{
if(alloc_ptr)
return(alloc_ptr(ws, w));
else
return(new StdClient(ws, w));
}
void PluginMgr::loadPlugin(QString nameStr)
{
static bool dlregistered = false;
static lt_dlhandle oldHandle = 0;
KConfig *config = KGlobal::config();
config->setGroup("Style");
config->writeEntry("PluginLib", nameStr);
oldHandle = handle;
if(nameStr.isNull()){
handle = 0;
alloc_ptr = NULL;
config->writeEntry("PluginLib", "standard");
}
else{
if(!dlregistered){
dlregistered = true;
lt_dlinit();
}
nameStr += ".la";
nameStr = KGlobal::dirs()->findResource("lib", nameStr);
if(!nameStr){
warning("KWin: cannot find client plugin.");
handle = 0;
alloc_ptr = NULL;
config->writeEntry("PluginLib", "standard");
}
else{
handle = lt_dlopen(nameStr.latin1());
if(!handle){
warning("KWin: cannot load client plugin %s.", nameStr.latin1());
handle = 0;
alloc_ptr = NULL;
config->writeEntry("PluginLib", "standard");
}
else{
lt_ptr_t alloc_func = lt_dlsym(handle, "allocate");
if(alloc_func)
alloc_ptr = (Client* (*)(Workspace *ws, WId w))alloc_func;
else{
warning("KWin: %s is not a KWin plugin.", nameStr.latin1());
lt_dlclose(handle);
handle = 0;
alloc_ptr = NULL;
config->writeEntry("PluginLib", "standard");
}
}
}
}
config->sync();
emit resetAllClients();
if(oldHandle)
lt_dlclose(oldHandle);
}