2007-07-30 17:25:13 +04:00
|
|
|
/*
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
* Evoke, head honcho of everything
|
|
|
|
* Part of Equinox Desktop Environment (EDE).
|
|
|
|
* Copyright (c) 2000-2007 EDE Authors.
|
|
|
|
*
|
|
|
|
* This program is licensed under terms of the
|
|
|
|
* GNU General Public License version 2 or newer.
|
|
|
|
* See COPYING for details.
|
|
|
|
*/
|
|
|
|
|
2008-09-08 15:09:37 +04:00
|
|
|
#include <stdio.h> // snprintf
|
|
|
|
|
2008-09-15 15:00:23 +04:00
|
|
|
#include <FL/Fl_Shared_Image.H>
|
|
|
|
#include <FL/Fl.H>
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
#include <edelib/Run.h>
|
|
|
|
#include <edelib/Debug.h>
|
|
|
|
#include <edelib/Nls.h>
|
|
|
|
|
2008-09-08 15:09:37 +04:00
|
|
|
#include "Splash.h"
|
|
|
|
#include "Spawn.h"
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
#define TIMEOUT_START 0.5 // timeout when splash is first time shown (also for first client)
|
|
|
|
#define TIMEOUT_CONTINUE 2.0 // timeout between starting rest of the cliens
|
|
|
|
|
2007-09-20 12:47:50 +04:00
|
|
|
extern void service_watcher_cb(int pid, int signum);
|
A lot of changes, especially the ways how screen is repainted (in composite).
Composite will now draw only damaged regions, and their damage is (now) correctly
reported, mostly due changes in main FLTK loop.
Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION
is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite
way (without emulation) it will relay on FLTK message passing, but it is very unpredictable
since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due
large XDamageNotify throttling. When emulation is used, there are no such problems
since all events are processed before they are routed to FLTK.
In composite is added another way of repainting (when USE_CHECK is defined), and it will
relay on Fl::add_check() function; there are some differences between this function
and timer used for screen refresh. Timer will try to refresh it every XX ms and when
there are large number of XDamageNotify reports, this will not be suitable for
movements smoothing on the screen; on other hand add_check() will call callback every
time when event is processed, which brings smooth movements. For now only timer is used
untill I finish compositing stuff.
Also composite will handle messages from it's own add_handler() since (somehow), all pending
XDamageNotify events will not be correctly reported inside EvokeService handler.
And about splash... splash will now keep it's window at the top, no matter what window is
raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't
have to say that this hack works for all wm's I tested :P).
Sound from splash is removed; reason for this is when evoke starts childs (only when X session
was started), device descriptors will be used by childs too making sound device unusable and
marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
|
|
|
|
|
|
|
#ifndef EDEWM_HAVE_NET_SPLASH
|
2008-09-08 15:09:37 +04:00
|
|
|
static Splash* global_splash = NULL;
|
2007-09-20 12:47:50 +04:00
|
|
|
|
2008-09-08 15:09:37 +04:00
|
|
|
static int splash_xmessage_handler(int e) {
|
A lot of changes, especially the ways how screen is repainted (in composite).
Composite will now draw only damaged regions, and their damage is (now) correctly
reported, mostly due changes in main FLTK loop.
Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION
is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite
way (without emulation) it will relay on FLTK message passing, but it is very unpredictable
since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due
large XDamageNotify throttling. When emulation is used, there are no such problems
since all events are processed before they are routed to FLTK.
In composite is added another way of repainting (when USE_CHECK is defined), and it will
relay on Fl::add_check() function; there are some differences between this function
and timer used for screen refresh. Timer will try to refresh it every XX ms and when
there are large number of XDamageNotify reports, this will not be suitable for
movements smoothing on the screen; on other hand add_check() will call callback every
time when event is processed, which brings smooth movements. For now only timer is used
untill I finish compositing stuff.
Also composite will handle messages from it's own add_handler() since (somehow), all pending
XDamageNotify events will not be correctly reported inside EvokeService handler.
And about splash... splash will now keep it's window at the top, no matter what window is
raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't
have to say that this hack works for all wm's I tested :P).
Sound from splash is removed; reason for this is when evoke starts childs (only when X session
was started), device descriptors will be used by childs too making sound device unusable and
marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
|
|
|
if(fl_xevent->type == MapNotify) {
|
|
|
|
XRaiseWindow(fl_display, fl_xid(global_splash));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(fl_xevent->type == ConfigureNotify) {
|
|
|
|
if(fl_xevent->xconfigure.event == DefaultRootWindow(fl_display)) {
|
|
|
|
XRaiseWindow(fl_display, fl_xid(global_splash));
|
2007-09-20 12:47:50 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2007-09-18 18:06:09 +04:00
|
|
|
}
|
A lot of changes, especially the ways how screen is repainted (in composite).
Composite will now draw only damaged regions, and their damage is (now) correctly
reported, mostly due changes in main FLTK loop.
Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION
is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite
way (without emulation) it will relay on FLTK message passing, but it is very unpredictable
since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due
large XDamageNotify throttling. When emulation is used, there are no such problems
since all events are processed before they are routed to FLTK.
In composite is added another way of repainting (when USE_CHECK is defined), and it will
relay on Fl::add_check() function; there are some differences between this function
and timer used for screen refresh. Timer will try to refresh it every XX ms and when
there are large number of XDamageNotify reports, this will not be suitable for
movements smoothing on the screen; on other hand add_check() will call callback every
time when event is processed, which brings smooth movements. For now only timer is used
untill I finish compositing stuff.
Also composite will handle messages from it's own add_handler() since (somehow), all pending
XDamageNotify events will not be correctly reported inside EvokeService handler.
And about splash... splash will now keep it's window at the top, no matter what window is
raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't
have to say that this hack works for all wm's I tested :P).
Sound from splash is removed; reason for this is when evoke starts childs (only when X session
was started), device descriptors will be used by childs too making sound device unusable and
marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
|
|
|
#endif
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* repeatedly call runner() untill all clients are
|
|
|
|
* started then hide splash window
|
|
|
|
*/
|
2008-09-08 15:09:37 +04:00
|
|
|
static void runner_cb(void* s) {
|
2007-07-30 17:25:13 +04:00
|
|
|
Splash* sp = (Splash*)s;
|
|
|
|
|
|
|
|
if(sp->next_client())
|
|
|
|
Fl::repeat_timeout(TIMEOUT_CONTINUE, runner_cb, sp);
|
|
|
|
else
|
|
|
|
sp->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
Splash::Splash(bool sp, bool dr) : Fl_Double_Window(480, 364), clist(NULL), bkg(NULL),
|
|
|
|
counter(0), no_splash(sp), dry_run(dr) {
|
|
|
|
icons = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Splash::~Splash() {
|
|
|
|
EVOKE_LOG("Cleaning splash data\n");
|
|
|
|
// elements of icons cleans Fl_Group
|
|
|
|
delete [] icons;
|
2007-09-20 12:47:50 +04:00
|
|
|
Fl::remove_timeout(runner_cb);
|
2007-07-30 17:25:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// after edewm got _NET_WM_WINDOW_TYPE_SPLASH support
|
A lot of changes, especially the ways how screen is repainted (in composite).
Composite will now draw only damaged regions, and their damage is (now) correctly
reported, mostly due changes in main FLTK loop.
Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION
is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite
way (without emulation) it will relay on FLTK message passing, but it is very unpredictable
since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due
large XDamageNotify throttling. When emulation is used, there are no such problems
since all events are processed before they are routed to FLTK.
In composite is added another way of repainting (when USE_CHECK is defined), and it will
relay on Fl::add_check() function; there are some differences between this function
and timer used for screen refresh. Timer will try to refresh it every XX ms and when
there are large number of XDamageNotify reports, this will not be suitable for
movements smoothing on the screen; on other hand add_check() will call callback every
time when event is processed, which brings smooth movements. For now only timer is used
untill I finish compositing stuff.
Also composite will handle messages from it's own add_handler() since (somehow), all pending
XDamageNotify events will not be correctly reported inside EvokeService handler.
And about splash... splash will now keep it's window at the top, no matter what window is
raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't
have to say that this hack works for all wm's I tested :P).
Sound from splash is removed; reason for this is when evoke starts childs (only when X session
was started), device descriptors will be used by childs too making sound device unusable and
marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
|
|
|
#if EDEWM_HAVE_NET_SPLASH
|
2007-07-30 17:25:13 +04:00
|
|
|
void Splash::show(void) {
|
|
|
|
if(shown())
|
|
|
|
return;
|
|
|
|
|
|
|
|
Fl_X::make_xid(this);
|
|
|
|
/*
|
|
|
|
* Edewm does not implement this for now. Alternative, working solution
|
|
|
|
* is used via register_top()/unregister_top(); also looks like later
|
|
|
|
* is working on othe wm's too.
|
|
|
|
*/
|
|
|
|
Atom win_type = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE", False);
|
|
|
|
Atom win_splash = XInternAtom(fl_display, "_NET_WM_WINDOW_TYPE_SPLASH", False);
|
|
|
|
XChangeProperty(fl_display, fl_xid(this), win_type, XA_ATOM, 32, PropModeReplace,
|
|
|
|
(unsigned char*)&win_splash, sizeof(Atom));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void Splash::run(void) {
|
2008-09-08 15:09:37 +04:00
|
|
|
E_ASSERT(clist != NULL);
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
if(no_splash) {
|
|
|
|
while(next_client_nosplash())
|
|
|
|
;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
fl_register_images();
|
|
|
|
|
|
|
|
// setup widgets
|
|
|
|
begin();
|
|
|
|
Fl_Box* bimg = new Fl_Box(0, 0, w(), h());
|
|
|
|
Fl_Image* splash_img = 0;
|
|
|
|
|
|
|
|
if(bkg)
|
|
|
|
splash_img = Fl_Shared_Image::get(bkg->c_str());
|
|
|
|
|
|
|
|
if(splash_img) {
|
|
|
|
int W = splash_img->w();
|
|
|
|
int H = splash_img->h();
|
|
|
|
// update window and Box sizes
|
|
|
|
size(W, H);
|
|
|
|
bimg->size(W, H);
|
|
|
|
|
|
|
|
bimg->image(splash_img);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* place message box at the bottom with
|
|
|
|
* nice offset (10 px) from window borders
|
|
|
|
*/
|
|
|
|
msgbox = new Fl_Box(10, h() - 25 - 10, w() - 20, 25);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Setup icons positions, based on position of msgbox assuming someone
|
|
|
|
* will not abuse splash to start hundrets of programs, since icons will
|
|
|
|
* be placed only in horizontal order, one line, so in case their large
|
|
|
|
* number, some of them will go out of window borders.
|
|
|
|
*
|
|
|
|
* Icon box will be 64x64 so larger icons can fit too.
|
|
|
|
*
|
|
|
|
* This code will use Fl_Group (moving group, later, will move all icons
|
|
|
|
* saving me from code mess), but will not update it's w() for two reasons:
|
|
|
|
* icons does not use it, and will be drawn correctly, and second, setting
|
|
|
|
* width will initiate fltk layout engine which will mess everything up.
|
|
|
|
*/
|
|
|
|
Fl_Group* icon_group = new Fl_Group(10, msgbox->y() - 10 - 64, 0, 64);
|
|
|
|
int X = icon_group->x();
|
|
|
|
int Y = icon_group->y();
|
|
|
|
// offset between icons
|
|
|
|
int ioffset = 5;
|
|
|
|
|
|
|
|
// FIXME: use malloc/something instead this
|
|
|
|
icons = new Fl_Box*[clist->size()];
|
|
|
|
|
|
|
|
icon_group->begin();
|
|
|
|
const char* imgpath;
|
|
|
|
Fl_Image* iconimg;
|
|
|
|
int i = 0;
|
|
|
|
for(ClientListIter it = clist->begin(); it != clist->end(); ++it, ++i) {
|
|
|
|
Fl_Box* bb = new Fl_Box(X, Y, 64, 64);
|
|
|
|
|
|
|
|
imgpath = (*it).icon.c_str();
|
|
|
|
iconimg = Fl_Shared_Image::get(imgpath);
|
|
|
|
if(!iconimg) {
|
|
|
|
bb->label(_("No image"));
|
|
|
|
bb->align(FL_ALIGN_INSIDE | FL_ALIGN_WRAP);
|
|
|
|
} else
|
|
|
|
bb->image(iconimg);
|
|
|
|
|
|
|
|
bb->hide();
|
|
|
|
|
|
|
|
X += bb->w() + ioffset;
|
|
|
|
icons[i] = bb;
|
|
|
|
}
|
|
|
|
icon_group->end();
|
|
|
|
|
|
|
|
// see X as width of all icons
|
|
|
|
int gx = w()/2 - X/2;
|
|
|
|
// gx can be negative
|
|
|
|
gx = (gx > 10) ? gx : 10;
|
|
|
|
icon_group->position(gx, Y);
|
|
|
|
end();
|
|
|
|
|
|
|
|
clear_border();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If set_override() is used, message boxes will be
|
|
|
|
* popped behind splash. Using it or not ???
|
|
|
|
*/
|
|
|
|
set_override();
|
|
|
|
|
|
|
|
// make sure window is centered
|
|
|
|
int sw = DisplayWidth(fl_display, fl_screen);
|
|
|
|
int sh = DisplayHeight(fl_display, fl_screen);
|
|
|
|
position(sw/2 - w()/2, sh/2 - h()/2);
|
|
|
|
|
|
|
|
show();
|
|
|
|
Fl::add_timeout(TIMEOUT_START, runner_cb, this);
|
|
|
|
|
A lot of changes, especially the ways how screen is repainted (in composite).
Composite will now draw only damaged regions, and their damage is (now) correctly
reported, mostly due changes in main FLTK loop.
Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION
is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite
way (without emulation) it will relay on FLTK message passing, but it is very unpredictable
since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due
large XDamageNotify throttling. When emulation is used, there are no such problems
since all events are processed before they are routed to FLTK.
In composite is added another way of repainting (when USE_CHECK is defined), and it will
relay on Fl::add_check() function; there are some differences between this function
and timer used for screen refresh. Timer will try to refresh it every XX ms and when
there are large number of XDamageNotify reports, this will not be suitable for
movements smoothing on the screen; on other hand add_check() will call callback every
time when event is processed, which brings smooth movements. For now only timer is used
untill I finish compositing stuff.
Also composite will handle messages from it's own add_handler() since (somehow), all pending
XDamageNotify events will not be correctly reported inside EvokeService handler.
And about splash... splash will now keep it's window at the top, no matter what window is
raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't
have to say that this hack works for all wm's I tested :P).
Sound from splash is removed; reason for this is when evoke starts childs (only when X session
was started), device descriptors will be used by childs too making sound device unusable and
marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
|
|
|
// to keep splash at the top
|
|
|
|
#ifndef HAVE_NET_SPLASH
|
|
|
|
global_splash = this;
|
|
|
|
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), SubstructureNotifyMask);
|
|
|
|
Fl::add_handler(splash_xmessage_handler);
|
|
|
|
#endif
|
|
|
|
|
2007-07-30 17:25:13 +04:00
|
|
|
while(shown())
|
|
|
|
Fl::wait();
|
2007-12-03 16:39:22 +03:00
|
|
|
|
A lot of changes, especially the ways how screen is repainted (in composite).
Composite will now draw only damaged regions, and their damage is (now) correctly
reported, mostly due changes in main FLTK loop.
Also there are two ways how evoke will be running: if USE_FLTK_LOOP_EMULATION
is defined (default yes), it will fully emulate FLTK loop (as done before). Oposite
way (without emulation) it will relay on FLTK message passing, but it is very unpredictable
since FLTK will sometime miss SelectionClear events (XSETTINGS relay on it), probably due
large XDamageNotify throttling. When emulation is used, there are no such problems
since all events are processed before they are routed to FLTK.
In composite is added another way of repainting (when USE_CHECK is defined), and it will
relay on Fl::add_check() function; there are some differences between this function
and timer used for screen refresh. Timer will try to refresh it every XX ms and when
there are large number of XDamageNotify reports, this will not be suitable for
movements smoothing on the screen; on other hand add_check() will call callback every
time when event is processed, which brings smooth movements. For now only timer is used
untill I finish compositing stuff.
Also composite will handle messages from it's own add_handler() since (somehow), all pending
XDamageNotify events will not be correctly reported inside EvokeService handler.
And about splash... splash will now keep it's window at the top, no matter what window is
raised. This is a small hack until I implement _NET_WM_WINDOW_TYPE_SPLASH in edewm (I don't
have to say that this hack works for all wm's I tested :P).
Sound from splash is removed; reason for this is when evoke starts childs (only when X session
was started), device descriptors will be used by childs too making sound device unusable and
marked as busy. This can be solved by using better sound library, which is story for itself...
2008-01-14 15:50:30 +03:00
|
|
|
#ifndef EDEWM_HAVE_NET_SPLASH
|
|
|
|
Fl::remove_handler(splash_xmessage_handler);
|
|
|
|
#endif
|
2007-07-30 17:25:13 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// called when splash option is on
|
|
|
|
bool Splash::next_client(void) {
|
|
|
|
if(clist->empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(counter == 0)
|
|
|
|
clist_it = clist->begin();
|
|
|
|
|
|
|
|
if(clist_it == clist->end()) {
|
|
|
|
counter = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-09-03 16:24:01 +04:00
|
|
|
|
2008-09-08 15:09:37 +04:00
|
|
|
E_ASSERT(counter < clist->size() && "Internal error; 'counter' out of bounds");
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
char buff[1024];
|
|
|
|
const char* msg = (*clist_it).desc.c_str();
|
|
|
|
const char* cmd = (*clist_it).exec.c_str();
|
|
|
|
snprintf(buff, sizeof(buff), _("Starting %s..."), msg);
|
|
|
|
|
|
|
|
icons[counter]->show();
|
|
|
|
msgbox->copy_label(buff);
|
|
|
|
redraw();
|
|
|
|
|
2007-12-28 13:58:56 +03:00
|
|
|
if(!dry_run) {
|
2007-09-20 12:47:50 +04:00
|
|
|
spawn_program(cmd, service_watcher_cb);
|
|
|
|
//spawn_program(cmd);
|
2007-12-28 13:58:56 +03:00
|
|
|
}
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
++clist_it;
|
|
|
|
++counter;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// called when splash option is off
|
|
|
|
bool Splash::next_client_nosplash(void) {
|
|
|
|
if(clist->empty())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(counter == 0)
|
|
|
|
clist_it = clist->begin();
|
|
|
|
|
|
|
|
if(clist_it == clist->end()) {
|
|
|
|
counter = 0;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2008-09-08 15:09:37 +04:00
|
|
|
E_ASSERT(counter < clist->size() && "Internal error; 'counter' out of bounds");
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
char buff[1024];
|
|
|
|
const char* msg = (*clist_it).desc.c_str();
|
|
|
|
const char* cmd = (*clist_it).exec.c_str();
|
|
|
|
snprintf(buff, sizeof(buff), _("Starting %s..."), msg);
|
|
|
|
|
|
|
|
printf("%s\n", buff);
|
|
|
|
|
|
|
|
if(!dry_run)
|
2007-09-20 12:47:50 +04:00
|
|
|
spawn_program(cmd, service_watcher_cb);
|
|
|
|
//spawn_program(cmd);
|
2007-07-30 17:25:13 +04:00
|
|
|
|
|
|
|
++clist_it;
|
|
|
|
++counter;
|
|
|
|
return true;
|
|
|
|
}
|