From df1dfbfc41e493d2425c000fd02bf6db77f96908 Mon Sep 17 00:00:00 2001 From: Sanel Zukan Date: Mon, 30 Jul 2007 13:25:13 +0000 Subject: [PATCH] Work, work... --- evoke/EvokeService.cpp | 191 +++++++++++++++--- evoke/EvokeService.h | 37 +++- evoke/Jamfile | 5 +- evoke/Spawn.cpp | 69 +++++++ evoke/Spawn.h | 33 ++++ evoke/Splash.cpp | 305 +++++++++++++++++++++++++++++ evoke/Splash.h | 53 +++++ evoke/evoke.conf | 31 ++- evoke/evoke.cpp | 59 +++--- evoke/evoke_csize.txt | 2 + evoke/images/edewm.png | Bin 0 -> 1237 bytes evoke/images/eiconman.png | Bin 0 -> 1710 bytes evoke/images/eworkpanel.png | Bin 0 -> 1055 bytes evoke/images/splash-alpha1.png | Bin 0 -> 12011 bytes evoke/images/splash-alpha1.png.old | Bin 0 -> 8272 bytes evoke/images/xscreensaver.png | Bin 0 -> 1725 bytes evoke/splash-alpha1.png | Bin 8100 -> 0 bytes evoke/splash.fl | 2 +- evoke/test/evoke_test.cpp | 63 ++++++ evoke/test/evoke_test.fl | 28 +++ 20 files changed, 795 insertions(+), 83 deletions(-) create mode 100644 evoke/Spawn.cpp create mode 100644 evoke/Spawn.h create mode 100644 evoke/Splash.cpp create mode 100644 evoke/Splash.h create mode 100644 evoke/evoke_csize.txt create mode 100644 evoke/images/edewm.png create mode 100644 evoke/images/eiconman.png create mode 100644 evoke/images/eworkpanel.png create mode 100644 evoke/images/splash-alpha1.png create mode 100644 evoke/images/splash-alpha1.png.old create mode 100644 evoke/images/xscreensaver.png delete mode 100644 evoke/splash-alpha1.png create mode 100644 evoke/test/evoke_test.cpp create mode 100644 evoke/test/evoke_test.fl diff --git a/evoke/EvokeService.cpp b/evoke/EvokeService.cpp index 80e0a8d..bbeb37f 100644 --- a/evoke/EvokeService.cpp +++ b/evoke/EvokeService.cpp @@ -12,23 +12,87 @@ #include "Log.h" #include "EvokeService.h" +#include "Splash.h" +#include "Spawn.h" + #include #include #include +#include +#include + +#include #include // getpid #include // #include // free #include // 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() { if(logfile) delete logfile; + if(lockfile) { + edelib::file_remove(lockfile); + free(lockfile); + } + if(pidfile) { edelib::file_remove(pidfile); free(pidfile); @@ -54,13 +118,20 @@ bool EvokeService::setup_logging(const char* file) { return true; } -bool EvokeService::setup_pid(const char* file) { +bool EvokeService::setup_pid(const char* file, const char* lock) { if(!file) return false; - if(edelib::file_exists(file)) + if(edelib::file_exists(lock)) return false; + FILE* l = fopen(lock, "w"); + if(!l) + return false; + fprintf(l, " "); + fclose(l); + lockfile = strdup(lock); + FILE* f = fopen(file, "w"); if(!f) return false; @@ -72,20 +143,35 @@ bool EvokeService::setup_pid(const char* file) { return true; } -bool EvokeService::setup_config(const char* config, bool do_startup) { - // for now if is not startup mode, ignore it - if(!do_startup) - return true; - +bool EvokeService::init_splash(const char* config, bool no_splash, bool dry_run) { edelib::Config c; if(!c.load(config)) return false; 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))) return false; - edelib::vector vs; + StringList vs; edelib::stringtok(vs, buff, ","); // nothing, fine, do nothing @@ -95,8 +181,9 @@ bool EvokeService::setup_config(const char* config, bool do_startup) { EvokeClient ec; 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); // 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 ec.exec = buff; - if(c.get(key_name, "Message", buff, sizeof(buff))) - ec.message = buff; - // it is no EDE app untill say so - c.get(key_name, "Core", ec.core, false); + if(c.get(key_name, "Description", buff, sizeof(buff))) + ec.desc = buff; if(c.get(key_name, "Icon", buff, sizeof(buff))) ec.icon = buff; @@ -116,23 +201,81 @@ bool EvokeService::setup_config(const char* config, bool do_startup) { clients.push_back(ec); } - for(unsigned int i = 0; i < clients.size(); i++) { - printf("Exec: %s\n", clients[i].exec.c_str()); - printf("Message: %s\n", clients[i].message.c_str()); - printf("Icon: %s\n", clients[i].icon.c_str()); - printf("Core: %i\n\n", clients[i].core); - } + /* + * Now, before data is send to Splash, resolve directories + * since Splash expects that. + */ + 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; } 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_evoke_quit = XInternAtom(d, "_EDE_EVOKE_QUIT", False); + _ede_spawn = XInternAtom(d, "_EDE_EVOKE_SPAWN", False); - _ede_shutdown_client = XInternAtom(d, "_EDE_SHUTDOWN", False); } -int EvokeService::handle(int event) { - logfile->printf("Got event %i\n", event); +int EvokeService::handle(const XEvent* ev) { + 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; } diff --git a/evoke/EvokeService.h b/evoke/EvokeService.h index 9229818..d4e06c4 100644 --- a/evoke/EvokeService.h +++ b/evoke/EvokeService.h @@ -14,42 +14,59 @@ #define __EVOKESERVICE_H__ #include "Log.h" -#include - -#include +#include #include +#include 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 exec; // program name/path to run - bool core; // does understaind _EDE_SHUTDOWN_SELF (only ede apps) }; +typedef edelib::list ClientList; +typedef edelib::list::iterator ClientListIter; +typedef edelib::list StringList; +typedef edelib::list::iterator StringListIter; + +class Fl_Double_Window; + class EvokeService { private: + bool is_running; Log* logfile; char* pidfile; + char* lockfile; + + Fl_Double_Window* top_win; Atom _ede_shutdown_all; - Atom _ede_shutdown_client; Atom _ede_spawn; + Atom _ede_evoke_quit; - edelib::vector clients; + ClientList clients; public: EvokeService(); ~EvokeService(); 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_pid(const char* file); - bool setup_config(const char* config, bool do_startup); + bool setup_pid(const char* file, const char* lock); 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; } + + void register_top(Fl_Double_Window* win) { top_win = win; } + void unregister_top(void) { top_win = NULL; } }; #define EVOKE_LOG EvokeService::instance()->log()->printf diff --git a/evoke/Jamfile b/evoke/Jamfile index facf74a..91ceb07 100644 --- a/evoke/Jamfile +++ b/evoke/Jamfile @@ -10,7 +10,8 @@ SubDir TOP evoke ; -SOURCE = evoke.cpp EvokeService.cpp Log.cpp ; +SOURCE = evoke.cpp EvokeService.cpp Spawn.cpp Splash.cpp Log.cpp ; EdeProgram evoke : $(SOURCE) ; -TranslationStrings locale : $(SOURCE) ; +FltkProgramBare test/evoke_test : test/evoke_test.cpp ; +#TranslationStrings locale : $(SOURCE) ; diff --git a/evoke/Spawn.cpp b/evoke/Spawn.cpp new file mode 100644 index 0000000..bf5437b --- /dev/null +++ b/evoke/Spawn.cpp @@ -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 // fork +#include // fork, open, close, dup +#include +#include +#include +#include + +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); +} diff --git a/evoke/Spawn.h b/evoke/Spawn.h new file mode 100644 index 0000000..679bc12 --- /dev/null +++ b/evoke/Spawn.h @@ -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 diff --git a/evoke/Splash.cpp b/evoke/Splash.cpp new file mode 100644 index 0000000..e4001b4 --- /dev/null +++ b/evoke/Splash.cpp @@ -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 +#include +#include + +#include +#include + +#include // 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 +} diff --git a/evoke/Splash.h b/evoke/Splash.h new file mode 100644 index 0000000..01e10f3 --- /dev/null +++ b/evoke/Splash.h @@ -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 +#include + +#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 diff --git a/evoke/evoke.conf b/evoke/evoke.conf index ad779be..6a0dce2 100644 --- a/evoke/evoke.conf +++ b/evoke/evoke.conf @@ -1,29 +1,26 @@ # evoke configuration sample - -# main section -# must be present +# main section; must be present [evoke] Startup = edewm,eiconman,eworkpanel,xscreensaver + ImagesDirectory = images + Splash = splash-alpha1.png [edewm] - Icon = wm.png - Exec = edewm - Core = True - Message = Starting window manager + Icon = edewm.png + Exec = gvim + Description = window manager [eiconman] - Icon = desktop.png - Exec = eiconman - Core = True - Message = Starting desktop + Icon = eiconman.png + Exec = mozilla + Description = desktop [eworkpanel] - Icon = workpanel.png - Exec = eworkpanel - Core = True - Message = Starting workpanel + Icon = eworkpanel.png + Exec = mrxvt -bg black + Description = panel [xscreensaver] Icon = xscreensaver.png - Exec = xscreensaver - Message = Starting screensaver + Exec = rxvt + Description = screensaver diff --git a/evoke/evoke.cpp b/evoke/evoke.cpp index 5bfe81c..9fbb0ae 100644 --- a/evoke/evoke.cpp +++ b/evoke/evoke.cpp @@ -26,18 +26,22 @@ #define CONFIG_FILE "evoke.conf" #define APPNAME "evoke" #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)) -bool running = false; - void quit_signal(int sig) { EVOKE_LOG("Got quit signal %i\n", sig); - running = false; + EvokeService::instance()->stop(); } 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) { @@ -57,9 +61,11 @@ void help(void) { puts("Options:"); puts(" -h, --help this help"); 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(" -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) { @@ -67,7 +73,9 @@ int main(int argc, char** argv) { const char* pid_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) { const char* a; @@ -99,7 +107,11 @@ int main(int argc, char** argv) { i++; } 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 { printf("Unknown parameter '%s'. Run '"APPNAME" -h' for options\n", a); return 1; @@ -110,20 +122,6 @@ int main(int argc, char** argv) { // make sure X11 is running before rest of code is called 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(); if(!service->setup_logging(log_file)) { @@ -136,8 +134,9 @@ int main(int argc, char** argv) { if(!pid_file) 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("Note: if program abnormaly crashed before, just remove '%s' and start it again\n", LOCK_FILE); EVOKE_LOG("= "APPNAME" abrupted shutdown =\n"); return 1; } @@ -145,10 +144,12 @@ int main(int argc, char** argv) { if(!config_file) config_file = CONFIG_FILE; // TODO: XDG paths - if(!service->setup_config(config_file, do_startup)) { - EVOKE_LOG("Unable to read correctly %s. Please check it is correct config file\n"); - EVOKE_LOG("= "APPNAME" abrupted shutdown =\n"); - return 1; + if(do_startup) { + 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"); + return 1; + } } service->setup_atoms(fl_display); @@ -157,9 +158,9 @@ int main(int argc, char** argv) { signal(SIGTERM, 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 @@ -171,7 +172,7 @@ int main(int argc, char** argv) { * So stick with the simplicity :) */ Fl::add_handler(xmessage_handler); - while(running) + while(service->running()) Fl::wait(FOREVER); EVOKE_LOG("= "APPNAME" nice shutdown =\n"); diff --git a/evoke/evoke_csize.txt b/evoke/evoke_csize.txt new file mode 100644 index 0000000..6405052 --- /dev/null +++ b/evoke/evoke_csize.txt @@ -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) diff --git a/evoke/images/edewm.png b/evoke/images/edewm.png new file mode 100644 index 0000000000000000000000000000000000000000..2ee792ddde5109296c8702d44d3e31aa81455d4d GIT binary patch literal 1237 zcmV;`1SNzt=3;Z6cE9E>+fJ@jBOz{wB~67-@}6Qkls@Ssu~3Z)`;x1Uf-x7*o|*_oXg z53p;2va`#Qc=4Z1=Hq?ld4BWE^FHq@Y}@9)l$^PEYyaM$DeMhT%dyKv+!W=P&Ye4F zIs&};#-8T7#?n2ydJz>4_=o=b!9n~b#;u+$0!X13JRXDvKbf~yUE6NtFdhxAp~1CtwT$yD5VN( zUfK?Tx-eIe^EQ+oOFSe)MslBf!+;1UI8@LNj-B2HLlK8!M_S`Q*zV&{7X%Q3h54yuE)H zrfCsRrnnM|y#qJ{7>2>xm1Q&rYqPbHIWN}E=6YH-H`2MQgtjnKF!V-)?!4Xn12jm)~;k#;1&A&`xze}r>Ccf zZOt3Fas3Jl(WQ%4yIY>^x6+ap4{3ZhLFkssTqMR{Gdg#p8p+u?YP~*CW5{lWfq?-I zA3jV=OAFVAM|iPqH%*(jq9~r6z8y1Q+wk(%dQ$o`l$ZIbSs5U(tP+BCL?)-HSrMSL z)K54Z24HY-koNX=y1TnMefl&z+FxaQGQ`wGn9Ry+7a>=Ap8ftWwcq~dXncWAyd)AxSP2k1yx@MFZ$5 zjfMGHEbCrj8@fh!cQ=ZnaQ5t3$1D^LU>FY;SxQTgPNz9?-w_S zUhitAz)U3*aomcJ^XJc#OvXvX)!YF0x6bcAJb3WH-aV4!`W)~U0suBzLM5iAG1Ep) z%c2|6@V4-Nt+bhglx@7yk=X|L|a-KNV)_@)}R8{KoXlcyxG?_ z_nxyKlDaWAE7jKJk)9v!%kw;+=X=gQ=Ukzb;%S=pRI3B_Zz^#t8gT=!D5ZvMHti)T z)sNz%iBG;!fLJsV28M(XuLH-tb#;z-O}szYKI11;Dy1%_>Ak6&F=N;Sks6J-UzwgRzeWH0b4@R|@}SSeNS z^?D0!ZEenAFo?_T(x#{W$>!!JHqC~S%hG$Gmm8l>?#bu#gKSe_R{*hSq~~#$uLCa% zA%x%Ww?d(i!{_s{y0+$ANvD~dyv~UeuX6P0OQh3je)rp76KZ>wLx&FGa=BDKpC8%| zP<04m(MSz&j4!1PIGxU7C=_x8gF#`p+exR>Y;11g-`~u^fkSjX*TdDnUuHG)fIu)% z%9Ttexjl26mCOSSBR4a0`a*A2fLJu*2Zn$*HBEb2N?GIc`HJCixW?b)$0+2vfA2mD zL04B7{R7`-e`6C$sgkd)W;kCJyAfe6G$6U(I`h(#kULWsY4 zz25d(ms|Op{NllbG<|)21OkDY@$qq1Rvz$tUq8dcZ%|uXi&7G$6qaR{0eC!hFGJZ;?gqJEEEc9z$>w6#90D}k0#a(!&sc1{fxQKX8}cB zU0o?C(Avt>t(%yp`PFWjG&TFlWHMC&g25n4sahUQ@R9-;Ms8$s;u@DPU!t$CuPmsh z#))BM+1e`XN(Ct`+%7lyLcRjPy_USuy@a1?%%)nAG)^6u5C6AOIk=ND{@(ug~Q4nXC%X8ff9O z+qWya-O0mkVUl`zuDQ86y1RSn>gvYh@dRSgNJ9xAKAI>hr7r5aZdL>EH~E>@=dm7l zXnlnW9*>9hjkQv|l#RGffk_z5J2QWK-=DMoXZDKueHX zS1kahX|lY$Ofs2detv$dP$)QnRi)H>z#oB&@zKOa#eqah>)gV^!og>rX{4*G6HWVa zp1Ry_vPO=J@4ru7eLbO2knW!D(mUB~mYJCubX~WWmzR-J+B8j@mQtPt#(-urG(f({FAAWe5j*fQ1;kMG#jDMc!kBAHCGu&}VTy1MERLKJ|%JnrE1HIp($=}4*))q@kOX#|;bX_-##iB#g zw7ZYHJg=0x6dz4gZUj5nPDipoMc;@WKYZi}MlMU{;R>hUjgvESYJF{8DW%Xf?V6PG z55QP_G%>Z?g1b=wh5XIL8)E*U>;M1&07*qoM6N<$ Ef^rx~K>z>% literal 0 HcmV?d00001 diff --git a/evoke/images/eworkpanel.png b/evoke/images/eworkpanel.png new file mode 100644 index 0000000000000000000000000000000000000000..781209ae61b7563d263937bb0049eadd836d4aa9 GIT binary patch literal 1055 zcmV+)1mOFLP)N0RII5#&f5J!a#hR z`lqbjyW8LF?Cd-njmE00@1)Zyr>iUOZdK=eJ{O*wn|sePO*1n1)YBb3J%^eSK0f~u z&!2uVwp9Rb-AXd@$#BF1P)ZQ-n-a9vf!JEpB1ox(_#Sq&4I>n~V*pAC0G380BKRWB z30enY4a-hXu`qg(>Rg(LWg}WsQGz%QvBX0hJTXKlY;6cYM9^p~bnQa?H4G>fhyfJS zvt0jd7+uH_jW|@5!ZZv}iqhf&OW%D>xtQnh@gb~ebVC5>Is0i2@BKXhaF$Umj&< zW`^v`;Zuot@}%KX$# zu77nQP-DfF02)(kP$E3hKR`UbpT0->5WmiVFHN4hb_HJvh6XRY#BUcy82{otzUOoN z>^rm`?B?EMPogRwS1*42NJyr61|D~g7|?Q5U)!9uM~cLJR!5D z;>%ON^X>cZ(*M${bU)fpbkE)V^yLV??_-xsl>W|Qw+5F{)fup~1`$=;%D@t?iWLi- zc;yXdCV%DT*d@y43fj<^hKbUeh2$R`9T=oicIh1$WN+62!jTC1+evmEePEqapqd%j z>=gKJ9y{XDd0&D$>b}@8H10kKrz6uwzlm>j>Hk z1Jrk5GaZnYRu(f0#G-BFvl$Gf>4^7WS{9b$u(X`Pw{2*3$cm2?a(G?^n;7OgdZJeA zK;vj^Gy)@JVeRY01-wcH(=sR*b70$8VGCthpi~1cL>$5q2MvMRuv!U$#l_5uHaDzP zDv?g70uKhPT!vh3^Sm{d&1P#a_VNqQ9tnrTX95V7azduLWuIe!YPI^QvGZrN1K@uT Z;2)f%a=^e)CzSvI002ovPDHLkV1i(D+3)}W literal 0 HcmV?d00001 diff --git a/evoke/images/splash-alpha1.png b/evoke/images/splash-alpha1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b6912110262e63e47414b664ddccbcfe82ff71d GIT binary patch literal 12011 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 literal 0 HcmV?d00001 diff --git a/evoke/images/splash-alpha1.png.old b/evoke/images/splash-alpha1.png.old new file mode 100644 index 0000000000000000000000000000000000000000..c6f9fcf461daaa68a26becbf9ae74893d23ac02c GIT binary patch literal 8272 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 literal 0 HcmV?d00001 diff --git a/evoke/images/xscreensaver.png b/evoke/images/xscreensaver.png new file mode 100644 index 0000000000000000000000000000000000000000..511d0c44b87b1f310c156c558aa97062b1737193 GIT binary patch literal 1725 zcmV;u215CXP)Dh1cT(wHw(V{QYa$$V4tfvLO`h4k_d_*YA?3hHoc??8SSK%iMqb zJ^*~r(}3r)r**p_j^`(fpoTkDLs3<>({z3md_ST?5pa|c8H-p!kSui>fi$30Qkmlu zWoBm&(+^|F`S{f_nyn72iytxQ2QaFDx>Xeb#}PbjakSuQVH=ATyOXz30%<@L6bd=M z_Vq8Z-0ZU6?$PZ>U9y*=p`cj(@ zHY!X_&!W9?L@5qVSSCxWcsjz@0iF)vq_5wG;C2nt6D#u!8d5j#pihQY)j z3RqiS;rf-U%s)KI`f`isf6;=xfoh9&v&h)wL26_3*wzvL`tAmw81K=KU25e%%dHaC zfUBZN85~mwWA6MyK>X&ty4I?iTbO zuTTp=&CQkLlzgGx_bGTWgV;eS$hn4`Yj7RG)rQ!_*=92W0$F)jV|o9L4+s{Uc!MfV zP(Y`Sk)cavr$11eEERr_SG>$2eVnR3h;NFxjw0t8@}42@8hqE{XtSfh-V|7y1Uj8A zHa2)Ss~q{%IQbc2@lrc^%&O#wvkI(2SrDTj)@;faM+<%0TxY5rVq%|Ocz}`~C+{U> zTy2S?2rD~yyHfyJZUC0AH;7jIcvO;rQD77*R!FQM(zwQFzH*ZH2A6qzaD}Sx(4mMC zp&c#L2qKQTlbo&1;A%@4MTr7tgn*C`7IG>9m#9FL1qY8|a$A|*^wlD>Ez!j_`7!k(Y3FdM~ zc&GgyeJ4(KWfGEp*#)Cn*&GmsA=cWx3P|QoW9^;bA<*Dyl&cZ#fC43oj_vce?aR2H z584?LNEEx#XrKcR6DopWfVGy`#3KZRkpsdYVzWD8-!^bSC-;;Hi7{h^=as=t$`pq2 zNTY`7DtUPZg8?GRd9W)5ahxdd*kfmSzV!l~t>6wX8$;w!l8Oj5qSf#?PHPkpg%(B5 z@i>snF@Nk>rob)&B0@AYN2OBY{P}Ot+}OezLu>^b+hj?V9w5nyCCWm2s;NW@V?bfC z0%9$WR)9rojWLFPzn`Qaj`k1;!{HH`R715|%*IK~X8qAm5>KB~ILacTl3j}B4Ko~{qoo@Gp=eltRZ=g$oy&qw#$S{4d)*|8x3J=2%W0 T)_IF000000NkvXXu0mjfiXb_H literal 0 HcmV?d00001 diff --git a/evoke/splash-alpha1.png b/evoke/splash-alpha1.png deleted file mode 100644 index 63b13d2e4871f2513b5eada93e952cbe583da96f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8100 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 aT=ACDaqIij1<+1MD9ETtf4p-);6DIK*LKnX diff --git a/evoke/splash.fl b/evoke/splash.fl index 45a6873..4754f66 100644 --- a/evoke/splash.fl +++ b/evoke/splash.fl @@ -5,7 +5,7 @@ code_name {.cxx} Function {} {open selected } { Fl_Window {} {open - xywh {365 175 480 364} type Double visible + xywh {365 175 480 365} type Double visible } { Fl_Box {} { image {splash-alpha1.png} xywh {0 0 480 364} labelsize 14 diff --git a/evoke/test/evoke_test.cpp b/evoke/test/evoke_test.cpp new file mode 100644 index 0000000..fb687ba --- /dev/null +++ b/evoke/test/evoke_test.cpp @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#include + +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(); +} diff --git a/evoke/test/evoke_test.fl b/evoke/test/evoke_test.fl new file mode 100644 index 0000000..4f2d3bc --- /dev/null +++ b/evoke/test/evoke_test.fl @@ -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 + } + } +}