kwin Library API Documentation

main.cpp

00001 /*****************************************************************
00002  KWin - the KDE window manager
00003  This file is part of the KDE project.
00004 
00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
00006 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
00007 
00008 You can Freely distribute this program under the GNU General Public
00009 License. See the file "COPYING" for the exact licensing terms.
00010 ******************************************************************/
00011 
00012 //#define QT_CLEAN_NAMESPACE
00013 #include <kconfig.h>
00014 
00015 #include "main.h"
00016 
00017 #include <klocale.h>
00018 #include <stdlib.h>
00019 #include <kcmdlineargs.h>
00020 #include <kaboutdata.h>
00021 #include <dcopclient.h>
00022 #include <unistd.h>
00023 #include <signal.h>
00024 #include <fcntl.h>
00025 
00026 #include "atoms.h"
00027 #include "options.h"
00028 #include "sm.h"
00029 
00030 #define INT8 _X11INT8
00031 #define INT32 _X11INT32
00032 #include <X11/Xproto.h>
00033 #undef INT8
00034 #undef INT32
00035 
00036 namespace KWinInternal
00037 {
00038 
00039 Options* options;
00040 
00041 Atoms* atoms;
00042 
00043 int screen_number = -1;
00044 
00045 static bool initting = FALSE;
00046 
00047 static
00048 int x11ErrorHandler(Display *d, XErrorEvent *e)
00049     {
00050     char msg[80], req[80], number[80];
00051     bool ignore_badwindow = TRUE; //maybe temporary
00052 
00053     if (initting &&
00054         (
00055          e->request_code == X_ChangeWindowAttributes
00056          || e->request_code == X_GrabKey
00057          )
00058         && (e->error_code == BadAccess))
00059         {
00060         fputs(i18n("kwin: it looks like there's already a window manager running. kwin not started.\n").local8Bit(), stderr);
00061         exit(1);
00062         }
00063 
00064     if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor))
00065         return 0;
00066 
00067     XGetErrorText(d, e->error_code, msg, sizeof(msg));
00068     sprintf(number, "%d", e->request_code);
00069     XGetErrorDatabaseText(d, "XRequest", number, "<unknown>", req, sizeof(req));
00070 
00071     fprintf(stderr, "kwin: %s(0x%lx): %s\n", req, e->resourceid, msg);
00072 
00073     if (initting)
00074         {
00075         fputs(i18n("kwin: failure during initialization; aborting").local8Bit(), stderr);
00076         exit(1);
00077         }
00078     return 0;
00079     }
00080 
00081 Application::Application( )
00082 : KApplication( ), owner( screen_number )
00083     {
00084     KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
00085     if (!config()->isImmutable() && args->isSet("lock"))
00086         {
00087         config()->setReadOnly(true);
00088         config()->reparseConfiguration();
00089         }
00090 
00091     if (screen_number == -1)
00092         screen_number = DefaultScreen(qt_xdisplay());
00093 
00094     if( !owner.claim( args->isSet( "replace" ), true ))
00095         {
00096         fputs(i18n("kwin: unable to claim manager selection, another wm running? (try using --replace)\n").local8Bit(), stderr);
00097         ::exit(1);
00098         }
00099     connect( &owner, SIGNAL( lostOwnership()), SLOT( lostSelection()));
00100 
00101     initting = TRUE; // startup....
00102 
00103     // install X11 error handler
00104     XSetErrorHandler( x11ErrorHandler );
00105 
00106     // check  whether another windowmanager is running
00107     XSelectInput(qt_xdisplay(), qt_xrootwin(), SubstructureRedirectMask  );
00108     syncX(); // trigger error now
00109 
00110     options = new Options;
00111     atoms = new Atoms;
00112 
00113     // create workspace.
00114     (void) new Workspace( isSessionRestored() );
00115 
00116     syncX(); // trigger possible errors, there's still a chance to abort
00117 
00118     initting = FALSE; // startup done, we are up and running now.
00119     dcopClient()->send( "ksplash", "", "upAndRunning(QString)", QString("wm started"));
00120     }
00121 
00122 
00123 Application::~Application()
00124     {
00125     delete Workspace::self();
00126     XSetInputFocus( qt_xdisplay(), PointerRoot, RevertToPointerRoot, CurrentTime );
00127     delete options;
00128     }
00129 
00130 void Application::lostSelection()
00131     {
00132     delete Workspace::self();
00133     // remove windowmanager privileges
00134     XSelectInput(qt_xdisplay(), qt_xrootwin(), PropertyChangeMask );
00135     quit();
00136     }
00137 
00138 bool Application::x11EventFilter( XEvent *e )
00139     {
00140     if ( Workspace::self()->workspaceEvent( e ) )
00141              return TRUE;
00142     return KApplication::x11EventFilter( e );
00143     }
00144 
00145 static void sighandler(int)
00146     {
00147     QApplication::exit();
00148     }
00149 
00150 
00151 } // namespace
00152 
00153 static const char version[] = "3.0";
00154 static const char description[] = I18N_NOOP( "The KDE window manager." );
00155 
00156 static KCmdLineOptions args[] =
00157     {
00158         { "lock", I18N_NOOP("Disable configuration options"), 0 },
00159         { "replace", I18N_NOOP("Replace already running ICCCM2.0 compliant window manager."), 0 },
00160         KCmdLineLastOption
00161     };
00162 
00163 extern "C"
00164 int kdemain( int argc, char * argv[] )
00165     {
00166     bool restored = false;
00167     for (int arg = 1; arg < argc; arg++)
00168         {
00169         if (! qstrcmp(argv[arg], "-session"))
00170             {
00171             restored = true;
00172             break;
00173             }
00174         }
00175 
00176     if (! restored)
00177         {
00178         // we only do the multihead fork if we are not restored by the session
00179     // manager, since the session manager will register multiple kwins,
00180         // one for each screen...
00181         QCString multiHead = getenv("KDE_MULTIHEAD");
00182         if (multiHead.lower() == "true")
00183             {
00184 
00185             Display* dpy = XOpenDisplay( NULL );
00186             if ( !dpy )
00187                 {
00188                 fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
00189                         argv[0], XDisplayName(NULL ) );
00190                 exit (1);
00191                 }
00192 
00193             int number_of_screens = ScreenCount( dpy );
00194             KWinInternal::screen_number = DefaultScreen( dpy );
00195             int pos; // temporarily needed to reconstruct DISPLAY var if multi-head
00196             QCString display_name = XDisplayString( dpy );
00197             XCloseDisplay( dpy );
00198             dpy = 0;
00199 
00200             if ((pos = display_name.findRev('.')) != -1 )
00201                 display_name.remove(pos,10); // 10 is enough to be sure we removed ".s"
00202 
00203             QCString envir;
00204             if (number_of_screens != 1)
00205                 {
00206                 for (int i = 0; i < number_of_screens; i++ )
00207                     {
00208             // if execution doesn't pass by here, then kwin
00209             // acts exactly as previously
00210                     if ( i != KWinInternal::screen_number && fork() == 0 )
00211                         {
00212                         KWinInternal::screen_number = i;
00213             // break here because we are the child process, we don't
00214             // want to fork() anymore
00215                         break;
00216                         }
00217                     }
00218         // in the next statement, display_name shouldn't contain a screen
00219         //   number. If it had it, it was removed at the "pos" check
00220                 envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWinInternal::screen_number);
00221 
00222                 if (putenv( strdup(envir.data())) )
00223                     {
00224                     fprintf(stderr,
00225                             "%s: WARNING: unable to set DISPLAY environment variable\n",
00226                             argv[0]);
00227                     perror("putenv()");
00228                     }
00229                 }
00230             }
00231         }
00232 
00233     KAboutData aboutData( "kwin", I18N_NOOP("KWin"),
00234                           version, description, KAboutData::License_GPL,
00235                           I18N_NOOP("(c) 1999-2003, The KDE Developers"));
00236     aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org");
00237     aboutData.addAuthor("Cristian Tibirna",0, "tibirna@kde.org");
00238     aboutData.addAuthor("Daniel M. Duley",0, "mosfet@kde.org");
00239     aboutData.addAuthor("Lubos Lunak", 0, "l.lunak@kde.org");
00240 
00241     KCmdLineArgs::init(argc, argv, &aboutData);
00242     KCmdLineArgs::addCmdLineOptions( args );
00243 
00244     if (signal(SIGTERM, KWinInternal::sighandler) == SIG_IGN)
00245         signal(SIGTERM, SIG_IGN);
00246     if (signal(SIGINT, KWinInternal::sighandler) == SIG_IGN)
00247         signal(SIGINT, SIG_IGN);
00248     if (signal(SIGHUP, KWinInternal::sighandler) == SIG_IGN)
00249         signal(SIGHUP, SIG_IGN);
00250 
00251     KApplication::disableAutoDcopRegistration();
00252     KWinInternal::Application a;
00253     KWinInternal::SessionManaged weAreIndeed;
00254     KWinInternal::SessionSaveDoneHelper helper;
00255 
00256     fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, 1);
00257 
00258     QCString appname;
00259     if (KWinInternal::screen_number == 0)
00260         appname = "kwin";
00261     else
00262         appname.sprintf("kwin-screen-%d", KWinInternal::screen_number);
00263 
00264     DCOPClient* client = a.dcopClient();
00265     client->registerAs( appname.data(), false);
00266     client->setDefaultObject( "KWinInterface" );
00267 
00268     return a.exec();
00269     }
00270 
00271 #include "main.moc"
KDE Logo
This file is part of the documentation for kwin Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Apr 29 21:20:52 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003