kde-workspace/ksplash/ksplashx/main.cpp
2015-07-13 19:51:51 +03:00

158 lines
5.1 KiB
C++

/********************************************************************
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
Please see file LICENSE for the licensing terms of ksplashx as a whole.
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 "pixmap.h"
#include "splash.h"
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <math.h>
int screen_number = 0;
int number_of_screens = 1;
static void usage( char* name )
{
fprintf( stderr, "Usage: %s <theme> [--test] [--pid]\n", name );
exit( 1 );
}
int main( int argc, char* argv[] )
{
if( argc != 2 && argc != 3 && argc != 4 )
usage( argv[ 0 ] );
bool test = false;
bool print_pid = false;
int* cpid = 0;
for( int i = 2; // 1 is the theme
i < argc;
++i )
{
if( strcmp( argv[ i ], "--test" ) == 0 )
test = true;
else if( strcmp( argv[ i ], "--pid" ) == 0 )
print_pid = true;
else
usage( argv[ 0 ] );
}
const char* theme = argv[ 1 ];
if( strcmp( theme, "DefaultFullscreen" ) == 0 )
theme = "Default"; // these are now the same
int parent_pipe = -1;
if( print_pid )
{
int pipes[ 2 ];
if( pipe( pipes ) < 0 )
{
perror( "pipe()" );
abort();
}
pid_t pid = fork();
if( pid < 0 )
{
perror( "fork()" );
abort();
}
if( pid == 0 )
{ // child
close( pipes[ 0 ] );
parent_pipe = pipes[ 1 ];
close( 0 ); // close stdin,stdout,stderr, otherwise startkde will block
close( 1 );
close( 2 );
Display* dpy = XOpenDisplay(NULL);
if (!dpy)
{
exit(1);
}
number_of_screens = ScreenCount(dpy);
if (number_of_screens > 1)
{
cpid = (int*)calloc(number_of_screens, sizeof(int));
screen_number = DefaultScreen(dpy);
char* display_name;
display_name = XDisplayString(dpy);
int breakpos = strlen(display_name);
for (int i = strlen(display_name) - 1; i >= 0; i--)
{
if (display_name[i] == '.')
{
breakpos = i;
break;
}
}
// Calculate the array size: part before the dot + length of the screen
// string (which is log10 + 1) + 1 for the dot itself + 8 for "DISPLAY=" + \0
const int envir_len = breakpos + log10(static_cast<double>(number_of_screens)) + 11;
char *envir = new char[envir_len];
char *server_name = new char[breakpos + 1];
strncpy(server_name, display_name, breakpos);
server_name[breakpos] = '\0';
XCloseDisplay(dpy);
dpy = 0;
for (int i = 0; i < number_of_screens; i++)
{
if (i != screen_number)
{
cpid[i] = fork();
if (cpid[i] == 0)
{
screen_number = i;
// Break here because we are the child process, we don't
// want to fork() anymore
break;
}
}
}
snprintf(envir, envir_len, "DISPLAY=%s.%d", server_name, screen_number);
putenv(strdup(envir));
delete[] envir;
delete[] server_name;
}
else
XCloseDisplay(dpy);
}
else
{ // parent
close( pipes[ 1 ] );
char buf;
while( read( pipes[ 0 ], &buf, 1 ) < 0
&& ( errno == EINTR || errno == EAGAIN || errno == ECHILD ))
;
if( print_pid )
printf( "%d\n", pid );
return 0;
}
}
if( !openDisplay())
return 2;
if( test )
XSynchronize( qt_xdisplay(), True );
runSplash( theme, test, parent_pipe );
closeDisplay();
if (number_of_screens > 1)
{
for (int i = 1; i < number_of_screens; i++)
kill(cpid[i], SIGTERM);
}
free(cpid);
}