mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Moving old evoke to branches
This commit is contained in:
parent
4491dd2948
commit
d0498c453d
@ -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();
|
|
||||||
}
|
|
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
1362
evoke/Composite.cpp
1362
evoke/Composite.cpp
File diff suppressed because it is too large
Load Diff
@ -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
|
|
@ -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
|
|
||||||
}
|
|
@ -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
|
|
@ -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 ;
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
51
evoke/Log.h
51
evoke/Log.h
@ -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
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
154
evoke/Spawn.cpp
154
evoke/Spawn.cpp
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
276
evoke/Splash.cpp
276
evoke/Splash.cpp
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
332
evoke/Xsm.cpp
332
evoke/Xsm.cpp
@ -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;
|
|
||||||
}
|
|
35
evoke/Xsm.h
35
evoke/Xsm.h
@ -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 |
@ -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
|
|
||||||
|
|
||||||
...
|
|
||||||
--------------
|
|
||||||
|
|
||||||
|
|
@ -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>
|
|
@ -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
|
|
289
evoke/evoke.cpp
289
evoke/evoke.cpp
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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@ "};
|
|
@ -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+#@$@%@%@%@+ + &@ ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" ",
|
|
||||||
" "};
|
|
@ -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();
|
|
||||||
}
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user