2 Copyright (c) 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include <config-workspace.h>
29 #include <kapplication.h>
30 #include <kcmdlineargs.h>
31 #include <kaboutdata.h>
33 #include <klibloader.h>
36 #include <kconfiggroup.h>
38 #include <ktoolinvocation.h>
39 #include <klauncher_iface.h>
40 #include <QtDBus/QtDBus>
46 #include <kservicetypetrader.h>
49 static int ready
[ 2 ];
50 static bool startup
= false;
52 static void sendReady()
54 if( ready
[ 1 ] == -1 )
57 write( ready
[ 1 ], &c
, 1 );
62 static void waitForReady()
66 read( ready
[ 0 ], &c
, 1 );
70 bool KCMInit::runModule(const QString
&libName
, KLibLoader
*loader
, KService::Ptr service
)
72 KLibrary
*lib
= loader
->library(libName
);
74 QVariant tmp
= service
->property("X-KDE-Init-Symbol", QVariant::String
);
78 kcminit
= tmp
.toString();
79 if( !kcminit
.startsWith( QLatin1String( "kcminit_" ) ) )
80 kcminit
= "kcminit_" + kcminit
;
83 kcminit
= "kcminit_" + libName
;
85 // get the kcminit_ function
86 KLibrary::void_function_ptr init
= lib
->resolveFunction(kcminit
.toUtf8());
88 // initialize the module
89 kDebug(1208) << "Initializing " << libName
<< ": " << kcminit
;
91 void (*func
)() = (void(*)())init
;
95 loader
->unloadLibrary(libName
);
100 void KCMInit::runModules( int phase
)
102 KLibLoader
*loader
= KLibLoader::self();
103 for(KService::List::Iterator it
= list
.begin();
106 KService::Ptr service
= (*it
);
108 QVariant tmp
= service
->property("X-KDE-Init-Library", QVariant::String
);
112 library
= tmp
.toString();
113 if( !library
.startsWith( QLatin1String( "kcminit_" ) ) )
114 library
= QLatin1String( "kcminit_" ) + library
;
118 library
= service
->library();
121 if (library
.isEmpty())
124 // see ksmserver's README for the description of the phases
125 QVariant vphase
= service
->property("X-KDE-Init-Phase", QVariant::Int
);
127 if( vphase
.isValid() )
128 libphase
= vphase
.toInt();
130 if( phase
!= -1 && libphase
!= phase
)
133 // try to load the library
134 if (! alreadyInitialized
.contains( library
.toAscii() )) {
135 if (!runModule(library
, loader
, service
)) {
136 library
= QLatin1String( "lib" ) + library
;
137 if (! alreadyInitialized
.contains( library
.toAscii() )) {
138 runModule(library
, loader
, service
);
139 alreadyInitialized
.append( library
.toAscii() );
142 alreadyInitialized
.append( library
.toAscii() );
147 KCMInit::KCMInit( KCmdLineArgs
* args
)
149 QDBusConnection::sessionBus().registerObject("/kcminit", this,
150 QDBusConnection::ExportScriptableSlots
|QDBusConnection::ExportScriptableSignals
);
152 if (args
->count() == 1) {
156 if (args
->isSet("list"))
158 list
= KServiceTypeTrader::self()->query( "KCModuleInit" );
160 for(KService::List::Iterator it
= list
.begin();
164 KService::Ptr service
= (*it
);
165 if (service
->library().isEmpty())
167 printf("%s\n", QFile::encodeName(service
->desktopEntryName()).data());
172 if (!arg
.isEmpty()) {
174 QString module
= arg
;
175 if (!module
.endsWith(".desktop"))
176 module
+= ".desktop";
178 KService::Ptr serv
= KService::serviceByStorageId( module
);
179 if ( !serv
|| serv
->library().isEmpty() ) {
180 kError(1208) << i18n("Module %1 not found", module
) << endl
;
187 // locate the desktop files
188 list
= KServiceTypeTrader::self()->query( "KCModuleInit" );
191 // This key has no GUI apparently
192 KConfig
_config( "kcmdisplayrc" );
193 KConfigGroup
config(&_config
, "X11");
195 bool multihead
= !config
.readEntry( "disableMultihead", false) &&
196 (ScreenCount(QX11Info::display()) > 1);
198 bool multihead
= false;
200 // Pass env. var to kdeinit.
201 QString name
= "KDE_MULTIHEAD";
202 QString value
= multihead
? "true" : "false";
203 KToolInvocation::klauncher()->setLaunchEnv(name
, value
);
204 setenv( name
.toLatin1().constData(), value
.toLatin1().constData(), 1 ); // apply effect also to itself
210 e
.xclient
.type
= ClientMessage
;
211 e
.xclient
.message_type
= XInternAtom( QX11Info::display(), "_KDE_SPLASH_PROGRESS", False
);
212 e
.xclient
.display
= QX11Info::display();
213 e
.xclient
.window
= QX11Info::appRootWindow();
214 e
.xclient
.format
= 8;
215 strcpy( e
.xclient
.data
.b
, "kcminit" );
216 XSendEvent( QX11Info::display(), QX11Info::appRootWindow(), False
, SubstructureNotifyMask
, &e
);
218 QTimer::singleShot( 300 * 1000, qApp
, SLOT( quit())); // just in case
219 qApp
->exec(); // wait for runPhase1() and runPhase2()
222 runModules( -1 ); // all phases
230 void KCMInit::runPhase1()
236 void KCMInit::runPhase2()
243 extern "C" KDE_EXPORT
int kdemain(int argc
, char *argv
[])
245 // kdeinit waits for kcminit to finish, but during KDE startup
246 // only important kcm's are started very early in the login process,
247 // the rest is delayed, so fork and make parent return after the initial phase
256 startup
= ( strcmp( argv
[ 0 ], "kcminit_startup" ) == 0 ); // started from startkde?
257 KAboutData
aboutData( "kcminit", "kcminit", ki18n("KCMInit"),
259 ki18n("KCMInit - runs startup initialization for Control Modules."));
261 KCmdLineArgs::init(argc
, argv
, &aboutData
);
263 KCmdLineOptions options
;
264 options
.add("list", ki18n("List modules that are run at startup"));
265 options
.add("+module", ki18n("Configuration module to run"));
266 KCmdLineArgs::addCmdLineOptions( options
); // Add our own options.
269 QDBusConnection::sessionBus().interface()->registerService( "org.kde.kcminit",
270 QDBusConnectionInterface::DontQueueService
);
271 KLocale::setMainCatalog(0);
272 KCMInit
kcminit( KCmdLineArgs::parsedArgs());