• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • @topname@
  • Sitemap
  • Contact Us
 

kwin

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 <kglobal.h>
00019 #include <kdebug.h>
00020 #include <stdlib.h>
00021 #include <kcmdlineargs.h>
00022 #include <kaboutdata.h>
00023 #include <dcopclient.h>
00024 #include <dcopref.h>
00025 #include <unistd.h>
00026 #include <signal.h>
00027 #include <fcntl.h>
00028 
00029 #include "atoms.h"
00030 #include "options.h"
00031 #include "sm.h"
00032 
00033 #define INT8 _X11INT8
00034 #define INT32 _X11INT32
00035 #include <X11/Xproto.h>
00036 #undef INT8
00037 #undef INT32
00038 
00039 extern Time qt_x_time;
00040 
00041 namespace KWinInternal
00042 {
00043 
00044 Options* options;
00045 
00046 Atoms* atoms;
00047 
00048 int screen_number = -1;
00049 
00050 static bool initting = FALSE;
00051 
00052 static
00053 int x11ErrorHandler(Display *d, XErrorEvent *e)
00054     {
00055     char msg[80], req[80], number[80];
00056     bool ignore_badwindow = TRUE; //maybe temporary
00057 
00058     if (initting &&
00059         (
00060          e->request_code == X_ChangeWindowAttributes
00061          || e->request_code == X_GrabKey
00062          )
00063         && (e->error_code == BadAccess)) 
00064         {
00065         fputs(i18n("kwin: it looks like there's already a window manager running. kwin not started.\n").local8Bit(), stderr);
00066         exit(1);
00067         }
00068 
00069     if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor))
00070         return 0;
00071 
00072     XGetErrorText(d, e->error_code, msg, sizeof(msg));
00073     sprintf(number, "%d", e->request_code);
00074     XGetErrorDatabaseText(d, "XRequest", number, "<unknown>", req, sizeof(req));
00075 
00076     fprintf(stderr, "kwin: %s(0x%lx): %s\n", req, e->resourceid, msg);
00077 
00078     if (initting) 
00079         {
00080         fputs(i18n("kwin: failure during initialization; aborting").local8Bit(), stderr);
00081         exit(1);
00082         }
00083     return 0;
00084     }
00085 
00086 Application::Application( )
00087 : KApplication( ), owner( screen_number )
00088     {
00089     KCmdLineArgs* args = KCmdLineArgs::parsedArgs();
00090     if (!config()->isImmutable() && args->isSet("lock"))
00091         {
00092         config()->setReadOnly(true);
00093         config()->reparseConfiguration();
00094         }
00095 
00096     if (screen_number == -1)
00097         screen_number = DefaultScreen(qt_xdisplay());
00098 
00099     if( !owner.claim( args->isSet( "replace" ), true ))
00100         {
00101         fputs(i18n("kwin: unable to claim manager selection, another wm running? (try using --replace)\n").local8Bit(), stderr);
00102         ::exit(1);
00103         }
00104     connect( &owner, SIGNAL( lostOwnership()), SLOT( lostSelection()));
00105     
00106     // if there was already kwin running, it saved its configuration after loosing the selection -> reread
00107     config()->reparseConfiguration();
00108 
00109     initting = TRUE; // startup....
00110 
00111     // install X11 error handler
00112     XSetErrorHandler( x11ErrorHandler );
00113 
00114     // check  whether another windowmanager is running
00115     XSelectInput(qt_xdisplay(), qt_xrootwin(), SubstructureRedirectMask  );
00116     syncX(); // trigger error now
00117 
00118     options = new Options;
00119     atoms = new Atoms;
00120 
00121     // create workspace.
00122     (void) new Workspace( isSessionRestored() );
00123 
00124     syncX(); // trigger possible errors, there's still a chance to abort
00125 
00126     DCOPRef ref( "kded", "kded" );
00127     ref.send( "unloadModule", QCString( "kdetrayproxy" ));
00128     
00129     initting = FALSE; // startup done, we are up and running now.
00130        
00131     dcopClient()->send( "ksplash", "", "upAndRunning(QString)", QString("wm started"));
00132     XEvent e;
00133     e.xclient.type = ClientMessage;
00134     e.xclient.message_type = XInternAtom( qt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
00135     e.xclient.display = qt_xdisplay();
00136     e.xclient.window = qt_xrootwin();
00137     e.xclient.format = 8;
00138     strcpy( e.xclient.data.b, "wm started" );
00139     XSendEvent( qt_xdisplay(), qt_xrootwin(), False, SubstructureNotifyMask, &e );
00140     }
00141 
00142 Application::~Application()
00143     {
00144     delete Workspace::self();
00145     if( owner.ownerWindow() != None ) // if there was no --replace (no new WM)
00146         {
00147         XSetInputFocus( qt_xdisplay(), PointerRoot, RevertToPointerRoot, qt_x_time );
00148         DCOPRef ref( "kded", "kded" );
00149         if( !ref.send( "loadModule", QCString( "kdetrayproxy" )))
00150             kdWarning( 176 ) << "Loading of kdetrayproxy failed." << endl;
00151         }
00152     delete options;
00153     }
00154 
00155 void Application::lostSelection()
00156     {
00157     delete Workspace::self();
00158     // remove windowmanager privileges
00159     XSelectInput(qt_xdisplay(), qt_xrootwin(), PropertyChangeMask );
00160     DCOPRef ref( "kded", "kded" );
00161     if( !ref.send( "loadModule", QCString( "kdetrayproxy" )))
00162         kdWarning( 176 ) << "Loading of kdetrayproxy failed." << endl;
00163     quit();
00164     }
00165 
00166 bool Application::x11EventFilter( XEvent *e )
00167     {
00168     if ( Workspace::self()->workspaceEvent( e ) )
00169              return TRUE;
00170     return KApplication::x11EventFilter( e );
00171     }
00172     
00173 static void sighandler(int) 
00174     {
00175     QApplication::exit();
00176     }
00177 
00178 
00179 } // namespace
00180 
00181 static const char version[] = "3.0";
00182 static const char description[] = I18N_NOOP( "KDE window manager" );
00183 
00184 static KCmdLineOptions args[] =
00185     {
00186         { "lock", I18N_NOOP("Disable configuration options"), 0 },
00187         { "replace", I18N_NOOP("Replace already-running ICCCM2.0-compliant window manager"), 0 },
00188         KCmdLineLastOption
00189     };
00190 
00191 extern "C"
00192 KDE_EXPORT int kdemain( int argc, char * argv[] )
00193     {
00194     bool restored = false;
00195     for (int arg = 1; arg < argc; arg++) 
00196         {
00197         if (! qstrcmp(argv[arg], "-session")) 
00198             {
00199             restored = true;
00200             break;
00201             }
00202         }
00203 
00204     if (! restored) 
00205         {
00206         // we only do the multihead fork if we are not restored by the session
00207     // manager, since the session manager will register multiple kwins,
00208         // one for each screen...
00209         QCString multiHead = getenv("KDE_MULTIHEAD");
00210         if (multiHead.lower() == "true") 
00211             {
00212 
00213             Display* dpy = XOpenDisplay( NULL );
00214             if ( !dpy ) 
00215                 {
00216                 fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
00217                         argv[0], XDisplayName(NULL ) );
00218                 exit (1);
00219                 }
00220 
00221             int number_of_screens = ScreenCount( dpy );
00222             KWinInternal::screen_number = DefaultScreen( dpy );
00223             int pos; // temporarily needed to reconstruct DISPLAY var if multi-head
00224             QCString display_name = XDisplayString( dpy );
00225             XCloseDisplay( dpy );
00226             dpy = 0;
00227 
00228             if ((pos = display_name.findRev('.')) != -1 )
00229                 display_name.remove(pos,10); // 10 is enough to be sure we removed ".s"
00230 
00231             QCString envir;
00232             if (number_of_screens != 1) 
00233                 {
00234                 for (int i = 0; i < number_of_screens; i++ ) 
00235                     {
00236             // if execution doesn't pass by here, then kwin
00237             // acts exactly as previously
00238                     if ( i != KWinInternal::screen_number && fork() == 0 ) 
00239                         {
00240                         KWinInternal::screen_number = i;
00241             // break here because we are the child process, we don't
00242             // want to fork() anymore
00243                         break;
00244                         }
00245                     }
00246         // in the next statement, display_name shouldn't contain a screen
00247         //   number. If it had it, it was removed at the "pos" check
00248                 envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWinInternal::screen_number);
00249 
00250                 if (putenv( strdup(envir.data())) ) 
00251                     {
00252                     fprintf(stderr,
00253                             "%s: WARNING: unable to set DISPLAY environment variable\n",
00254                             argv[0]);
00255                     perror("putenv()");
00256                     }
00257                 }
00258             }
00259         }
00260 
00261     KGlobal::locale()->setMainCatalogue("kwin");
00262 
00263     KAboutData aboutData( "kwin", I18N_NOOP("KWin"),
00264                           version, description, KAboutData::License_GPL,
00265                           I18N_NOOP("(c) 1999-2005, The KDE Developers"));
00266     aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org");
00267     aboutData.addAuthor("Cristian Tibirna",0, "tibirna@kde.org");
00268     aboutData.addAuthor("Daniel M. Duley",0, "mosfet@kde.org");
00269     aboutData.addAuthor("Luboš Luňák", I18N_NOOP( "Maintainer" ), "l.lunak@kde.org");
00270 
00271     KCmdLineArgs::init(argc, argv, &aboutData);
00272     KCmdLineArgs::addCmdLineOptions( args );
00273 
00274     if (signal(SIGTERM, KWinInternal::sighandler) == SIG_IGN)
00275         signal(SIGTERM, SIG_IGN);
00276     if (signal(SIGINT, KWinInternal::sighandler) == SIG_IGN)
00277         signal(SIGINT, SIG_IGN);
00278     if (signal(SIGHUP, KWinInternal::sighandler) == SIG_IGN)
00279         signal(SIGHUP, SIG_IGN);
00280 
00281     KApplication::disableAutoDcopRegistration();
00282     KWinInternal::Application a;
00283     KWinInternal::SessionManaged weAreIndeed;
00284     KWinInternal::SessionSaveDoneHelper helper;
00285 
00286     fcntl(ConnectionNumber(qt_xdisplay()), F_SETFD, 1);
00287 
00288     QCString appname;
00289     if (KWinInternal::screen_number == 0)
00290         appname = "kwin";
00291     else
00292         appname.sprintf("kwin-screen-%d", KWinInternal::screen_number);
00293 
00294     DCOPClient* client = a.dcopClient();
00295     client->registerAs( appname.data(), false);
00296     client->setDefaultObject( "KWinInterface" );
00297 
00298     return a.exec();
00299     }
00300 
00301 #include "main.moc"

kwin

Skip menu "kwin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

@topname@

Skip menu "@topname@"
  • kate
  • kwin
  •   lib
  • libkonq
Generated for @topname@ by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal