mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-27 04:13:02 +00:00
278 lines
10 KiB
C++
278 lines
10 KiB
C++
/***************************************************************************
|
|
* Copyright 2004 Lubos Lunak <l.lunak@kde.org> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <config-workspace.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
#include <X11/Xutil.h>
|
|
#include <config-X11.h>
|
|
#ifdef HAVE_XINERAMA
|
|
extern "C" { // for older XFree86 versions
|
|
#include <X11/extensions/Xinerama.h>
|
|
}
|
|
#endif
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
|
|
# ifdef HAVE_SYS_TIME_H
|
|
# include <sys/time.h>
|
|
# endif
|
|
#include <time.h>
|
|
|
|
|
|
//#define DEBUG
|
|
|
|
int main( int argc, char* argv[])
|
|
{
|
|
bool small = false;
|
|
bool test = false;
|
|
bool print_pid = false;
|
|
for( int i = 1;
|
|
i < argc;
|
|
++i )
|
|
{
|
|
if( strcmp( argv[ i ], "--test" ) == 0 )
|
|
test = true;
|
|
if( strcmp( argv[ i ], "--pid" ) == 0 )
|
|
print_pid = true;
|
|
if( strcmp( argv[ i ], "SimpleSmall" ) == 0 )
|
|
small = true;
|
|
}
|
|
pid_t pid = fork();
|
|
if( pid < -1 )
|
|
{
|
|
perror( "fork()" );
|
|
return -1;
|
|
}
|
|
if( pid != 0 )
|
|
{ // parent
|
|
if( print_pid )
|
|
printf( "%d\n", pid );
|
|
return 0;
|
|
}
|
|
// child
|
|
close( 0 ); // close stdin,stdout,stderr, otherwise startkde will block
|
|
close( 1 );
|
|
close( 2 );
|
|
Display* dpy = XOpenDisplay( NULL );
|
|
if( dpy == NULL )
|
|
return 1;
|
|
int sx, sy, sw, sh;
|
|
Window* wins = NULL;
|
|
int wins_count = 0;
|
|
#ifdef HAVE_XINERAMA
|
|
// Xinerama code from Qt
|
|
XineramaScreenInfo *xinerama_screeninfo = 0;
|
|
int unused;
|
|
bool use_xinerama = XineramaQueryExtension( dpy, &unused, &unused )
|
|
&& XineramaIsActive( dpy );
|
|
if (use_xinerama)
|
|
{
|
|
int screenCount;
|
|
xinerama_screeninfo = XineramaQueryScreens( dpy, &screenCount );
|
|
sx = xinerama_screeninfo[ 0 ].x_org;
|
|
sy = xinerama_screeninfo[ 0 ].y_org;
|
|
sw = xinerama_screeninfo[ 0 ].width;
|
|
sh = xinerama_screeninfo[ 0 ].height;
|
|
if( !small )
|
|
{ // create windows covering other xinerama screens
|
|
wins_count = screenCount;
|
|
wins = new Window[ wins_count ];
|
|
for( int i = 1; // not 0
|
|
i < wins_count;
|
|
++i )
|
|
{
|
|
XSetWindowAttributes attrs;
|
|
attrs.override_redirect = True;
|
|
attrs.background_pixel = BlackPixel( dpy, 0 ); // background
|
|
wins[ i ] = XCreateWindow( dpy, DefaultRootWindow( dpy ),
|
|
xinerama_screeninfo[ i ].x_org, xinerama_screeninfo[ i ].y_org,
|
|
xinerama_screeninfo[ i ].width, xinerama_screeninfo[ i ].height,
|
|
0, CopyFromParent, CopyFromParent, CopyFromParent,
|
|
CWOverrideRedirect | CWBackPixel, &attrs );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
sx = sy = 0;
|
|
sw = WidthOfScreen( ScreenOfDisplay( dpy, DefaultScreen( dpy )));
|
|
sh = HeightOfScreen( ScreenOfDisplay( dpy, DefaultScreen( dpy )));
|
|
}
|
|
XSetWindowAttributes attrs;
|
|
attrs.override_redirect = True;
|
|
const int states = 6;
|
|
const int frame = 3;
|
|
const int segment = sw / 2 / states;
|
|
const int pw = segment * states + 2 * frame; // size of progressbar
|
|
const int ph = sh / 20 + frame;
|
|
const int px = small ? 0 : sx + ( sw - pw ) / 2; // position in the pixmap
|
|
const int py = small ? 0 : sy + ( sh - ph ) / 2;
|
|
const int x = small ? sx + ( sw - pw ) / 2 : sx; // position of the window
|
|
const int y = small ? sy + ( sh - ph ) / 2 : sy;
|
|
const int w = small ? pw : sw;
|
|
const int h = small ? ph : sh;
|
|
if( wins == NULL )
|
|
{
|
|
wins = new Window[ 1 ];
|
|
wins_count = 1;
|
|
}
|
|
Window win = XCreateWindow( dpy, DefaultRootWindow( dpy ), x, y, w, h,
|
|
0, CopyFromParent, CopyFromParent, CopyFromParent, CWOverrideRedirect, &attrs );
|
|
wins[ 0 ] = win;
|
|
Pixmap pix = XCreatePixmap( dpy, DefaultRootWindow( dpy ), w, h, DefaultDepth( dpy, 0 ));
|
|
XGCValues values;
|
|
values.foreground = BlackPixel( dpy, 0 ); // background
|
|
GC gc = XCreateGC( dpy, pix, GCForeground, &values );
|
|
XFillRectangle( dpy, pix, gc, 0, 0, w, h );
|
|
values.foreground = WhitePixel( dpy, 0 ); // outline
|
|
XChangeGC( dpy, gc, GCForeground, &values );
|
|
XFillRectangle( dpy, pix, gc, px, py, pw, ph );
|
|
values.foreground = BlackPixel( dpy, 0 ); // progressbar
|
|
XChangeGC( dpy, gc, GCForeground, &values );
|
|
XSetWindowBackgroundPixmap( dpy, win, pix );
|
|
XSelectInput( dpy, DefaultRootWindow( dpy ), SubstructureNotifyMask );
|
|
for( int i = 0;
|
|
i < wins_count;
|
|
++i )
|
|
{
|
|
XSelectInput( dpy, wins[ i ], ButtonPressMask );
|
|
XClassHint class_hint;
|
|
class_hint.res_name = const_cast< char* >( "ksplashsimple" );
|
|
class_hint.res_class = const_cast< char* >( "ksplashsimple" );
|
|
XSetWMProperties( dpy, wins[ i ], NULL, NULL, NULL, 0, NULL, NULL, &class_hint );
|
|
XMapWindow( dpy, wins[ i ] );
|
|
}
|
|
int pos = 0;
|
|
int state = 1; // cannot check dcop connection - make this state initial
|
|
const int delay = 200; // ms
|
|
const int doubleclick_delay = 200; // mouse doubleclick delay - in ms
|
|
time_t final_time = time( NULL ) + 300;
|
|
time_t test_time = time( NULL ) + 1;
|
|
struct timeval button_press_time, current_time; // we need timeval to deal with milliseconds
|
|
button_press_time.tv_sec = 0;
|
|
button_press_time.tv_usec = 0;
|
|
long click_delay, click_delay_seconds, click_delay_useconds;
|
|
Atom kde_splash_progress = XInternAtom( dpy, "_KDE_SPLASH_PROGRESS", False );
|
|
for(;;)
|
|
{
|
|
while( XPending( dpy ))
|
|
{
|
|
XEvent ev;
|
|
XNextEvent( dpy, &ev );
|
|
if( ev.type == ButtonPress && ev.xbutton.button == Button1 )
|
|
{
|
|
gettimeofday( ¤t_time, NULL );
|
|
|
|
// find difference in milliseconds with current and previous mouse presses times
|
|
click_delay_seconds = current_time.tv_sec - button_press_time.tv_sec;
|
|
click_delay_useconds = current_time.tv_usec - button_press_time.tv_usec;
|
|
click_delay = ( click_delay_seconds * 1000 + click_delay_useconds / 1000.0 ) + 0.5;
|
|
|
|
if( click_delay <= doubleclick_delay )
|
|
{
|
|
// close splash on doubleclick
|
|
final_time = time( NULL );
|
|
break;
|
|
}
|
|
gettimeofday( &button_press_time, NULL );
|
|
}
|
|
if( ev.type == ConfigureNotify && ev.xconfigure.event == DefaultRootWindow( dpy ))
|
|
{
|
|
XRaiseWindow( dpy, wins[ 0 ] );
|
|
if( wins_count > 1 )
|
|
XRestackWindows( dpy, wins, wins_count );
|
|
}
|
|
if( ev.type == ClientMessage && ev.xclient.window == DefaultRootWindow( dpy )
|
|
&& ev.xclient.message_type == kde_splash_progress )
|
|
{
|
|
// these are also in ksplashx and in krunner
|
|
const char* s = ev.xclient.data.b;
|
|
#ifdef DEBUG
|
|
fprintf( stderr,"MESSAGE: %s\n", s );
|
|
#endif
|
|
if( strcmp( s, "initial" ) == 0 && state < 0 )
|
|
state = 0; // not actually used
|
|
else if( strcmp( s, "kded" ) == 0 && state < 1 )
|
|
state = 1;
|
|
else if( strcmp( s, "confupdate" ) == 0 && state < 2 )
|
|
state = 2;
|
|
else if( strcmp( s, "kcminit" ) == 0 && state < 3 )
|
|
state = 3;
|
|
else if( strcmp( s, "ksmserver" ) == 0 && state < 4 )
|
|
state = 4;
|
|
else if( strcmp( s, "wm" ) == 0 && state < 5 )
|
|
state = 5;
|
|
else if( strcmp( s, "desktop" ) == 0 && state < 6 )
|
|
state = 6;
|
|
// This last one isn't used, make splash go away as soon as desktop is ready.
|
|
// else if( strcmp( s, "ready" ) == 0 && state < 7 )
|
|
// state = 7;
|
|
}
|
|
}
|
|
if( test && time( NULL ) >= test_time )
|
|
{
|
|
++state;
|
|
test_time = time( NULL ) + 1;
|
|
}
|
|
if( pos != state )
|
|
{
|
|
while( pos < state && pos < states )
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf( stderr, "POS: %d\n", pos );
|
|
#endif
|
|
XFillRectangle( dpy, pix, gc, px + frame + pos * segment, py + frame, segment, ph - 2 * frame );
|
|
XSetWindowBackgroundPixmap( dpy, win, pix );
|
|
XClearWindow( dpy, win );
|
|
++pos;
|
|
if( pos >= states )
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf( stderr, "CLOSING DOWN\n" );
|
|
#endif
|
|
final_time = time( NULL ) + 2;
|
|
}
|
|
}
|
|
}
|
|
fd_set set;
|
|
FD_ZERO( &set );
|
|
FD_SET( XConnectionNumber( dpy ), &set );
|
|
struct timeval tv;
|
|
tv.tv_sec = 0;
|
|
tv.tv_usec = delay * 1000;
|
|
select( XConnectionNumber( dpy ) + 1, &set, NULL, NULL, &tv );
|
|
if( time( NULL ) >= final_time )
|
|
{
|
|
#ifdef DEBUG
|
|
fprintf( stderr, "EXITING\n" );
|
|
#endif
|
|
break; // --->
|
|
}
|
|
}
|
|
XFreePixmap( dpy, pix );
|
|
for( int i = 0;
|
|
i < wins_count;
|
|
++i )
|
|
XDestroyWindow( dpy, wins[ i ] );
|
|
delete[] wins;
|
|
XFreeGC( dpy, gc );
|
|
XCloseDisplay( dpy );
|
|
}
|