Moving old evoke to branches

This commit is contained in:
Sanel Zukan 2009-02-19 08:10:30 +00:00
parent 4491dd2948
commit d0498c453d
40 changed files with 0 additions and 5295 deletions

View File

@ -1,126 +0,0 @@
/*
* $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 "Autostart.h"
#include "icons/warning.xpm"
#include "EvokeService.h"
#include <edelib/Nls.h>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl.H>
Fl_Pixmap warnpix(warning_xpm);
void closeit_cb(Fl_Widget*, void* w) {
AstartDialog* win = (AstartDialog*)w;
win->hide();
}
void run_sel_cb(Fl_Widget*, void* w) {
AstartDialog* win = (AstartDialog*)w;
win->run_selected();
}
void run_all_cb(Fl_Widget*, void* w) {
AstartDialog* win = (AstartDialog*)w;
win->run_all();
}
AstartDialog::AstartDialog(unsigned int sz, bool do_show) : Fl_Window(370, 305, _("Autostart warning")),
curr(0), lst_sz(sz), show_dialog(do_show), lst(0) {
if(lst_sz)
lst = new AstartItem[lst_sz];
if(!show_dialog)
return;
begin();
img = new Fl_Box(10, 10, 65, 60);
img->image(warnpix);
txt = new Fl_Box(80, 10, 280, 60, _("The following applications are registered for starting. Please choose what to do next"));
txt->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_WRAP);
cbrowser = new Fl_Check_Browser(10, 75, 350, 185);
rsel = new Fl_Button(45, 270, 125, 25, _("Run &selected"));
rsel->callback(run_sel_cb, this);
rall = new Fl_Button(175, 270, 90, 25, _("&Run all"));
rall->callback(run_all_cb, this);
cancel = new Fl_Button(270, 270, 90, 25, _("&Cancel"));
cancel->callback(closeit_cb, this);
cancel->take_focus();
end();
}
AstartDialog::~AstartDialog() {
if(lst_sz)
delete [] lst;
}
void AstartDialog::add_item(const edelib::String& n, const edelib::String& e) {
if(!lst_sz)
return;
if(e.empty())
return;
AstartItem it;
it.name = n;
it.exec = e;
lst[curr++] = it;
}
#include <stdio.h>
#include <unistd.h>
void AstartDialog::run(void) {
if(!show_dialog) {
run_all();
return;
}
for(unsigned int i = 0; i < curr; i++)
cbrowser->add(lst[i].name.c_str());
if(!shown())
show();
while(shown()) {
//puts("WAIT WAIT");
Fl::wait();
}
}
void AstartDialog::run_selected(void) {
if(!show_dialog)
return;
int it = cbrowser->nchecked();
if(!it)
return;
for(unsigned int i = 0; i < curr; i++) {
if(cbrowser->checked(i+1))
EvokeService::instance()->run_program(lst[i].exec.c_str());
}
hide();
}
void AstartDialog::run_all(void) {
if(!curr)
return;
for(unsigned int i = 0; i < curr; i++)
EvokeService::instance()->run_program(lst[i].exec.c_str());
hide();
}

View File

@ -1,54 +0,0 @@
/*
* $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 __AUTOSTART_H__
#define __AUTOSTART_H__
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Check_Browser.H>
#include <FL/Fl_Button.H>
#include <edelib/String.h>
struct AstartItem {
edelib::String name;
edelib::String exec;
};
class AstartDialog : public Fl_Window {
private:
unsigned int curr;
unsigned int lst_sz;
bool show_dialog;
AstartItem* lst;
Fl_Box* img;
Fl_Box* txt;
Fl_Check_Browser* cbrowser;
Fl_Button* rsel;
Fl_Button* rall;
Fl_Button* cancel;
public:
AstartDialog(unsigned int sz, bool do_show);
~AstartDialog();
unsigned int list_size(void) { return curr; }
void add_item(const edelib::String& n, const edelib::String& e);
void run(void);
void run_all(void);
void run_selected(void);
};
#endif

View File

@ -1,17 +0,0 @@
/*
* $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 "ClassHack.h"
int get_attributes_class_hack(XWindowAttributes* attr) {
return attr->class;
}

View File

@ -1,36 +0,0 @@
/*
* $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 __CLASSHACK_H__
#define __CLASSHACK_H__
#include <X11/Xlib.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* A stupid hack to extract value from 'class' member in XWindowAttributes structure.
* Calling it in regular C++ translation unit will yield compilation error (sic)
* so we must force it to be seen as regular C source.
*
* Does X developers ever heard for C++ language ?@#?#!@
*/
int get_attributes_class_hack(XWindowAttributes* attr);
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +0,0 @@
/*
* $Id$
*
* Evoke, head honcho of everything
* Part of Equinox Desktop Environment (EDE).
* Based on xcompmgr (c) 2003 Keith Packard.
* 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 __COMPOSITE_H__
#define __COMPOSITE_H__
#include <X11/Xlib.h>
#include <X11/extensions/Xdamage.h> // XserverRegion already included in Xdamage.h
#include <edelib/List.h>
struct CWindow;
typedef edelib::list<CWindow*> CWindowList;
typedef edelib::list<CWindow*>::iterator CWindowListIter;
class Composite {
private:
bool manual_redirect;
CWindowList window_list;
void add_window(Window id, Window previous);
void map_window(Window id, unsigned long sequence, bool fade);
void unmap_window(Window id, bool fade);
void finish_unmap_window(CWindow* win);
CWindow* find_window(Window id);
XserverRegion window_extents(CWindow* win);
void configure_window(const XConfigureEvent* ce);
void restack_window(CWindow* win, Window new_above);
void property_notify(const XPropertyEvent* pe);
void expose_event(const XExposeEvent* ee);
void reparent_notify(const XReparentEvent* re);
void circulate_window(const XCirculateEvent* ce);
void damage_window(XDamageNotifyEvent* de);
void repair_window(CWindow* win);
void destroy_window(Window id, bool gone, bool fade);
void finish_destroy_window(Window id, bool gone);
void paint_root(void);
public:
Composite();
~Composite();
bool init(void);
int handle_xevents(const XEvent* xev);
void paint_all(XserverRegion region);
void update_screen(void);
};
#endif

View File

@ -1,798 +0,0 @@
/*
* $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 <sys/types.h> // getpid
#include <unistd.h> // pipe
#include <fcntl.h> // fcntl
#include <stdlib.h> // free
#include <string.h> // strdup, memset
#include <errno.h>
#include <signal.h>
#include <edelib/File.h>
#include <edelib/Config.h>
#include <edelib/DesktopFile.h>
#include <edelib/Directory.h>
#include <edelib/StrUtil.h>
#include <edelib/Util.h>
#include <edelib/Debug.h>
#include <edelib/MessageBox.h>
#include <edelib/Nls.h>
#include "Log.h"
#include "Logout.h"
#include "EvokeService.h"
#include "Splash.h"
#include "Spawn.h"
#include "Autostart.h"
static void resolve_path(const edelib::String& datadir, edelib::String& item, bool have_datadir) {
if(item.empty())
return;
const char* i = item.c_str();
if(!edelib::file_exists(i) && have_datadir) {
item = edelib::build_filename(datadir.c_str(), i);
i = item.c_str();
if(!edelib::file_exists(i)) {
// no file, send then empty
item.clear();
}
}
}
static char* get_basename(const char* path) {
char* p = strrchr(path, '/');
if(p)
return (p + 1);
return (char*)path;
}
/*
* 'Remove' duplicate entries by looking at their basename
* (aka. filename, but ignoring directory path). Item is not actually removed from
* the list (will mess up list pointers, but this can be resolved), but data it points
* to is cleared, which is a sort of marker to caller to skip it. Dumb yes, but very simple.
*
* It will use brute force for lookup and 'removal' and (hopfully) it should not have
* a large impact on startup since, afaik, no one keeps hundreds of files in autostart
* directories (if keeps them, then that issue is not up to this program :-P).
*
* Alternative would be to sort items (by their basename) and apply consecutive unique on
* them, but... is it worth ?
*/
static void basename_unique(StringList& lst) {
if(lst.empty())
return;
StringListIter first, last, first1, last1;
first = lst.begin();
last = lst.end();
if(first == last)
return;
const char* p1, *p2;
for(; first != last; ++first) {
for(first1 = lst.begin(), last1 = lst.end(); first1 != last1; ++first1) {
p1 = (*first).c_str();
p2 = (*first1).c_str();
if(first != first1 && strcmp(get_basename(p1), get_basename(p2)) == 0)
(*first1).clear();
}
}
}
static 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;
}
#if 0
static 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;
}
#endif
/*
* This is re-implementation of XmuClientWindow() so I don't have to link code with libXmu.
* XmuClientWindow() will return parent window of given window; this is used so we don't
* send delete message to some button or else, but it's parent.
*/
static Window mu_try_children(Display* dpy, Window win, Atom wm_state) {
Atom real;
Window root, parent;
Window* children = 0;
Window ret = 0;
unsigned int nchildren;
unsigned char* prop;
unsigned long n, extra;
int format;
if(!XQueryTree(dpy, win, &root, &parent, &children, &nchildren))
return 0;
for(unsigned int i = 0; (i < nchildren) && !ret; i++) {
prop = NULL;
XGetWindowProperty(dpy, children[i], wm_state, 0, 0, False, AnyPropertyType,
&real, &format, &n, &extra, (unsigned char**)&prop);
if(prop)
XFree(prop);
if(real)
ret = children[i];
}
for(unsigned int i = 0; (i < nchildren) && !ret; i++)
ret = mu_try_children(dpy, win, wm_state);
if(children)
XFree(children);
return ret;
}
static Window mu_client_window(Display* dpy, Window win, Atom wm_state) {
Atom real;
int format;
unsigned long n, extra;
unsigned char* prop;
int status = XGetWindowProperty(dpy, win, wm_state, 0, 0, False, AnyPropertyType,
&real, &format, &n, &extra, (unsigned char**)&prop);
if(prop)
XFree(prop);
if(status != Success)
return win;
if(real)
return win;
Window w = mu_try_children(dpy, win, wm_state);
if(!w) w = win;
return w;
}
void service_watcher_cb(int pid, int signum) {
EvokeService::instance()->service_watcher(pid, signum);
}
static void wake_up_cb(int fd, void* v) {
EvokeService::instance()->wake_up(fd);
}
EvokeService::EvokeService() :
is_running(0), logfile(NULL), xsm(NULL),
#ifdef HAVE_COMPOSITE
composite(NULL),
#endif
pidfile(NULL), lockfile(NULL) {
wake_up_pipe[0] = wake_up_pipe[1] = -1;
}
EvokeService::~EvokeService() {
if(logfile)
delete logfile;
#ifdef HAVE_COMPOSITE
delete composite;
#endif
stop_xsettings_manager(true);
if(lockfile) {
edelib::file_remove(lockfile);
free(lockfile);
}
if(pidfile) {
edelib::file_remove(pidfile);
free(pidfile);
}
processes.clear();
if(wake_up_pipe[0] != -1)
close(wake_up_pipe[0]);
if(wake_up_pipe[1] != -1)
close(wake_up_pipe[1]);
}
EvokeService* EvokeService::instance(void) {
static EvokeService es;
return &es;
}
bool EvokeService::setup_channels(void) {
if(pipe(wake_up_pipe) != 0)
return false;
fcntl(wake_up_pipe[1], F_SETFL, fcntl(wake_up_pipe[1], F_GETFL) | O_NONBLOCK);
Fl::add_fd(wake_up_pipe[0], FL_READ, wake_up_cb);
return true;
}
bool EvokeService::setup_logging(const char* file) {
if(!file)
logfile = new DummyLog();
else
logfile = new RealLog();
if(!logfile->open(file)) {
delete logfile;
logfile = NULL;
return false;
}
return true;
}
bool EvokeService::setup_pid(const char* file, const char* lock) {
if(!file)
return false;
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;
fprintf(f, "%i", getpid());
fclose(f);
pidfile = strdup(file);
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_datadir = false;
c.get("evoke", "DataDirectory", buff, sizeof(buff));
// no evoke section
if(c.error() == edelib::CONF_ERR_SECTION)
return false;
edelib::String datadir;
if(c.error() == edelib::CONF_SUCCESS) {
datadir = buff;
have_datadir = 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;
StringList vs;
edelib::stringtok(vs, buff, ",");
// nothing, fine, do nothing
unsigned int sz = vs.size();
if(sz == 0)
return true;
EvokeClient ec;
const char* key_name;
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
if(!c.get(key_name, "Exec", buff, sizeof(buff)))
continue;
else
ec.exec = buff;
if(c.get(key_name, "Description", buff, sizeof(buff)))
ec.desc = buff;
if(c.get(key_name, "Icon", buff, sizeof(buff)))
ec.icon = buff;
clients.push_back(ec);
}
/*
* Now, before data is send to Splash, resolve directories
* since Splash expects that.
*/
resolve_path(datadir, splashimg, have_datadir);
ClientListIter it, it_end;
for(it = clients.begin(), it_end = clients.end(); it != it_end; ++it)
resolve_path(datadir, (*it).icon, have_datadir);
Splash sp(no_splash, dry_run);
sp.set_clients(&clients);
sp.set_background(&splashimg);
sp.run();
return true;
}
/*
* This is implementation of Autostart Spec (http://standards.freedesktop.org/autostart-spec/autostart-spec-0.5.html).
* The Autostart Directories are $XDG_CONFIG_DIRS/autostart.
* If the same filename is located under multiple Autostart Directories
* only the file under the most important directory should be used.
* Example: If $XDG_CONFIG_HOME is not set the Autostart Directory in the user's home
* directory is ~/.config/autostart/
* Example: If $XDG_CONFIG_DIRS is not set the system wide Autostart Directory
* is /etc/xdg/autostart/
* Example: If $XDG_CONFIG_HOME and $XDG_CONFIG_DIRS are not set and the two
* files /etc/xdg/autostart/foo.desktop and ~/.config/autostart/foo.desktop exist
* then only the file ~/.config/autostart/foo.desktop will be used because ~/.config/autostart/
* is more important than /etc/xdg/autostart/
* If Hidden key is set true in .desktop file, file MUST be ignored.
* OnlyShowIn and NotShowIn (list of strings identifying desktop environments) if (or if not)
* contains environment name, MUST not be started/not started.
* TryExec is same as for .desktop spec.
*/
void EvokeService::init_autostart(bool safe) {
const char* autostart_dirname = "/autostart/";
edelib::String adir = edelib::user_config_dir();
adir += autostart_dirname;
StringList dfiles, sysdirs, tmp;
StringListIter it, it_end, tmp_it, tmp_it_end;
edelib::dir_list(adir.c_str(), dfiles, true);
edelib::system_config_dirs(sysdirs);
if(!sysdirs.empty()) {
for(it = sysdirs.begin(), it_end = sysdirs.end(); it != it_end; ++it) {
*it += autostart_dirname;
/*
* append content
* FIXME: too much of copying. There should be some way to merge list items
* probably via merge() member
*/
edelib::dir_list((*it).c_str(), tmp, true);
for(tmp_it = tmp.begin(), tmp_it_end = tmp.end(); tmp_it != tmp_it_end; ++tmp_it)
dfiles.push_back(*tmp_it);
}
}
if(dfiles.empty())
return;
/*
* Remove duplicates where first one seen have priority to be keept.
* This way is required by spec.
*
* Also handle this case (noted in spec):
* if $XDG_CONFIG_HOME/autostart/foo.desktop and $XDG_CONFIG_DIRS/autostart/foo.desktop
* exists, but $XDG_CONFIG_HOME/autostart/foo.desktop have 'Hidden = true',
* $XDG_CONFIG_DIRS/autostart/foo.autostart is ignored too.
*
* Latter is implied via basename_unique().
*/
basename_unique(dfiles);
const char* name;
char buff[1024];
edelib::DesktopFile df;
edelib::String item_name;
AstartDialog dlg(dfiles.size(), safe);
for(it = dfiles.begin(), it_end = dfiles.end(); it != it_end; ++it) {
if((*it).empty())
continue;
name = (*it).c_str();
if(!edelib::str_ends(name, ".desktop"))
continue;
if(!df.load(name)) {
EVOKE_LOG("Can't load %s. Skipping...\n", name);
continue;
}
// If Hidden key is set true in .desktop file, file MUST be ignored.
if(df.hidden())
continue;
if(df.name(buff, sizeof(buff)))
item_name = buff;
else
item_name = name;
if(df.try_exec(buff, sizeof(buff)) || df.exec(buff, sizeof(buff)))
dlg.add_item(item_name, buff);
}
if(dlg.list_size() > 0)
dlg.run();
}
void EvokeService::init_xsettings_manager(void) {
xsm = new Xsm;
if(Xsm::manager_running(fl_display, fl_screen)) {
int ret = edelib::ask(_("XSETTINGS manager already running on this screen. Would you like to replace it?"));
if(ret < 1) {
stop_xsettings_manager(false);
return;
} else
goto do_it;
}
do_it:
if(!xsm->init(fl_display, fl_screen)) {
edelib::alert(_("Unable to load XSETTINGS manager properly"));
stop_xsettings_manager(false);
}
if(!xsm) return;
if(xsm->load_serialized("ede-settings.xml"))
xsm->notify();
}
void EvokeService::stop_xsettings_manager(bool serialize) {
if(!xsm)
return;
if(serialize)
xsm->save_serialized("ede-settings.xml");
delete xsm;
xsm = NULL;
}
void EvokeService::init_composite(void) {
#ifdef HAVE_COMPOSITE
composite = new Composite();
if(!composite->init()) {
delete composite;
composite = NULL;
}
#endif
}
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);
}
void EvokeService::quit_x11(void) {
Window dummy, *wins;
Window root = RootWindow(fl_display, fl_screen);
unsigned int n;
if(!XQueryTree(fl_display, root, &dummy, &dummy, &wins, &n))
return;
Atom _wm_protocols = XInternAtom(fl_display, "WM_PROTOCOLS", False);
Atom _wm_delete_window = XInternAtom(fl_display, "WM_DELETE_WINDOW", False);
Atom _wm_state = XInternAtom(fl_display, "WM_STATE", False);
XWindowAttributes attr;
XEvent ev;
for(unsigned int i = 0; i < n; i++) {
if(XGetWindowAttributes(fl_display, wins[i], &attr) && (attr.map_state == IsViewable))
wins[i] = mu_client_window(fl_display, wins[i], _wm_state);
else
wins[i] = 0;
}
/*
* Hm... probably we should first quit known processes started by us
* then rest of the X familly
*/
for(unsigned int i = 0; i < n; i++) {
if(wins[i]) {
EVOKE_LOG("closing %i window\n", i);
// FIXME: check WM_PROTOCOLS before sending WM_DELETE_WINDOW ???
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = wins[i];
ev.xclient.message_type = _wm_protocols;
ev.xclient.format = 32;
ev.xclient.data.l[0] = (long)_wm_delete_window;
ev.xclient.data.l[1] = CurrentTime;
XSendEvent(fl_display, wins[i], False, 0L, &ev);
EVOKE_LOG("%i window closed\n", i);
}
}
XSync(fl_display, False);
sleep(1);
// kill remaining windows
for(unsigned int i = 0; i < n; i++) {
if(wins[i]) {
EVOKE_LOG("killing remaining %i window\n", i);
XKillClient(fl_display, wins[i]);
}
}
XSync(fl_display, False);
XFree(wins);
EVOKE_LOG("now close myself\n");
stop();
}
/*
* This is run each time when some of the managed childs quits.
* Instead directly running wake_up(), it will be notified wia
* wake_up_pipe[] channel, via add_fd() monitor.
*/
void EvokeService::service_watcher(int pid, int ret) {
write(wake_up_pipe[1], &pid, sizeof(int));
write(wake_up_pipe[1], &ret, sizeof(int));
}
void EvokeService::wake_up(int fd) {
puts("=== wake_up() ===");
int child_pid = -1;
// child can return anything so there is no default value
int child_ret;
if(read(wake_up_pipe[0], &child_pid, sizeof(int)) == -1 || child_pid == -1) {
puts("unable to read from channel");
return;
}
if(read(wake_up_pipe[0], &child_ret, sizeof(int)) == -1) {
puts("unable to read from channel");
return;
}
Mutex mutex;
if(child_ret == SPAWN_CHILD_CRASHED) {
EvokeProcess pc;
bool ret;
mutex.lock();
ret = find_and_unregister_process(child_pid, pc);
mutex.unlock();
if(ret) {
printf("%s crashed with core dump\n", pc.cmd.c_str());
}
} else {
mutex.lock();
unregister_process(child_pid);
mutex.unlock();
switch(child_ret) {
case SPAWN_CHILD_KILLED:
printf("child %i killed\n", child_pid);
break;
case 127:
edelib::alert(_("Program not found"));
break;
case 126:
edelib::alert(_("Program not executable"));
break;
default:
printf("child %i exited with %i\n", child_pid, child_ret);
break;
}
}
}
/*
* Execute program. It's return status
* will be reported via service_watcher()
*/
void EvokeService::run_program(const char* cmd, bool enable_vars) {
EASSERT(cmd != NULL);
edelib::String scmd(cmd);
pid_t child;
if(enable_vars && scmd.length() > 6) {
if(scmd.substr(0, 6) == "$TERM ") {
char* term = getenv("TERM");
if(!term)
term = "xterm";
edelib::String tmp(term);
tmp += " -e ";
tmp += scmd.substr(6, scmd.length());
scmd = tmp;
}
}
int r = spawn_program_with_core(scmd.c_str(), service_watcher_cb, &child);
if(r != 0)
edelib::alert("Unable to start %s. Got code %i", cmd, r);
else {
Mutex mutex;
mutex.lock();
register_process(scmd.c_str(), child);
mutex.unlock();
}
}
void EvokeService::register_process(const char* cmd, pid_t pid) {
EvokeProcess pc;
pc.cmd = cmd;
pc.pid = pid;
printf("registering %s with %i\n", cmd, pid);
processes.push_back(pc);
}
void EvokeService::unregister_process(pid_t pid) {
if(processes.empty())
return;
ProcessListIter it = processes.begin();
ProcessListIter it_end = processes.end();
while(it != it_end) {
if((*it).pid == pid) {
printf("Found %s with pid %i, cleaning...\n", (*it).cmd.c_str(), pid);
processes.erase(it);
return;
}
++it;
}
}
bool EvokeService::find_and_unregister_process(pid_t pid, EvokeProcess& pc) {
if(processes.empty())
return 0;
ProcessListIter it = processes.begin();
ProcessListIter it_end = processes.end();
while(it != it_end) {
if((*it).pid == pid) {
printf("Found %s with pid %i, cleaning...\n", (*it).cmd.c_str(), pid);
pc.cmd = (*it).cmd;
pc.pid = pid;
processes.erase(it);
return 1;
}
++it;
}
return 0;
}
int EvokeService::composite_handle(const XEvent* xev) {
#ifdef HAVE_COMPOSITE
if(composite)
return composite->handle_xevents(xev);
#endif
return 1;
}
/*
* Main loop for processing got X events.
*
* Great care must be taken to route this events to FLTK too (via fl_handle()), since
* add_fd() (in evoke.cpp) will not do that. If events are not routed to fltk, popped
* dialogs, especially from service_watcher() will not be correctly drawn and will hang
* whole program.
*/
int EvokeService::handle(const XEvent* xev) {
if(xsm && xsm->should_terminate(xev)) {
EVOKE_LOG("XSETTINGS manager shutdown\n");
stop_xsettings_manager(true);
return 1;
}
if(xev->type == PropertyNotify) {
#if 0
if(xev->xproperty.atom == _ede_spawn) {
char buff[1024];
if(get_string_property_value(_ede_spawn, buff, sizeof(buff))) {
EVOKE_LOG("Got _EDE_EVOKE_SPAWN with %s. Starting client...\n", buff);
run_program(buff);
} else {
EVOKE_LOG("Got _EDE_EVOKE_SPAWN with malformed data. Ignoring...\n");
}
}
#endif
if(xev->xproperty.atom == _ede_evoke_quit) {
int val = get_int_property_value(_ede_evoke_quit);
if(val == 1) {
EVOKE_LOG("Got accepted _EDE_EVOKE_QUIT\n");
stop();
} else
EVOKE_LOG("Got _EDE_EVOKE_QUIT with bad code (%i). Ignoring...\n", val);
}
if(xev->xproperty.atom == _ede_shutdown_all) {
int val = get_int_property_value(_ede_shutdown_all);
if(val == 1) {
EVOKE_LOG("Got accepted _EDE_EVOKE_SHUTDOWN_ALL\n");
int dw = DisplayWidth(fl_display, fl_screen);
int dh = DisplayHeight(fl_display, fl_screen);
// TODO: add XDM service permissions
printf("got %i\n", logout_dialog(dw, dh, LOGOUT_OPT_SHUTDOWN | LOGOUT_OPT_RESTART));
//quit_x11();
} else
EVOKE_LOG("Got _EDE_EVOKE_SHUTDOWN_ALL with bad code (%i). Ignoring...\n", val);
}
}
#ifdef USE_FLTK_LOOP_EMULATION
// let FLTK handle the rest
fl_handle(*xev);
return 0;
#else
// let composite manager do the rest
return composite_handle(xev);
#endif
}

View File

@ -1,132 +0,0 @@
/*
* $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 __EVOKESERVICE_H__
#define __EVOKESERVICE_H__
#include <FL/x.H>
#include <pthread.h>
#include <edelib/List.h>
#include <edelib/String.h>
#include "Log.h"
#include "Xsm.h"
#ifdef HAVE_COMPOSITE
#include "Composite.h"
#endif
struct EvokeClient {
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
};
struct EvokeProcess {
edelib::String cmd;
pid_t pid;
};
struct QueuedSignal {
pid_t pid;
int signum;
};
typedef edelib::list<EvokeClient> ClientList;
typedef edelib::list<EvokeClient>::iterator ClientListIter;
typedef edelib::list<edelib::String> StringList;
typedef edelib::list<edelib::String>::iterator StringListIter;
typedef edelib::list<EvokeProcess> ProcessList;
typedef edelib::list<EvokeProcess>::iterator ProcessListIter;
typedef edelib::list<QueuedSignal> SignalQueue;
typedef edelib::list<QueuedSignal>::iterator SignalQueueIter;
class EvokeService {
private:
bool is_running;
Log* logfile;
Xsm* xsm;
#ifdef HAVE_COMPOSITE
Composite* composite;
#endif
char* pidfile;
char* lockfile;
Atom _ede_shutdown_all;
Atom _ede_spawn;
Atom _ede_evoke_quit;
ClientList clients;
ProcessList processes;
int wake_up_pipe[2];
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_channels(void);
bool setup_logging(const char* file);
bool setup_pid(const char* file, const char* lock);
void setup_atoms(Display* d);
bool init_splash(const char* config, bool no_splash, bool dry_run);
void init_autostart(bool safe);
void init_xsettings_manager(void);
void stop_xsettings_manager(bool serialize);
void init_composite(void);
int handle(const XEvent* ev);
int composite_handle(const XEvent* ev);
Log* log(void) { return logfile; }
void service_watcher(int pid, int signum);
void wake_up(int fd);
void run_program(const char* cmd, bool enable_vars = 1);
void register_process(const char* cmd, pid_t pid);
void unregister_process(pid_t pid);
bool find_and_unregister_process(pid_t pid, EvokeProcess& pc);
void quit_x11(void);
//void update_screen(void);
};
#define EVOKE_LOG EvokeService::instance()->log()->printf
/*
* FIXME: This should be probably declared somewhere outside
* or in edelib as separate class
*/
class Mutex {
private:
pthread_mutex_t mutex;
Mutex(const Mutex&);
Mutex& operator=(const Mutex&);
public:
Mutex() { pthread_mutex_init(&mutex, 0); }
~Mutex() { pthread_mutex_destroy(&mutex); }
void lock(void) { pthread_mutex_lock(&mutex); }
void unlock(void) { pthread_mutex_unlock(&mutex); }
};
#endif

View File

@ -1,43 +0,0 @@
#
# $Id$
#
# 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.
SubDir TOP evoke ;
# use SIGHUP for now as default
ObjectC++Flags evoke.cpp : -DUSE_SIGHUP ;
# relay on FLTK loop emulation for now
ObjectC++Flags EvokeService.cpp evoke.cpp : -DUSE_FLTK_LOOP_EMULATION ;
# for smooth repainting
#ObjectC++Flags Composite.cpp : -DUSE_CHECK ;
SOURCE = evoke.cpp
EvokeService.cpp
ClassHack.c
Xsm.cpp
Spawn.cpp
Splash.cpp
Log.cpp
Logout.cpp
Autostart.cpp ;
# for composite
SOURCE += Composite.cpp ;
ObjectC++Flags $(SOURCE) : -DHAVE_COMPOSITE ;
LinkAgainst evoke : -lXcomposite -lXdamage -lXfixes -lXrender ;
#LinkAgainst evoke : -lpthread ;
EdeProgram evoke : $(SOURCE) ;
FltkProgramBare test/evoke_test : test/evoke_test.cpp : "noinstall" ;
FltkProgramBare test/stress_test : test/stress_test.cpp : "noinstall" ;
FltkProgramBare test/opacity_test : test/opacity_test.cpp : "noinstall" ;
#TranslationStrings locale : $(SOURCE) ;
EdeManual doc/evoke.txt ;

View File

@ -1,73 +0,0 @@
/*
* $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 "Log.h"
#include <edelib/Debug.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
RealLog::RealLog() : f(NULL), buff(NULL), tbuff(NULL), bufflen(256), tbufflen(20),
to_stdout(false), to_stderr(false) {
}
RealLog::~RealLog() {
if(f) {
puts("RealLog::~RealLog()\n");
fclose(f);
}
if(buff)
delete [] buff;
if(tbuff)
delete [] tbuff;
}
bool RealLog::open(const char* file) {
EASSERT(file != NULL);
if(strcmp(file, "stdout") == 0)
to_stdout = true;
else if(strcmp(file, "stderr") == 0)
to_stderr = true;
else {
f = fopen(file, "a");
if(!f)
return false;
}
buff = new char[bufflen];
tbuff = new char[tbufflen];
return true;
}
void RealLog::printf(const char* fmt, ...) {
EASSERT(buff != NULL);
EASSERT(tbuff != NULL);
va_list ap;
va_start(ap, fmt);
vsnprintf(buff, bufflen, fmt, ap);
va_end(ap);
time_t t = time(NULL);
strftime(tbuff, tbufflen, "%F %T", localtime(&t));
if(to_stdout)
fprintf(stdout, "[%s] %s", tbuff, buff);
else if(to_stderr)
fprintf(stderr, "[%s] %s", tbuff, buff);
else {
fprintf(f, "[%s] %s", tbuff, buff);
fflush(f);
}
}

View File

@ -1,51 +0,0 @@
/*
* $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 __LOG_H__
#define __LOG_H__
#include <stdio.h>
class Log {
public:
Log() { }
virtual ~Log() { }
virtual bool open(const char* file) = 0;
virtual void printf(const char* fmt, ...) = 0;
};
class DummyLog : public Log {
public:
DummyLog() { }
virtual ~DummyLog() { }
virtual bool open(const char* file) { return true; }
virtual void printf(const char* fmt, ...) { }
};
class RealLog : public Log {
private:
FILE* f;
char* buff;
char* tbuff;
int bufflen;
int tbufflen;
bool to_stdout;
bool to_stderr;
public:
RealLog();
virtual ~RealLog();
virtual bool open(const char* file);
virtual void printf(const char* fmt, ...);
};
#endif

View File

@ -1,95 +0,0 @@
/*
* $Id$
*
* Evoke, head honcho of everything
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2008 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl.H>
#include <edelib/Nls.h>
#include "Logout.h"
// Note that order of initialized items is important so LOGOUT_OPT_XXX can work
struct LogoutOptions {
const char* opt_short;
const char* opt_long;
} logout_options[] = {
{ _("Logout"), _("This option will close all programs and logs out from the current session") },
{ _("Restart"), _("This option will restart the computer closing all running programs") },
{ _("Shut down"), _("This option will shut down the computer closing all running programs") }
};
static Fl_Window* win;
static Fl_Box* description;
static int ret_option;
static void ok_cb(Fl_Widget*, void*) {
win->hide();
}
static void cancel_cb(Fl_Widget*, void*) {
ret_option = LOGOUT_RET_CANCEL;
win->hide();
}
static void option_cb(Fl_Widget*, void* o) {
Fl_Choice* c = (Fl_Choice*)o;
int v = c->value();
description->label(logout_options[v].opt_long);
ret_option = v;
}
int logout_dialog(int screen_w, int screen_h, int opt) {
ret_option = LOGOUT_RET_LOGOUT;
win = new Fl_Window(335, 180, _("Quit EDE?"));
win->begin();
Fl_Box* b1 = new Fl_Box(10, 9, 315, 25, _("How do you want to quit?"));
b1->labelfont(1);
b1->align(196|FL_ALIGN_INSIDE);
Fl_Choice* c = new Fl_Choice(10, 45, 315, 25);
c->down_box(FL_BORDER_BOX);
// fill choice menu
c->add(logout_options[0].opt_short, 0, option_cb, c);
if(opt & LOGOUT_OPT_RESTART)
c->add(logout_options[1].opt_short, 0, option_cb, c);
if(opt & LOGOUT_OPT_SHUTDOWN)
c->add(logout_options[2].opt_short, 0, option_cb, c);
description = new Fl_Box(10, 80, 315, 55);
description->align(197|FL_ALIGN_INSIDE);
// set to first menu item
c->value(0);
description->label(logout_options[0].opt_long);
Fl_Button* ok = new Fl_Button(140, 145, 90, 25, _("&OK"));
ok->callback(ok_cb, c);
Fl_Button* cancel = new Fl_Button(235, 145, 90, 25, _("&Cancel"));
cancel->callback(cancel_cb);
win->end();
// so when X in titlebar was clicked, we can get LOGOUT_RET_CANCEL
win->callback(cancel_cb);
win->position(screen_w / 2 - win->w() / 2, screen_h / 2 - win->h() / 2);
win->show();
while(win->shown())
Fl::wait();
return ret_option;
}

View File

@ -1,26 +0,0 @@
/*
* $Id$
*
* Evoke, head honcho of everything
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2008 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#ifndef __LOGOUT_H__
#define __LOGOUT_H__
#define LOGOUT_RET_CANCEL -1
#define LOGOUT_RET_LOGOUT 0
#define LOGOUT_RET_RESTART 1
#define LOGOUT_RET_SHUTDOWN 2
#define LOGOUT_OPT_RESTART (1 << 1)
#define LOGOUT_OPT_SHUTDOWN (1 << 2)
int logout_dialog(int screen_w, int screen_h, int opt);
#endif

View File

@ -1,154 +0,0 @@
/*
* $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 <sys/types.h> // fork
#include <unistd.h> // fork, open, close, dup
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h> // getrlimit, setrlimit
#include <sys/resource.h> //
#include "Spawn.h"
extern char** environ;
SignalWatch* global_watch = 0;
void sigchld_handler(int sig) {
int pid, status;
do {
errno = 0;
pid = waitpid(WAIT_ANY, &status, WNOHANG | WUNTRACED);
if(global_watch != 0) {
if(WIFEXITED(status))
status = WEXITSTATUS(status);
else if(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)
status = SPAWN_CHILD_CRASHED;
else
status = SPAWN_CHILD_KILLED;
global_watch(pid, status);
}
} while(pid <= 0 && errno == EINTR);
}
int spawn_program(const char* cmd, SignalWatch wf, pid_t* child_pid_ret, const char* ofile) {
if(!cmd)
return SPAWN_EMPTY;
int nulldev = -1;
int status_ret = 0;
#if 0
struct sigaction sa;
sa.sa_handler = sigchld_handler;
sa.sa_flags = SA_NOCLDSTOP;
/*sa.sa_flags = SA_NOCLDWAIT;*/
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, (struct sigaction*)0);
#endif
struct sigaction sa;
sigset_t chld_mask, old_mask;
sa.sa_handler = sigchld_handler;
sa.sa_flags = SA_NOCLDSTOP;
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, (struct sigaction*)0);
// block SIGCHLD until we set up stuff
sigemptyset(&chld_mask);
sigaddset(&chld_mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &chld_mask, &old_mask);
global_watch = wf;
pid_t pid = fork();
if(pid == -1)
return SPAWN_FORK_FAILED;
if(pid == 0) {
// child
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(ofile)
nulldev = open(ofile, O_WRONLY | O_TRUNC | O_CREAT, 0770);
else
nulldev = open("/dev/null", O_RDWR);
if(nulldev == -1)
return SPAWN_OPEN_FAILED;
/* TODO: redirect these to EvokeService log */
close(0); dup(nulldev);
close(1); dup(nulldev);
close(2); dup(nulldev);
errno = 0;
if(execve(argv[0], argv, environ) == -1) {
// should not get here
return SPAWN_EXECVE_FAILED;
}
}
// parent
if(nulldev != -1)
close(nulldev);
/*
* Record child pid; it is returned by fork(), but since this
* function does not wait until child quits, it will return
* immediately, filling (if) requested child pid
*/
if(child_pid_ret)
*child_pid_ret = pid;
// unblock SIGCHLD
sigprocmask(SIG_SETMASK, &old_mask, NULL);
return status_ret;
}
int spawn_program_with_core(const char* cmd, SignalWatch* wf, pid_t* child_pid_ret) {
struct rlimit r;
if(getrlimit(RLIMIT_CORE, &r) == -1)
return -1;
rlim_t old = r.rlim_cur;
r.rlim_cur = RLIM_INFINITY;
// FIXME: add own core limit ?
if(setrlimit(RLIMIT_CORE, &r) == -1)
return -1;
int ret = spawn_program(cmd, wf, child_pid_ret);
r.rlim_cur = old;
if(setrlimit(RLIMIT_CORE, &r) == -1)
return -1;
return ret;
}

View File

@ -1,40 +0,0 @@
/*
* $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__
#include <unistd.h> // pid_t
/*
* 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_OK 0
#define SPAWN_FORK_FAILED 1
#define SPAWN_EMPTY 2
#define SPAWN_EXECVE_FAILED 3
#define SPAWN_OPEN_FAILED 4
#define SPAWN_PIPE_FAILED 5
#define SPAWN_CHILD_CRASHED -2
#define SPAWN_CHILD_KILLED -3
typedef void (SignalWatch)(int pid, int status);
int spawn_program(const char* cmd, SignalWatch* wf = 0, pid_t* child_pid_ret = 0, const char* ofile = 0);
int spawn_program_with_core(const char* cmd, SignalWatch* wf = 0, pid_t* child_pid_ret = 0);
#endif

View File

@ -1,276 +0,0 @@
/*
* $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 <stdio.h> // snprintf
#include <FL/Fl_Shared_Image.H>
#include <FL/Fl.H>
#include <edelib/Run.h>
#include <edelib/Debug.h>
#include <edelib/Nls.h>
#include "Splash.h"
#include "Spawn.h"
#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 void service_watcher_cb(int pid, int signum);
#ifndef EDEWM_HAVE_NET_SPLASH
static Splash* global_splash = NULL;
static int splash_xmessage_handler(int e) {
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));
return 1;
}
}
return 0;
}
#endif
/*
* repeatedly call runner() untill all clients are
* started then hide splash window
*/
static 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;
Fl::remove_timeout(runner_cb);
}
// after edewm got _NET_WM_WINDOW_TYPE_SPLASH support
#if EDEWM_HAVE_NET_SPLASH
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) {
E_ASSERT(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);
// 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
while(shown())
Fl::wait();
#ifndef EDEWM_HAVE_NET_SPLASH
Fl::remove_handler(splash_xmessage_handler);
#endif
}
// 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;
}
E_ASSERT(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, service_watcher_cb);
//spawn_program(cmd);
}
++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;
}
E_ASSERT(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, service_watcher_cb);
//spawn_program(cmd);
++clist_it;
++counter;
return true;
}

View File

@ -1,56 +0,0 @@
/*
* $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:
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(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);
#if EDEWM_HAVE_NET_SPLASH
virtual void show(void);
#endif
};
#endif

View File

@ -1,332 +0,0 @@
/*
* $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 <string.h>
#include <limits.h>
#include <FL/x.H>
#include <X11/Xresource.h>
#include <edelib/Debug.h>
#include <edelib/TiXml.h>
#include <edelib/File.h>
#include <edelib/Color.h>
#include <edelib/String.h>
#include <edelib/Util.h>
#include <edelib/Directory.h>
#include <edelib/XSettingsCommon.h>
#include "Xsm.h"
#define USER_XRESOURCE ".Xdefaults"
#define USER_XRESOURCE_TMP ".Xdefaults-tmp"
#define USER_XRESOURCE_SAVED ".Xdefaults-ede-saved"
struct ResourceMap {
char* name;
char* xresource_key;
char* xresource_klass;
};
/*
* Make sure xresource_klass with '*' is listed last since it have
* highest priority and will override all previous classes (X Resource class, not C++ one :P)
* with the same xresource_key.
*/
static ResourceMap resource_map [] = {
{ "Fltk/Background2", "background", "*Text" },
{ "Fltk/Background", "background", "*" },
{ "Fltk/Foreground", "foreground", "*" }
};
#define RESOURCE_MAP_SIZE(x) (sizeof(x)/sizeof(x[0]))
static int ignore_xerrors(Display* display, XErrorEvent* xev) {
return True;
}
Xsm::Xsm() {
}
Xsm::~Xsm() {
EDEBUG("Xsm::~Xsm()\n");
}
/*
* This is a short explaination how evoke's XSETTINGS part is combined
* with X Resource database (xrdb). First of all, why mess with this? Almost
* all pure X apps (xterm, xedit, rxvt) reads color (and more) from xrdb, not to say
* that FLTK apps do that too, at least those not linked with edelib::Window. On other
* hand since edelib::Window already have builtin XSETTINGS and FLTK backend, you will
* that colors for edelib::Window will be specified twice, but this is not a big deal
* since painting is done only once.
*
* Here, in the code, we look for XSETTINGS names listed in resource_map[] and they should
* be colors only; when they are found, their equivalents will be created in xrdb as class/key
* (see X Resource manual about these).
*
* Values picked up from XSETTINGS color items will be converted to html since because clients
* who reads xrdb expects html colors (or X11 ones, like red/green/blue names, but let we not
* complicate). After conversion, everything is stored in ~/.Xdefaults file. If this file
* already exists (someone else made it), it will be first merged, picking old values and backed up.
*
* After evoke quits, file is restored, if existed before or deleted if not. This is also a
* workaround for missing functions to delete key/value pairs from xrdb (what was they thinking for??).
*/
void Xsm::xresource_replace(void) {
// with inheritance we got manager_data
if(!manager_data->settings)
return;
edelib::String home = edelib::dir_home();
// try to open ~/.Xdefaults; if failed, X Resource will not complain
edelib::String db_file = edelib::build_filename(home.c_str(), USER_XRESOURCE);
// initialize XResource manager
XrmInitialize();
// load XResource database
XrmDatabase db = XrmGetFileDatabase(db_file.c_str());
edelib::XSettingsSetting* s;
int status;
char* type, *value;
XrmValue xrmv;
char color_val[8];
edelib::String tmp;
/*
* XSETTINGS does not contains duplicate entries so there is no need to
* check for them. We only scan ResourceMap table for XSETTINGS name and
* its X Resource equivalent.
*/
for(unsigned int i = 0; i < RESOURCE_MAP_SIZE(resource_map); i++) {
s = edelib::xsettings_list_find(manager_data->settings, resource_map[i].name);
if(!s)
continue;
// assure that XSETTINGS key is color type
if(s->type != edelib::XSETTINGS_TYPE_COLOR) {
EWARNING(ESTRLOC ": Expected color type in %s, but it is not, skipping...\n", s->name);
continue;
}
// check if resource is present
status = XrmGetResource(db, resource_map[i].xresource_key, resource_map[i].xresource_klass, &type, &xrmv);
if(status && strcmp(type, "String") == 0) {
EDEBUG(ESTRLOC ": %s.%s found in database\n",
resource_map[i].xresource_klass, resource_map[i].xresource_key);
value = xrmv.addr;
}
/*
* Now convert color from XSETTINGS to html value. First convert to fltk color.
* TODO: Strange, didn't implemented something like color_rgb_to_html in edelib ?
*/
int fltk_color = edelib::color_rgb_to_fltk(s->data.v_color.red, s->data.v_color.green, s->data.v_color.blue);
edelib::color_fltk_to_html(fltk_color, color_val);
// and save it
tmp.clear();
tmp.printf("%s.%s: %s", resource_map[i].xresource_klass, resource_map[i].xresource_key, color_val);
XrmPutLineResource(&db, tmp.c_str());
}
edelib::String tmp_db_file = edelib::build_filename(home.c_str(), USER_XRESOURCE_TMP);
/*
* Try to merge existing ~/.Xdefaults (if present) with our changes. If there is existing
* key/values, they will be replaced with our. If XrmCombineFileDatabase() fails, this means
* there is no ~/.Xdefaults, so we don't need to backup it; opposite, backup it before we do
* final rename.
*/
status = XrmCombineFileDatabase(db_file.c_str(), &db, 0);
XrmPutFileDatabase(db, tmp_db_file.c_str());
//XrmSetDatabase(fl_display, db);
XrmDestroyDatabase(db);
if(status) {
edelib::String db_backup = edelib::build_filename(home.c_str(), USER_XRESOURCE_SAVED);
edelib::file_rename(db_file.c_str(), db_backup.c_str());
}
edelib::file_rename(tmp_db_file.c_str(), db_file.c_str());
}
void Xsm::xresource_undo(void) {
edelib::String home, db_file_backup, db_file;
home = edelib::dir_home();
db_file_backup = edelib::build_filename(home.c_str(), USER_XRESOURCE_SAVED);
db_file = edelib::build_filename(home.c_str(), USER_XRESOURCE);
/*
* If we have backup, restore it; otherwise delete ~/.Xdefaults.
* TODO: what if user something write in it? Changes will be lost...
*/
if(edelib::file_exists(db_file_backup.c_str()))
edelib::file_rename(db_file_backup.c_str(), db_file.c_str());
else
edelib::file_remove(db_file.c_str());
}
bool Xsm::load_serialized(const char* file) {
TiXmlDocument doc(file);
if(!doc.LoadFile())
return false;
const char* name = NULL, *type = NULL;
const char* v_string = NULL;
int v_int = 0;
int v_red = 0, v_green = 0, v_blue = 0, v_alpha = 0;
int cmp = 0;
TiXmlNode* elem = doc.FirstChild("ede-settings");
if(!elem)
return false;
for(elem = elem->FirstChildElement(); elem; elem = elem->NextSibling()) {
if(strcmp(elem->Value(), "setting") != 0) {
EWARNING(ESTRLOC ": Got unknown child in 'ede-setting' %s\n", elem->Value());
continue;
}
name = elem->ToElement()->Attribute("name");
if(!name) {
EWARNING(ESTRLOC ": Missing name key\n");
continue;
}
type = elem->ToElement()->Attribute("type");
if(!type) {
EWARNING(ESTRLOC ": Missing type key\n");
continue;
}
if(strcmp(type, "int") == 0)
cmp = 1;
else if(strcmp(type, "string") == 0)
cmp = 2;
else if(strcmp(type, "color") == 0)
cmp = 3;
else {
EWARNING(ESTRLOC ": Unknown type %s\n", type);
continue;
}
switch(cmp) {
case 1:
if(elem->ToElement()->QueryIntAttribute("value", &v_int) == TIXML_SUCCESS)
set(name, v_int);
else
EWARNING(ESTRLOC ": Unable to query integer value\n");
break;
case 2:
v_string = elem->ToElement()->Attribute("value");
if(v_string)
set(name, v_string);
break;
case 3:
if((elem->ToElement()->QueryIntAttribute("red", &v_red) == TIXML_SUCCESS) &&
(elem->ToElement()->QueryIntAttribute("green", &v_green) == TIXML_SUCCESS) &&
(elem->ToElement()->QueryIntAttribute("blue", &v_blue) == TIXML_SUCCESS) &&
(elem->ToElement()->QueryIntAttribute("alpha", &v_alpha) == TIXML_SUCCESS)) {
set(name, v_red, v_green, v_blue, v_alpha);
}
break;
default:
break;
}
}
xresource_replace();
return true;
}
bool Xsm::save_serialized(const char* file) {
// FIXME: a lot of this code could be in edelib
Atom type;
int format;
unsigned long n_items, bytes_after;
unsigned char* data;
int result;
edelib::XSettingsList* settings = NULL, *iter = NULL;
int (*old_handler)(Display*, XErrorEvent*);
// possible ?
if(!manager_data->manager_win)
return false;
old_handler = XSetErrorHandler(ignore_xerrors);
result = XGetWindowProperty(manager_data->display, manager_data->manager_win, manager_data->xsettings_atom,
0, LONG_MAX, False, manager_data->xsettings_atom,
&type, &format, &n_items, &bytes_after, (unsigned char**)&data);
XSetErrorHandler(old_handler);
if(result == Success && type != None) {
if(type != manager_data->xsettings_atom)
EWARNING(ESTRLOC ": Invalid type for XSETTINGS property\n");
else if(format != 8)
EWARNING(ESTRLOC ": Invalid format for XSETTINGS property\n");
else
settings = edelib::xsettings_decode(data, n_items, NULL);
XFree(data);
}
if(!settings)
return false;
edelib::File setting_file;
if(!setting_file.open(file, edelib::FIO_WRITE)) {
EWARNING(ESTRLOC ": Unable to write to %s\n", file);
edelib::xsettings_list_free(settings);
return false;
}
setting_file.printf("<? xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
setting_file.printf("<ede-settings>\n");
iter = settings;
while(iter) {
setting_file.printf("\t<setting name=\"%s\" ", iter->setting->name);
switch(iter->setting->type) {
case edelib::XSETTINGS_TYPE_INT:
setting_file.printf("type=\"int\" value=\"%i\" />\n", iter->setting->data.v_int);
break;
case edelib::XSETTINGS_TYPE_STRING:
setting_file.printf("type=\"string\" value=\"%s\" />\n", iter->setting->data.v_string);
break;
case edelib::XSETTINGS_TYPE_COLOR:
setting_file.printf("type=\"color\" red=\"%i\" green=\"%i\" blue=\"%i\" alpha=\"%i\" />\n",
iter->setting->data.v_color.red,
iter->setting->data.v_color.green,
iter->setting->data.v_color.blue,
iter->setting->data.v_color.alpha);
break;
}
iter = iter->next;
}
setting_file.printf("</ede-settings>\n");
setting_file.close();
edelib::xsettings_list_free(settings);
xresource_undo();
return true;
}

View File

@ -1,35 +0,0 @@
/*
* $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 __XSM_H__
#define __XSM_H__
#include <edelib/XSettingsManager.h>
/*
* XSETTINGS manager with serialization capability.
* Also it will write/undo to xrdb (X Resource database).
*/
class Xsm : public edelib::XSettingsManager {
public:
Xsm();
~Xsm();
bool load_serialized(const char* file);
bool save_serialized(const char* file);
// replace XResource values from one from XSETTINGS
void xresource_replace(void);
// undo old XResource values
void xresource_undo(void);
};
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,120 +0,0 @@
Evoke documentation
===================
Evoke is EDE head service responsible for starting environment, running
requested applications and shutting down environment respectively.
It is usually started at EDE startup, placing in 'startede' script and
will allow only one instance of itself to be running.
Options
-------
-s, --startup::
Run in starup mode. Startup mode should be used when environment is
starting and it will read evoke.conf file looking for compontents to
be started.
-n, --no-splash::
Do not display splash during startup. Only usefull if in startup mode
(given '-s' or '--startup').
-d, --dry-run::
Only valid in startup or autostart mode. It will show what will be started,
but will not start anything. Usefull for testing.
-a, --autostart::
Run in autostart mode. It will check 'autostart' directory and run .desktop
files from it. This will be done according to freedesktop.org autostart specification.
-u, --autostart-safe::
Same as '-a' or '--autostart' option, but display dialog with items that should
be run.
-c, --config [FILE]::
Read [FILE] as config file. This file is only used in startup mode to read
components to be started.
-p, --pid [FILE]::
Store session pid to [FILE].
-l, --log [FILE]::
Log events to [FILE]. [FILE] can be 'stdout' or 'stderr' (literally) where logging
will be to standard output or standard error output.
-h, --help::
This help.
Details
-------
Evoke can be started with or without options. If started without options, it will do nothing
until external application send request to start something or to quit (here 'quit' means
to quit evoke, not some running application).
As you can see from options, there are two 'modes' (if parameteres for them are given):
* autstart mode
* startup mode
*Autostart mode* is used to run applications from 'autostart' directory. This directory is
usually located at $HOME/.config/autostart or if not exists, in /etc/xdg/autostart. Of course,
both directories can exists and evoke will run applications from both, but with one exception:
if application with the same .desktop name exists in both (and is valid desktop file), it will
be run only from prefered directory, which is $HOME/.config/autostart.
If you want some application to be run at EDE startup (implying evoke is started with '-a' option),
just copy it's .desktop file to autostart directory. Before that, make sure that .desktop file
confirms to http://freedesktop.org specification for Desktop Files.
On other hand if you want to disable running some application from autostart directory, you can
simply delete that file, or set this:
---------------
Hidden = true
---------------
Make sure that 'Hidden' key is under '[Desktop Entry]' section.
Autostart mode can be run in two ways: safe and unsafe. Safe way ('-u' or '--autostart-safe') will
popup window with programs that are 'registered' for starting, from where you can choose either to
start some of them, start all of them or to start nothing. On other hand, unsafe way ('-a' or '--autostart')
will simply run all 'registered' items without any questioning (should I say that this can be very insecure).
These options are intentionally provided so you can choose startup policy depending on your security
options.
*Startup mode* is meant to be used when EDE is starting, running each component (or program)
from evoke.conf (or file specified with '-c' option). This configuration file must be in the following form:
--------------
# [evoke] section must be present
[evoke]
# Startup key is used to notify evoke what to start
# and program keys must be separated with comma (if multiple ones are given)
Startup = program1, program2, program3
# ImagesDirectory is directory with icons used for splash screen
ImagesDirectory = /some/path/some_dir_name
# Splash is image used for splash screen (it will be searched in ImagesDirectory)
Splash = image.png
# now comes each value from Startup key as separate key
[program1]
# Icon is icon used in splash screen progress (searched in ImagesDirectory)
Icon = icon1.png
# Exec is program executable to be run
Exec = program1
# Description is used to describe what is starting
Description = my cool program
[program2]
Icon = icon2.png
Exec = program2
Description = my cool second program
...
--------------

View File

@ -1,19 +0,0 @@
<? xml version="1.0" encoding="UTF-8" ?>
<ede-settings>
<setting name="Fltk/Background" type="color" red="220" green="222" blue="227" alpha="0" />
<setting name="Fltk/Background2" type="color" red="239" green="239" blue="239" alpha="0" />
<setting name="Gtk/CanChangeAccels" type="int" value="0" />
<setting name="Gtk/CursorThemeName" type="string" value="default" />
<setting name="Gtk/CursorThemeSize" type="int" value="16" />
<setting name="Gtk/FontName" type="string" value="Sans 8" />
<setting name="Gtk/KeyThemeName" type="string" value="Default" />
<setting name="Gtk/ToolbarStyle" type="string" value="icons" />
<setting name="Net/Background/Normal" type="color" red="186" green="45" blue="23" alpha="0" />
<setting name="Net/CursorBlink" type="int" value="1" />
<setting name="Net/CursorBlinkTime" type="int" value="500" />
<setting name="Net/DndDragThreshold" type="int" value="8" />
<setting name="Net/DoubleClickTime" type="int" value="300" />
<setting name="Net/IconThemeName" type="string" value="edeneu" />
<setting name="Net/ThemeName" type="string" value="Raleigh" />
<setting name="Net/UserName" type="string" value="John Foo" />
</ede-settings>

View File

@ -1,35 +0,0 @@
# evoke configuration sample
# main section; must be present
[evoke]
Startup = edewm,eiconman,eworkpanel,xscreensaver
# DataDirectory = data
DataDirectory = /home/sanel/programs/EDE/ede2/evoke/data
Splash = splash-alpha1.png
[edewm]
Icon = edewm.png
# Exec = gvim
Exec = edewm
# Exec = fluxbox
Description = window manager
[eiconman]
Icon = eiconman.png
# Exec = mozilla
# Exec = /home/sanel/blentavo/EDE/ede2/eiconman/eiconman
Exec = eiconman
# Exec = /home/sanel/abc
Description = desktop
[eworkpanel]
Icon = eworkpanel.png
# Exec = mrxvt -bg black
Exec = eworkpanel
Description = panel
[xscreensaver]
Icon = xscreensaver.png
# Exec = rxvt
# Exec = /home/sanel/abc
Exec = xscreensaver -nosplash
Description = screensaver

View File

@ -1,289 +0,0 @@
/*
* $Id$
*
* Evoke, head honcho of everything
* Part of Equinox Desktop Environment (EDE).
* Copyright (c) 2007-2008 EDE Authors.
*
* This program is licensed under terms of the
* GNU General Public License version 2 or newer.
* See COPYING for details.
*/
#include <string.h>
#include <signal.h>
#include <edelib/Config.h>
#include <edelib/Debug.h>
#include <edelib/File.h>
#include <FL/Fl.H>
#include <FL/x.H>
#include "EvokeService.h"
#define FOREVER 1e20
#define CONFIG_FILE "evoke.conf"
#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))
static void quit_signal(int sig) {
EVOKE_LOG("Got quit signal %i\n", sig);
EvokeService::instance()->stop();
}
static int xmessage_handler(int) {
#ifdef USE_FLTK_LOOP_EMULATION
XEvent xev;
while(XEventsQueued(fl_display, QueuedAfterReading)) {
XNextEvent(fl_display, &xev);
EvokeService::instance()->handle((const XEvent*)&xev);
}
return 1;
#else
return EvokeService::instance()->handle(fl_xevent);
#endif
}
#ifdef USE_FLTK_LOOP_EMULATION
static void xmessage_handler_fd(int, void*) {
xmessage_handler(0);
}
static int composite_handler(int ev) {
return EvokeService::instance()->composite_handle(fl_xevent);
}
#endif
static const char* next_param(int curr, char** argv, int argc) {
int j = curr + 1;
if(j >= argc)
return NULL;
if(argv[j][0] == '-')
return NULL;
return argv[j];
}
static void help(void) {
puts("Usage: evoke [OPTIONS]");
puts("EDE startup manager responsible for starting, quitting and tracking");
puts("various pieces of desktop environment and external programs.");
puts("...and to popup a nice window when something crashes...\n");
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(" -a, --autostart read autostart directory and run all items");
puts(" -u, --autostart-safe read autostart directory and display dialog what will be run");
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 (FILE can be stdout/stderr for console output)\n");
}
int main(int argc, char** argv) {
const char* config_file = NULL;
const char* pid_file = NULL;
const char* log_file = NULL;
bool do_startup = 0;
bool do_dryrun = 0;
bool no_splash = 0;
bool do_autostart = 0;
bool do_autostart_safe = 0;
if(argc > 1) {
const char* a;
for(int i = 1; i < argc; i++) {
a = argv[i];
if(CHECK_ARGV(a, "-h", "--help")) {
help();
return 0;
} else if(CHECK_ARGV(a, "-c", "--config")) {
config_file = next_param(i, argv, argc);
if(!config_file) {
puts("Missing configuration filename");
return 1;
}
i++;
} else if(CHECK_ARGV(a, "-p", "--pid")) {
pid_file = next_param(i, argv, argc);
if(!pid_file) {
puts("Missing pid filename");
return 1;
}
i++;
} else if(CHECK_ARGV(a, "-l", "--log")) {
log_file = next_param(i, argv, argc);
if(!log_file) {
puts("Missing log filename");
return 1;
}
i++;
}
else if(CHECK_ARGV(a, "-s", "--startup"))
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 if(CHECK_ARGV(a, "-a", "--autostart"))
do_autostart = 1;
else if(CHECK_ARGV(a, "-u", "--autostart-safe"))
do_autostart_safe = 1;
else {
printf("Unknown parameter '%s'. Run 'evoke -h' for options\n", a);
return 1;
}
}
}
// make sure X11 is running before rest of code is called
fl_open_display();
// initialize main service object
EvokeService* service = EvokeService::instance();
if(!service->setup_logging(log_file)) {
printf("Can't open %s for logging. Please choose some writeable place\n", log_file);
return 1;
}
if(!service->setup_channels()) {
printf("Can't setup internal channels\n");
return 1;
}
EVOKE_LOG("= evoke started =\n");
if(!pid_file)
pid_file = DEFAULT_PID;
if(!service->setup_pid(pid_file, LOCK_FILE)) {
printf("Either another evoke instance is running or can't create pid file. Please correct this\n");
printf("Note: if program abnormaly crashed before, just remove '%s' and start it again\n", LOCK_FILE);
printf("= evoke abrupted shutdown =\n");
return 1;
}
if(!config_file)
config_file = CONFIG_FILE; // TODO: XDG paths
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("= evoke abrupted shutdown =\n");
return 1;
}
}
service->setup_atoms(fl_display);
service->init_xsettings_manager();
/*
* Run autostart code after XSETTINGS manager since some Gtk apps (mozilla) will eats a lot
* of cpu during runtime settings changes
*/
if(do_autostart || do_autostart_safe)
service->init_autostart(do_autostart_safe);
/*
* Let composite manager be run the latest. Running autostart after it will not deliver
* X events to possible shown autostart window, and I'm not sure why. Probably due event
* throttle from XDamage ?
*/
service->init_composite();
signal(SIGINT, quit_signal);
signal(SIGTERM, quit_signal);
signal(SIGKILL, quit_signal);
signal(SIGQUIT, quit_signal);
#ifdef USE_SIGHUP
/*
* This is mostly used when we get request to shutdown session and close/kill all windows.
* If evoke is started from gui console (xterm, rxvt), closing that window we will get
* SIGHUP since terminal will disconnect all controlling processes. On other hand, if evoke
* is started as session carrier (eg. run from xinitrc), this is not needed.
*/
signal(SIGHUP, quit_signal);
#endif
#if 0
XSelectInput(fl_display, RootWindow(fl_display, fl_screen), PropertyChangeMask | SubstructureNotifyMask | ClientMessage);
#endif
// composite engine included too
XSelectInput(fl_display, RootWindow(fl_display, fl_screen),
SubstructureNotifyMask | ExposureMask | StructureNotifyMask | PropertyChangeMask | ClientMessage);
/*
* Register event listener and run in infinite loop. Loop will be
* interrupted from one of the received signals.
*
* I choose to use fltk for this since wait() will nicely poll events
* and pass expecting ones to xmessage_handler(). Other (non-fltk) solution would
* be to manually pool events via select() and that code could be very messy.
* So stick with the simplicity :)
*
* Also note that '1' in add_fd (when USE_FLTK_LOOP_EMULATION is defined) parameter
* means POLLIN, and for the details see Fl_x.cxx
*
* Let me explaint what these USE_FLTK_LOOP_EMULATION parts means. It was introduced
* since FLTK eats up SelectionClear event and so other parts (evoke specific atoms, splash etc.)
* could be used and tested. FLTK does not have event handler that could be registered
* _before_ it process events, but only add_handler() which will be called _after_ FLTK process
* all events and where will be reported ones that FLTK does not understainds or for those
* windows it already don't know.
*/
#ifdef USE_FLTK_LOOP_EMULATION
Fl::add_fd(ConnectionNumber(fl_display), 1, xmessage_handler_fd);
Fl::add_handler(composite_handler);
#else
/*
* NOTE: composite_handler() is not needed since it will be included
* within xmessage_handler() call
*/
Fl::add_handler(xmessage_handler);
#endif
service->start();
while(service->running()) {
#ifdef USE_FLTK_LOOP_EMULATION
/*
* Seems that when XQLength() is not used, damage events will not be correctly
* send to xmessage_handler() and composite will wrongly draw the screen.
*/
if(XQLength(fl_display)) {
xmessage_handler(0);
continue;
}
#else
/*
* FLTK will not report SelectionClear needed for XSETTINGS manager
* so we must catch it first before FLTK discards it (if we can :P)
* This can be missed greatly due a large number of XDamage events
* and using this method is not quite safe.
*/
if(fl_xevent && fl_xevent->type == SelectionClear)
service->handle(fl_xevent);
#endif
Fl::wait(FOREVER);
#ifndef USE_FLTK_LOOP_EMULATION
if(fl_xevent && fl_xevent->type == SelectionClear)
service->handle(fl_xevent);
#endif
}
EVOKE_LOG("= evoke nice shutdown =\n");
return 0;
}

View File

@ -1,33 +0,0 @@
# data file for the Fltk User Interface Designer (fluid)
version 1.0108
header_name {.h}
code_name {.cxx}
Function {} {open selected
} {
Fl_Window {} {open
xywh {344 264 370 305} type Double visible
} {
Fl_Box {} {
label {The following applications are registered to be started. Please choose what to do next}
xywh {80 10 280 61} align 148
}
Fl_Check_Browser {} {
xywh {10 75 350 185} labelsize 14
}
Fl_Button {} {
label {&Cancel}
xywh {270 270 90 25}
}
Fl_Button {} {
label {&Run all}
xywh {175 270 90 25}
}
Fl_Button {} {
label {Run &selected}
xywh {45 270 125 25}
}
Fl_Box {} {
image {../icons/warning.xpm} xywh {10 10 65 61} labelsize 14
}
}
}

View File

@ -1,28 +0,0 @@
# data file for the Fltk User Interface Designer (fluid)
version 1.0108
header_name {.h}
code_name {.cxx}
Function {} {open
} {
Fl_Window {} {open
xywh {354 160 380 130} type Double visible
} {
Fl_Box {} {
image {icons/core.xpm} xywh {10 10 70 75} labelsize 14
}
Fl_Box {} {
label {Program foo just crashed !!!
You can inspect details about this crash by clicking on 'Show details' below} selected
xywh {85 10 285 75} align 148
}
Fl_Button {} {
label {&Close}
xywh {280 95 90 25}
}
Fl_Button {} {
label {@> Show details}
xywh {10 95 265 25} box FLAT_BOX align 20
}
}
}

View File

@ -1,39 +0,0 @@
# data file for the Fltk User Interface Designer (fluid)
version 1.0108
header_name {.h}
code_name {.cxx}
Function {} {open selected
} {
Fl_Window {} {open
xywh {354 160 380 340} type Double visible
} {
Fl_Box {} {
image {icons/core.xpm} xywh {10 10 70 75} labelsize 14
}
Fl_Box {} {
label {Program foo just crashed !!!
You can inspect details about this crash by clicking on 'Show details' below}
xywh {85 10 285 75} align 148
}
Fl_Button {} {
label {&Close}
xywh {280 95 90 25}
}
Fl_Button {} {
label {@< Hide details}
xywh {10 95 265 25} box FLAT_BOX align 20
}
Fl_Text_Display {} {
xywh {10 130 360 165} labelsize 14 textsize 14
}
Fl_Button {} {
label {&Save As...}
xywh {280 305 90 25}
}
Fl_Button {} {
label {&Copy}
xywh {185 305 90 25}
}
}
}

View File

@ -1,30 +0,0 @@
# data file for the Fltk User Interface Designer (fluid)
version 1.0108
header_name {.h}
code_name {.cxx}
Function {} {open
} {
Fl_Window {} {open
xywh {479 284 335 180} type Double visible
} {
Fl_Box {} {
label {How do you want to quit?}
xywh {10 9 315 25} labelfont 1 align 212
}
Fl_Choice {} {open
xywh {10 45 315 25} down_box BORDER_BOX labelsize 14 textsize 14
} {}
Fl_Box {} {
label {This option will close all programs and logs out from the current session}
xywh {10 80 315 55} align 213
}
Fl_Button {} {
label {&OK} selected
xywh {140 145 90 25}
}
Fl_Button {} {
label {&Cancel}
xywh {235 145 90 25}
}
}
}

View File

@ -1,416 +0,0 @@
/* XPM */
static char * core_xpm[] = {
"48 48 365 2",
" c None",
". c #FAE601",
"+ c #FCF001",
"@ c #FEF800",
"# c #F9E202",
"$ c #F2BE04",
"% c #F2BD04",
"& c #F5CC03",
"* c #FBE901",
"= c #FBEC01",
"- c #EB9A06",
"; c #EEAA05",
"> c #FEFC00",
", c #F7D506",
"' c #E78808",
") c #E88D06",
"! c #D1B46D",
"~ c #C7AF75",
"{ c #C2994A",
"] c #F1BB04",
"^ c #F5CF03",
"/ c #FCEE01",
"( c #EDD426",
"_ c #DCBC76",
": c #E3C06E",
"< c #CCAB4F",
"[ c #E7C16F",
"} c #ECC36B",
"| c #CCB34C",
"1 c #FCFB04",
"2 c #D1C652",
"3 c #D0B76B",
"4 c #DDBA6C",
"5 c #DAB96E",
"6 c #CFBB40",
"7 c #A7A7A7",
"8 c #A8A8A8",
"9 c #A9A9A9",
"0 c #A4A4A4",
"a c #9F9F9F",
"b c #999999",
"c c #919191",
"d c #A5B4BE",
"e c #E7E7E1",
"f c #C3C2C7",
"g c #B3AB9B",
"h c #B5A679",
"i c #C5AF6A",
"j c #D6B86A",
"k c #CDB16B",
"l c #C9B05B",
"m c #B7A27C",
"n c #EBDC19",
"o c #AFAFAF",
"p c #B8B8B8",
"q c #BBBBBB",
"r c #BCBCBC",
"s c #BABABA",
"t c #B4B4B4",
"u c #888888",
"v c #7B7B7B",
"w c #102032",
"x c #808285",
"y c #FBF5F2",
"z c #D9D0BF",
"A c #C6AD71",
"B c #DFBB69",
"C c #D9B86B",
"D c #C0AC7C",
"E c #BBA785",
"F c #AAAAAA",
"G c #ADADAD",
"H c #D6D6D6",
"I c #EBEBEB",
"J c #FCFCFC",
"K c #FEFEFE",
"L c #FFFFFF",
"M c #FBFBFB",
"N c #F5F5F5",
"O c #E7E7E7",
"P c #D2D2D2",
"Q c #868686",
"R c #636363",
"S c #616161",
"T c #6E6E6E",
"U c #3E3E3D",
"V c #3B3A3A",
"W c #161311",
"X c #65605D",
"Y c #C3BCB7",
"Z c #D8CFB0",
"` c #D1B873",
" . c #DFBD6A",
".. c #C8B37E",
"+. c #AAAEBF",
"@. c #FFFD00",
"#. c #B1B1B1",
"$. c #CACACA",
"%. c #E9E9E9",
"&. c #F0F0F0",
"*. c #E5E5E5",
"=. c #E3E3E3",
"-. c #E1E1E1",
";. c #DFDFDF",
">. c #898989",
",. c #3C3C3C",
"'. c #393939",
"). c #262626",
"!. c #1D1D1E",
"~. c #0F0F0F",
"{. c #5A5857",
"]. c #5A5955",
"^. c #4D4D45",
"/. c #918E7A",
"(. c #D3CBA7",
"_. c #E5DCB3",
":. c #E0DECD",
"<. c #AEAEAE",
"[. c #D3D3D3",
"}. c #FAFAFA",
"|. c #FDFDFD",
"1. c #EFEFEF",
"2. c #EAEAEA",
"3. c #DDDDDD",
"4. c #D7D7D7",
"5. c #D0D0D0",
"6. c #C9C9C9",
"7. c #C1C1C1",
"8. c #BDBDBD",
"9. c #7D7D7D",
"0. c #333333",
"a. c #131313",
"b. c #4F4F4F",
"c. c #484848",
"d. c #5F5F60",
"e. c #393C3A",
"f. c #080C09",
"g. c #1F1F1B",
"h. c #817F74",
"i. c #D8D6C6",
"j. c #F2F2E8",
"k. c #DFE7F0",
"l. c #F9F9F9",
"m. c #F3F3F3",
"n. c #EDEDED",
"o. c #E8E8E8",
"p. c #E4E4E4",
"q. c #DEDEDE",
"r. c #CCCCCC",
"s. c #C3C3C3",
"t. c #B9B9B9",
"u. c #ABABAB",
"v. c #A1A1A1",
"w. c #151515",
"x. c #4B4B4B",
"y. c #6B6B6B",
"z. c #3F3F3F",
"A. c #1B1B1B",
"B. c #121211",
"C. c #050604",
"D. c #000000",
"E. c #0C0707",
"F. c #433F37",
"G. c #7E7F79",
"H. c #F7F7F7",
"I. c #ECECEC",
"J. c #E2E2E2",
"K. c #DCDCDC",
"L. c #B0B0B0",
"M. c #A5A5A5",
"N. c #979797",
"O. c #969696",
"P. c #434343",
"Q. c #191919",
"R. c #010101",
"S. c #060001",
"T. c #0C0203",
"U. c #050002",
"V. c #0B0D14",
"W. c #EEEEEE",
"X. c #DADADA",
"Y. c #C6C6C6",
"Z. c #BEBEBE",
"`. c #B6B6B6",
" + c #9C9C9C",
".+ c #909090",
"++ c #848484",
"@+ c #6C6C6C",
"#+ c #1A1A1A",
"$+ c #060606",
"%+ c #020101",
"&+ c #010403",
"*+ c #020405",
"=+ c #010202",
"-+ c #D8D8D8",
";+ c #CFCFCF",
">+ c #C2C2C2",
",+ c #A2A2A2",
"'+ c #878787",
")+ c #787878",
"!+ c #656565",
"~+ c #252525",
"{+ c #080C0D",
"]+ c #F4F4F4",
"^+ c #D9D9D9",
"/+ c #D4D4D4",
"(+ c #CECECE",
"_+ c #C5C5C5",
":+ c #BFBFBF",
"<+ c #B2B2B2",
"[+ c #A0A0A0",
"}+ c #989898",
"|+ c #8E8E8E",
"1+ c #737373",
"2+ c #6D6D6D",
"3+ c #585858",
"4+ c #202020",
"5+ c #070707",
"6+ c #4B4C4C",
"7+ c #767676",
"8+ c #D1D1D1",
"9+ c #A3A3A3",
"0+ c #9B9B9B",
"a+ c #949494",
"b+ c #8C8C8C",
"c+ c #838383",
"d+ c #797979",
"e+ c #6F6F6F",
"f+ c #676767",
"g+ c #4A4A4A",
"h+ c #030303",
"i+ c #181818",
"j+ c #040404",
"k+ c #565656",
"l+ c #D5D5D5",
"m+ c #C7C7C7",
"n+ c #C4C4C4",
"o+ c #ACACAC",
"p+ c #9E9E9E",
"q+ c #7E7E7E",
"r+ c #666666",
"s+ c #606060",
"t+ c #575757",
"u+ c #353535",
"v+ c #383738",
"w+ c #777677",
"x+ c #494949",
"y+ c #CBCBCB",
"z+ c #B5B5B5",
"A+ c #9A9A9A",
"B+ c #939393",
"C+ c #8B8B8B",
"D+ c #7C7C7C",
"E+ c #5E5E5E",
"F+ c #595959",
"G+ c #424242",
"H+ c #171717",
"I+ c #0C0C0C",
"J+ c #5D5D5D",
"K+ c #2F2F2F",
"L+ c #8F8F8F",
"M+ c #8A8A8A",
"N+ c #858585",
"O+ c #7F7F7F",
"P+ c #757575",
"Q+ c #686868",
"R+ c #5B5B5B",
"S+ c #4D4D4D",
"T+ c #6F6D6E",
"U+ c #3B3B3B",
"V+ c #9D9D9D",
"W+ c #959595",
"X+ c #8D8D8D",
"Y+ c #828282",
"Z+ c #6A6A6A",
"`+ c #646464",
" @ c #555555",
".@ c #2E2E2E",
"+@ c #0B0B0B",
"@@ c #020202",
"#@ c #222222",
"$@ c #1D1D1D",
"%@ c #080808",
"&@ c #808080",
"*@ c #7A7A7A",
"=@ c #707070",
"-@ c #5F5F5F",
";@ c #545454",
">@ c #525252",
",@ c #2B2B2B",
"'@ c #0D0D0D",
")@ c #050505",
"!@ c #111111",
"~@ c #5A5A5A",
"{@ c #929292",
"]@ c #717171",
"^@ c #515151",
"/@ c #3D3D3D",
"(@ c #272727",
"_@ c #323232",
":@ c #6D6C6C",
"<@ c #1C1C1C",
"[@ c #535353",
"}@ c #414141",
"|@ c #0A0A0A",
"1@ c #646363",
"2@ c #161616",
"3@ c #696969",
"4@ c #313131",
"5@ c #1F1F1F",
"6@ c #0E0E0E",
"7@ c #090909",
"8@ c #121212",
"9@ c #444444",
"0@ c #464646",
"a@ c #282828",
"b@ c #5C5C5C",
"c@ c #141414",
"d@ c #212121",
"e@ c #101010",
"f@ c #616061",
"g@ c #626262",
"h@ c #232323",
"i@ c #373737",
"j@ c #5B5959",
"k@ c #1E1E1E",
"l@ c #2C2C2C",
"m@ c #505050",
"n@ c #494646",
"o@ c #303030",
"p@ c #626162",
"q@ c #292929",
"r@ c #2A2A2A",
"s@ c #616060",
"t@ c #2D2D2D",
"u@ c #575656",
"v@ c #363636",
"w@ c #3E3E3E",
"x@ c #5F5E5E",
"y@ c #3A3A3A",
"z@ c #242424",
"A@ c #343434",
"B@ c #383838",
"C@ c #474747",
"D@ c #4F4D4D",
"E@ c #737272",
"F@ c #404040",
"G@ c #5B5A5A",
"H@ c #696869",
"I@ c #4E4E4E",
"J@ c #3D3C3C",
"K@ c #5D5B5C",
"L@ c #6A696A",
"M@ c #454545",
"N@ c #5B595A",
"O@ c #6A6969",
"P@ c #515050",
"Q@ c #595859",
"R@ c #656464",
"S@ c #413F3F",
"T@ c #747373",
"U@ c #5F5E5F",
"V@ c #605F5F",
"W@ c #595858",
"X@ c #545252",
" . + ",
" @ # $ % & * ",
" = - ; $ ",
" > , ' ) ",
" > ! ~ { ] ^ ",
" / ( _ : < . ",
" [ } | ",
" 1 2 3 4 5 6 ",
" 7 8 9 0 a b c d e f g h i j k l m n ",
" 8 o p q r s t 8 b u v w x y z A B C D E ",
" F G s H I J K L M N O P t Q R S T U V W X Y Z ` ...+. @. ",
" 7 #.$.%.L L L M N &.%.*.=.-.;.$.>.,.'.).!.~.{.].^./.(._.:. ",
" <.[.}.L L |.N 1.2.=.3.4.5.6.7.8.7.s 9.0.a.b.c.d.e.f.g.h.i.j.k. ",
" #.I L L l.m.n.I o.p.q.4.[.r.s.t.u.v.G u w.x.y.z.A.B.C.D.E.F.G. ",
" #.m.L H.1.I.I.o.*.J.K.H 5.6.7.t.L.M.N.O.u P.S P.Q.R.D.S.T.U.D.V. ",
" 8 W.L &.%.o.O *.J.3.X.[.r.Y.Z.`.G 0 +.+Q ++@+0.#+$+D.R.%+&+*+=+ ",
" c q.L I.-.=.-.;.3.-+[.;+$.>+r t u.,+b c '+9.)+!+~+R.D.R.R.D.D.{+ ",
" )+L.]+o.^+X.^+H /+P (+6._+:+t.<+8 [+}+|+++v 1+2+3+4+D.D.D.D.D.5+6+ ",
" 7+8+%.4.8+8+5.(+$.Y.s.Z.p <+u.9+0+a+b+c+d+e+f+R g+w.D.D.D.h+i+j+k+ ",
" y.>.l+H 6.m+m+n+7.Z.q `.L.o+M.p+O..+u q+7+e+r+s+t+u+5+D.D.D.D.D.D.v+w+ ",
" x+a+y+_+q r q p z+<+<.9 0 a A+B+C+c+D+1+2+!+E+F+G+H+R.D.D.D.D.D.D.I+r+ ",
" J+K+L+Z.z+<.o G F 7 M.[+ +N.c M+N+O+P+e+Q+S R+F+S+~+h+D.D.D.D.D.D.D.D.c.T+ ",
" U+i+2+t 9 a [+V+A+}+W+c X+>.Y+v )+1+Z+`+J+t+ @x..@+@@@h+@@@@D.D.D.D.D.#@P+ ",
" $@%@U+O.0 B+X+|+b+M+'+c+&@*@P+=@@+`+-@F+;@>@c.,@'@j+j+j+j+j+@@D.D.D.D.)@t+ ",
"@++@D.!@~@{@.+&@O+O+v d+7+]@@+Q+!+s+3+ @^@g+/@(@'@)@$+$+j+j+$+$+h+R.D.D.D._@:@ ",
"J+@@D.D.<@~@D+D+7+1+=@T y.r+S -@R+3+[@x.}@K+#+|@)@$+$+$+)@$+5+%@%@h+D.D.D.$@1@ ",
"3+@@D.D.D.2@G+s+3@Q+r+`+S J+F+[@S+g+}@4@5@6@)@$+)@5+5+5+5+%@7@|@+@5+@@D.D.8@E+ ",
";@@@D.D.D.D.|@~+U+9@c.g+g+0@P.U+4@a@$@~.5+$+5+5+5+%@%@7@7@|@+@I+'@'@$+D.D.'@b@ ",
"b.@@D.D.D.D.R.@@+@c@$@d@#@5@<@H+!@7@$+5+5+5+%@|@+@+@7@+@I+'@6@6@e@a.6@h+D.I+~@ ",
"-@)@D.D.D.D.h+h+@@h+j+)@j+$+$+5+$+$+$+5+5+5+7@+@I+I+I+'@~.e@8@a.a.2@2@5+D.e@E+ ",
"-@+@D.D.D.D.h+@@h+j+j+)@)@$+$+5+%@%@%@%@7@|@|@+@'@'@6@~.!@!@a.w.w.2@<@7@D.a.f@ ",
"g@!@D.D.D.D.h+j+$+$+$+$+$+5+5+%@7@7@7@|@+@I+I+'@~.~.e@!@a.c@2@i+Q.#+h@I+D.#@!+ ",
" 5@@@D.D.D.$+$+$+$+5+5+5+%@7@7@|@|@|@+@I+'@e@8@8@c@2@2@H+#+A.<@$@4+a@~.D.i@j@ ",
" P.h+D.D.D.5+%@5+%@|@|@+@|@I+I+'@6@~.~.~.e@8@8@c@H+i+Q.#+<@k@4+d@).l@a.@@m@n@ ",
" Q+I+D.D.D.$+%@7@|@|@+@I+I+'@'@~.e@e@e@e@8@c@2@H+Q.A.$@k@4+h@~+).l@o@c@6@p@ ",
" ++q@@@D.D.%@|@+@I+I++@I+6@e@!@!@8@c@c@c@w.i+A.A.$@5@#@h@~+a@r@l@u+4@a._@s@ ",
" k+5+D.D.%@I+~.6@6@6@~.8@8@a.c@w.H+i+H+Q.<@5@5@d@h@).a@l@t@o@0.,.t@6@u@ ",
" =@).D.D.)@+@8@!@!@a.c@c@w.2@H+i+#+A.<@k@4+#@h@).q@,@.@_@0.v@z.w@<@4@x@ ",
" 3+6@D.R.$+8@2@w.2@H+i+Q.#+#+A.$@5@d@h@~+).a@,@.@o@0.v@y@P.x+K+2@x@ ",
" 9@j+D.@@6@Q.A.Q.Q.A.k@5@k@4+#@h@z@(@r@l@K+_@A@v@B@U+C@S+U+w.x.D@ ",
" E@i@R.D.)@8@k@#@d@5@d@h@z@~+(@q@a@l@K+4@A@B@'.,.P.x.b./@Q.F@G@ ",
" H@4@D.D.$+c@h@r@r@q@(@(@q@,@.@K+_@A@v@y@w@P.g+^@I@B@<@J@K@ ",
" L@0.)@D.)@8@#@o@0.0._@_@_@A@v@i@y@F@M@g+m@^@M@l@k@P.N@ ",
" O@z.6@D.@@|@A.r@i@w@/@w@F@}@P.0@x+x.x.P..@4+).P@Q@ ",
" F+(@+@j+j++@c@#@t@'.}@9@0@G+'..@#@H+z@^@R@S@ ",
" R@k+0.|@5+j+)@@@R.D.D.R.R.j+c@u+F+T@ ",
" U@s@;@,.z@|@'@)@5+i+d@,.E@ ",
" E+V@W@R+W@X@ "};

View File

@ -1,319 +0,0 @@
/* XPM */
static char * warning_xpm[] = {
"32 32 284 2",
" c None",
". c #D04D00",
"+ c #D24E00",
"@ c #C64900",
"# c #E37B00",
"$ c #D14E00",
"% c #D55600",
"& c #FCBF00",
"* c #EE9A00",
"= c #FFC700",
"- c #DA6500",
"; c #FFD32E",
"> c #FFFDCB",
", c #CB4C00",
"' c #F4AA02",
") c #FFF3AB",
"! c #FFFFE1",
"~ c #B44300",
"{ c #E37C00",
"] c #FFDE58",
"^ c #FFFFE0",
"/ c #FFFFDF",
"( c #FFDE56",
"_ c #F9BF0D",
": c #FFF9C3",
"< c #C6C6B8",
"[ c #969696",
"} c #FFF8C1",
"| c #BD4600",
"1 c #E99002",
"2 c #FFEA7C",
"3 c #EDEDD4",
"4 c #979797",
"5 c #989898",
"6 c #949494",
"7 c #D9D9C6",
"8 c #FFEA7A",
"9 c #E98F01",
"0 c #D85F00",
"a c #FFDA26",
"b c #FFFCCD",
"c c #E5E5C8",
"d c #C9C9B6",
"e c #FFFCCB",
"f c #FFD924",
"g c #C94B00",
"h c #F1AB01",
"i c #FFF292",
"j c #FFFFD3",
"k c #EBEBC7",
"l c #959595",
"m c #929292",
"n c #DCDCBC",
"o c #FFFFD1",
"p c #FFF28C",
"q c #DD7100",
"r c #FFE43F",
"s c #FFFEC5",
"t c #FFFFCB",
"u c #FFFFCC",
"v c #989894",
"w c #919191",
"x c #909090",
"y c #8E8E8E",
"z c #F8F8C6",
"A c #FFFFC7",
"B c #FFFEBF",
"C c #FFE236",
"D c #F9CC0A",
"E c #FFF99D",
"F c #FFFFC4",
"G c #FFFFC3",
"H c #B7B7A1",
"I c #8B8B8B",
"J c #8A8A8A",
"K c #9E9E93",
"L c #FFFFC1",
"M c #FFFFBE",
"N c #FFFFBC",
"O c #FFF892",
"P c #F9CB06",
"Q c #B84500",
"R c #E68D00",
"S c #FFEC51",
"T c #FFFFBA",
"U c #FFFFB9",
"V c #FFFFBB",
"W c #D1D1A6",
"X c #838383",
"Y c #B8B898",
"Z c #FFFFB6",
"` c #FFFFB3",
" . c #FFFFAF",
".. c #FFFFAB",
"+. c #FFEA43",
"@. c #D55700",
"#. c #FCDB13",
"$. c #FFFB97",
"%. c #FFFFAE",
"&. c #EEEEA8",
"*. c #7A7A7A",
"=. c #797979",
"-. c #DCDC9E",
";. c #FFFFA9",
">. c #FFFFA5",
",. c #FFFFA1",
"'. c #FFFF9E",
"). c #FFFB82",
"!. c #FCDA0C",
"~. c #EEAC00",
"{. c #FFF356",
"]. c #FFFFA4",
"^. c #FFFFA2",
"/. c #FFFFA3",
"(. c #8B8B79",
"_. c #6E6E6E",
":. c #FFFF9D",
"<. c #FFFF9B",
"[. c #FFFF98",
"}. c #FFFF93",
"|. c #FFFF8D",
"1. c #FFFF8B",
"2. c #FFF243",
"3. c #DA6B00",
"4. c #FFEB18",
"5. c #FFFE8A",
"6. c #FFFF92",
"7. c #FFFF94",
"8. c #A7A776",
"9. c #88886C",
"0. c #FFFF8A",
"a. c #FFFF87",
"b. c #FFFF82",
"c. c #FFFF7C",
"d. c #FFFF78",
"e. c #FFFD6D",
"f. c #FFEA0E",
"g. c #F4C400",
"h. c #FFF854",
"i. c #FFFF81",
"j. c #FFFF80",
"k. c #F4F47C",
"l. c #E9E978",
"m. c #FFFF7A",
"n. c #FFFF77",
"o. c #FFFF73",
"p. c #FFFF6F",
"q. c #FFFF6B",
"r. c #FFFF65",
"s. c #FFFF62",
"t. c #FFF73A",
"u. c #E38A00",
"v. c #FFF21E",
"w. c #FFFF69",
"x. c #FFFF6E",
"y. c #FFFF6C",
"z. c #FFFF66",
"A. c #FFFF5F",
"B. c #FFFF5C",
"C. c #FFFF57",
"D. c #FFFF53",
"E. c #FFFF4D",
"F. c #FFFF4A",
"G. c #FFF111",
"H. c #D55800",
"I. c #F9DD01",
"J. c #FFFC43",
"K. c #FFFF58",
"L. c #FFFF5B",
"M. c #B5B54D",
"N. c #46463C",
"O. c #373737",
"P. c #9A9A44",
"Q. c #FFFF50",
"R. c #FFFF4C",
"S. c #FFFF49",
"T. c #FFFF45",
"U. c #FFFF40",
"V. c #FFFF3D",
"W. c #FFFF3A",
"X. c #FFFB29",
"Y. c #F9DD00",
"Z. c #E9A100",
"`. c #FFF819",
" + c #FFFF41",
".+ c #FFFF43",
"++ c #FFFF48",
"@+ c #FFFF47",
"#+ c #FFFF46",
"$+ c #3C3C31",
"%+ c #2E2E2E",
"&+ c #2C2C2C",
"*+ c #292929",
"=+ c #E4E43A",
"-+ c #FFFF39",
";+ c #FFFF37",
">+ c #FFFF33",
",+ c #FFFF30",
"'+ c #FFFF2C",
")+ c #FFFF29",
"!+ c #FFFF27",
"~+ c #FFF70D",
"{+ c #D86300",
"]+ c #FCED05",
"^+ c #FFFE25",
"/+ c #FFFF2D",
"(+ c #FFFF32",
"_+ c #FFFF31",
":+ c #323225",
"<+ c #232323",
"[+ c #202020",
"}+ c #1E1E1E",
"|+ c #E3E326",
"1+ c #FFFF25",
"2+ c #FFFF22",
"3+ c #FFFF20",
"4+ c #FFFF1E",
"5+ c #FFFF1B",
"6+ c #FFFF19",
"7+ c #FFFF17",
"8+ c #FFFE13",
"9+ c #FCED02",
"0+ c #C54900",
"a+ c #F1C500",
"b+ c #FFFB0E",
"c+ c #FFFF1A",
"d+ c #FFFF1D",
"e+ c #FFFF1F",
"f+ c #A9A91C",
"g+ c #191919",
"h+ c #181818",
"i+ c #6E6E16",
"j+ c #FFFF14",
"k+ c #FFFF13",
"l+ c #FFFF11",
"m+ c #FFFF0F",
"n+ c #FFFF0D",
"o+ c #FFFF0B",
"p+ c #FFFF0A",
"q+ c #FFFF08",
"r+ c #FFFB04",
"s+ c #DD7A00",
"t+ c #FFFE00",
"u+ c #FFFE0F",
"v+ c #FFFF15",
"w+ c #FFFF16",
"x+ c #FFFF12",
"y+ c #FFFF10",
"z+ c #FFFF0E",
"A+ c #FFFF0C",
"B+ c #FFFF09",
"C+ c #FFFF07",
"D+ c #FFFF06",
"E+ c #FFFF05",
"F+ c #FFFE02",
"G+ c #E08500",
"H+ c #F4D300",
"I+ c #F5D50C",
"J+ c #F5D50D",
"K+ c #F5D50E",
"L+ c #F5D60F",
"M+ c #F5D610",
"N+ c #F4D50B",
"O+ c #F4D509",
"P+ c #F4D408",
"Q+ c #F4D407",
"R+ c #F4D406",
"S+ c #F4D405",
"T+ c #F4D404",
"U+ c #F4D403",
"V+ c #F4D302",
"W+ c #F4D301",
"X+ c #CA4B00",
"Y+ c #D35104",
"Z+ c #D35307",
"`+ c #D35408",
" @ c #D45409",
".@ c #D4550A",
"+@ c #D35206",
"@@ c #D35105",
"#@ c #D35003",
"$@ c #D24F02",
"%@ c #D24F01",
"&@ c #B14200",
" ",
" ",
" . + + @ ",
" + # # + ",
" $ % & & % @ ",
" + * = = * + ",
" $ - ; > > ; - , ",
" . + ' ) ! ! ) ' + ~ ",
" $ { ] ^ / / / ( { . ",
" . % _ : < [ [ < } _ % | ",
" + 1 2 3 [ 4 5 6 7 8 9 + ",
" $ 0 a b c [ [ [ 6 d e f 0 g ",
" + h i j k l l 6 m n o p h + ",
" + q r s t u v w x y z A B C q . ",
" . + D E F G F H I J K L M N O P + Q ",
" + R S T U T V W X X Y Z ` ...+.R + ",
" $ @.#.$. .%. . .&.*.=.-.;.>.,.'.).!.@.@ ",
" + ~.{.].,.,.^./.,.(._.:.<.[.}.|.1.2.~.+ ",
" $ 3.4.5.6.6.7.7.7.6.8.9.|.0.a.b.c.d.e.f.3., ",
" . + g.h.i.j.i.b.b.i.i.k.l.m.n.o.p.q.r.s.t.g.+ ~ ",
" $ u.v.w.q.x.x.p.x.x.y.q.w.z.s.A.B.C.D.E.F.G.u.. ",
" . H.I.J.C.K.L.B.B.L.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.H.| ",
" + Z.`. +.+T.++++++@+#+$+%+&+*+=+-+;+>+,+'+)+!+~+Z.+ ",
" $ {+]+^+/+,+(+(+(+(+(+_+:+<+[+}+|+1+2+3+4+5+6+7+8+9+{+0+ ",
" + a+b+c+5+d+e+e+3+3+e+e+f+g+h+i+7+j+k+l+m+n+o+p+q+r+a++ ",
"$ s+t+u+k+j+v+w+7+w+7+v+v+j+k+x+y+m+z+A+A+B+q+C+D+E+F+t+s+, ",
"+ G+H+I+J+K+L+L+M+M+M+L+L+K+J+J+N+O+O+P+Q+R+S+T+U+V+W+H+G++ ",
"X++ + Y+Z+`+`+ @.@.@ @ @ @`+`+Z++@@@+@@@Y+Y+#@$@%@%@%@+ + &@ ",
" ",
" ",
" ",
" "};

View File

@ -1,63 +0,0 @@
#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();
}

View File

@ -1,28 +0,0 @@
# 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
}
}
}

View File

@ -1,46 +0,0 @@
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/x.H>
#include <stdio.h>
Fl_Window* win;
Fl_Value_Slider* slider;
Atom opacity_atom;
void slider_cb(Fl_Widget*, void*) {
printf("callback %i\n", (int)slider->value());
//int v = (int)slider->value();
//unsigned int v = (unsigned int)0xe0000000;
unsigned int v = (unsigned int)4;
XChangeProperty(fl_display, fl_xid(win), opacity_atom, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&v, 1);
XFlush(fl_display);
}
int main(void) {
fl_open_display();
opacity_atom = XInternAtom(fl_display, "_NET_WM_WINDOW_OPACITY", False);
win = new Fl_Window(240, 175, "Opacity test");
win->begin();
Fl_Box* sbox = new Fl_Box(10, 9, 220, 102, "sample text");
sbox->box(FL_ENGRAVED_BOX);
sbox->color((Fl_Color)186);
sbox->labelcolor((Fl_Color)23);
slider = new Fl_Value_Slider(10, 142, 220, 18, "Opacity percent:");
slider->type(1);
slider->step(1);
slider->maximum(100);
slider->minimum(1);
slider->value(100);
slider->callback(slider_cb);
slider->align(FL_ALIGN_TOP_LEFT);
win->end();
win->show();
slider_cb(0,0);
return Fl::run();
}

View File

@ -1,63 +0,0 @@
#include <FL/x.H>
#include <FL/Fl.H>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#define CMDS_NUM 11
const char* cmds[] = {
"fluid",
"/this/command/does/not/exists",
"ls",
"ls -la",
"/home/sanel/abc",
"/home/sanel/readme.txt",
"mozilla",
"firefox",
"xedit",
"/usr/bin/xedit",
"gvim"
};
void run_cmd(const char* cmd, Atom _XA_EDE_EVOKE_SPAWN) {
// max size
unsigned char txt_send[8192];
int i;
int len = strlen(cmd);
for(i = 0; i < 8192-2 && i < len; i++)
txt_send[i] = cmd[i];
txt_send[i] = '\0';
// send text
if(XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
_XA_EDE_EVOKE_SPAWN, XA_STRING, 8, PropModeReplace,
txt_send, i + 1) == Success) {
puts("Success");
} else {
puts("Fail");
}
}
int main(int argc, char **argv) {
fl_open_display();
srand(time(0));
Atom _XA_EDE_EVOKE_SPAWN = XInternAtom(fl_display, "_EDE_EVOKE_SPAWN", False);
for(int i = 0, j = 0; i < 5; i++) {
j = rand() % CMDS_NUM;
printf("%i (%s)\n", i, cmds[j]);
sleep(1);
run_cmd(cmds[j], _XA_EDE_EVOKE_SPAWN);
XFlush(fl_display);
}
return 0;
}