|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 1999 David Faure (maintainer)
|
|
|
|
|
|
|
|
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., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <kuniqueapplication.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <dcopclient.h>
|
|
|
|
#include <kaboutdata.h>
|
|
|
|
#include <kcmdlineargs.h>
|
|
|
|
#include <kopenwith.h>
|
|
|
|
#include <kcrash.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kglobalsettings.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <kmanagerselection.h>
|
|
|
|
|
|
|
|
#include "desktop.h"
|
|
|
|
#include "lockeng.h"
|
|
|
|
#include "init.h"
|
|
|
|
#include "krootwm.h"
|
|
|
|
#include "kdesktopsettings.h"
|
|
|
|
#include "kdesktopapp.h"
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#if defined(Q_WS_X11) && defined(HAVE_XRENDER) && QT_VERSION >= 0x030300
|
|
|
|
#define COMPOSITE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef COMPOSITE
|
|
|
|
# include <X11/Xlib.h>
|
|
|
|
# include <X11/extensions/Xrender.h>
|
|
|
|
# include <fixx11h.h>
|
|
|
|
# include <dlfcn.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static const char description[] =
|
|
|
|
I18N_NOOP("The KDE desktop");
|
|
|
|
|
|
|
|
static const char version[] = VERSION;
|
|
|
|
|
|
|
|
static KCmdLineOptions options[] =
|
|
|
|
{
|
|
|
|
{ "x-root", I18N_NOOP("Use this if the desktop window appears as a real window"), 0 },
|
|
|
|
{ "noautostart", I18N_NOOP("Obsolete"), 0 },
|
|
|
|
{ "waitforkded", I18N_NOOP("Wait for kded to finish building database"), 0 },
|
|
|
|
#ifdef COMPOSITE
|
|
|
|
{ "bg-transparency", I18N_NOOP("Enable background transparency"), 0 },
|
|
|
|
#endif
|
|
|
|
KCmdLineLastOption
|
|
|
|
};
|
|
|
|
|
|
|
|
bool argb_visual = false;
|
|
|
|
KDesktopApp *myApp = NULL;
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
int kdesktop_screen_number = 0;
|
|
|
|
TQCString kdesktop_name, kicker_name, kwin_name;
|
|
|
|
|
|
|
|
static void crashHandler(int sigId)
|
|
|
|
{
|
|
|
|
DCOPClient::emergencyClose(); // unregister DCOP
|
|
|
|
sleep( 1 );
|
|
|
|
system("kdesktop &"); // try to restart
|
|
|
|
fprintf(stderr, "*** kdesktop (%ld) got signal %d\n", (long) getpid(), sigId);
|
|
|
|
::exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void signalHandler(int sigId)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "*** kdesktop got signal %d (Exiting)\n", sigId);
|
|
|
|
KCrash::setEmergencySaveFunction(0); // No restarts any more
|
|
|
|
// try to cleanup all windows
|
|
|
|
signal(SIGTERM, SIG_DFL); // next one kills
|
|
|
|
signal(SIGHUP, SIG_DFL); // next one kills
|
|
|
|
if (kapp)
|
|
|
|
kapp->quit(); // turn catchable signals into clean shutdown
|
|
|
|
}
|
|
|
|
|
|
|
|
void KDesktop::slotUpAndRunning()
|
|
|
|
{
|
|
|
|
// Activate crash recovery
|
|
|
|
if (getenv("KDE_DEBUG") == NULL)
|
|
|
|
KCrash::setEmergencySaveFunction(crashHandler); // Try to restart on crash
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" KDE_EXPORT int kdemain( int argc, char **argv )
|
|
|
|
{
|
|
|
|
//setup signal handling
|
|
|
|
signal(SIGTERM, signalHandler);
|
|
|
|
signal(SIGHUP, signalHandler);
|
|
|
|
|
|
|
|
{
|
|
|
|
if (KGlobalSettings::isMultiHead())
|
|
|
|
{
|
|
|
|
Display *dpy = XOpenDisplay(NULL);
|
|
|
|
if (! dpy) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: FATAL ERROR: couldn't open display '%s'\n",
|
|
|
|
argv[0], XDisplayName(NULL));
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int number_of_screens = ScreenCount(dpy);
|
|
|
|
kdesktop_screen_number = DefaultScreen(dpy);
|
|
|
|
int pos;
|
|
|
|
TQCString display_name = XDisplayString(dpy);
|
|
|
|
XCloseDisplay(dpy);
|
|
|
|
dpy = 0;
|
|
|
|
|
|
|
|
if ((pos = display_name.findRev('.')) != -1)
|
|
|
|
display_name.remove(pos, 10);
|
|
|
|
|
|
|
|
TQCString env;
|
|
|
|
if (number_of_screens != 1) {
|
|
|
|
for (int i = 0; i < number_of_screens; i++) {
|
|
|
|
if (i != kdesktop_screen_number && fork() == 0) {
|
|
|
|
kdesktop_screen_number = i;
|
|
|
|
// break here because we are the child process, we don't
|
|
|
|
// want to fork() anymore
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
env.sprintf("DISPLAY=%s.%d", display_name.data(),
|
|
|
|
kdesktop_screen_number);
|
|
|
|
|
|
|
|
if (putenv(strdup(env.data()))) {
|
|
|
|
fprintf(stderr,
|
|
|
|
"%s: WARNING: unable to set DISPLAY environment variable\n",
|
|
|
|
argv[0]);
|
|
|
|
perror("putenv()");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
KGlobal::locale()->setMainCatalogue("kdesktop");
|
|
|
|
|
|
|
|
if (kdesktop_screen_number == 0) {
|
|
|
|
kdesktop_name = "kdesktop";
|
|
|
|
kicker_name = "kicker";
|
|
|
|
kwin_name = "kwin";
|
|
|
|
} else {
|
|
|
|
kdesktop_name.sprintf("kdesktop-screen-%d", kdesktop_screen_number);
|
|
|
|
kicker_name.sprintf("kicker-screen-%d", kdesktop_screen_number);
|
|
|
|
kwin_name.sprintf("kwin-screen-%d", kdesktop_screen_number);
|
|
|
|
}
|
|
|
|
|
|
|
|
KAboutData aboutData( kdesktop_name, I18N_NOOP("KDesktop"),
|
|
|
|
version, description, KAboutData::License_GPL,
|
|
|
|
"(c) 1998-2000, The KDesktop Authors");
|
|
|
|
aboutData.addAuthor("David Faure", 0, "faure@kde.org");
|
|
|
|
aboutData.addAuthor("Martin Koller", 0, "m.koller@surfeu.at");
|
|
|
|
aboutData.addAuthor("Waldo Bastian", 0, "bastian@kde.org");
|
|
|
|
aboutData.addAuthor("Luboš Luňák", 0, "l.lunak@kde.org");
|
|
|
|
aboutData.addAuthor("Joseph Wenninger", 0, "kde@jowenn.at");
|
|
|
|
aboutData.addAuthor("Tim Jansen", 0, "tim@tjansen.de");
|
|
|
|
aboutData.addAuthor("Benoit Walter", 0, "b.walter@free.fr");
|
|
|
|
aboutData.addAuthor("Torben Weis", 0, "weis@kde.org");
|
|
|
|
aboutData.addAuthor("Matthias Ettrich", 0, "ettrich@kde.org");
|
|
|
|
|
|
|
|
KCmdLineArgs::init( argc, argv, &aboutData );
|
|
|
|
KCmdLineArgs::addCmdLineOptions( options );
|
|
|
|
|
|
|
|
if (!KUniqueApplication::start()) {
|
|
|
|
fprintf(stderr, "kdesktop is already running!\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
DCOPClient* cl = new DCOPClient;
|
|
|
|
cl->attach();
|
|
|
|
DCOPRef r( "ksmserver", "ksmserver" );
|
|
|
|
r.setDCOPClient( cl );
|
|
|
|
r.send( "suspendStartup", TQCString( "kdesktop" ));
|
|
|
|
delete cl;
|
|
|
|
|
|
|
|
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
|
|
|
|
|
|
|
#ifdef COMPOSITE
|
|
|
|
|
|
|
|
KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt");
|
|
|
|
|
|
|
|
if ( args->isSet("bg-transparency")) {
|
|
|
|
char *display = 0;
|
|
|
|
if ( qtargs->isSet("display"))
|
|
|
|
display = qtargs->getOption( "display" ).data();
|
|
|
|
|
|
|
|
Display *dpy = XOpenDisplay( display );
|
|
|
|
if ( !dpy ) {
|
|
|
|
kdError() << "cannot connect to X server " << display << endl;
|
|
|
|
exit( 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
int screen = DefaultScreen( dpy );
|
|
|
|
|
|
|
|
Visual *visual = 0;
|
|
|
|
int event_base, error_base;
|
|
|
|
|
|
|
|
if ( XRenderQueryExtension( dpy, &event_base, &error_base ) ) {
|
|
|
|
int nvi;
|
|
|
|
XVisualInfo templ;
|
|
|
|
templ.screen = screen;
|
|
|
|
templ.depth = 32;
|
|
|
|
templ.c_class = TrueColor;
|
|
|
|
XVisualInfo *xvi = XGetVisualInfo( dpy, VisualScreenMask
|
|
|
|
| VisualDepthMask | VisualClassMask, &templ, &nvi );
|
|
|
|
|
|
|
|
for ( int i = 0; i < nvi; i++ ) {
|
|
|
|
XRenderPictFormat *format =
|
|
|
|
XRenderFindVisualFormat( dpy, xvi[i].visual );
|
|
|
|
if ( format->type == PictTypeDirect && format->direct.alphaMask ) {
|
|
|
|
visual = xvi[i].visual;
|
|
|
|
kdDebug() << "found visual with alpha support" << endl;
|
|
|
|
argb_visual = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// The TQApplication ctor used is normally intended for applications not using Qt
|
|
|
|
// as the primary toolkit (e.g. Motif apps also using Qt), with some slightly
|
|
|
|
// unpleasant side effects (e.g. #83974). This code checks if qt-copy patch #0078
|
|
|
|
// is applied, which allows turning this off.
|
|
|
|
bool* qt_no_foreign_hack =
|
|
|
|
static_cast< bool* >( dlsym( RTLD_DEFAULT, "qt_no_foreign_hack" ));
|
|
|
|
if( qt_no_foreign_hack )
|
|
|
|
*qt_no_foreign_hack = true;
|
|
|
|
// else argb_visual = false ... ? *shrug*
|
|
|
|
if( argb_visual )
|
|
|
|
myApp = new KDesktopApp( dpy, Qt::HANDLE( visual ), 0 );
|
|
|
|
else
|
|
|
|
XCloseDisplay( dpy );
|
|
|
|
}
|
|
|
|
if( myApp == NULL )
|
|
|
|
myApp = new KDesktopApp;
|
|
|
|
#else
|
|
|
|
myApp = new KDesktopApp;
|
|
|
|
#endif
|
|
|
|
myApp->disableSessionManagement(); // Do SM, but don't restart.
|
|
|
|
|
|
|
|
KDesktopSettings::instance(kdesktop_name + "rc");
|
|
|
|
|
|
|
|
bool x_root_hack = args->isSet("x-root");
|
|
|
|
bool wait_for_kded = args->isSet("waitforkded");
|
|
|
|
|
|
|
|
// This MUST be created before any widgets are created
|
|
|
|
SaverEngine saver;
|
|
|
|
|
|
|
|
// Do this before forking so that if a dialog box appears it won't
|
|
|
|
// be covered by other apps.
|
|
|
|
// And before creating KDesktop too, of course.
|
|
|
|
testLocalInstallation();
|
|
|
|
|
|
|
|
// Mark kdeskop as immutable if all of its config modules have been disabled
|
|
|
|
if (!myApp->config()->isImmutable() &&
|
|
|
|
kapp->authorizeControlModules(KRootWm::configModules()).isEmpty())
|
|
|
|
{
|
|
|
|
myApp->config()->setReadOnly(true);
|
|
|
|
myApp->config()->reparseConfiguration();
|
|
|
|
}
|
|
|
|
|
|
|
|
// for the KDE-already-running check in startkde
|
|
|
|
KSelectionOwner kde_running( "_KDE_RUNNING", 0 );
|
|
|
|
kde_running.claim( false );
|
|
|
|
|
|
|
|
KDesktop desktop( x_root_hack, wait_for_kded );
|
|
|
|
|
|
|
|
args->clear();
|
|
|
|
|
|
|
|
myApp->dcopClient()->setDefaultObject( "KDesktopIface" );
|
|
|
|
|
|
|
|
|
|
|
|
return myApp->exec();
|
|
|
|
}
|