• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • twin
 

twin

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 <tdeconfig.h>
00014 
00015 #include "main.h"
00016 
00017 #include <tdelocale.h>
00018 #include <tdeglobal.h>
00019 #include <kdebug.h>
00020 #include <stdlib.h>
00021 #include <tdecmdlineargs.h>
00022 #include <tdeaboutdata.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 namespace KWinInternal
00040 {
00041 
00042 Options* options;
00043 
00044 Atoms* atoms;
00045 
00046 int screen_number = -1;
00047 bool disable_twin_composition_manager = false;
00048 
00049 static bool initting = FALSE;
00050 
00051 static
00052 int x11ErrorHandler(Display *d, XErrorEvent *e)
00053     {
00054     char msg[80], req[80], number[80];
00055     bool ignore_badwindow = TRUE; //maybe temporary
00056 
00057     if (initting &&
00058         (
00059          e->request_code == X_ChangeWindowAttributes
00060          || e->request_code == X_GrabKey
00061          )
00062         && (e->error_code == BadAccess)) 
00063         {
00064         fputs(i18n("[twin] it looks like there's already a window manager running. twin not started.\n").local8Bit(), stderr);
00065         exit(1);
00066         }
00067 
00068     if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor))
00069         return 0;
00070 
00071     XGetErrorText(d, e->error_code, msg, sizeof(msg));
00072     sprintf(number, "%d", e->request_code);
00073     XGetErrorDatabaseText(d, "XRequest", number, "<unknown>", req, sizeof(req));
00074 
00075     fprintf(stderr, "[twin] %s(0x%lx): %s\n", req, e->resourceid, msg);
00076 
00077     if (initting) 
00078         {
00079         fputs(i18n("[twin] failure during initialization; aborting").local8Bit(), stderr);
00080         exit(1);
00081         }
00082     return 0;
00083     }
00084 
00085 Application::Application( )
00086 : TDEApplication( ), owner( screen_number )
00087     {
00088 #ifdef USE_QT4
00089     // I'm special...
00090     setQuitOnLastWindowClosed(false);
00091 #endif // USE_QT4
00092     TDECmdLineArgs* args = TDECmdLineArgs::parsedArgs();
00093     if (!config()->isImmutable() && args->isSet("lock"))
00094         {
00095         config()->setReadOnly(true);
00096         config()->reparseConfiguration();
00097         }
00098 
00099     if (screen_number == -1) {
00100         screen_number = DefaultScreen(tqt_xdisplay());
00101     }
00102 
00103     if (args->isSet( "disablecompositionmanager" )) {
00104         disable_twin_composition_manager = true;
00105     }
00106 
00107     if( !owner.claim( args->isSet( "replace" ), true ))
00108         {
00109         Display* dpy = tqt_xdisplay();
00110         Window w;
00111         Atom a;
00112         static char net_wm_sm[] = "WM_Sxx";
00113 
00114         snprintf (net_wm_sm, sizeof (net_wm_sm), "WM_S%d", screen_number);
00115         a = XInternAtom (dpy, net_wm_sm, False);
00116 
00117         w = XGetSelectionOwner (dpy, a);
00118 
00119         if (w != None)
00120             {
00121             Atom actual;
00122             int format;
00123             unsigned long n, left;
00124             unsigned char *data;
00125             Atom twinRunningAtom = XInternAtom (dpy, "_KDE_WM_IS_KWIN", True);
00126 
00127             int result = XGetWindowProperty (dpy, w, twinRunningAtom, 0L, 1L, False,
00128                 XA_ATOM, &actual, &format,
00129                 &n, &left, &data);
00130 
00131             if (result == Success && data != None && format == 32 )
00132                 {
00133                 Atom a;
00134                 a = *(long*)data;
00135                 XFree ( (void *) data);
00136                 if( !owner.claim( true, true ))
00137                     {
00138                     fputs(i18n("[twin] unable to claim manager selection, another wm running? (try using --replace)\n").local8Bit(), stderr);
00139                     ::exit(1);
00140                     }
00141                 }
00142             else
00143                 {
00144                 fputs(i18n("[twin] unable to claim manager selection, another wm running? (try using --replace)\n").local8Bit(), stderr);
00145                 ::exit(1);
00146                 }
00147             }
00148         else
00149             {
00150             fputs(i18n("[twin] unable to claim manager selection, another wm running? (try using --replace)\n").local8Bit(), stderr);
00151             ::exit(1);
00152             }
00153         }
00154     connect( &owner, TQT_SIGNAL( lostOwnership()), TQT_SLOT( lostSelection()));
00155     
00156     // if there was already twin running, it saved its configuration after loosing the selection -> reread
00157     config()->reparseConfiguration();
00158 
00159     initting = TRUE; // startup....
00160 
00161     // install X11 error handler
00162     XSetErrorHandler( x11ErrorHandler );
00163 
00164     // check  whether another windowmanager is running
00165     XSelectInput(tqt_xdisplay(), tqt_xrootwin(), SubstructureRedirectMask  );
00166     syncX(); // trigger error now
00167 
00168     options = new Options;
00169     atoms = new Atoms;
00170 
00171     // Signal that we are The KWin!
00172     Atom kde_wm_system_modal_notification;
00173     kde_wm_system_modal_notification = XInternAtom(tqt_xdisplay(), "_KDE_WM_IS_KWIN", False);
00174     XChangeProperty(tqt_xdisplay(), owner.ownerWindow(), kde_wm_system_modal_notification, XA_INTEGER, 32, PropModeReplace, (unsigned char *) "TRUE", 1L);
00175 
00176     // create workspace.
00177     (void) new Workspace( isSessionRestored() );
00178 
00179     syncX(); // trigger possible errors, there's still a chance to abort
00180 
00181     DCOPRef ref( "kded", "kded" );
00182     ref.send( "unloadModule", TQCString( "kdetrayproxy" ));
00183     
00184     initting = FALSE; // startup done, we are up and running now.
00185        
00186     dcopClient()->send( "ksplash", "", "upAndRunning(TQString)", TQString("wm started"));
00187     XEvent e;
00188     e.xclient.type = ClientMessage;
00189     e.xclient.message_type = XInternAtom( tqt_xdisplay(), "_KDE_SPLASH_PROGRESS", False );
00190     e.xclient.display = tqt_xdisplay();
00191     e.xclient.window = tqt_xrootwin();
00192     e.xclient.format = 8;
00193     strcpy( e.xclient.data.b, "wm started" );
00194     XSendEvent( tqt_xdisplay(), tqt_xrootwin(), False, SubstructureNotifyMask, &e );
00195     }
00196 
00197 Application::~Application()
00198     {
00199     delete Workspace::self();
00200     if( owner.ownerWindow() != None ) // if there was no --replace (no new WM)
00201         {
00202         XSetInputFocus( tqt_xdisplay(), PointerRoot, RevertToPointerRoot, GET_QT_X_TIME() );
00203         DCOPRef ref( "kded", "kded" );
00204         if( !ref.send( "loadModule", TQCString( "kdetrayproxy" )))
00205             kdWarning( 176 ) << "Loading of kdetrayproxy failed." << endl;
00206         }
00207     delete options;
00208     }
00209 
00210 void Application::lostSelection()
00211     {
00212     delete Workspace::self();
00213     // remove windowmanager privileges
00214     XSelectInput(tqt_xdisplay(), tqt_xrootwin(), PropertyChangeMask );
00215     DCOPRef ref( "kded", "kded" );
00216     if( !ref.send( "loadModule", TQCString( "kdetrayproxy" )))
00217         kdWarning( 176 ) << "Loading of kdetrayproxy failed." << endl;
00218     quit();
00219     }
00220 
00221 bool Application::x11EventFilter( XEvent *e )
00222     {
00223     if ( Workspace::self()->workspaceEvent( e ) )
00224              return TRUE;
00225     return TDEApplication::x11EventFilter( e );
00226     }
00227     
00228 static void sighandler(int) 
00229     {
00230     TQApplication::exit();
00231     }
00232 
00233 
00234 } // namespace
00235 
00236 static const char version[] = "3.0";
00237 static const char description[] = I18N_NOOP( "TDE window manager" );
00238 
00239 static TDECmdLineOptions args[] =
00240     {
00241         { "lock", I18N_NOOP("Disable configuration options"), 0 },
00242         { "replace", I18N_NOOP("Replace already-running ICCCM2.0-compliant window manager"), 0 },
00243         { "disablecompositionmanager", I18N_NOOP("Do not start composition manager"), 0 },
00244         TDECmdLineLastOption
00245     };
00246 
00247 extern "C"
00248 KDE_EXPORT int kdemain( int argc, char * argv[] )
00249     {
00250     bool restored = false;
00251     for (int arg = 1; arg < argc; arg++) 
00252         {
00253         if (! qstrcmp(argv[arg], "-session")) 
00254             {
00255             restored = true;
00256             break;
00257             }
00258         }
00259 
00260     if (! restored) 
00261         {
00262         // we only do the multihead fork if we are not restored by the session
00263     // manager, since the session manager will register multiple twins,
00264         // one for each screen...
00265         TQCString multiHead = getenv("TDE_MULTIHEAD");
00266         if (multiHead.lower() == "true") 
00267             {
00268 
00269             Display* dpy = XOpenDisplay( NULL );
00270             if ( !dpy ) 
00271                 {
00272                 fprintf(stderr, "%s: FATAL ERROR while trying to open display %s\n",
00273                         argv[0], XDisplayName(NULL ) );
00274                 exit (1);
00275                 }
00276 
00277             int number_of_screens = ScreenCount( dpy );
00278             KWinInternal::screen_number = DefaultScreen( dpy );
00279             int pos; // temporarily needed to reconstruct DISPLAY var if multi-head
00280             TQCString display_name = XDisplayString( dpy );
00281             XCloseDisplay( dpy );
00282             dpy = 0;
00283 
00284             if ((pos = display_name.findRev('.')) != -1 )
00285                 display_name.remove(pos,10); // 10 is enough to be sure we removed ".s"
00286 
00287             TQCString envir;
00288             if (number_of_screens != 1) 
00289                 {
00290                 for (int i = 0; i < number_of_screens; i++ ) 
00291                     {
00292             // if execution doesn't pass by here, then twin
00293             // acts exactly as previously
00294                     if ( i != KWinInternal::screen_number && fork() == 0 ) 
00295                         {
00296                         KWinInternal::screen_number = i;
00297             // break here because we are the child process, we don't
00298             // want to fork() anymore
00299                         break;
00300                         }
00301                     }
00302         // in the next statement, display_name shouldn't contain a screen
00303         //   number. If it had it, it was removed at the "pos" check
00304                 envir.sprintf("DISPLAY=%s.%d", display_name.data(), KWinInternal::screen_number);
00305 
00306                 if (putenv( strdup(envir.data())) ) 
00307                     {
00308                     fprintf(stderr,
00309                             "[twin] %s: WARNING: unable to set DISPLAY environment variable\n",
00310                             argv[0]);
00311                     perror("[twin] putenv()");
00312                     }
00313                 }
00314             }
00315         }
00316 
00317     TDEGlobal::locale()->setMainCatalogue("twin");
00318 
00319     TDEAboutData aboutData( "twin", I18N_NOOP("TWin"),
00320                           version, description, TDEAboutData::License_GPL,
00321                           I18N_NOOP("(c) 1999-2005, The KDE Developers"));
00322     aboutData.addAuthor("Matthias Ettrich",0, "ettrich@kde.org");
00323     aboutData.addAuthor("Cristian Tibirna",0, "tibirna@kde.org");
00324     aboutData.addAuthor("Daniel M. Duley",0, "mosfet@kde.org");
00325     aboutData.addAuthor("Luboš Luňák", I18N_NOOP( "Maintainer" ), "l.lunak@kde.org");
00326 
00327     TDECmdLineArgs::init(argc, argv, &aboutData);
00328     TDECmdLineArgs::addCmdLineOptions( args );
00329 
00330     if (signal(SIGTERM, KWinInternal::sighandler) == SIG_IGN)
00331         signal(SIGTERM, SIG_IGN);
00332     if (signal(SIGINT, KWinInternal::sighandler) == SIG_IGN)
00333         signal(SIGINT, SIG_IGN);
00334     if (signal(SIGHUP, KWinInternal::sighandler) == SIG_IGN)
00335         signal(SIGHUP, SIG_IGN);
00336 
00337     TDEApplication::disableAutoDcopRegistration();
00338     KWinInternal::Application a;
00339     KWinInternal::SessionManaged weAreIndeed;
00340     KWinInternal::SessionSaveDoneHelper helper;
00341 
00342     fcntl(ConnectionNumber(tqt_xdisplay()), F_SETFD, 1);
00343 
00344     TQCString appname;
00345     if (KWinInternal::screen_number == 0)
00346         appname = "twin";
00347     else
00348         appname.sprintf("twin-screen-%d", KWinInternal::screen_number);
00349 
00350     DCOPClient* client = a.dcopClient();
00351     client->registerAs( appname.data(), false);
00352     client->setDefaultObject( "KWinInterface" );
00353 
00354     return a.exec();
00355     }
00356 
00357 #include "main.moc"

twin

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

twin

Skip menu "twin"
  • kate
  • libkonq
  • twin
  •   lib
Generated for twin by doxygen 1.7.1
This website is maintained by Timothy Pearson.