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