add more spacing
[personal-kdebase.git] / workspace / ksplash / simple / main.cpp
bloba67c6ff951499d47de4a7c458daba87841f0cae9
1 /***************************************************************************
2 * Copyright 2004 Lubos Lunak <l.lunak@kde.org> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License (version 2) as *
6 * published by the Free Software Foundation. (The original KSplash/ML *
7 * codebase (upto version 0.95.3) is BSD-licensed.) *
8 * *
9 ***************************************************************************/
11 #include <config-workspace.h>
13 #include <X11/Xlib.h>
14 #include <X11/Xutil.h>
15 #include <config-X11.h>
16 #ifdef HAVE_XINERAMA
17 extern "C" { // for older XFree86 versions
18 #include <X11/extensions/Xinerama.h>
20 #endif
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <string.h>
25 # ifdef HAVE_SYS_TIME_H
26 # include <sys/time.h>
27 # endif
28 #include <time.h>
31 //#define DEBUG
33 int main( int argc, char* argv[])
35 bool small = false;
36 bool test = false;
37 bool print_pid = false;
38 for( int i = 1;
39 i < argc;
40 ++i )
42 if( strcmp( argv[ i ], "--test" ) == 0 )
43 test = true;
44 if( strcmp( argv[ i ], "--pid" ) == 0 )
45 print_pid = true;
46 if( strcmp( argv[ i ], "SimpleSmall" ) == 0 )
47 small = true;
49 pid_t pid = fork();
50 if( pid < -1 )
52 perror( "fork()" );
53 return -1;
55 if( pid != 0 )
56 { // parent
57 if( print_pid )
58 printf( "%d\n", pid );
59 return 0;
61 // child
62 close( 0 ); // close stdin,stdout,stderr, otherwise startkde will block
63 close( 1 );
64 close( 2 );
65 Display* dpy = XOpenDisplay( NULL );
66 if( dpy == NULL )
67 return 1;
68 int sx, sy, sw, sh;
69 Window* wins = NULL;
70 int wins_count = 0;
71 #ifdef HAVE_XINERAMA
72 // Xinerama code from Qt
73 XineramaScreenInfo *xinerama_screeninfo = 0;
74 int unused;
75 bool use_xinerama = XineramaQueryExtension( dpy, &unused, &unused )
76 && XineramaIsActive( dpy );
77 if (use_xinerama)
79 int screenCount;
80 xinerama_screeninfo = XineramaQueryScreens( dpy, &screenCount );
81 sx = xinerama_screeninfo[ 0 ].x_org;
82 sy = xinerama_screeninfo[ 0 ].y_org;
83 sw = xinerama_screeninfo[ 0 ].width;
84 sh = xinerama_screeninfo[ 0 ].height;
85 if( !small )
86 { // create windows covering other xinerama screens
87 wins_count = screenCount;
88 wins = new Window[ wins_count ];
89 for( int i = 1; // not 0
90 i < wins_count;
91 ++i )
93 XSetWindowAttributes attrs;
94 attrs.override_redirect = True;
95 attrs.background_pixel = BlackPixel( dpy, 0 ); // background
96 wins[ i ] = XCreateWindow( dpy, DefaultRootWindow( dpy ),
97 xinerama_screeninfo[ i ].x_org, xinerama_screeninfo[ i ].y_org,
98 xinerama_screeninfo[ i ].width, xinerama_screeninfo[ i ].height,
99 0, CopyFromParent, CopyFromParent, CopyFromParent,
100 CWOverrideRedirect | CWBackPixel, &attrs );
104 else
105 #endif
107 sx = sy = 0;
108 sw = WidthOfScreen( ScreenOfDisplay( dpy, DefaultScreen( dpy )));
109 sh = HeightOfScreen( ScreenOfDisplay( dpy, DefaultScreen( dpy )));
111 XSetWindowAttributes attrs;
112 attrs.override_redirect = True;
113 const int states = 6;
114 const int frame = 3;
115 const int segment = sw / 2 / states;
116 const int pw = segment * states + 2 * frame; // size of progressbar
117 const int ph = sh / 20 + frame;
118 const int px = small ? 0 : sx + ( sw - pw ) / 2; // position in the pixmap
119 const int py = small ? 0 : sy + ( sh - ph ) / 2;
120 const int x = small ? sx + ( sw - pw ) / 2 : sx; // position of the window
121 const int y = small ? sy + ( sh - ph ) / 2 : sy;
122 const int w = small ? pw : sw;
123 const int h = small ? ph : sh;
124 if( wins == NULL )
126 wins = new Window[ 1 ];
127 wins_count = 1;
129 Window win = XCreateWindow( dpy, DefaultRootWindow( dpy ), x, y, w, h,
130 0, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attrs );
131 wins[ 0 ] = win;
132 Pixmap pix = XCreatePixmap( dpy, DefaultRootWindow( dpy ), w, h, DefaultDepth( dpy, 0 ));
133 XGCValues values;
134 values.foreground = BlackPixel( dpy, 0 ); // background
135 GC gc = XCreateGC( dpy, pix, GCForeground, &values );
136 XFillRectangle( dpy, pix, gc, 0, 0, w, h );
137 values.foreground = WhitePixel( dpy, 0 ); // outline
138 XChangeGC( dpy, gc, GCForeground, &values );
139 XFillRectangle( dpy, pix, gc, px, py, pw, ph );
140 values.foreground = BlackPixel( dpy, 0 ); // progressbar
141 XChangeGC( dpy, gc, GCForeground, &values );
142 XSetWindowBackgroundPixmap( dpy, win, pix );
143 XSelectInput( dpy, DefaultRootWindow( dpy ), SubstructureNotifyMask );
144 for( int i = 0;
145 i < wins_count;
146 ++i )
148 XSelectInput( dpy, wins[ i ], ButtonPressMask );
149 XClassHint class_hint;
150 class_hint.res_name = const_cast< char* >( "ksplashsimple" );
151 class_hint.res_class = const_cast< char* >( "ksplashsimple" );
152 XSetWMProperties( dpy, wins[ i ], NULL, NULL, NULL, NULL, NULL, NULL, &class_hint );
153 XMapWindow( dpy, wins[ i ] );
155 int pos = 0;
156 int state = 1; // cannot check dcop connection - make this state initial
157 const int delay = 200; // ms
158 time_t final_time = time( NULL ) + 300;
159 time_t test_time = time( NULL ) + 1;
160 Atom kde_splash_progress = XInternAtom( dpy, "_KDE_SPLASH_PROGRESS", False );
161 for(;;)
163 while( XPending( dpy ))
165 XEvent ev;
166 XNextEvent( dpy, &ev );
167 if( ev.type == ButtonPress && ev.xbutton.button == Button1 )
169 final_time = time( NULL );
170 break;
172 if( ev.type == ConfigureNotify && ev.xconfigure.event == DefaultRootWindow( dpy ))
174 XRaiseWindow( dpy, wins[ 0 ] );
175 if( wins_count > 1 )
176 XRestackWindows( dpy, wins, wins_count );
178 if( ev.type == ClientMessage && ev.xclient.window == DefaultRootWindow( dpy )
179 && ev.xclient.message_type == kde_splash_progress )
181 // these are also in ksplashx and in krunner
182 const char* s = ev.xclient.data.b;
183 #ifdef DEBUG
184 fprintf( stderr,"MESSAGE: %s\n", s );
185 #endif
186 if( strcmp( s, "initial" ) == 0 && state < 0 )
187 state = 0; // not actually used
188 else if( strcmp( s, "kded" ) == 0 && state < 1 )
189 state = 1;
190 else if( strcmp( s, "confupdate" ) == 0 && state < 2 )
191 state = 2;
192 else if( strcmp( s, "kcminit" ) == 0 && state < 3 )
193 state = 3;
194 else if( strcmp( s, "ksmserver" ) == 0 && state < 4 )
195 state = 4;
196 else if( strcmp( s, "wm" ) == 0 && state < 5 )
197 state = 5;
198 else if( strcmp( s, "desktop" ) == 0 && state < 6 )
199 state = 6;
200 // This last one isn't used, make splash go away as soon as desktop is ready.
201 // else if( strcmp( s, "ready" ) == 0 && state < 7 )
202 // state = 7;
205 if( test && time( NULL ) >= test_time )
207 ++state;
208 test_time = time( NULL ) + 1;
210 if( pos != state )
212 while( pos < state && pos < states )
214 #ifdef DEBUG
215 fprintf( stderr, "POS: %d\n", pos );
216 #endif
217 XFillRectangle( dpy, pix, gc, px + frame + pos * segment, py + frame, segment, ph - 2 * frame );
218 XSetWindowBackgroundPixmap( dpy, win, pix );
219 XClearWindow( dpy, win );
220 ++pos;
221 if( pos >= states )
223 #ifdef DEBUG
224 fprintf( stderr, "CLOSING DOWN\n" );
225 #endif
226 final_time = time( NULL ) + 2;
230 fd_set set;
231 FD_ZERO( &set );
232 FD_SET( XConnectionNumber( dpy ), &set );
233 struct timeval tv;
234 tv.tv_sec = 0;
235 tv.tv_usec = delay * 1000;
236 select( XConnectionNumber( dpy ) + 1, &set, NULL, NULL, &tv );
237 if( time( NULL ) >= final_time )
239 #ifdef DEBUG
240 fprintf( stderr, "EXITING\n" );
241 #endif
242 break; // --->
245 XFreePixmap( dpy, pix );
246 for( int i = 0;
247 i < wins_count;
248 ++i )
249 XDestroyWindow( dpy, wins[ i ] );
250 delete[] wins;
251 XFreeGC( dpy, gc );
252 XCloseDisplay( dpy );