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