[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Re: KIconLoader improvements: icon server
From: Gustavo Pichorim Boiko <gustavo.boiko () kdemail ! net>
Date: 2005-06-14 14:03:25
Message-ID: 200506141103.28049.gustavo.boiko () kdemail ! net
[Download RAW message or body]
[Attachment #2 (multipart/mixed)]
Oops, sorry, I have attached the wrong patch file...
This time is the right one.
Sorry about that.
Cheers
--
Gustavo Pichorim Boiko
-----------------------------------------------------
KDE Developer Ciência da Computação - UFPR
Mandriva Labs gustavo . boiko @ kdemail . net
-----------------------------------------------------
["kdelibs-iconserver.patch" (text/x-diff)]
Index: kdecore/iconserver/pixmap.cpp
===================================================================
--- kdecore/iconserver/pixmap.cpp (revisão 0)
+++ kdecore/iconserver/pixmap.cpp (revisão 0)
@@ -0,0 +1,75 @@
+/****************************************************************************
+
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#include <kcmdlineargs.h>
+#include <kapplication.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <dcopclient.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <X11/Xlib.h>
+
+static const KCmdLineOptions options[] =
+{
+ { "+[handle]", I18N_NOOP("The pixmap handle"), 0 },
+ { "+[size]", I18N_NOOP("The icon size"), "16" },
+ KCmdLineLastOption // End of options.
+};
+
+int main( int argc, char* argv[] )
+{
+ KCmdLineArgs::init( argc, argv, "a", "b", "c" );
+
+
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KApplication app;
+ app.dcopClient()->attach();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ int handle = 0;
+ int size = 32;
+ if (args->count() >= 1)
+ handle = QString(args->arg(0)).toInt();
+ if (args->count() >=2)
+ size = QString(args->arg(1)).toInt();
+
+ QPixmap pm(size,size);
+ Drawable src = handle;
+ XGCValues values;
+ GC gc = XCreateGC(qt_xdisplay(), src, 0, &values);
+ XCopyArea(qt_xdisplay(), src, pm.handle(), gc, 0, 0, size, size, 0, 0);
+ QWidget w;
+ w.setGeometry( 10, 10, 100, 100 );
+ QLabel l( &w );
+ l.resize( pm.width(), pm.height());
+ l.setPixmap( pm );
+ l.move( 10, 10 );
+ w.show();
+ app.setMainWidget( &w );
+ return app.exec();
+}
Index: kdecore/iconserver/kiconserver.h
===================================================================
--- kdecore/iconserver/kiconserver.h (revisão 0)
+++ kdecore/iconserver/kiconserver.h (revisão 0)
@@ -0,0 +1,80 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifndef __KICONSERVER_H
+#define __KICONSERVER_H
+
+#include <kdedmodule.h>
+#include <qcstring.h>
+#include <qstring.h>
+#include <qstringlist.h>
+
+#include <kiconserverclient_p.h>
+
+#include <kdelibs_export.h>
+
+#include <X11/Xlib.h>
+
+#define appref_h "appref.h"
+#include appref_h // avoid including it in stub generated from this .h file
+#undef appref_h
+
+class KDECORE_EXPORT KIconServer : public KDEDModule
+{
+ Q_OBJECT
+ K_DCOP
+k_dcop:
+ bool serverRunning();
+ ASYNC newIcons( KIconSendDataList icons ); // means also refIcons
+ ASYNC refIcons( QValueList< QCString > keys );
+ ASYNC derefIcons( QValueList< QCString > keys );
+ QStringList availableIcons();
+public:
+ KIconServer(const QCString &obj);
+ ~KIconServer();
+private slots:
+ void flushIcons();
+ void ageIcons();
+ void app_reg( const QCString& );
+ void app_rem( const QCString& );
+ void app_ren( const QCString&, const QCString& );
+private:
+ void createIconsFile( const QString& path_P );
+ bool readOldIconsFile( const QString& path_P );
+ int makeKeySizes();
+ bool publishIcons( const QString& path_P, int mmap_size_P );
+ void defaultIcons();
+ void addIcon( const QString& name, int group, int size, int state );
+ bool splitKey( const QString& key, QString& name, int& size ) const;
+ void app_ref_deref( const QCString& app_id_P,
+ const QValueList< QCString >& keys_P, bool ref_P );
+ QTimer update_timer;
+ QTimer age_timer;
+ int old_icons_count; // number of icons scheduled for removal ( no longer published )
+ IconsMap icons;
+ typedef QValueList< KIconAppRef > AppRefList;
+ AppRefList app_ref_list;
+};
+
+#endif
Index: kdecore/iconserver/kiconserver.desktop
===================================================================
--- kdecore/iconserver/kiconserver.desktop (revisão 0)
+++ kdecore/iconserver/kiconserver.desktop (revisão 0)
@@ -0,0 +1,13 @@
+[Desktop Entry]
+Encoding=UTF-8
+Type=Service
+
+ServiceTypes=KDEDModule
+X-KDE-ModuleType=Library
+X-KDE-Library=kiconserver
+X-KDE-Factory=kiconserver
+X-KDE-Kded-autoload=false
+X-KDE-Kded-load-on-demand=true
+
+Name=KDE Icon Server
+Comment=A server providing icons for applications
Index: kdecore/iconserver/appref.h
===================================================================
--- kdecore/iconserver/appref.h (revisão 0)
+++ kdecore/iconserver/appref.h (revisão 0)
@@ -0,0 +1,120 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifndef __APP_REF_H
+#define __APP_REF_H
+
+#include <qcstring.h>
+
+#include "kicondata.h"
+
+struct KIconAppRefData
+{
+ QCString key;
+ int count;
+ bool operator==( const KIconAppRefData& r_P ) const;
+ bool operator<( const KIconAppRefData& r_P ) const;
+ bool operator>( const KIconAppRefData& r_P ) const;
+ bool operator!=( const KIconAppRefData& r_P ) const;
+ bool operator<=( const KIconAppRefData& r_P ) const;
+ bool operator>=( const KIconAppRefData& r_P ) const;
+ static int cmp( const QCString& l_P, const QCString& r_P );
+};
+
+class KIconAppRef
+{
+public:
+ KIconAppRef( const QCString& app_id_P );
+ KIconAppRef(); // only for QValueList
+ KIconAppRef( const KIconAppRef& src_P ); // only for QValueList
+ ~KIconAppRef();
+ void ref( const QValueList< QCString > keys_P );
+ void deref( const QValueList< QCString > keys_P );
+ void free( IconsMap& icons );
+ void change_app_id( const QCString& app_id_P );
+ const QCString& app_id() const;
+private:
+ void resize( unsigned int new_size_P );
+ QCString _app_id;
+ mutable KIconAppRefData* arr; // mutable only because of KIconAppRef( const KIconAppRef& \
); + int used_size;
+ int allocated_size;
+};
+
+// Inline
+
+inline
+KIconAppRef::KIconAppRef()
+{
+}
+
+inline
+void KIconAppRef::change_app_id( const QCString& app_id_P )
+{
+ _app_id = app_id_P;
+}
+
+inline
+const QCString& KIconAppRef::app_id() const
+{
+ return _app_id;
+}
+
+inline
+bool KIconAppRefData::operator==( const KIconAppRefData& r_P ) const
+{
+ return cmp( key, r_P.key ) == 0;
+}
+
+inline
+bool KIconAppRefData::operator<( const KIconAppRefData& r_P ) const
+{
+ return cmp( key, r_P.key ) < 0;
+}
+
+inline
+bool KIconAppRefData::operator>( const KIconAppRefData& r_P ) const
+{
+ return cmp( key, r_P.key ) > 0;
+}
+
+inline
+bool KIconAppRefData::operator!=( const KIconAppRefData& r_P ) const
+{
+ return cmp( key, r_P.key ) != 0;
+}
+
+inline
+bool KIconAppRefData::operator<=( const KIconAppRefData& r_P ) const
+{
+ return cmp( key, r_P.key ) <= 0;
+}
+
+inline
+bool KIconAppRefData::operator>=( const KIconAppRefData& r_P ) const
+{
+ return cmp( key, r_P.key ) >= 0;
+}
+
+#endif
Index: kdecore/iconserver/kicondata.h
===================================================================
--- kdecore/iconserver/kicondata.h (revisão 0)
+++ kdecore/iconserver/kicondata.h (revisão 0)
@@ -0,0 +1,96 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifndef __KICONDATA_H
+#define __KICONDATA_H
+
+#include <qcstring.h>
+
+#include <kiconserverclient_p.h>
+
+struct KIconData
+{
+public:
+ KIconData();
+ KIconData( const QPixmap& pm_P, int group_P, int state_P, int usage_P );
+ bool ref(); // true if was old before ref()
+ bool deref(); // false if became unused
+ bool in_use() const;
+ bool age(); // return true if became old
+ bool old() const; // scheduled for removal
+ bool too_old() const;
+ KIconDataPixmap pixmap;
+ int group;
+ int state;
+ int key_pos; // used only when saving
+private:
+ int usage; // >0 = refcount, <0 = age
+};
+
+typedef QMap< QCString, KIconData > IconsMap;
+
+// Inline
+
+inline
+KIconData::KIconData()
+{
+}
+
+inline
+KIconData::KIconData( const QPixmap& pm_P, int group_P, int state_P, int usage_P )
+ : pixmap( pm_P ), group( group_P ), state( state_P ), usage( usage_P )
+{
+}
+
+inline
+bool KIconData::deref()
+{
+ return usage > 0 && --usage == 0;
+}
+
+inline
+bool KIconData::in_use() const
+{
+ return usage > 0;
+}
+
+inline
+bool KIconData::age()
+{
+ return usage <= 0 && --usage == -5; // <= -5 = old
+}
+
+inline
+bool KIconData::old() const
+{
+ return usage <= -5; // < -5 = old
+}
+
+inline
+bool KIconData::too_old() const
+{
+ return usage <= -10; // <= - 10 = too old
+}
+
+#endif
Index: kdecore/iconserver/icontest.cpp
===================================================================
--- kdecore/iconserver/icontest.cpp (revisão 0)
+++ kdecore/iconserver/icontest.cpp (revisão 0)
@@ -0,0 +1,137 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#include <kcmdlineargs.h>
+#include <kapplication.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+#include <kiconloader.h>
+#include <kglobal.h>
+#include <dcopclient.h>
+#include <qlabel.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kiconpixmap_p.h>
+#include <qdatetime.h>
+#include <qfile.h>
+
+static const KCmdLineOptions options[] =
+{
+ { "f", 0, 0 },
+ { "file <icon list file>", I18N_NOOP("A file with a list of icons/sizes to be loaded"), 0 \
}, + { "+[icon]", I18N_NOOP("The icon to be loaded"), "about_kde" },
+ { "+[size]", I18N_NOOP("The icon size"), "16" },
+ KCmdLineLastOption // End of options.
+};
+
+struct Icon
+{
+ int size;
+ QString name;
+};
+
+typedef QValueList<struct Icon> IconList;
+
+IconList getIcons(const QString& file)
+{
+ IconList list;
+
+ QFile f(file);
+
+ if (!f.open(IO_ReadOnly))
+ return list;
+ QTextStream stream(&f);
+ QString iconString;
+ struct Icon icon;
+ while ( !(iconString = stream.readLine()).isNull() )
+ {
+ icon.name = iconString.section(" ", 0, 0);
+ icon.size = iconString.section(" ", 1, 1).toInt();
+
+ list.append(icon);
+ }
+ return list;
+}
+
+int main( int argc, char* argv[] )
+{
+ KCmdLineArgs::init( argc, argv, "a", "b", "c" );
+ KCmdLineArgs::addCmdLineOptions(options);
+
+ KApplication app;
+ app.dcopClient()->attach();
+
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+
+ QPixmap pm;
+
+ QWidget w;
+ w.setGeometry( 10, 10, 100, 100 );
+ QLabel l( &w );
+
+
+ if (args->isSet("file"))
+ {
+ IconList list = getIcons(args->getOption("file"));
+
+ QTime time;
+ int ms, total = 0;
+
+ IconList::iterator it;
+ KIconLoader *loader = kapp->iconLoader();
+ for ( it = list.begin(); it != list.end(); ++it )
+ {
+ time.start();
+ pm = loader->loadIcon( (*it).name, KIcon::NoGroup, (*it).size );
+ ms = time.elapsed();
+ total += ms;
+ }
+ time.setHMS(0,0,0);
+ time.addMSecs(total);
+ kdDebug() << "Time for loading " << list.count() << " icons: " << total << " ms (" << \
time.toString() << ")" << endl; + }
+ else
+ {
+ QString icon = "about_kde";
+ int size = 32;
+
+
+ if (args->count() >= 1)
+ icon = args->arg(0);
+ if (args->count() >=2)
+ size = QString(args->arg(1)).toInt();
+ QTime time;
+ int ms;
+ time.start();
+ pm = kapp->iconLoader()->loadIcon( icon, KIcon::NoGroup, size );
+ ms = time.elapsed();
+ kdDebug() << "Time for loading the icon: " << ms << " ms" << endl;
+ }
+ l.resize( pm.width(), pm.height());
+ l.setPixmap( pm );
+ l.move( 10, 10 );
+ w.show();
+ app.setMainWidget( &w );
+ return app.exec();
+}
Index: kdecore/iconserver/Makefile.am
===================================================================
--- kdecore/iconserver/Makefile.am (revisão 0)
+++ kdecore/iconserver/Makefile.am (revisão 0)
@@ -0,0 +1,24 @@
+INCLUDES = $(all_includes) -I$(srcdir)/.. $(KDEINIT_XFT_INCLUDES)
+
+noinst_HEADERS = kiconserver.h appref.h kicondata.h
+
+kde_module_LTLIBRARIES = kded_kiconserver.la
+
+kded_kiconserver_la_SOURCES = kiconserver.cpp kiconserver.skel appref.cpp
+kded_kiconserver_la_LDFLAGS = $(all_libraries) -module -avoid-version
+kded_kiconserver_la_LIBADD = $(LIB_KDECORE)
+
+METASOURCES = AUTO
+
+servicesdir = $(kde_servicesdir)/kded
+services_DATA = kiconserver.desktop
+
+check_PROGRAMS = icontest pixmap
+
+icontest_SOURCES = icontest.cpp
+icontest_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+icontest_LDADD = $(LIB_KDECORE)
+
+pixmap_SOURCES = pixmap.cpp
+pixmap_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+pixmap_LDADD = $(LIB_KDECORE)
Index: kdecore/iconserver/kiconserver.cpp
===================================================================
--- kdecore/iconserver/kiconserver.cpp (revisão 0)
+++ kdecore/iconserver/kiconserver.cpp (revisão 0)
@@ -0,0 +1,477 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef HAVE_MMAP
+#error This works only with HAVE_MMAP
+#endif
+
+#include "kiconserver.h"
+
+#include <kiconserverclient_p.h>
+
+#include <qfile.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+#include <kglobal.h>
+#include <kstandarddirs.h>
+#include <ksavefile.h>
+#include <kiconloader.h>
+#include <kicontheme.h>
+#include <kdebug.h>
+#include <kapplication.h>
+#include <dcopclient.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+// CHECKME handling of NO_XRENDER is missing here
+
+KIconServer::KIconServer(const QCString &obj)
+ : KDEDModule(obj)
+{
+ kdDebug( 179 ) << k_funcinfo << "starting up" << endl;
+ ( void ) KGlobal::iconLoader(); // trigger iconloader ( and iconserverclient ) creation
+
+ kapp->dcopClient()->setNotifications( true );
+
+ connect( kapp->dcopClient(), SIGNAL( applicationRegistered( const QCString& )),
+ SLOT( app_reg( const QCString& )));
+ connect( kapp->dcopClient(), SIGNAL( applicationRemoved( const QCString& )),
+ SLOT( app_rem( const QCString& )));
+ connect( kapp->dcopClient(), SIGNAL( applicationRenamed( const QCString&, const QCString& \
)), + SLOT( app_ren( const QCString&, const QCString& )));
+ connect( &update_timer, SIGNAL( timeout()), this, SLOT( flushIcons()));
+ connect( &age_timer, SIGNAL( timeout()), this, SLOT( ageIcons()));
+ old_icons_count = 0;
+ age_timer.start( 20000 ); // 20s * 5 = 100s before becomes old and another 100s before \
removed + // CHECKME search the newest kiconsfile and read from it the list for loading
+ QString path = KGlobal::dirs()->saveLocation("tmp") + "kiconsfile-" + getenv( "DISPLAY" );
+ if( !QFile::exists( path ) || !readOldIconsFile( path ))
+ defaultIcons();
+ createIconsFile( path );
+ kdDebug(179) << k_funcinfo << "running" << endl;
+}
+
+KIconServer::~KIconServer()
+{
+}
+
+bool KIconServer::serverRunning()
+{
+ return true;
+}
+
+bool KIconServer::readOldIconsFile( const QString& path_P )
+{ // from KIconLoader
+ QFile* icons_file = new QFile( path_P );
+ if( !icons_file->open( IO_ReadOnly ))
+ {
+ delete icons_file;
+ kdDebug(179) << "No old icons file" << endl;
+ return false;
+ }
+ int mmap_size = icons_file->size();
+ KIconsFile* icons_mmap = reinterpret_cast< KIconsFile* >( mmap( 0, mmap_size,
+ PROT_READ, MAP_PRIVATE, icons_file->handle(), 0 ));
+ if( icons_mmap == NULL )
+ {
+ delete icons_file;
+ return false;
+ }
+ if( icons_mmap->version != KICONSFILEVERSION )
+ {
+ munmap( (char*) icons_mmap, mmap_size );
+ delete icons_file;
+ return false;
+ }
+ for( int i = 0;
+ i < icons_mmap->count;
+ ++i )
+ {
+ KIconFileEntry& data = icons_mmap->entries[ i ];
+ const char* key = reinterpret_cast< char* >( icons_mmap ) + data.key_ref;
+ QString name;
+ int size;
+ if( !splitKey( QString::fromUtf8( key ), name, size ))
+ continue;
+ // CHECKME try to create one big image from all image and create one big pixmap from \
it ? + KIconDataPixmap pm = KGlobal::iconLoader()->loadIcon( "@force@" + name,
+ KIcon::Group(data.group), size, data.state, NULL, true );
+ if( pm.isNull())
+ {
+ kdDebug( 179 ) << "cannot load old icon " << key << endl;
+ continue;
+ }
+ if( pm.width() != pm.height())
+ {
+ kdWarning( 179 ) << "icon \"" << key << "\" has size " << pm.width()
+ << "x" << pm.height() << endl;
+ continue;
+ }
+ kdDebug( 179 ) << "reading icon from old file \"" << key << "\" ("
+ << pm.handle() << "/" << pm.maskHandle() << "/" << pm.alphaHandle() << ")" << \
endl; + icons[ key ] = KIconData( pm, data.group, data.state, 0 );
+ }
+ munmap( (char*) icons_mmap, mmap_size );
+ delete icons_file;
+ return true;
+}
+
+bool KIconServer::splitKey( const QString& key, QString& name, int& size ) const
+{
+ QString k = key.mid( 6 ); // strip leading "$kico_"
+ int pos = k.find( ':' );
+ if( pos < 1 )
+ return false;
+ name = k.left( pos ); // name
+ k = k.mid( pos + 1 );
+ pos = k.find( '_' );
+ if( pos < 1 )
+ return false;
+ size = k.left( pos ).toInt(); // size
+ return true;
+}
+
+
+void KIconServer::createIconsFile( const QString& path_P )
+{
+ int mmap_size = makeKeySizes();
+ if( !publishIcons( path_P, mmap_size ))
+ kapp->quit(); // oops CHECKME can't do this, it has to stay running while there's \
still refcount +}
+
+int KIconServer::makeKeySizes()
+{
+ int pos = sizeof( KIconsFile ) + ( icons.size() - old_icons_count - 1 ) * sizeof( \
KIconFileEntry ); + for( IconsMap::Iterator it = icons.begin(); it != icons.end(); ++it )
+ {
+ ( *it ).key_pos = pos;
+ pos += it.key().length() + 1;
+ }
+ return pos;
+}
+
+bool KIconServer::publishIcons( const QString& path_P, int mmap_size_P )
+{
+ bool ok = true;
+ KIconsFile* file_data = static_cast< KIconsFile* >( operator new( mmap_size_P ));
+ file_data->version = KICONSFILEVERSION;
+ file_data->depth = QPixmap::defaultDepth();
+ int pos = -1;
+ for( IconsMap::Iterator it = icons.begin(); it != icons.end(); ++it )
+ {
+ if( ( *it ).old()) // scheduled for removal
+ continue;
+ ++pos;
+
+ kdDebug( 179 ) << "putting " << it.key() << " ("
+ << ( *it ).pixmap.handle() << "/" << ( *it ).pixmap.maskHandle()
+ << "/" << ( *it ).pixmap.alphaHandle() << ")" << endl;
+
+ file_data->entries[ pos ].key_ref = ( *it ).key_pos;
+ file_data->entries[ pos ].xid = ( *it ).pixmap.handle();
+ file_data->entries[ pos ].mask_xid = ( *it ).pixmap.maskHandle();
+ file_data->entries[ pos ].alpha_xid = ( *it ).pixmap.alphaHandle();
+ file_data->entries[ pos ].size = ( *it ).pixmap.width();
+ file_data->entries[ pos ].group = ( *it ).group;
+ file_data->entries[ pos ].state = ( *it ).state;
+ }
+ char* keys = reinterpret_cast< char* >( file_data ) + sizeof( KIconsFile )
+ + ( icons.size() - old_icons_count - 1 ) * sizeof( KIconFileEntry );
+ for( IconsMap::Iterator it = icons.begin();
+ it != icons.end();
+ ++it )
+ {
+ strcpy( keys, it.key().data());
+ keys += it.key().length() + 1;
+ }
+ file_data->count = icons.size() - old_icons_count;
+ kdDebug( 179 ) << "saving icons file, published=" << icons.size() - old_icons_count
+ << ", hidden=" << old_icons_count << endl;
+ KSaveFile file( path_P );
+ if( file.status() != 0 )
+ ok = false;
+ else
+ {
+ file.file()->writeBlock( reinterpret_cast< char* >( file_data ), mmap_size_P );
+ operator delete( file_data );
+ ok = file.close();
+ }
+ // notify ALL applications
+ QByteArray data;
+ QDataStream stream( data, IO_WriteOnly );
+ stream << ok;
+ kapp->dcopClient()->send( "*", "iconserverclient*", "iconsFileChanged(bool)", data );
+ return ok;
+}
+
+// only for adding often used icons ... such icons won't age
+void KIconServer::addIcon( const QString& name, int group, int size, int state )
+{
+ KIconDataPixmap pm = KGlobal::iconLoader()->loadIcon( "@force@" + name, \
KIcon::Group(group), + size, state, \
NULL, true ); + if( pm.isNull())
+ return;
+ if( size == 0 )
+ size = IconSize( KIcon::Group(group) );
+ QString dummy;
+ QCString key = KGlobal::iconLoader()->makeKey( name, group, size, state, dummy ).utf8();
+ if( pm.width() != pm.height())
+ {
+ kdWarning( 179 ) << "icon \"" << key << "\" has size " << pm.width()
+ << "x" << pm.height() << endl;
+ return;
+ }
+ icons[ key ] = KIconData( pm, group, state, 1 ); // 1 => prevent aging
+ kdDebug( 179 ) << "added icon: " << pm.handle() << "(" << key << ") ("
+ << pm.handle() << "/" << pm.maskHandle() << "/" << pm.alphaHandle() << ")" << \
endl; +}
+
+// CHECKME have some timeout when destroying pixmaps, in case an app still uses
+// the old index file
+
+void KIconServer::defaultIcons()
+{
+ //addIcon( "go", KIcon::Desktop, 0, KIcon::DefaultState );
+ // TODO
+}
+
+
+// CHECKME check that the application hasn't crashed meanwhile
+void KIconServer::newIcons( KIconSendDataList icons_P )
+{
+ kdDebug( 179 ) << "got new icons from app" << endl;
+ bool added = false;
+ QValueList< QCString > keys;
+ for( KIconSendDataList::ConstIterator it = icons_P.begin(); it != icons_P.end(); ++it )
+ {
+ const KIconSendData& data = ( *it );
+ kdDebug( 179 ) << "checking new icon " << data.key << endl;
+ if( icons.contains( data.key ))
+ {
+ kdDebug( 179 ) << "increasing refcount" << endl;
+ if( icons[ data.key ].ref())
+ --old_icons_count;
+ continue;
+ }
+ // holder_pix must be destroyed before holder_alpha and holder_mask
+ // all three of them must be destroyed before pix
+ KIconPixmapHolder holder_mask, holder_alpha, holder_pix;
+ KIconPixmap pix( data.size, data.size, data.xid, data.mask_xid, data.alpha_xid );
+ if( pix.isNull()) // just in case... ?
+ continue;
+ holder_pix = pix; // prevent QPixmap from freeing the client's pixmap
+ if( pix.mask() != NULL )
+ holder_mask = *pix.mask();
+ if( pix.alpha() != NULL )
+ holder_alpha = *pix.alpha();
+ KIconPixmap pix_copy( pix );
+ pix_copy.detach(); // force creating a deep copy of the pixmap
+ if( pix.mask() != NULL ) // X pixmap handles we got from the client
+ { // will become invalid after the client exits
+ QBitmap bm_copy( *pix.mask() );
+ bm_copy.detach();
+ pix_copy.setMask( bm_copy );
+ }
+ if( pix.alpha() != NULL ) // the alpha pixmap is deleted by setMask()
+ pix_copy.setAlpha( *pix.alpha() ); //so create it again
+
+#ifndef NDEBUG
+ Q_ASSERT( data.xid != pix_copy.handle());
+ Q_ASSERT( pix_copy.mask() == NULL || pix_copy.mask()->handle() != data.mask_xid );
+ KIconDataPixmap dt( pix_copy );
+ Q_ASSERT( pix.alpha() == NULL || dt.alphaHandle() != data.alpha_xid );
+#endif
+ icons[ data.key ] = KIconData( pix_copy, data.group, data.state, 1 ); // 1 = used by \
the app + kdDebug( 179 ) << "icon added" << endl;
+ keys.prepend( data.key );
+ added = true;
+ }
+ refIcons( keys );
+ if( added && !update_timer.isActive())
+ update_timer.start( 10000, true ); // CHECKME 10 secs ?
+ // maybe rather 20 seconds first and 5 seconds following ones
+}
+
+void KIconServer::flushIcons()
+{
+ QString path = KGlobal::dirs()->saveLocation("tmp") + "kiconsfile-" + getenv( "DISPLAY" );
+ createIconsFile( path );
+}
+
+void KIconServer::refIcons( QValueList< QCString > keys_P )
+{
+ if( keys_P.empty())
+ return;
+ for( QValueList< QCString >::ConstIterator it = keys_P.begin(); it != keys_P.end(); ++it )
+ {
+ if( icons.contains( *it ))
+ {
+ kdDebug( 179 ) << "increasing refcount: " << *it << endl;
+ if( icons[ *it ].ref())
+ --old_icons_count;
+ continue;
+ }
+ kdWarning( 179 ) << "unknown icon in refIcons" << endl;
+ }
+ app_ref_deref( kapp->dcopClient()->senderId(), keys_P, true );
+}
+
+void KIconServer::derefIcons( QValueList< QCString > keys_P )
+{
+ if( keys_P.empty())
+ return;
+ for( QValueList< QCString >::ConstIterator it = keys_P.begin(); it != keys_P.end(); ++it )
+ {
+ if( icons.contains( *it ))
+ {
+ if( icons[ *it ].deref())
+ kdDebug( 179 ) << "no longer in use: " << *it << endl;
+ continue;
+ }
+ kdWarning( 179 ) << "unknown icon in refIcons" << endl;
+ }
+ app_ref_deref( kapp->dcopClient()->senderId(), keys_P, false );
+}
+
+QStringList KIconServer::availableIcons()
+{
+ QStringList iconList;
+ IconsMap::ConstIterator it;
+ for (it = icons.begin(); it != icons.end(); ++it)
+ iconList.append(it.key());
+ return iconList;
+}
+
+void KIconServer::ageIcons()
+{
+// CHECKME TODO only when there are many icons
+ bool flush = false;
+ for( IconsMap::Iterator it = icons.begin(); it != icons.end(); )
+ {
+ if( ( *it ).in_use())
+ {
+ ++it;
+ continue;
+ }
+ if( ( *it ).age())
+ {
+ kdDebug( 179 ) << "hiding icon:" << it.key() << endl;
+ ++old_icons_count;
+ flush = true;
+ }
+ if( ( *it ).too_old())
+ {
+ kdDebug( 179 ) << "deleting icon:" << it.key() << endl;
+ --old_icons_count;
+ IconsMap::Iterator it2 = it;
+ ++it2;
+ icons.remove( it );
+ it = it2;
+ continue;
+ }
+ ++it;
+ }
+ if( flush && !update_timer.isActive())
+ update_timer.start( 10000, true ); // CHECKME 10 secs ?
+}
+
+void KIconServer::app_reg( const QCString& app_id_P )
+{
+ for( AppRefList::ConstIterator it = app_ref_list.begin(); it != app_ref_list.end(); ++it )
+ if( ( *it ).app_id() == app_id_P )
+ return;
+ app_ref_list.prepend( KIconAppRef( app_id_P ));
+}
+
+void KIconServer::app_rem( const QCString& app_id_P )
+{
+ for( AppRefList::Iterator it = app_ref_list.begin(); it != app_ref_list.end(); ++it )
+ if( ( *it ).app_id() == app_id_P )
+ {
+ ( *it ).free( icons );
+ app_ref_list.remove( it );
+ return;
+ }
+// CHECKME here could be a problem when an app does dcop detach, but stays running
+}
+
+void KIconServer::app_ren( const QCString& old_app_id_P, const QCString& new_app_id_P )
+{
+ for( AppRefList::Iterator it = app_ref_list.begin(); it != app_ref_list.end(); ++it )
+ if( ( *it ).app_id() == old_app_id_P )
+ {
+ ( *it ).change_app_id( new_app_id_P );
+ return;
+ }
+}
+
+void KIconServer::app_ref_deref( const QCString& app_id_P, const QValueList< QCString >& \
keys_P , + bool ref_P )
+{
+ for( AppRefList::Iterator it = app_ref_list.begin(); it != app_ref_list.end(); ++it )
+ {
+ if( ( *it ).app_id() == app_id_P )
+ {
+ kdDebug( 179 ) << "(de)ref-ing in " << app_id_P << endl;
+ if( ref_P )
+ ( *it ).ref( keys_P );
+ else
+ ( *it ).deref( keys_P );
+ return;
+ }
+ }
+ if( ref_P )
+ {
+ app_ref_list.prepend( KIconAppRef( app_id_P ));
+ app_ref_list.front().ref( keys_P );
+ }
+}
+
+bool KIconData::ref()
+{
+ bool ret = ( usage <= -5 );
+ if( usage < 0 )
+ usage = 1;
+ else
+ ++usage;
+ return ret;
+}
+
+extern "C"
+ {
+ KDE_EXPORT KDEDModule *create_kiconserver(const QCString &obj)
+ {
+ return new KIconServer(obj);
+ }
+ };
+
+#include "kiconserver.moc"
Index: kdecore/iconserver/configure.in.in
===================================================================
--- kdecore/iconserver/configure.in.in (revisão 0)
+++ kdecore/iconserver/configure.in.in (revisão 0)
@@ -0,0 +1,10 @@
+AC_TRY_COMPILE([],
+ [
+ #ifdef HAVE_MMAP
+ return 0;
+ #else
+ return 1;
+ #endif
+ ], [ ICONSERVER_COMPILE=iconserver
+ AC_SUBST( ICONSERVER_COMPILE ) ]
+ )
Index: kdecore/iconserver/appref.cpp
===================================================================
--- kdecore/iconserver/appref.cpp (revisão 0)
+++ kdecore/iconserver/appref.cpp (revisão 0)
@@ -0,0 +1,148 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "appref.h"
+
+#include <kdebug.h>
+
+KIconAppRef::KIconAppRef( const QCString& app_id_P )
+ : _app_id( app_id_P ), arr( NULL ), used_size( 0 ), allocated_size( 0 )
+{
+}
+
+KIconAppRef::KIconAppRef( const KIconAppRef& src_P )
+ : _app_id( src_P._app_id ), arr( src_P.arr ), used_size( src_P.used_size ),
+ allocated_size( src_P.allocated_size )
+{
+ kdDebug( 179 ) << "copy (" << (void*)this << "<-" << (void*)&src_P << ") :" << arr << \
endl; + src_P.arr = NULL; // copies will be created only when passing to QValueList
+}
+
+KIconAppRef::~KIconAppRef()
+{
+ kdDebug( 179 ) << "deleting (" << (void*)this << ") :" << (void*)arr << endl;
+ //delete[] arr;
+}
+
+void KIconAppRef::free( IconsMap& icons )
+{
+ for( KIconAppRefData* pos = arr; pos != arr + used_size; ++pos )
+ {
+ if( pos->key.isNull())
+ continue;
+ KIconData& ref = icons[ pos->key ];
+ kdDebug( 179 ) << "appderef: " << pos->key << endl;
+ for( int i = 0; i < pos->count; ++i )
+ ref.deref();
+ }
+ used_size = 0;
+}
+
+void KIconAppRef::ref( const QValueList< QCString > keys_P )
+{
+ QValueList< QCString > keys( keys_P );
+ qHeapSort( keys );
+ resize( keys.count() + used_size );
+ KIconAppRefData* pos = arr;
+ for( QValueList< QCString >::ConstIterator it = keys.begin(); it != keys.end(); ++it )
+ {
+ int dif;
+ kdDebug( 179 ) << "appref: " << *it << endl;
+ while( pos && ( dif = KIconAppRefData::cmp( pos->key, *it ) ) < 0 )
+ ++pos;
+ if( dif == 0 )
+ ++pos->count;
+ else
+ {
+ arr[ used_size ].key = ( *it );
+ arr[ used_size ].count = 1;
+ ++used_size;
+ }
+ }
+ qHeapSort( arr, arr + used_size );
+}
+
+void KIconAppRef::deref( const QValueList< QCString > keys_P )
+{
+ QValueList< QCString > keys( keys_P );
+ qHeapSort( keys );
+ KIconAppRefData* pos = arr;
+ for( QValueList< QCString >::ConstIterator it = keys.begin(); it != keys.end(); ++it )
+ {
+ int dif=-1;
+ while( pos && ( dif = KIconAppRefData::cmp( pos->key, *it ) ) < 0 )
+ ++pos;
+
+ if( dif == 0 )
+ {
+ kdDebug( 179 ) << "appderef: " << pos->key << endl;
+ if( --pos->count == 0 )
+ {
+ pos->key = QCString();
+ ++pos; // position after this one
+ }
+ }
+ else
+ kdDebug( 179 ) << "KIconAppRef::deref(): key not found:" << *it << endl;
+ }
+ qHeapSort( arr, arr + used_size );
+ while( used_size > 0 && arr[ used_size - 1 ].key.isNull())
+ --used_size;
+ kdDebug( 179 ) << "KIconAppRef: derefs : " << used_size << endl;
+}
+
+void KIconAppRef::resize( unsigned int new_size_P )
+{
+ unsigned int old_size = allocated_size;
+ unsigned int new_size = old_size;
+ if( new_size == 0 )
+ new_size = 4;
+ while( new_size < new_size_P )
+ new_size *= 2;
+ if( new_size == old_size )
+ return;
+ KIconAppRefData* new_arr = new KIconAppRefData[ new_size ];
+ KIconAppRefData* src = arr;
+ KIconAppRefData* dst = new_arr;
+ while( old_size-- > 0 )
+ *dst++ = *src++;
+ delete[] arr;
+ arr = new_arr;
+ allocated_size = new_size;
+}
+
+int KIconAppRefData::cmp( const QCString& l_P, const QCString& r_P )
+{
+ if( !l_P.isNull() && !r_P.isNull() )
+ return strcmp( l_P, r_P );
+ if( !l_P.isNull())
+ return -1; // NULL keys go last, not first
+ if( !r_P.isNull())
+ return 1; // NULL keys go last, not first
+ return 0;
+}
Index: kdecore/kiconpixmap_p.h
===================================================================
--- kdecore/kiconpixmap_p.h (revisão 0)
+++ kdecore/kiconpixmap_p.h (revisão 0)
@@ -0,0 +1,90 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifndef __KICONPIXMAP_H
+#define __KICONPIXMAP_H
+
+#include <kdelibs_export.h>
+
+#include <qpixmap.h>
+#include <qbitmap.h>
+
+#include <X11/Xlib.h>
+
+#ifndef QT_NO_XRENDER // CHECKME
+#include <X11/extensions/Xrender.h>
+#endif
+
+class KDECORE_EXPORT KIconPixmap : public QPixmap
+{
+public:
+ KIconPixmap( int w_P, int h_P, Pixmap pm_P, Pixmap mask_P, Pixmap alpha_P );
+ const QPixmap* alpha() const;
+ void setAlpha(const QPixmap& alpha);
+};
+
+class KDECORE_EXPORT KIconBitmap : public QBitmap
+{
+public:
+ KIconBitmap( int w_P, int h_P, Pixmap pixmap_P );
+};
+
+class KDECORE_EXPORT KIconAlpha : public QPixmap
+{
+public:
+ KIconAlpha( const QPixmap& pixmap );
+ KIconAlpha( int w_P, int h_P, Pixmap pixmap_P );
+ virtual void detach();
+};
+
+class KDECORE_EXPORT KIconDataPixmap : public QPixmap
+{
+public:
+ KIconDataPixmap( const QPixmap& pm_P );
+ KIconDataPixmap() {}; // for QValueList
+ const QPixmap* alpha() const;
+ Pixmap maskHandle() const;
+ Pixmap alphaHandle() const;
+};
+
+// prevents freeing the X pixmap and XRender handle
+class KDECORE_EXPORT KIconPixmapHolder : public QPixmap
+{
+public:
+ KIconPixmapHolder();
+ KIconPixmapHolder( const QPixmap& pm_P );
+ KIconPixmapHolder& operator=( const QPixmap& pm_P );
+ virtual ~KIconPixmapHolder();
+};
+
+class KDECORE_EXPORT KIconSharedPixmap : public QPixmap
+{
+public:
+ KIconSharedPixmap( const QCString& key_P, const QPixmap& pm_P );
+ virtual ~KIconSharedPixmap();
+ bool unused() const;
+ QCString key;
+};
+
+#endif
Index: kdecore/Makefile.am
===================================================================
--- kdecore/Makefile.am (revisão 421621)
+++ kdecore/Makefile.am (cópia de trabalho)
@@ -20,14 +20,15 @@
# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
-INCLUDES = -I$(top_srcdir)/kdefx -I$(top_srcdir)/kdecore/network $(all_includes) \
$(LIBART_CFLAGS) +INCLUDES = -I$(top_srcdir)/kdefx -I$(top_srcdir)/kdecore/network \
$(all_includes) $(LIBART_CFLAGS) \ + $(KDEINIT_XFT_INCLUDES)
if include_SVGICONS
SVGICONS=svgicons
SVGICON_LIB=svgicons/libkdesvgicons.la
endif
-SUBDIRS = malloc network $(SVGICONS) . kconfig_compiler tests
+SUBDIRS = malloc network $(SVGICONS) . kconfig_compiler iconserver tests
# For the future: examine if condensing the tons of *_LDFLAGS variables
# into $(all_libraries) isn't better
@@ -81,7 +82,7 @@
kregpriv.h kshortcutmenu.h ksycocadict.h ksycocafactory.h netsupp.h \
kcheckaccelerators.h kcalendarsystemgregorian.h \
kcalendarsystemhijri.h kcalendarsystemhebrew.h kcalendarsystemjalali.h \
- kprotocolinfofactory.h
+ kprotocolinfofactory.h kiconserverclient_p.h kiconpixmap_p.h
libkdecore_la_SOURCES = libintl.cpp kapplication.cpp \
kdebug.cpp netwm.cpp kconfigbase.cpp kconfig.cpp ksimpleconfig.cpp \
@@ -112,7 +113,8 @@
kcalendarsystemfactory.cpp kmacroexpander.cpp kidna.cpp \
ktempdir.cpp kshell.cpp kmountpoint.cpp kcalendarsystemjalali.cpp \
kprotocolinfo_kdecore.cpp kprotocolinfofactory.cpp kxerrorhandler.cpp \
- kuser.cpp kconfigskeleton.cpp kconfigdialogmanager.cpp klockfile.cpp
+ kuser.cpp kconfigskeleton.cpp kconfigdialogmanager.cpp klockfile.cpp \
+ kiconserverclient.cpp kiconserverclient_p.skel kiconpixmap.cpp
libkdecore_la_LDFLAGS = $(QT_LDFLAGS) $(KDE_RPATH) $(KDE_MT_LDFLAGS) $(X_LDFLAGS) \
$(USER_LDFLAGS) -version-info 6:0:2 -no-undefined libkdecore_la_LIBADD = malloc/libklmalloc.la \
network/libkdecorenetwork.la $(SVGICON_LIB) ../dcop/libDCOP.la ../libltdl/libltdlc.la \
$(LIB_XEXT) $(LIBRESOLV) $(LIBUTIL) $(LIBART_LIBS) $(LIB_IDN) ../kdefx/libkdefx.la @@ -124,6 \
+126,8 @@
SRCDOC_DEST=$(kde_htmldir)/en/kdelibs/kdecore
+kiconserver_DIR = $(srcdir)/iconserver
+
kdebugdir = $(kde_confdir)
kdebug_DATA = kdebug.areas kdebugrc language.codes
Index: kdecore/kiconpixmap.cpp
===================================================================
--- kdecore/kiconpixmap.cpp (revisão 0)
+++ kdecore/kiconpixmap.cpp (revisão 0)
@@ -0,0 +1,302 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qapplication.h>
+
+#include "kiconpixmap_p.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#ifndef QT_NO_XRENDER
+#include <X11/extensions/Xrender.h>
+#include <X11/Xft/Xft.h>
+#endif
+
+#include <kdebug.h>
+
+extern bool qt_use_xrender;
+
+/*
+ The code here is based on QPixmap code from Qt
+*/
+
+// Based on QPixmap::init() and QPixmap::setMask()
+KIconPixmap::KIconPixmap( int w, int h, Pixmap pm_P, Pixmap mask_P, Pixmap alpha_P )
+ : QPixmap( 0, 0, -1 )
+{
+ data->w = w;
+ data->uninit = false;
+ data->h = h;
+ assert( pm_P != None );
+ hd = pm_P;
+
+#ifndef QT_NO_XRENDER
+ if (qt_use_xrender)
+ {
+#ifndef QT_NO_XFTFREETYPE
+ if (data->d == 1)
+ rendhd = (HANDLE) XftDrawCreateBitmap( x11Display(), hd );
+ else
+ rendhd = (HANDLE) XftDrawCreate( x11Display (), hd,
+ (Visual *) x11Visual(), x11Colormap() );
+#endif //QT_NO_XFTFREETYPE
+ }
+#endif // QT_NO_XRENDER
+ data->selfmask = FALSE;
+ if( mask_P != None )
+ {
+ KIconBitmap* newmaskcopy;
+ newmaskcopy = new KIconBitmap( w, h, mask_P );
+ data->mask = newmaskcopy;
+ }
+
+ if( alpha_P != None )
+ {
+#ifndef QT_NO_XRENDER
+ if (qt_use_xrender)
+ {
+ KIconAlpha* alpha = new KIconAlpha( w, h, alpha_P );
+ data->alphapm = alpha;
+ }
+#endif
+ }
+ data->ximage = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes, data->d == 1 ? XYPixmap \
: ZPixmap ); +}
+
+void KIconPixmap::setAlpha( const QPixmap& alpha )
+{
+ KIconAlpha *pm = new KIconAlpha(alpha);
+ pm->detach();
+ data->alphapm = pm;
+}
+
+// Once again for bitmap
+
+// Based on QPixmap::init()
+KIconBitmap::KIconBitmap( int w, int h, Pixmap pm_P )
+ : QBitmap( 0, 0 )
+{
+ data->uninit = false;
+ data->w = w;
+ data->h = h;
+ hd = pm_P;
+
+#ifndef QT_NO_XRENDER
+ if (qt_use_xrender)
+ {
+#ifndef QT_NO_XFTFREETYPE
+ if (data->d == 1)
+ rendhd = (HANDLE) XftDrawCreateBitmap( x11Display(), hd );
+ else
+ rendhd = (HANDLE) XftDrawCreate( x11Display(), hd,
+ (Visual *) x11Visual(), x11Colormap() );
+#endif //QT_NO_XFTFREETYPE
+ }
+#endif // QT_NO_XRENDER
+ data->ximage = XGetImage( x11Display(), hd, 0, 0, w, h, AllPlanes, data->d == 1 ? XYPixmap \
: ZPixmap ); +}
+
+// Once again for alpha pixmap
+
+KIconAlpha::KIconAlpha( const QPixmap& pixmap )
+ : QPixmap( pixmap )
+{
+}
+
+// Based on QPixmap::convertFromImage()
+KIconAlpha::KIconAlpha( int w, int h, Pixmap pm_P )
+ : QPixmap()
+{
+ data->uninit = false;
+#ifndef QT_NO_XRENDER
+ if(qt_use_xrender)
+ {
+ // setup pixmap data
+ data->w = w;
+ data->h = h;
+ data->d = 8;
+
+ hd = pm_P;
+
+#ifndef QT_NO_XFTFREETYPE
+ rendhd = (HANDLE) XftDrawCreateAlpha( x11Display(), hd, 8 );
+#endif // QT_NO_XFTFREETYPE
+ }
+ data->ximage = XGetImage( x11Display(), hd, 0, 0, data->w, data->h, AllPlanes, data->d == \
1 ? XYPixmap : ZPixmap ); +#endif // QT_NO_XRENDER
+
+}
+
+void KIconAlpha::detach()
+{
+ QPixmap tmp(*this);
+
+ // create 8bpp pixmap and render picture
+ hd = XCreatePixmap(x11Display(),
+ RootWindow(x11Display(), x11Screen()),
+ data->w, data->h, 8);
+
+ // create the alpha render handle
+ rendhd = (Qt::HANDLE) XftDrawCreateAlpha( x11Display(), hd, 8 );
+
+ //copy data
+ GC gc = XCreateGC(x11Display(), hd, 0, 0);
+ XCopyArea(x11Display(), tmp.handle(), hd, gc, 0, 0, data->w, data->h, 0, 0);
+
+ data->ximage = XGetImage( x11Display(), hd, 0, 0, data->w, data->h, AllPlanes,
+ data->d == 1 ? XYPixmap : ZPixmap );
+}
+
+KIconDataPixmap::KIconDataPixmap( const QPixmap& pm_P )
+ : QPixmap( pm_P )
+{
+}
+
+Pixmap KIconDataPixmap::maskHandle() const
+{
+ return mask() != NULL ? mask()->handle() : None;
+}
+
+Pixmap KIconDataPixmap::alphaHandle() const
+{
+ return data->alphapm != NULL ? data->alphapm->handle() : None;
+}
+
+const QPixmap* KIconDataPixmap::alpha() const
+{
+ return data->alphapm;
+}
+
+const QPixmap* KIconPixmap::alpha() const
+{
+ return data->alphapm;
+}
+
+KIconPixmapHolder::KIconPixmapHolder()
+{
+}
+
+// just attach to the shared QPixmapData, it doesn't matter if it's
+// QPixmap or QBitmap
+KIconPixmapHolder::KIconPixmapHolder( const QPixmap& pm_P )
+ : QPixmap( pm_P )
+{
+}
+
+// just attach to the shared QPixmapData, it doesn't matter if it's
+// QPixmap or QBitmap
+KIconPixmapHolder& KIconPixmapHolder::operator=( const QPixmap& pm_P )
+{
+ QPixmap::operator=( pm_P );
+ return *this;
+}
+
+// based on QPixmap::deref()
+KIconPixmapHolder::~KIconPixmapHolder()
+{
+ if( data->count > 1 ) // if it's still in use
+ {
+ // it looks like most KDE apps don't delete their widgets, so complain only if the app
+ // is not quiting
+ if( !QApplication::closingDown())
+ fprintf( stderr, "KIconPixmapHolder: Cannot free pixmap holder (count==%d)\n", \
data->count );; + ++data->count; // prevent QPixmap from freeing the X pixmap
+ }
+ else
+ {
+ if ( qApp && hd)
+ {
+#ifndef QT_NO_XRENDER
+ if (rendhd)
+ {
+ XftDrawDestroy( (XftDraw *) rendhd );
+ rendhd = 0;
+ }
+#endif // QT_NO_XRENDER
+ hd = 0;
+ }
+ }
+}
+
+KIconSharedPixmap::KIconSharedPixmap( const QCString& key_P, const QPixmap& pm_P )
+ : QPixmap( pm_P ), key( key_P )
+{
+}
+
+class QPixmapDataHack
+ : public QBitmap
+{
+public:
+ bool unused() const { return data->count == 1; }
+};
+
+bool KIconSharedPixmap::unused() const
+{
+ return data->count == 1
+ && ( data->mask == NULL || static_cast< QPixmapDataHack* >( data->mask )->unused() == \
1 ) + && ( data->alphapm == NULL || static_cast< QPixmapDataHack* >( data->alphapm \
)->unused() == 1 ); +}
+
+KIconSharedPixmap::~KIconSharedPixmap()
+{
+ if( !unused()) // if it's still in use
+ {
+ // it looks like most KDE apps don't delete their widgets, so complain only if the app
+ // is not quiting
+ if( !QApplication::closingDown())
+ fprintf( stderr, "KIconSharedPixmap: Cannot free pixmap holder (count==%d)\n",
+ data->count );;
+ ++data->count; // prevent QPixmap from freeing the X pixmaps
+ return;
+ }
+ if( data->alphapm != NULL )
+ {
+ KIconPixmapHolder hold( *data->alphapm );
+ delete data->alphapm;
+ data->alphapm = NULL;
+ }
+ if( data->mask != NULL )
+ {
+ KIconPixmapHolder hold( *data->mask );
+ delete data->mask;
+ data->mask = NULL;
+ }
+ if ( qApp && hd)
+ {
+#ifndef QT_NO_XRENDER
+ if (rendhd)
+ {
+ XftDrawDestroy( (XftDraw *) rendhd );
+ rendhd = 0;
+ }
+#endif // QT_NO_XRENDER
+
+ hd = 0;
+ }
+}
Index: kdecore/kiconloader.cpp
===================================================================
--- kdecore/kiconloader.cpp (revisão 421621)
+++ kdecore/kiconloader.cpp (cópia de trabalho)
@@ -36,6 +36,7 @@
#include <kicontheme.h>
#include <kiconloader.h>
#include <kiconeffect.h>
+#include <kiconserverclient_p.h>
#include <sys/types.h>
#include <stdlib.h> //for abs
@@ -134,6 +135,7 @@
QPtrList<KIconThemeNode> links;
bool extraDesktopIconsLoaded :1;
bool delayedLoading :1;
+ KIconServerClient* iconClient;
};
#define KICONLOADER_CHECKS
@@ -197,6 +199,22 @@
else
d->mpDirs = KGlobal::dirs();
+ d->iconClient = NULL;
+ if( d->mpDirs == KGlobal::dirs() ||
+ d->mpDirs->resourceDirs("icon") == KGlobal::dirs()->resourceDirs("icon") )
+ {
+ KConfigGroupSaver saver( KGlobal::config(), "Icons" );
+ if( KGlobal::config()->readBoolEntry( "UseIconServer", true ))
+ {
+ d->iconClient = new KIconServerClient;
+ if( !d->iconClient->isActive()) // some startup problem
+ {
+ delete d->iconClient;
+ d->iconClient = NULL;
+ }
+ }
+ }
+
// If this is unequal to 0, the iconloader is initialized
// successfully.
d->mpThemeRoot = 0L;
@@ -292,6 +310,8 @@
deleted when the elements of d->links are deleted */
d->mpThemeRoot=0;
delete[] d->mpGroups;
+ if (d->iconClient)
+ delete d->iconClient;
delete d;
}
@@ -597,11 +617,17 @@
QString name = _name;
QPixmap pix;
QString key;
- bool absolutePath=false, favIconOverlay=false;
+ bool absolutePath=false, favIconOverlay=false, forceLoading = false;
if (d->mpThemeRoot == 0L)
return pix;
+ if (name.startsWith("@force@"))
+ {
+ name.remove("@force@");
+ forceLoading = true;
+ }
+
// Special case for absolute path icons.
if (name.startsWith("favicons/"))
{
@@ -687,31 +713,21 @@
}
favIconOverlay = favIconOverlay && size > 22;
- // Generate a unique cache key for the icon.
-
- key = "$kico_";
- key += name; key += '_';
- key += QString::number(size); key += '_';
-
- QString overlayStr = QString::number( overlay );
-
- QString noEffectKey = key + '_' + overlayStr;
-
- if (group >= 0)
- {
- key += d->mpEffect.fingerprint(group, state);
- if (d->mpGroups[group].dblPixels)
- key += QString::fromLatin1(":dblsize");
- } else
- key += QString::fromLatin1("noeffect");
- key += '_';
- key += overlayStr;
-
+ QString noEffectKey;
+ key = makeKey( name, group, size, state | overlay, noEffectKey );
+
// Is the icon in the cache?
bool inCache = QPixmapCache::find(key, pix);
if (inCache && (path_store == 0L))
return pix;
+ // Checking if the icon is in the iconserver
+ if( !forceLoading && d->iconClient && d->iconClient->iconServerCheck( key, pix ))
+ {
+ QPixmapCache::insert(key, pix);
+ return pix;
+ }
+
QImage *img = 0;
int iconType;
int iconThreshold;
@@ -735,7 +751,7 @@
if (!icon.isValid())
{
// Try "User" icon too. Some apps expect this.
- if (!name.isEmpty())
+ if (!name.isEmpty()) //CHECKME: wheter to use the iconserver
pix = loadIcon(name, KIcon::User, size, state, path_store, true);
if (!pix.isNull() || canReturnNull)
return pix;
@@ -870,9 +886,40 @@
}
QPixmapCache::insert(key, pix);
+
+ if( d->iconClient )
+ d->iconClient->iconServerAdd( key, pix, group, state | overlay );
+
return pix;
}
+QString KIconLoader::makeKey( const QString& name, int group, int size, int state,
+ QString& noEffectKey ) const
+{
+ int overlay = (state & KIcon::OverlayMask);
+ state &= ~KIcon::OverlayMask;
+
+ QString key = "$kico_";
+ key += name; key += ':';
+ key += QString::number(size); key += '_';
+
+ QString overlayStr = QString::number( overlay );
+
+ noEffectKey = key + '_' + overlayStr;
+
+ if (group >= 0)
+ {
+ key += d->mpEffect.fingerprint(group, state);
+ if (d->mpGroups[group].dblPixels)
+ key += QString::fromLatin1(":dblsize");
+ }
+ else
+ key += QString::fromLatin1("noeffect");
+ key += '_';
+ key += overlayStr;
+ return key;
+}
+
QImage *KIconLoader::loadOverlay(const QString &name, int size) const
{
QString key = name + '_' + QString::number(size);
Index: kdecore/kiconserverstructs.h
===================================================================
--- kdecore/kiconserverstructs.h (revisão 0)
+++ kdecore/kiconserverstructs.h (revisão 0)
@@ -0,0 +1,85 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifndef KICONSERVERSTRUCTS_H
+#define KICONSERVERSTRUCTS_H
+
+struct KIconFileEntry
+{
+ int key_ref;
+ Pixmap xid;
+ Pixmap mask_xid;
+ Pixmap alpha_xid;
+ int size;
+ int group;
+ int state;
+};
+
+struct KIconsFile
+{
+ int version;
+ int depth;
+ int count;
+ KIconFileEntry entries[ 1 ]; // will grow
+}; // + keys
+
+const int KICONSFILEVERSION = 1;
+
+// KIconLoader saves these for sending them to iconserver later
+struct KIconNewData
+{
+ KIconNewData( const QString& key_P, const QPixmap& pix_P, int group_P, int state_P );
+ KIconNewData() {}; // for QValueList
+ QString key;
+ KIconDataPixmap pix;
+ int group;
+ int state;
+};
+
+typedef QValueList< KIconNewData > KIconNewDataList;
+
+inline
+KIconNewData::KIconNewData( const QString& key_P, const QPixmap& pix_P, int group_P, int \
state_P ) + : key( key_P ), pix( pix_P ), group( group_P ), state( state_P )
+{
+}
+
+// for the newIcons DCOP call
+struct KIconSendData
+{
+ KIconSendData( const KIconNewData& data_P );
+ KIconSendData() {}; // for QValueList
+ QCString key;
+ Pixmap xid;
+ Pixmap mask_xid;
+ Pixmap alpha_xid;
+ int size;
+ int group;
+ int state;
+};
+
+KDECORE_EXPORT QDataStream& operator<<( QDataStream& stream_P, const KIconSendData& data_P );
+KDECORE_EXPORT QDataStream& operator>>( QDataStream& stream_P, KIconSendData& data_P );
+
+#endif
Index: kdecore/kiconloader.h
===================================================================
--- kdecore/kiconloader.h (revisão 421621)
+++ kdecore/kiconloader.h (cópia de trabalho)
@@ -336,8 +336,15 @@
*/
bool isDelayedIconSetLoadingEnabled() const;
+ /**
+ * Generate a unique cache key for the icon.
+ * @internal
+ */
+ QString makeKey( const QString& name, int group, int size, int state,
+ QString& noEffectKey ) const;
private:
+
/**
* @internal
*/
Index: kdecore/kiconserverclient_p.h
===================================================================
--- kdecore/kiconserverclient_p.h (revisão 0)
+++ kdecore/kiconserverclient_p.h (revisão 0)
@@ -0,0 +1,84 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+#ifndef __KICONSERVERCLIENT_H
+#define __KICONSERVERCLIENT_H
+
+#include <kdelibs_export.h>
+
+#include <qvaluelist.h>
+#include <qobject.h>
+#include <qtimer.h>
+#include <dcopobject.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+
+#include <kiconpixmap_p.h>
+#include <kiconserverstructs.h>
+
+#include <X11/X.h>
+
+class QFile;
+
+typedef QValueList< KIconSendData > KIconSendDataList;
+
+class KIconSharedPixmap;
+
+class KDECORE_EXPORT KIconServerClient : public QObject, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+k_dcop:
+ void iconsFileChanged( bool serverRunning );
+public:
+ KIconServerClient();
+ virtual ~KIconServerClient();
+ bool iconServerCheck( const QString& key_P, QPixmap& pix_O );
+ void iconServerAdd( const QString& key_P, QPixmap& pix_P, int group_P, int state_P );
+ bool isActive() const;
+private:
+ bool openIconsFile();
+ void closeIconsFile();
+ bool iconServerRunning();
+private slots:
+ void sendIconsToServer();
+ void refDerefIcons();
+ void checkUnusedIcons();
+private:
+ static void init_icons_holder();
+ static void finish_icons_holder();
+ bool active;
+ const KIconsFile* icons_mmap;
+ int icons_size;
+ QFile* icons_file;
+ QTimer send_timer;
+ QTimer ref_timer;
+ QTimer unused_check_timer;
+ KIconNewDataList icons_send;
+ QValueList< QCString > ref_icons;
+ QValueList< QCString > deref_icons;
+ static QValueList< KIconSharedPixmap* >* icons_holder; // CHECKME static ?
+};
+
+#endif
Index: kdecore/kdebug.areas
===================================================================
--- kdecore/kdebug.areas (revisão 421621)
+++ kdecore/kdebug.areas (cópia de trabalho)
@@ -22,6 +22,7 @@
176 kdecore (KWin)
177 kdecore (KConfigSkeleton)
178 kdecore (KConfigDialogManager)
+179 kdecore (KIconServer)
180 kdecore (kdelibs)
200 kdeui (KMainWindow)
220 kdeui (KToolBar)
Index: kdecore/kiconserverclient.cpp
===================================================================
--- kdecore/kiconserverclient.cpp (revisão 0)
+++ kdecore/kiconserverclient.cpp (revisão 0)
@@ -0,0 +1,335 @@
+/****************************************************************************
+
+ Copyright (C) 2001 Lubos Lunak <llunak@suse.cz>
+ Copyright (C) 2005 Gustavo Pichorim Boiko <boiko@mandriva.com>
+
+ This file is part of the KDE libraries
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+
+****************************************************************************/
+
+//#define NDEBUG
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <qbitmap.h>
+#include <qfile.h>
+#include <qtimer.h>
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kapplication.h>
+#include <kdebug.h>
+#include <dcopclient.h>
+#include <dcopref.h>
+#include <kstandarddirs.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include <X11/Xlib.h>
+
+#include "kiconserverclient_p.h"
+#include "kiconpixmap_p.h"
+
+
+QValueList< KIconSharedPixmap* >* KIconServerClient::icons_holder = NULL;
+
+// CHECKME what will this do with multihead, will it work?
+
+KIconServerClient::KIconServerClient()
+ : DCOPObject( "iconserverclient" ), active( false ), icons_mmap( NULL )
+{
+// CHECKME this probably won't work with multihead !? ( different bpp )
+// shared_icons.setAutoDelete( true ); // CHECKME
+ KConfigGroupSaver saver( KGlobal::config(), "Icons" );
+ if( !KGlobal::config()->readBoolEntry( "UseIconServer", true ))
+ return;
+
+ if( !kapp->dcopClient()->isAttached()) // apps usually automatically register with DCOP,
+ return; // so if this one has it turned off, don't attach \
either +
+ DCOPRef kiconserver("kded", "kiconserver");
+ DCOPReply reply = kiconserver.callExt("serverRunning");
+
+ bool res;
+ if (!reply.isValid() || !(res = reply))
+ {
+ kdDebug( 179 ) << "no icon server available" << endl;
+ return;
+ }
+
+ if(!openIconsFile())
+ return;
+
+ connect( &send_timer, SIGNAL( timeout()), this, SLOT( sendIconsToServer()));
+ connect( &ref_timer, SIGNAL( timeout()), this, SLOT( refDerefIcons()));
+ connect( &unused_check_timer, SIGNAL( timeout()), this, SLOT( checkUnusedIcons()));
+ unused_check_timer.start( 30000 ); // CHECKME 30s ?
+ active = true;
+}
+
+KIconServerClient::~KIconServerClient()
+{
+ closeIconsFile();
+}
+
+bool KIconServerClient::openIconsFile()
+{
+#ifndef HAVE_MMAP
+ return false; // sorry
+#else
+ Q_ASSERT( icons_mmap == NULL );
+ QString path = KGlobal::dirs()->saveLocation("tmp") + "kiconsfile-" + getenv( "DISPLAY" );
+ icons_file = new QFile( path );
+ if( !icons_file->open( IO_ReadOnly ))
+ {
+ delete icons_file;
+ return false;
+ }
+ icons_size = icons_file->size();
+ icons_mmap = reinterpret_cast< KIconsFile* >( mmap( 0, icons_size,
+ PROT_READ, MAP_PRIVATE, icons_file->handle(), 0 ));
+ if( icons_mmap == NULL )
+ {
+ kdDebug( 179 ) << "mmap failed. (length = " << icons_size << ")" << endl;
+ delete icons_file;
+ return false; // sorry
+ }
+ if( icons_mmap->version != KICONSFILEVERSION )
+ {
+ kdDebug( 179 ) << "icons file version doesn't match (found " << icons_mmap->version
+ << ", expected " << KICONSFILEVERSION << ")" << endl;
+ closeIconsFile();
+ return false;
+ }
+ if( icons_mmap->depth != QPixmap::defaultDepth())
+ {
+ kdDebug( 179 ) << "icons file depth doesn't match (found " << icons_mmap->depth
+ << ", depth is " << QPixmap::defaultDepth() << ")" << endl;
+ closeIconsFile();
+ return false;
+ }
+ return true;
+#endif
+}
+
+void KIconServerClient::closeIconsFile()
+{
+ if( icons_mmap == NULL )
+ return;
+#ifdef HAVE_MMAP
+ munmap( (char*) icons_mmap, icons_size );
+ icons_mmap = NULL;
+ delete icons_file;
+#endif
+}
+
+bool KIconServerClient::iconServerCheck( const QString& key_P, QPixmap& pix_O )
+{
+ if( !active )
+ return false;
+
+ kdDebug( 179 ) << "checking for \"" << key_P << "\" icon in iconserver" <<endl;
+
+ int min = 0, max = icons_mmap->count - 1;
+ QCString key = key_P.utf8();
+ int index = -1;
+ while( min <= max ) // this is just a simple binary search in the icons_mmap
+ {
+ int pos = ( min + max ) / 2;
+ const char* pos_key = reinterpret_cast< const char* >( icons_mmap )
+ + icons_mmap->entries[ pos ].key_ref;
+ int dif = qstrcmp( key, pos_key );
+ if( dif < 0 )
+ max = pos - 1;
+ else if( dif > 0 )
+ min = pos + 1;
+ else // key == pos_key
+ {
+ index = pos;
+ break;
+ }
+ }
+ if( index < 0 )
+ return false;
+
+ const KIconFileEntry& data = icons_mmap->entries[ index ];
+
+ kdDebug( 179 ) << "getting icon from iconserver: " << data.xid << "/"
+ << data.mask_xid << "/" << data.alpha_xid << endl;
+
+ KIconPixmap pix( data.size, data.size, data.xid,
+ data.mask_xid, data.alpha_xid );
+ pix_O = pix;
+ init_icons_holder();
+ icons_holder->prepend( new KIconSharedPixmap( key, pix ));
+ ref_icons.prepend( key );
+ if( !ref_timer.isActive())
+ ref_timer.start( 10000, true ); // CHECKME 10 sec ?
+ return true;
+}
+
+void KIconServerClient::iconServerAdd( const QString& key_P, QPixmap& pix_P, int group_P, int \
state_P ) +{
+ if( !active )
+ return;
+ if( pix_P.width() != pix_P.height())
+ {
+ kdWarning( 179 ) << "icon \"" << key_P << "\" has size "
+ << pix_P.width() << "x" << pix_P.height() << endl;
+ return;
+ }
+ icons_send.append( KIconNewData( key_P, pix_P, group_P, state_P ));
+ if( !send_timer.isActive())
+ send_timer.start( 10000, true ); // CHECKME 10 sec ?
+}
+
+void KIconServerClient::sendIconsToServer()
+{
+ if( icons_send.empty())
+ return;
+ kdDebug( 179 ) << "sending icons to icon server" << endl;
+ KIconSendDataList send_data;
+ for( KIconNewDataList::ConstIterator it = icons_send.begin(); it != icons_send.end(); ++it \
) + {
+ send_data.append( KIconSendData( *it ));
+ KIconDataPixmap pix( ( *it ).pix );
+
+ kdDebug( 179 ) << "sending icon \"" << ( *it ).key << "\"" << endl;
+
+ init_icons_holder();
+ icons_holder->prepend( new KIconSharedPixmap( ( *it ).key.utf8(), pix )); // CHECKME \
utf8 ? + }
+ DCOPRef kiconserver("kded","kiconserver");
+ bool result = kiconserver.send("newIcons(KIconSendDataList)", send_data);
+
+ if (!result)
+ kdWarning( 179 ) << "Could not send new icons to the icon server" << endl;
+
+ // CHECKME this below only after delay, so that the iconserver can read in everything
+ // or in case the app crashes
+ icons_send.clear();
+}
+
+void KIconServerClient::iconsFileChanged( bool server_running_P )
+{
+ if( !active )
+ return;
+ if( server_running_P )
+ {
+ kdDebug( 179 ) << "reloading index file" << endl;
+ closeIconsFile();
+ if( !openIconsFile())
+ active = false;
+ }
+ else
+ {
+ kdDebug( 179 ) << "shutting down icon client" << endl;
+ closeIconsFile();
+ active = false;
+ }
+}
+
+void KIconServerClient::refDerefIcons()
+{
+ DCOPRef kiconserver("kded", "kiconserver");
+ bool result;
+ if( !ref_icons.empty())
+ {
+ result = kiconserver.send("refIcons(QValueList<QCString>", ref_icons);
+ if (!result)
+ kdWarning( 179 ) << "Could not ref icons in the server" << endl;
+ ref_icons.clear();
+ }
+ if( !deref_icons.empty())
+ {
+ result = kiconserver.send("derefIcons(QValueList<QCString>)", deref_icons);
+ if (!result)
+ kdWarning( 179 ) << "Could not deref icons in the server" << endl;
+ deref_icons.clear();
+ }
+}
+
+void KIconServerClient::checkUnusedIcons()
+{
+ if( icons_holder == NULL )
+ return;
+ for( QValueList< KIconSharedPixmap* >::Iterator it = icons_holder->begin();
+ it != icons_holder->end(); )
+ {
+ if( ( *it )->unused())
+ {
+ deref_icons.prepend( ( *it )->key );
+ if( !ref_timer.isActive())
+ ref_timer.start( 10000, true ); // CHECKME 10 sec ?
+ delete *it; // must delete manually (QValueList is used)
+ it = icons_holder->remove( it );
+ continue;
+ }
+ ++it;
+ }
+}
+
+bool KIconServerClient::isActive() const
+{
+ return active;
+}
+
+QDataStream& operator<<( QDataStream& stream_P, const KIconSendData& data_P )
+{
+ return stream_P << data_P.key << data_P.xid << data_P.mask_xid << data_P.alpha_xid
+ << data_P.size << data_P.group << data_P.state;
+}
+
+QDataStream& operator>>( QDataStream& stream_P, KIconSendData& data_P )
+{
+ return stream_P >> data_P.key >> data_P.xid >> data_P.mask_xid >> data_P.alpha_xid
+ >> data_P.size >> data_P.group >> data_P.state;
+}
+
+KIconSendData::KIconSendData( const KIconNewData& data_P )
+ : key( data_P.key.utf8()),
+ xid( data_P.pix.handle()),
+ mask_xid( data_P.pix.maskHandle()),
+ alpha_xid( data_P.pix.alphaHandle()),
+ size( data_P.pix.width()),
+ group( data_P.group ),
+ state( data_P.state )
+{
+}
+
+void KIconServerClient::init_icons_holder()
+{
+ if( icons_holder != NULL )
+ return;
+ icons_holder = new QValueList< KIconSharedPixmap* >;
+ qAddPostRoutine( finish_icons_holder );
+}
+
+void KIconServerClient::finish_icons_holder()
+{
+ if( icons_holder == NULL )
+ return;
+ delete icons_holder;
+ icons_holder = NULL;
+}
+
+#include "kiconserverclient_p.moc"
Index: kdecore/kuniqueapplication.cpp
===================================================================
--- kdecore/kuniqueapplication.cpp (revisão 421621)
+++ kdecore/kuniqueapplication.cpp (cópia de trabalho)
@@ -139,6 +139,7 @@
kdError() << "KUniqueApplication: pipe() failed!" << endl;
::exit(255);
}
+
int fork_result = fork();
switch(fork_result) {
case -1:
@@ -205,7 +206,7 @@
#endif
return false;
}
- dc->setPriorityCall(true);
+ //dc->setPriorityCall(true);
}
{
@@ -288,7 +289,7 @@
KCmdLineArgs::saveAppArgs(ds);
ds << new_asn_id;
- dc->setPriorityCall(true);
+ //dc->setPriorityCall(true);
QCString replyType;
if (!dc->call(appName, KCmdLineArgs::about->appName(), "newInstance()", data, replyType, \
reply)) {
@@ -296,7 +297,7 @@
delete dc; // Clean up DCOP commmunication
::exit(255);
}
- dc->setPriorityCall(false);
+ //dc->setPriorityCall(false);
if (replyType != "int")
{
kdError() << "KUniqueApplication: DCOP communication error!" << endl;
Index: dcop/dcopserver.cpp
===================================================================
--- dcop/dcopserver.cpp (revisão 424083)
+++ dcop/dcopserver.cpp (cópia de trabalho)
@@ -1443,13 +1443,13 @@
qDebug("DCOP: register '%s' -> number of clients is now %d", app2.data(), \
currentClientNumber ); #endif
}
-#ifndef NDEBUG
else
{
oldAppId = conn->appId;
+#ifndef NDEBUG
qDebug("DCOP: '%s' now known as '%s'", conn->appId.data(), app2.data() );
+#endif
}
-#endif
conn->appId = app2;
if ( appIds.find( app2 ) != 0 ) {
@@ -1472,9 +1472,12 @@
else
conn->plainAppId = conn->appId;
- if( !oldAppId.isEmpty())
+ if( !oldAppId.isEmpty()) {
+ broadcastApplicationRegistration( conn,
+ "applicationRenamed(QCString,QCString)", oldAppId, conn->appId );
broadcastApplicationRegistration( conn,
"applicationRemoved(QCString)", oldAppId );
+ }
broadcastApplicationRegistration( conn, "applicationRegistered(QCString)", \
conn->appId ); }
replyType = "QCString";
@@ -1558,10 +1561,38 @@
}
void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
- const QCString& appId )
+ const QCString oldAppId, const QCString appId )
{
QByteArray data;
QDataStream datas( data, IO_WriteOnly );
+ datas << oldAppId << appId;
+ QPtrDictIterator<DCOPConnection> it( clients );
+ QByteArray ba;
+ QDataStream ds( ba, IO_WriteOnly );
+ ds <<QCString("DCOPServer") << QCString("") << QCString("")
+ << type << data;
+ int datalen = ba.size();
+ DCOPMsg *pMsg = 0;
+ while ( it.current() ) {
+ DCOPConnection* c = it.current();
+ ++it;
+ if ( c->notifyRegister && (c != conn) ) {
+ IceGetHeader( c->iceConn, majorOpcode, DCOPSend,
+ sizeof(DCOPMsg), DCOPMsg, pMsg );
+ pMsg->key = 1;
+ pMsg->length += datalen;
+ _DCOPIceSendBegin(c->iceConn);
+ DCOPIceSendData( c->iceConn, ba );
+ _DCOPIceSendEnd();
+ }
+ }
+}
+
+void DCOPServer::broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
+ const QCString appId )
+{
+ QByteArray data;
+ QDataStream datas( data, IO_WriteOnly );
datas << appId;
QPtrDictIterator<DCOPConnection> it( clients );
QByteArray ba;
Index: dcop/dcopclient.h
===================================================================
--- dcop/dcopclient.h (revisão 424083)
+++ dcop/dcopclient.h (cópia de trabalho)
@@ -638,7 +638,7 @@
/**
* Enables / disables the applicationRegistered() /
- * applicationRemoved() signals.
+ * applicationRemoved() / applicationRenamed() signals.
* Note that a counter is maintained about how often this method
* was called. If this method is called twice with @p enabled set to
* true, notifications will be enabled until it was called with
@@ -749,6 +749,19 @@
void applicationRemoved( const QCString& appId );
/**
+ * Indicates that the application @p oldAppId has changed its
+ * name to @p newAppId.
+ *
+ * You need to call @ref setNotifications() first, to tell the @ref DCOPServer
+ * that you want to get these events.
+ *
+ * For backward compatibility, applicationRenamed() is immediatelly followed
+ * by matching @ref applicationRemoved() and @ref applicationRegistered()
+ * calls.
+ */
+ void applicationRenamed( const QCString& oldAppId, const QCString& newAppId );
+
+ /**
* Indicates that the process of establishing DCOP communications failed
* in some manner.
*
Index: dcop/dcopserver.h
===================================================================
--- dcop/dcopserver.h (revisão 424083)
+++ dcop/dcopserver.h (cópia de trabalho)
@@ -154,7 +154,9 @@
#endif
private:
void broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
- const QCString& data );
+ const QCString oldAppId, const QCString appId );
+ void broadcastApplicationRegistration( DCOPConnection* conn, const QCString type,
+ const QCString data );
bool suicide;
bool shutdown;
int majorOpcode;
Index: dcop/dcopclient.cpp
===================================================================
--- dcop/dcopclient.cpp (revisão 424083)
+++ dcop/dcopclient.cpp (cópia de trabalho)
@@ -1590,6 +1590,12 @@
ds >> r;
emit applicationRemoved( r );
return true;
+ } else if ( fun == "applicationRenamed(QCString,QCString)" ) {
+ QDataStream ds( data, IO_ReadOnly );
+ QCString r1, r2;
+ ds >> r1 >> r2;
+ emit applicationRenamed( r1, r2 );
+ return true;
}
if ( process( fun, data, replyType, replyData ) )
[Attachment #6 (application/pgp-signature)]
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic