[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-optimize
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/signed)]

[Attachment #4 (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 #8 (application/pgp-signature)]

_______________________________________________
Kde-optimize mailing list
Kde-optimize@kde.org
https://mail.kde.org/mailman/listinfo/kde-optimize


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic