Work, work...
@ -12,23 +12,87 @@
|
|||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "EvokeService.h"
|
#include "EvokeService.h"
|
||||||
|
#include "Splash.h"
|
||||||
|
#include "Spawn.h"
|
||||||
|
|
||||||
#include <edelib/File.h>
|
#include <edelib/File.h>
|
||||||
#include <edelib/Config.h>
|
#include <edelib/Config.h>
|
||||||
#include <edelib/StrUtil.h>
|
#include <edelib/StrUtil.h>
|
||||||
|
#include <edelib/Util.h>
|
||||||
|
#include <edelib/Debug.h>
|
||||||
|
|
||||||
|
#include <FL/fl_ask.h>
|
||||||
|
|
||||||
#include <sys/types.h> // getpid
|
#include <sys/types.h> // getpid
|
||||||
#include <unistd.h> //
|
#include <unistd.h> //
|
||||||
#include <stdlib.h> // free
|
#include <stdlib.h> // free
|
||||||
#include <string.h> // strdup
|
#include <string.h> // strdup
|
||||||
|
|
||||||
|
void resolve_path(const edelib::String& imgdir, edelib::String& img, bool have_imgdir) {
|
||||||
|
if(img.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
EvokeService::EvokeService() : logfile(NULL), pidfile(NULL) {
|
const char* im = img.c_str();
|
||||||
|
|
||||||
|
if(!edelib::file_exists(im) && have_imgdir) {
|
||||||
|
img = edelib::build_filename("/", imgdir.c_str(), im);
|
||||||
|
im = img.c_str();
|
||||||
|
if(!edelib::file_exists(im)) {
|
||||||
|
// no file, send then empty
|
||||||
|
img.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_int_property_value(Atom at) {
|
||||||
|
Atom real;
|
||||||
|
int format;
|
||||||
|
unsigned long n, extra;
|
||||||
|
unsigned char* prop;
|
||||||
|
|
||||||
|
int status = XGetWindowProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
at, 0L, 0x7fffffff, False, XA_CARDINAL, &real, &format, &n, &extra,
|
||||||
|
(unsigned char**)&prop);
|
||||||
|
int ret = -1;
|
||||||
|
if(status != Success && !prop)
|
||||||
|
return ret;
|
||||||
|
ret = int(*(long*)prop);
|
||||||
|
XFree(prop);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_string_property_value(Atom at, char* txt, int txt_len) {
|
||||||
|
XTextProperty names;
|
||||||
|
XGetTextProperty(fl_display, RootWindow(fl_display, fl_screen), &names, at);
|
||||||
|
if(!names.nitems || !names.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
char** vnames;
|
||||||
|
int nsz = 0;
|
||||||
|
if(!XTextPropertyToStringList(&names, &vnames, &nsz)) {
|
||||||
|
XFree(names.value);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(txt, vnames[0], txt_len);
|
||||||
|
txt[txt_len] = '\0';
|
||||||
|
XFreeStringList(vnames);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvokeService::EvokeService() : is_running(0), logfile(NULL), pidfile(NULL), lockfile(NULL) {
|
||||||
|
top_win = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
EvokeService::~EvokeService() {
|
EvokeService::~EvokeService() {
|
||||||
if(logfile)
|
if(logfile)
|
||||||
delete logfile;
|
delete logfile;
|
||||||
|
|
||||||
|
if(lockfile) {
|
||||||
|
edelib::file_remove(lockfile);
|
||||||
|
free(lockfile);
|
||||||
|
}
|
||||||
|
|
||||||
if(pidfile) {
|
if(pidfile) {
|
||||||
edelib::file_remove(pidfile);
|
edelib::file_remove(pidfile);
|
||||||
free(pidfile);
|
free(pidfile);
|
||||||
@ -54,13 +118,20 @@ bool EvokeService::setup_logging(const char* file) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EvokeService::setup_pid(const char* file) {
|
bool EvokeService::setup_pid(const char* file, const char* lock) {
|
||||||
if(!file)
|
if(!file)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(edelib::file_exists(file))
|
if(edelib::file_exists(lock))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
FILE* l = fopen(lock, "w");
|
||||||
|
if(!l)
|
||||||
|
return false;
|
||||||
|
fprintf(l, " ");
|
||||||
|
fclose(l);
|
||||||
|
lockfile = strdup(lock);
|
||||||
|
|
||||||
FILE* f = fopen(file, "w");
|
FILE* f = fopen(file, "w");
|
||||||
if(!f)
|
if(!f)
|
||||||
return false;
|
return false;
|
||||||
@ -72,20 +143,35 @@ bool EvokeService::setup_pid(const char* file) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EvokeService::setup_config(const char* config, bool do_startup) {
|
bool EvokeService::init_splash(const char* config, bool no_splash, bool dry_run) {
|
||||||
// for now if is not startup mode, ignore it
|
|
||||||
if(!do_startup)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
edelib::Config c;
|
edelib::Config c;
|
||||||
if(!c.load(config))
|
if(!c.load(config))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
char buff[1024];
|
char buff[1024];
|
||||||
|
bool have_imgdir = false;
|
||||||
|
|
||||||
|
c.get("evoke", "ImagesDirectory", buff, sizeof(buff));
|
||||||
|
|
||||||
|
// no evoke section
|
||||||
|
if(c.error() == edelib::CONF_ERR_SECTION)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
edelib::String imgdir;
|
||||||
|
if(c.error() == edelib::CONF_SUCCESS) {
|
||||||
|
imgdir = buff;
|
||||||
|
have_imgdir = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
edelib::String splashimg;
|
||||||
|
if(c.get("evoke", "Splash", buff, sizeof(buff)))
|
||||||
|
splashimg = buff;
|
||||||
|
|
||||||
|
// Startup key must exists
|
||||||
if(!c.get("evoke", "Startup", buff, sizeof(buff)))
|
if(!c.get("evoke", "Startup", buff, sizeof(buff)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
edelib::vector<edelib::String> vs;
|
StringList vs;
|
||||||
edelib::stringtok(vs, buff, ",");
|
edelib::stringtok(vs, buff, ",");
|
||||||
|
|
||||||
// nothing, fine, do nothing
|
// nothing, fine, do nothing
|
||||||
@ -95,8 +181,9 @@ bool EvokeService::setup_config(const char* config, bool do_startup) {
|
|||||||
|
|
||||||
EvokeClient ec;
|
EvokeClient ec;
|
||||||
const char* key_name;
|
const char* key_name;
|
||||||
for(unsigned int i = 0; i < sz; i++) {
|
|
||||||
key_name = vs[i].c_str();
|
for(StringListIter it = vs.begin(); it != vs.end(); ++it) {
|
||||||
|
key_name = (*it).c_str();
|
||||||
edelib::str_trim((char*)key_name);
|
edelib::str_trim((char*)key_name);
|
||||||
|
|
||||||
// probably listed but not the same key; also Exec value must exists
|
// probably listed but not the same key; also Exec value must exists
|
||||||
@ -105,10 +192,8 @@ bool EvokeService::setup_config(const char* config, bool do_startup) {
|
|||||||
else
|
else
|
||||||
ec.exec = buff;
|
ec.exec = buff;
|
||||||
|
|
||||||
if(c.get(key_name, "Message", buff, sizeof(buff)))
|
if(c.get(key_name, "Description", buff, sizeof(buff)))
|
||||||
ec.message = buff;
|
ec.desc = buff;
|
||||||
// it is no EDE app untill say so
|
|
||||||
c.get(key_name, "Core", ec.core, false);
|
|
||||||
|
|
||||||
if(c.get(key_name, "Icon", buff, sizeof(buff)))
|
if(c.get(key_name, "Icon", buff, sizeof(buff)))
|
||||||
ec.icon = buff;
|
ec.icon = buff;
|
||||||
@ -116,23 +201,81 @@ bool EvokeService::setup_config(const char* config, bool do_startup) {
|
|||||||
clients.push_back(ec);
|
clients.push_back(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < clients.size(); i++) {
|
/*
|
||||||
printf("Exec: %s\n", clients[i].exec.c_str());
|
* Now, before data is send to Splash, resolve directories
|
||||||
printf("Message: %s\n", clients[i].message.c_str());
|
* since Splash expects that.
|
||||||
printf("Icon: %s\n", clients[i].icon.c_str());
|
*/
|
||||||
printf("Core: %i\n\n", clients[i].core);
|
resolve_path(imgdir, splashimg, have_imgdir);
|
||||||
}
|
for(ClientListIter it = clients.begin(); it != clients.end(); ++it)
|
||||||
|
resolve_path(imgdir, (*it).icon, have_imgdir);
|
||||||
|
|
||||||
|
Splash sp(no_splash, dry_run);
|
||||||
|
sp.set_clients(&clients);
|
||||||
|
sp.set_background(&splashimg);
|
||||||
|
|
||||||
|
sp.run();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvokeService::setup_atoms(Display* d) {
|
void EvokeService::setup_atoms(Display* d) {
|
||||||
|
// with them must be send '1' or property will be ignored (except _EDE_EVOKE_SPAWN)
|
||||||
_ede_shutdown_all = XInternAtom(d, "_EDE_EVOKE_SHUTDOWN_ALL", False);
|
_ede_shutdown_all = XInternAtom(d, "_EDE_EVOKE_SHUTDOWN_ALL", False);
|
||||||
|
_ede_evoke_quit = XInternAtom(d, "_EDE_EVOKE_QUIT", False);
|
||||||
|
|
||||||
_ede_spawn = XInternAtom(d, "_EDE_EVOKE_SPAWN", False);
|
_ede_spawn = XInternAtom(d, "_EDE_EVOKE_SPAWN", False);
|
||||||
_ede_shutdown_client = XInternAtom(d, "_EDE_SHUTDOWN", False);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int EvokeService::handle(int event) {
|
int EvokeService::handle(const XEvent* ev) {
|
||||||
logfile->printf("Got event %i\n", event);
|
logfile->printf("Got event %i\n", ev->type);
|
||||||
|
|
||||||
|
if(ev->type == MapNotify) {
|
||||||
|
if(top_win) {
|
||||||
|
// for splash to keep it at top (working in old edewm)
|
||||||
|
XRaiseWindow(fl_display, fl_xid(top_win));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if(ev->type == ConfigureNotify) {
|
||||||
|
if(ev->xconfigure.event == DefaultRootWindow(fl_display) && top_win) {
|
||||||
|
// splash too, but keep window under other wm's
|
||||||
|
XRaiseWindow(fl_display, fl_xid(top_win));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if(ev->type == PropertyNotify) {
|
||||||
|
if(ev->xproperty.atom == _ede_spawn) {
|
||||||
|
char buff[1024];
|
||||||
|
|
||||||
|
if(get_string_property_value(_ede_spawn, buff, sizeof(buff))) {
|
||||||
|
logfile->printf("Got _EVOKE_SPAWN with %s. Starting client...\n", buff);
|
||||||
|
int r = spawn_program(buff, false);
|
||||||
|
|
||||||
|
if(r != 0)
|
||||||
|
fl_alert("Unable to start %s. Got code %i", buff, r);
|
||||||
|
} else
|
||||||
|
logfile->printf("Got _EVOKE_SPAWN with malformed data. Ignoring...\n");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ev->xproperty.atom == _ede_evoke_quit) {
|
||||||
|
int val = get_int_property_value(_ede_evoke_quit);
|
||||||
|
if(val == 1) {
|
||||||
|
logfile->printf("Got accepted _EDE_EVOKE_QUIT\n");
|
||||||
|
stop();
|
||||||
|
} else
|
||||||
|
logfile->printf("Got _EDE_EVOKE_QUIT with bad code (%i). Ignoring...\n", val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ev->xproperty.atom == _ede_shutdown_all) {
|
||||||
|
int val = get_int_property_value(_ede_shutdown_all);
|
||||||
|
if(val == 1)
|
||||||
|
logfile->printf("Got accepted _EDE_EVOKE_SHUTDOWN_ALL\n");
|
||||||
|
else
|
||||||
|
logfile->printf("Got _EDE_EVOKE_SHUTDOWN_ALL with bad code (%i). Ignoring...\n", val);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -14,42 +14,59 @@
|
|||||||
#define __EVOKESERVICE_H__
|
#define __EVOKESERVICE_H__
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include <X11/Xlib.h>
|
#include <edelib/List.h>
|
||||||
|
|
||||||
#include <edelib/Vector.h>
|
|
||||||
#include <edelib/String.h>
|
#include <edelib/String.h>
|
||||||
|
#include <FL/x.h>
|
||||||
|
|
||||||
struct EvokeClient {
|
struct EvokeClient {
|
||||||
edelib::String message; // message during startup
|
edelib::String desc; // short program description (used in Starting... message)
|
||||||
edelib::String icon; // icon for this client
|
edelib::String icon; // icon for this client
|
||||||
edelib::String exec; // program name/path to run
|
edelib::String exec; // program name/path to run
|
||||||
bool core; // does understaind _EDE_SHUTDOWN_SELF (only ede apps)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef edelib::list<EvokeClient> ClientList;
|
||||||
|
typedef edelib::list<EvokeClient>::iterator ClientListIter;
|
||||||
|
typedef edelib::list<edelib::String> StringList;
|
||||||
|
typedef edelib::list<edelib::String>::iterator StringListIter;
|
||||||
|
|
||||||
|
class Fl_Double_Window;
|
||||||
|
|
||||||
class EvokeService {
|
class EvokeService {
|
||||||
private:
|
private:
|
||||||
|
bool is_running;
|
||||||
Log* logfile;
|
Log* logfile;
|
||||||
char* pidfile;
|
char* pidfile;
|
||||||
|
char* lockfile;
|
||||||
|
|
||||||
|
Fl_Double_Window* top_win;
|
||||||
|
|
||||||
Atom _ede_shutdown_all;
|
Atom _ede_shutdown_all;
|
||||||
Atom _ede_shutdown_client;
|
|
||||||
Atom _ede_spawn;
|
Atom _ede_spawn;
|
||||||
|
Atom _ede_evoke_quit;
|
||||||
|
|
||||||
edelib::vector<EvokeClient> clients;
|
ClientList clients;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EvokeService();
|
EvokeService();
|
||||||
~EvokeService();
|
~EvokeService();
|
||||||
static EvokeService* instance(void);
|
static EvokeService* instance(void);
|
||||||
|
|
||||||
|
void start(void) { is_running = true; }
|
||||||
|
void stop(void) { is_running = false; }
|
||||||
|
bool running(void) { return is_running; }
|
||||||
|
|
||||||
bool setup_logging(const char* file);
|
bool setup_logging(const char* file);
|
||||||
bool setup_pid(const char* file);
|
bool setup_pid(const char* file, const char* lock);
|
||||||
bool setup_config(const char* config, bool do_startup);
|
|
||||||
void setup_atoms(Display* d);
|
void setup_atoms(Display* d);
|
||||||
|
|
||||||
int handle(int event);
|
bool init_splash(const char* config, bool no_splash, bool dry_run);
|
||||||
|
|
||||||
|
int handle(const XEvent* ev);
|
||||||
|
|
||||||
Log* log(void) { return logfile; }
|
Log* log(void) { return logfile; }
|
||||||
|
|
||||||
|
void register_top(Fl_Double_Window* win) { top_win = win; }
|
||||||
|
void unregister_top(void) { top_win = NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EVOKE_LOG EvokeService::instance()->log()->printf
|
#define EVOKE_LOG EvokeService::instance()->log()->printf
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
|
|
||||||
SubDir TOP evoke ;
|
SubDir TOP evoke ;
|
||||||
|
|
||||||
SOURCE = evoke.cpp EvokeService.cpp Log.cpp ;
|
SOURCE = evoke.cpp EvokeService.cpp Spawn.cpp Splash.cpp Log.cpp ;
|
||||||
|
|
||||||
EdeProgram evoke : $(SOURCE) ;
|
EdeProgram evoke : $(SOURCE) ;
|
||||||
TranslationStrings locale : $(SOURCE) ;
|
FltkProgramBare test/evoke_test : test/evoke_test.cpp ;
|
||||||
|
#TranslationStrings locale : $(SOURCE) ;
|
||||||
|
69
evoke/Spawn.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* $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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Spawn.h"
|
||||||
|
|
||||||
|
#include <sys/types.h> // fork
|
||||||
|
#include <unistd.h> // fork, open, close, dup
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
extern char** environ;
|
||||||
|
|
||||||
|
int run_fork(const char* cmd, bool wait) {
|
||||||
|
if(!cmd)
|
||||||
|
return SPAWN_EMPTY;
|
||||||
|
|
||||||
|
int nulldev = -1;
|
||||||
|
int status_ret = 0;
|
||||||
|
|
||||||
|
pid_t pid = fork();
|
||||||
|
|
||||||
|
if(pid == -1)
|
||||||
|
return SPAWN_FORK_FAILED;
|
||||||
|
|
||||||
|
// run the child
|
||||||
|
if(pid == 0) {
|
||||||
|
char* argv[4];
|
||||||
|
argv[0] = "/bin/sh";
|
||||||
|
argv[1] = "-c";
|
||||||
|
argv[2] = (char*)cmd;
|
||||||
|
argv[3] = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following is to avoid X locking when executing
|
||||||
|
* terminal based application that requires user input
|
||||||
|
*/
|
||||||
|
if((nulldev = open("/dev/null", O_RDWR)) == -1)
|
||||||
|
return SPAWN_FORK_FAILED;
|
||||||
|
|
||||||
|
/* TODO: redirect these to EvokeService log */
|
||||||
|
close(0); dup(nulldev);
|
||||||
|
close(1); dup(nulldev);
|
||||||
|
close(2); dup(nulldev);
|
||||||
|
|
||||||
|
if(execve(argv[0], argv, environ) == -1) {
|
||||||
|
close(nulldev);
|
||||||
|
// should not get here
|
||||||
|
return SPAWN_EXECVE_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return status_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int spawn_program(const char* cmd, bool wait) {
|
||||||
|
return run_fork(cmd, wait);
|
||||||
|
}
|
33
evoke/Spawn.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* $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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SPAWN_H__
|
||||||
|
#define __SPAWN_H__
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is little bit modified code from edelib run_program()
|
||||||
|
* so evoke specific stuff can be added. Also, possible option
|
||||||
|
* is that edelib run_program(), at some time, consult evoke
|
||||||
|
* for running programs.
|
||||||
|
*/
|
||||||
|
#define SPAWN_NOT_FOUND 65535 // executable not found
|
||||||
|
#define SPAWN_EMPTY 65534 // given parameter is NULL
|
||||||
|
#define SPAWN_NOT_EXEC 65533 // given parameter is not executable on system
|
||||||
|
#define SPAWN_FORK_FAILED 65532 // internal fork failed
|
||||||
|
#define SPAWN_WAITPID_FAILED 65531 // internal waitpid failed
|
||||||
|
#define SPAWN_EXECVE_FAILED 65530 // internal execve failed
|
||||||
|
#define SPAWN_PTY_FAILED 65529 // TODO
|
||||||
|
#define SPAWN_USER_CANCELED 65528 // TODO
|
||||||
|
|
||||||
|
int spawn_program(const char* cmd, bool wait);
|
||||||
|
|
||||||
|
#endif
|
305
evoke/Splash.cpp
Normal file
@ -0,0 +1,305 @@
|
|||||||
|
/*
|
||||||
|
* $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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Splash.h"
|
||||||
|
#include "Spawn.h"
|
||||||
|
|
||||||
|
#include <edelib/Run.h>
|
||||||
|
#include <edelib/Debug.h>
|
||||||
|
#include <edelib/Nls.h>
|
||||||
|
|
||||||
|
#include <FL/Fl_Shared_Image.h>
|
||||||
|
#include <FL/Fl.h>
|
||||||
|
|
||||||
|
#include <stdio.h> // snprintf
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
extern int xmessage_handler(int e);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* repeatedly call runner() untill all clients are
|
||||||
|
* started then hide splash window
|
||||||
|
*/
|
||||||
|
void runner_cb(void* s) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// after edewm got _NET_WM_WINDOW_TYPE_SPLASH support
|
||||||
|
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) {
|
||||||
|
EASSERT(clist != NULL);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fl::wait() will block all events to EvokeService and it will not
|
||||||
|
* be able to keep this window at the top. So we again select event inputs
|
||||||
|
* and redirect them to EvokeService::handle().
|
||||||
|
*/
|
||||||
|
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), SubstructureNotifyMask);
|
||||||
|
Fl::add_handler(xmessage_handler);
|
||||||
|
|
||||||
|
// make sure MappingNotify keeps this window at the top
|
||||||
|
EvokeService::instance()->register_top(this);
|
||||||
|
|
||||||
|
while(shown())
|
||||||
|
Fl::wait();
|
||||||
|
|
||||||
|
EvokeService::instance()->unregister_top();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
EASSERT(counter < clist->size() && "Internal error; 'counter' out of bounds");
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
if(!dry_run)
|
||||||
|
spawn_program(cmd, false);
|
||||||
|
|
||||||
|
++clist_it;
|
||||||
|
++counter;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This was vector implementation; I'm leaving here
|
||||||
|
* untill list is proven to be safe. If code is changed
|
||||||
|
* back to vector, make sure to update rest code removing
|
||||||
|
* iterators.
|
||||||
|
*/
|
||||||
|
if(counter >= clist->size()) {
|
||||||
|
counter = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char buff[1024];
|
||||||
|
const char* msg = (*clist)[counter].message.c_str();
|
||||||
|
const char* cmd = (*clist)[counter].exec.c_str();
|
||||||
|
snprintf(buff, sizeof(buff), _("Starting %s..."), msg);
|
||||||
|
|
||||||
|
icons[counter]->show();
|
||||||
|
msgbox->copy_label(buff);
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
if(!dry_run)
|
||||||
|
spawn_program(cmd, false);
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
EASSERT(counter < clist->size() && "Internal error; 'counter' out of bounds");
|
||||||
|
|
||||||
|
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)
|
||||||
|
spawn_program(cmd, false);
|
||||||
|
|
||||||
|
++clist_it;
|
||||||
|
++counter;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
* This was vector implementation; I'm leaving here
|
||||||
|
* untill list is proven to be safe. If code is changed
|
||||||
|
* back to vector, make sure to update rest code removing
|
||||||
|
* iterators.
|
||||||
|
*/
|
||||||
|
if(counter >= clist->size()) {
|
||||||
|
counter = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char buff[1024];
|
||||||
|
const char* msg = (*clist)[counter].message.c_str();
|
||||||
|
const char* cmd = (*clist)[counter].exec.c_str();
|
||||||
|
snprintf(buff, sizeof(buff), _("Starting %s..."), msg);
|
||||||
|
|
||||||
|
printf("%s\n", buff);
|
||||||
|
|
||||||
|
if(!dry_run)
|
||||||
|
spawn_program(cmd, false);
|
||||||
|
|
||||||
|
counter++;
|
||||||
|
#endif
|
||||||
|
}
|
53
evoke/Splash.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* $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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SPLASH_H__
|
||||||
|
#define __SPLASH_H__
|
||||||
|
|
||||||
|
#include <FL/Fl_Double_Window.h>
|
||||||
|
#include <FL/Fl_Box.h>
|
||||||
|
|
||||||
|
#include "EvokeService.h"
|
||||||
|
|
||||||
|
class Splash : public Fl_Double_Window {
|
||||||
|
private:
|
||||||
|
const ClientList* clist;
|
||||||
|
const edelib::String* bkg;
|
||||||
|
unsigned int counter;
|
||||||
|
bool no_splash;
|
||||||
|
bool dry_run;
|
||||||
|
|
||||||
|
ClientListIter clist_it;
|
||||||
|
|
||||||
|
Fl_Box* msgbox;
|
||||||
|
Fl_Box** icons;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Splash(bool sp, bool dr);
|
||||||
|
~Splash();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: clients() and set_background() uses address of passed data,
|
||||||
|
* so make sure passed data does not destroys.
|
||||||
|
*/
|
||||||
|
void set_clients(const ClientList* cl) { clist = cl; }
|
||||||
|
void set_background(const edelib::String* s) { bkg = s; }
|
||||||
|
|
||||||
|
const ClientList* get_clients(void) const { return clist; }
|
||||||
|
bool next_client(void);
|
||||||
|
bool next_client_nosplash(void);
|
||||||
|
|
||||||
|
void run(void);
|
||||||
|
//virtual void show(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,29 +1,26 @@
|
|||||||
# evoke configuration sample
|
# evoke configuration sample
|
||||||
|
# main section; must be present
|
||||||
# main section
|
|
||||||
# must be present
|
|
||||||
[evoke]
|
[evoke]
|
||||||
Startup = edewm,eiconman,eworkpanel,xscreensaver
|
Startup = edewm,eiconman,eworkpanel,xscreensaver
|
||||||
|
ImagesDirectory = images
|
||||||
|
Splash = splash-alpha1.png
|
||||||
|
|
||||||
[edewm]
|
[edewm]
|
||||||
Icon = wm.png
|
Icon = edewm.png
|
||||||
Exec = edewm
|
Exec = gvim
|
||||||
Core = True
|
Description = window manager
|
||||||
Message = Starting window manager
|
|
||||||
|
|
||||||
[eiconman]
|
[eiconman]
|
||||||
Icon = desktop.png
|
Icon = eiconman.png
|
||||||
Exec = eiconman
|
Exec = mozilla
|
||||||
Core = True
|
Description = desktop
|
||||||
Message = Starting desktop
|
|
||||||
|
|
||||||
[eworkpanel]
|
[eworkpanel]
|
||||||
Icon = workpanel.png
|
Icon = eworkpanel.png
|
||||||
Exec = eworkpanel
|
Exec = mrxvt -bg black
|
||||||
Core = True
|
Description = panel
|
||||||
Message = Starting workpanel
|
|
||||||
|
|
||||||
[xscreensaver]
|
[xscreensaver]
|
||||||
Icon = xscreensaver.png
|
Icon = xscreensaver.png
|
||||||
Exec = xscreensaver
|
Exec = rxvt
|
||||||
Message = Starting screensaver
|
Description = screensaver
|
||||||
|
@ -26,18 +26,22 @@
|
|||||||
#define CONFIG_FILE "evoke.conf"
|
#define CONFIG_FILE "evoke.conf"
|
||||||
#define APPNAME "evoke"
|
#define APPNAME "evoke"
|
||||||
#define DEFAULT_PID "/tmp/evoke.pid"
|
#define DEFAULT_PID "/tmp/evoke.pid"
|
||||||
|
/*
|
||||||
|
* Used to assure unique instance, even if is given another
|
||||||
|
* path for pid. This option can't be modified by user.
|
||||||
|
* TODO: add lock on file so it can't be removed ?
|
||||||
|
*/
|
||||||
|
#define LOCK_FILE "/tmp/.evoke.lock"
|
||||||
|
|
||||||
#define CHECK_ARGV(argv, pshort, plong) ((strcmp(argv, pshort) == 0) || (strcmp(argv, plong) == 0))
|
#define CHECK_ARGV(argv, pshort, plong) ((strcmp(argv, pshort) == 0) || (strcmp(argv, plong) == 0))
|
||||||
|
|
||||||
bool running = false;
|
|
||||||
|
|
||||||
void quit_signal(int sig) {
|
void quit_signal(int sig) {
|
||||||
EVOKE_LOG("Got quit signal %i\n", sig);
|
EVOKE_LOG("Got quit signal %i\n", sig);
|
||||||
running = false;
|
EvokeService::instance()->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
int xmessage_handler(int e) {
|
int xmessage_handler(int e) {
|
||||||
return EvokeService::instance()->handle(e);
|
return EvokeService::instance()->handle(fl_xevent);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* next_param(int curr, char** argv, int argc) {
|
const char* next_param(int curr, char** argv, int argc) {
|
||||||
@ -57,9 +61,11 @@ void help(void) {
|
|||||||
puts("Options:");
|
puts("Options:");
|
||||||
puts(" -h, --help this help");
|
puts(" -h, --help this help");
|
||||||
puts(" -s, --startup run in starup mode");
|
puts(" -s, --startup run in starup mode");
|
||||||
|
puts(" -n, --no-splash do not show splash screen in starup mode");
|
||||||
|
puts(" -d, --dry-run run in starup mode, but don't execute anything");
|
||||||
puts(" -c, --config [FILE] use FILE as config file");
|
puts(" -c, --config [FILE] use FILE as config file");
|
||||||
puts(" -p, --pid [FILE] use FILE to store PID number");
|
puts(" -p, --pid [FILE] use FILE to store PID number");
|
||||||
puts(" -l, --log [FILE] log traffic to FILE\n");
|
puts(" -l, --log [FILE] log traffic to FILE (FILE can be stdout/stderr for console output)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -67,7 +73,9 @@ int main(int argc, char** argv) {
|
|||||||
const char* pid_file = NULL;
|
const char* pid_file = NULL;
|
||||||
const char* log_file = NULL;
|
const char* log_file = NULL;
|
||||||
|
|
||||||
bool do_startup = false;
|
bool do_startup = 0;
|
||||||
|
bool do_dryrun = 0;
|
||||||
|
bool no_splash = 0;
|
||||||
|
|
||||||
if(argc > 1) {
|
if(argc > 1) {
|
||||||
const char* a;
|
const char* a;
|
||||||
@ -99,7 +107,11 @@ int main(int argc, char** argv) {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
else if(CHECK_ARGV(a, "-s", "--startup"))
|
else if(CHECK_ARGV(a, "-s", "--startup"))
|
||||||
do_startup = true;
|
do_startup = 1;
|
||||||
|
else if(CHECK_ARGV(a, "-d", "--dry-run"))
|
||||||
|
do_dryrun = 1;
|
||||||
|
else if(CHECK_ARGV(a, "-n", "--no-splash"))
|
||||||
|
no_splash = 1;
|
||||||
else {
|
else {
|
||||||
printf("Unknown parameter '%s'. Run '"APPNAME" -h' for options\n", a);
|
printf("Unknown parameter '%s'. Run '"APPNAME" -h' for options\n", a);
|
||||||
return 1;
|
return 1;
|
||||||
@ -110,20 +122,6 @@ int main(int argc, char** argv) {
|
|||||||
// make sure X11 is running before rest of code is called
|
// make sure X11 is running before rest of code is called
|
||||||
fl_open_display();
|
fl_open_display();
|
||||||
|
|
||||||
// actually, evoke must not fork itself
|
|
||||||
#if 0
|
|
||||||
// start service
|
|
||||||
if(!do_foreground) {
|
|
||||||
int x;
|
|
||||||
if((x = fork()) > 0)
|
|
||||||
exit(0);
|
|
||||||
else if(x == -1) {
|
|
||||||
printf("Fatal: fork failed !\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
EvokeService* service = EvokeService::instance();
|
EvokeService* service = EvokeService::instance();
|
||||||
|
|
||||||
if(!service->setup_logging(log_file)) {
|
if(!service->setup_logging(log_file)) {
|
||||||
@ -136,8 +134,9 @@ int main(int argc, char** argv) {
|
|||||||
if(!pid_file)
|
if(!pid_file)
|
||||||
pid_file = DEFAULT_PID;
|
pid_file = DEFAULT_PID;
|
||||||
|
|
||||||
if(!service->setup_pid(pid_file)) {
|
if(!service->setup_pid(pid_file, LOCK_FILE)) {
|
||||||
EVOKE_LOG("Either another "APPNAME" instance is running or can't create pid file. Please correct this\n");
|
EVOKE_LOG("Either another "APPNAME" instance is running or can't create pid file. Please correct this\n");
|
||||||
|
EVOKE_LOG("Note: if program abnormaly crashed before, just remove '%s' and start it again\n", LOCK_FILE);
|
||||||
EVOKE_LOG("= "APPNAME" abrupted shutdown =\n");
|
EVOKE_LOG("= "APPNAME" abrupted shutdown =\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -145,11 +144,13 @@ int main(int argc, char** argv) {
|
|||||||
if(!config_file)
|
if(!config_file)
|
||||||
config_file = CONFIG_FILE; // TODO: XDG paths
|
config_file = CONFIG_FILE; // TODO: XDG paths
|
||||||
|
|
||||||
if(!service->setup_config(config_file, do_startup)) {
|
if(do_startup) {
|
||||||
EVOKE_LOG("Unable to read correctly %s. Please check it is correct config file\n");
|
if(!service->init_splash(config_file, no_splash, do_dryrun)) {
|
||||||
|
EVOKE_LOG("Unable to read correctly %s. Please check it is correct config file\n", config_file);
|
||||||
EVOKE_LOG("= "APPNAME" abrupted shutdown =\n");
|
EVOKE_LOG("= "APPNAME" abrupted shutdown =\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
service->setup_atoms(fl_display);
|
service->setup_atoms(fl_display);
|
||||||
|
|
||||||
@ -157,9 +158,9 @@ int main(int argc, char** argv) {
|
|||||||
signal(SIGTERM, quit_signal);
|
signal(SIGTERM, quit_signal);
|
||||||
signal(SIGKILL, quit_signal);
|
signal(SIGKILL, quit_signal);
|
||||||
|
|
||||||
running = true;
|
service->start();
|
||||||
|
|
||||||
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), PropertyChangeMask | StructureNotifyMask | ClientMessage);
|
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), PropertyChangeMask | SubstructureNotifyMask | ClientMessage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Register event listener and run in infinite loop. Loop will be
|
* Register event listener and run in infinite loop. Loop will be
|
||||||
@ -171,7 +172,7 @@ int main(int argc, char** argv) {
|
|||||||
* So stick with the simplicity :)
|
* So stick with the simplicity :)
|
||||||
*/
|
*/
|
||||||
Fl::add_handler(xmessage_handler);
|
Fl::add_handler(xmessage_handler);
|
||||||
while(running)
|
while(service->running())
|
||||||
Fl::wait(FOREVER);
|
Fl::wait(FOREVER);
|
||||||
|
|
||||||
EVOKE_LOG("= "APPNAME" nice shutdown =\n");
|
EVOKE_LOG("= "APPNAME" nice shutdown =\n");
|
||||||
|
2
evoke/evoke_csize.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
-rwx--x--x 1 sanel users 1794407 2007-07-30 02:27 evoke (std::vector)
|
||||||
|
-rwx--x--x 1 sanel users 1607516 2007-07-30 02:54 evoke (edelib::list)
|
BIN
evoke/images/edewm.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
evoke/images/eiconman.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
evoke/images/eworkpanel.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
evoke/images/splash-alpha1.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
evoke/images/splash-alpha1.png.old
Normal file
After Width: | Height: | Size: 8.1 KiB |
BIN
evoke/images/xscreensaver.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 7.9 KiB |
@ -5,7 +5,7 @@ code_name {.cxx}
|
|||||||
Function {} {open selected
|
Function {} {open selected
|
||||||
} {
|
} {
|
||||||
Fl_Window {} {open
|
Fl_Window {} {open
|
||||||
xywh {365 175 480 364} type Double visible
|
xywh {365 175 480 365} type Double visible
|
||||||
} {
|
} {
|
||||||
Fl_Box {} {
|
Fl_Box {} {
|
||||||
image {splash-alpha1.png} xywh {0 0 480 364} labelsize 14
|
image {splash-alpha1.png} xywh {0 0 480 364} labelsize 14
|
||||||
|
63
evoke/test/evoke_test.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <FL/Fl.h>
|
||||||
|
#include <FL/Fl_Double_Window.h>
|
||||||
|
#include <FL/Fl_Input.h>
|
||||||
|
#include <FL/Fl_Button.h>
|
||||||
|
#include <FL/x.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Fl_Input* inp;
|
||||||
|
Fl_Double_Window* win;
|
||||||
|
|
||||||
|
void run_cb(Fl_Widget*, void*) {
|
||||||
|
Atom _XA_EDE_EVOKE_SPAWN = XInternAtom(fl_display, "_EDE_EVOKE_SPAWN", False);
|
||||||
|
// max size
|
||||||
|
unsigned char txt_send[8192];
|
||||||
|
int i;
|
||||||
|
const char* txt_val = inp->value() ? inp->value() : "(none)";
|
||||||
|
int len = strlen(txt_val);
|
||||||
|
|
||||||
|
for(i = 0; i < 8192-2 && i < len; i++)
|
||||||
|
txt_send[i] = txt_val[i];
|
||||||
|
|
||||||
|
txt_send[i] = '\0';
|
||||||
|
|
||||||
|
// send text
|
||||||
|
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
_XA_EDE_EVOKE_SPAWN, XA_STRING, 8, PropModeReplace,
|
||||||
|
txt_send, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void evoke_quit_cb(Fl_Widget*, void*) {
|
||||||
|
Atom _XA_EDE_EVOKE_QUIT = XInternAtom(fl_display, "_EDE_EVOKE_QUIT", False);
|
||||||
|
|
||||||
|
int dummy = 1;
|
||||||
|
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
_XA_EDE_EVOKE_QUIT, XA_CARDINAL, 32, PropModeReplace,
|
||||||
|
(unsigned char*)&dummy, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit_all_cb(Fl_Widget*, void*) {
|
||||||
|
Atom _XA_EDE_EVOKE_SHUTDOWN_ALL = XInternAtom(fl_display, "_EDE_EVOKE_SHUTDOWN_ALL", False);
|
||||||
|
|
||||||
|
int dummy = 1;
|
||||||
|
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
_XA_EDE_EVOKE_SHUTDOWN_ALL, XA_CARDINAL, 32, PropModeReplace,
|
||||||
|
(unsigned char*)&dummy, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
win = new Fl_Double_Window(355, 94, "Evoke test");
|
||||||
|
win->begin();
|
||||||
|
inp = new Fl_Input(10, 25, 335, 25, "Program to run:");
|
||||||
|
inp->align(FL_ALIGN_TOP_LEFT);
|
||||||
|
Fl_Button* b1 = new Fl_Button(255, 60, 90, 25, "&Run");
|
||||||
|
b1->callback(run_cb);
|
||||||
|
Fl_Button* b2 = new Fl_Button(150, 60, 90, 25, "&Quit evoke");
|
||||||
|
b2->callback(evoke_quit_cb);
|
||||||
|
Fl_Button* b3 = new Fl_Button(55, 60, 90, 25, "&Quit all");
|
||||||
|
b3->callback(quit_all_cb);
|
||||||
|
win->end();
|
||||||
|
win->show(argc, argv);
|
||||||
|
return Fl::run();
|
||||||
|
}
|
28
evoke/test/evoke_test.fl
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# data file for the Fltk User Interface Designer (fluid)
|
||||||
|
version 1.0108
|
||||||
|
header_name {.h}
|
||||||
|
code_name {.cxx}
|
||||||
|
Function {} {open
|
||||||
|
} {
|
||||||
|
Fl_Window {} {
|
||||||
|
label {Evoke test} open
|
||||||
|
xywh {493 478 355 94} type Double visible
|
||||||
|
} {
|
||||||
|
Fl_Input {} {
|
||||||
|
label {Program to run:} selected
|
||||||
|
xywh {10 25 335 25} labelsize 14 align 5 textsize 14
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label {&Run}
|
||||||
|
xywh {255 60 90 25} labelsize 14
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label {&Quit evoke}
|
||||||
|
xywh {150 60 90 25} labelsize 14
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label {&Quit all}
|
||||||
|
xywh {55 60 90 25} labelsize 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|