Re: KIconLoader improvements: icon server
Gustavo Pichorim Boiko <[email protected]> Tue, 14 Jun 2005 11:03:25 -0300
| Newsgroups | gmane.comp.kde.devel.optimize,gmane.comp.kde.devel.core |
|---|---|
| Message-ID | <[email protected]> |
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 ----------------------------------------------------- _______________________________________________ Kde-optimize mailing list [email protected] https://mail.kde.org/mailman/listinfo/kde-optimize
kdelibs-iconserver.patch
(text/x-diff, 79.1 KB)
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 <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 <[email protected]> + Copyright (C) 2005 Gustavo Pichorim Boiko <[email protected]> + + 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 ) )
signature.asc
(application/pgp-signature, 189 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQBCruOvZQYlDr5VjykRAjRnAJ9ygPlB/At4gyq0v6TSIpGUGNEXDACfQpxo iPr+DRd//QCrMU9RvD2m48w= =nWJ5 -----END PGP SIGNATURE-----