Moving back an newer evoke
287
evoke/Autostart.cpp
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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 <stdlib.h>
|
||||||
|
#include <FL/Fl_Pixmap.H>
|
||||||
|
#include <FL/Fl_Check_Browser.H>
|
||||||
|
#include <FL/Fl_Button.H>
|
||||||
|
#include <FL/Fl_Window.H>
|
||||||
|
#include <FL/Fl_Box.H>
|
||||||
|
#include <FL/Fl.H>
|
||||||
|
|
||||||
|
#include <edelib/String.h>
|
||||||
|
#include <edelib/StrUtil.h>
|
||||||
|
#include <edelib/List.h>
|
||||||
|
#include <edelib/Util.h>
|
||||||
|
#include <edelib/DesktopFile.h>
|
||||||
|
#include <edelib/Directory.h>
|
||||||
|
#include <edelib/Nls.h>
|
||||||
|
#include <edelib/Debug.h>
|
||||||
|
#include <edelib/Run.h>
|
||||||
|
|
||||||
|
#include "Autostart.h"
|
||||||
|
#include "icons/warning.xpm"
|
||||||
|
|
||||||
|
EDELIB_NS_USING(String)
|
||||||
|
EDELIB_NS_USING(DesktopFile)
|
||||||
|
EDELIB_NS_USING(list)
|
||||||
|
EDELIB_NS_USING(dir_list)
|
||||||
|
EDELIB_NS_USING(system_config_dirs)
|
||||||
|
EDELIB_NS_USING(user_config_dir)
|
||||||
|
EDELIB_NS_USING(str_ends)
|
||||||
|
EDELIB_NS_USING(run_program)
|
||||||
|
|
||||||
|
#ifdef DEBUG_AUTOSTART_RUN
|
||||||
|
#define AUTOSTART_RUN(s) E_DEBUG("Executing %s\n", s)
|
||||||
|
#else
|
||||||
|
#define AUTOSTART_RUN(s) run_program(s, false)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct DialogEntry {
|
||||||
|
String name;
|
||||||
|
String exec;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef list<String> StringList;
|
||||||
|
typedef list<String>::iterator StringListIter;
|
||||||
|
|
||||||
|
typedef list<DialogEntry*> DialogEntryList;
|
||||||
|
typedef list<DialogEntry*>::iterator DialogEntryListIter;
|
||||||
|
|
||||||
|
static Fl_Window* dialog_win;
|
||||||
|
static Fl_Check_Browser* cbrowser;
|
||||||
|
static Fl_Pixmap warnpix(warning_xpm);
|
||||||
|
|
||||||
|
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 unique_by_basename(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 void entry_list_run_clear(DialogEntryList& l, bool run) {
|
||||||
|
DialogEntryListIter dit = l.begin(), dit_end = l.end();
|
||||||
|
for(; dit != dit_end; ++dit) {
|
||||||
|
if(run)
|
||||||
|
AUTOSTART_RUN((*dit)->exec.c_str());
|
||||||
|
delete *dit;
|
||||||
|
}
|
||||||
|
|
||||||
|
l.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dialog_runsel_cb(Fl_Widget*, void* e) {
|
||||||
|
DialogEntryList* lst = (DialogEntryList*)e;
|
||||||
|
E_ASSERT(lst->size() == (unsigned int)cbrowser->nitems() && "Size mismatch in local list and browser widget");
|
||||||
|
|
||||||
|
DialogEntryListIter it = lst->begin();
|
||||||
|
for(int i = 1; i <= cbrowser->nitems(); i++, ++it) {
|
||||||
|
if(cbrowser->checked(i))
|
||||||
|
AUTOSTART_RUN((*it)->exec.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_win->hide();
|
||||||
|
entry_list_run_clear(*lst, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dialog_runall_cb(Fl_Widget*, void* e) {
|
||||||
|
DialogEntryList* lst = (DialogEntryList*)e;
|
||||||
|
E_DEBUG("%i != %i\n", lst->size(), cbrowser->nitems());
|
||||||
|
E_ASSERT(lst->size() == (unsigned int)cbrowser->nitems() && "Size mismatch in local list and browser widget");
|
||||||
|
|
||||||
|
dialog_win->hide();
|
||||||
|
entry_list_run_clear(*lst, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dialog_close_cb(Fl_Widget*, void* e) {
|
||||||
|
dialog_win->hide();
|
||||||
|
|
||||||
|
DialogEntryList* lst = (DialogEntryList*)e;
|
||||||
|
entry_list_run_clear(*lst, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_autostart_dialog(DialogEntryList& l) {
|
||||||
|
DialogEntryList* ptr = (DialogEntryList*)&l;
|
||||||
|
|
||||||
|
dialog_win = new Fl_Window(370, 305, _("Autostart warning"));
|
||||||
|
dialog_win->begin();
|
||||||
|
Fl_Box* img = new Fl_Box(10, 10, 65, 60);
|
||||||
|
img->image(warnpix);
|
||||||
|
Fl_Box* txt = new Fl_Box(80, 10, 280, 60, _("The following applications are registered for starting. Please chose what to do next"));
|
||||||
|
txt->align(FL_ALIGN_INSIDE | FL_ALIGN_LEFT | FL_ALIGN_WRAP);
|
||||||
|
cbrowser = new Fl_Check_Browser(10, 75, 350, 185);
|
||||||
|
|
||||||
|
DialogEntryListIter it = l.begin(), it_end = l.end();
|
||||||
|
for(; it != it_end; ++it)
|
||||||
|
cbrowser->add((*it)->name.c_str());
|
||||||
|
|
||||||
|
Fl_Button* rsel = new Fl_Button(45, 270, 125, 25, _("Run &selected"));
|
||||||
|
rsel->callback(dialog_runsel_cb, ptr);
|
||||||
|
|
||||||
|
Fl_Button* rall = new Fl_Button(175, 270, 90, 25, _("&Run all"));
|
||||||
|
rall->callback(dialog_runall_cb, ptr);
|
||||||
|
|
||||||
|
Fl_Button* cancel = new Fl_Button(270, 270, 90, 25, _("&Cancel"));
|
||||||
|
cancel->callback(dialog_close_cb, ptr);
|
||||||
|
cancel->take_focus();
|
||||||
|
dialog_win->end();
|
||||||
|
dialog_win->show();
|
||||||
|
|
||||||
|
while(dialog_win->shown())
|
||||||
|
Fl::wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 perform_autostart(bool safe) {
|
||||||
|
const char* autostart_dirname = "/autostart/";
|
||||||
|
|
||||||
|
String adir = edelib::user_config_dir();
|
||||||
|
adir += autostart_dirname;
|
||||||
|
|
||||||
|
StringList dfiles, sysdirs, tmp;
|
||||||
|
StringListIter it, it_end, tmp_it, tmp_it_end;
|
||||||
|
|
||||||
|
dir_list(adir.c_str(), dfiles, true);
|
||||||
|
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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 unique_by_basename().
|
||||||
|
*/
|
||||||
|
unique_by_basename(dfiles);
|
||||||
|
|
||||||
|
const char* name;
|
||||||
|
char buff[1024];
|
||||||
|
DesktopFile df;
|
||||||
|
DialogEntryList entry_list;
|
||||||
|
|
||||||
|
for(it = dfiles.begin(), it_end = dfiles.end(); it != it_end; ++it) {
|
||||||
|
if((*it).empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
name = (*it).c_str();
|
||||||
|
|
||||||
|
if(!str_ends(name, ".desktop"))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(!df.load(name)) {
|
||||||
|
E_WARNING(E_STRLOC ": 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.try_exec(buff, sizeof(buff)) || df.exec(buff, sizeof(buff))))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
DialogEntry* en = new DialogEntry;
|
||||||
|
en->exec = buff;
|
||||||
|
|
||||||
|
/* figure out the name */
|
||||||
|
if(df.name(buff, sizeof(buff)))
|
||||||
|
en->name = buff;
|
||||||
|
else
|
||||||
|
en->name = name;
|
||||||
|
|
||||||
|
entry_list.push_back(en);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(safe)
|
||||||
|
run_autostart_dialog(entry_list);
|
||||||
|
else
|
||||||
|
entry_list_run_clear(entry_list, true);
|
||||||
|
}
|
18
evoke/Autostart.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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__
|
||||||
|
|
||||||
|
void perform_autostart(bool safe);
|
||||||
|
|
||||||
|
#endif
|
231
evoke/EvokeService.cpp
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <edelib/File.h>
|
||||||
|
#include <edelib/Debug.h>
|
||||||
|
#include <edelib/Config.h>
|
||||||
|
#include <edelib/Resource.h>
|
||||||
|
#include <edelib/StrUtil.h>
|
||||||
|
#include <edelib/MessageBox.h>
|
||||||
|
#include <edelib/Nls.h>
|
||||||
|
|
||||||
|
#include "EvokeService.h"
|
||||||
|
#include "Splash.h"
|
||||||
|
#include "Logout.h"
|
||||||
|
#include "Xsm.h"
|
||||||
|
|
||||||
|
EDELIB_NS_USING(Config)
|
||||||
|
EDELIB_NS_USING(Resource)
|
||||||
|
EDELIB_NS_USING(RES_SYS_ONLY)
|
||||||
|
EDELIB_NS_USING(file_exists)
|
||||||
|
EDELIB_NS_USING(file_remove)
|
||||||
|
EDELIB_NS_USING(str_trim)
|
||||||
|
|
||||||
|
#ifdef USE_LOCAL_CONFIG
|
||||||
|
#define CONFIG_GET_STRVAL(object, section, key, buff) object.get(section, key, buff, sizeof(buff))
|
||||||
|
#else
|
||||||
|
#define CONFIG_GET_STRVAL(object, section, key, buff) object.get(section, key, buff, sizeof(buff), RES_SYS_ONLY)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static Atom XA_EDE_EVOKE_SHUTDOWN_ALL;
|
||||||
|
static Atom XA_EDE_EVOKE_QUIT;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
EvokeService::EvokeService() : lock_name(NULL), xsm(NULL), is_running(false) {
|
||||||
|
/* TODO: or add setup_atoms() function */
|
||||||
|
XA_EDE_EVOKE_SHUTDOWN_ALL = XInternAtom(fl_display, "_EDE_EVOKE_SHUTDOWN_ALL", False);
|
||||||
|
XA_EDE_EVOKE_QUIT = XInternAtom(fl_display, "_EDE_EVOKE_QUIT", False);
|
||||||
|
}
|
||||||
|
|
||||||
|
EvokeService::~EvokeService() {
|
||||||
|
E_DEBUG(E_STRLOC ": EvokeService::~EvokeService()\n");
|
||||||
|
|
||||||
|
clear_startup_items();
|
||||||
|
stop_xsettings_manager(true);
|
||||||
|
remove_lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
EvokeService* EvokeService::instance(void) {
|
||||||
|
static EvokeService es;
|
||||||
|
return &es;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EvokeService::setup_lock(const char* name) {
|
||||||
|
if(file_exists(name))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FILE* f = fopen(name, "w");
|
||||||
|
if(!f)
|
||||||
|
return false;
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
lock_name = strdup(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvokeService::remove_lock(void) {
|
||||||
|
if(!lock_name)
|
||||||
|
return;
|
||||||
|
|
||||||
|
file_remove(lock_name);
|
||||||
|
free(lock_name);
|
||||||
|
lock_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvokeService::clear_startup_items(void) {
|
||||||
|
E_DEBUG(E_STRLOC ": EvokeService::clear_startup_items()\n");
|
||||||
|
|
||||||
|
if(startup_items.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
StartupItemListIter it = startup_items.begin(), it_end = startup_items.end();
|
||||||
|
for(; it != it_end; ++it)
|
||||||
|
delete *it;
|
||||||
|
|
||||||
|
startup_items.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvokeService::read_startup(void) {
|
||||||
|
#ifdef USE_LOCAL_CONFIG
|
||||||
|
/*
|
||||||
|
* this will load SETTINGS_FILENAME only from local directory;
|
||||||
|
* intended for development and testing only
|
||||||
|
*/
|
||||||
|
Config c;
|
||||||
|
int ret = c.load("ede-startup.conf");
|
||||||
|
#else
|
||||||
|
/* only system resource will be loaded; use ede-startup will be skipped */
|
||||||
|
Resource c;
|
||||||
|
int ret = c.load("ede/ede-startup");
|
||||||
|
#endif
|
||||||
|
if(!ret) {
|
||||||
|
E_WARNING(E_STRLOC ": Unable to load EDE startup file\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tok_buff[256], buff[256];
|
||||||
|
|
||||||
|
/* if nothing found, exit */
|
||||||
|
if(!CONFIG_GET_STRVAL(c, "Startup", "start_order", tok_buff))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(CONFIG_GET_STRVAL(c, "Startup", "splash_theme", buff))
|
||||||
|
splash_theme = buff;
|
||||||
|
|
||||||
|
for(const char* sect = strtok(tok_buff, ","); sect; sect = strtok(NULL, ",")) {
|
||||||
|
/* remove leading/ending spaces, if exists */
|
||||||
|
str_trim(buff);
|
||||||
|
|
||||||
|
/* assure each startup item has 'exec' key */
|
||||||
|
if(!CONFIG_GET_STRVAL(c, sect, "exec", buff)) {
|
||||||
|
E_WARNING(E_STRLOC ": Startup item '%s' does not have anything to execute. Skipping...\n", sect);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
StartupItem *s = new StartupItem;
|
||||||
|
s->exec = buff;
|
||||||
|
|
||||||
|
if(CONFIG_GET_STRVAL(c, sect, "icon", buff))
|
||||||
|
s->icon = buff;
|
||||||
|
if(CONFIG_GET_STRVAL(c, sect, "description", buff))
|
||||||
|
s->description = buff;
|
||||||
|
|
||||||
|
startup_items.push_back(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvokeService::run_startup(bool splash, bool dryrun) {
|
||||||
|
if(startup_items.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Splash s(startup_items, splash_theme, splash, dryrun);
|
||||||
|
s.run();
|
||||||
|
clear_startup_items();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvokeService::start_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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!xsm->init(fl_display, fl_screen)) {
|
||||||
|
edelib::alert(_("Unable to load XSETTINGS manager properly :-("));
|
||||||
|
stop_xsettings_manager(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
E_RETURN_IF_FAIL(xsm);
|
||||||
|
|
||||||
|
if(xsm->load_serialized())
|
||||||
|
xsm->notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvokeService::stop_xsettings_manager(bool serialize) {
|
||||||
|
if(!xsm)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(serialize)
|
||||||
|
xsm->save_serialized();
|
||||||
|
|
||||||
|
delete xsm;
|
||||||
|
xsm = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int EvokeService::handle(const XEvent* xev) {
|
||||||
|
if(xsm && xsm->should_terminate(xev)) {
|
||||||
|
E_DEBUG(E_STRLOC ": Terminating XSETTINGS manager on request by X event\n");
|
||||||
|
stop_xsettings_manager(true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(xev->xproperty.atom == XA_EDE_EVOKE_QUIT) {
|
||||||
|
int val = get_int_property_value(XA_EDE_EVOKE_QUIT);
|
||||||
|
if(val == 1)
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(xev->xproperty.atom == XA_EDE_EVOKE_SHUTDOWN_ALL) {
|
||||||
|
int val = get_int_property_value(XA_EDE_EVOKE_SHUTDOWN_ALL);
|
||||||
|
if(val == 1) {
|
||||||
|
int dw = DisplayWidth(fl_display, fl_screen);
|
||||||
|
int dh = DisplayHeight(fl_display, fl_screen);
|
||||||
|
|
||||||
|
logout_dialog_show(dw, dh, LOGOUT_OPT_SHUTDOWN | LOGOUT_OPT_RESTART);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
60
evoke/EvokeService.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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 <edelib/List.h>
|
||||||
|
#include <edelib/String.h>
|
||||||
|
|
||||||
|
struct StartupItem {
|
||||||
|
edelib::String exec;
|
||||||
|
edelib::String icon;
|
||||||
|
edelib::String description;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef edelib::list<StartupItem*> StartupItemList;
|
||||||
|
typedef edelib::list<StartupItem*>::iterator StartupItemListIter;
|
||||||
|
class Xsm;
|
||||||
|
|
||||||
|
class EvokeService {
|
||||||
|
private:
|
||||||
|
char* lock_name;
|
||||||
|
Xsm* xsm;
|
||||||
|
bool is_running;
|
||||||
|
StartupItemList startup_items;
|
||||||
|
edelib::String splash_theme;
|
||||||
|
|
||||||
|
void clear_startup_items(void);
|
||||||
|
public:
|
||||||
|
EvokeService();
|
||||||
|
~EvokeService();
|
||||||
|
static EvokeService* instance(void);
|
||||||
|
|
||||||
|
bool setup_lock(const char* name);
|
||||||
|
void remove_lock(void);
|
||||||
|
|
||||||
|
void start(void) { is_running = true; }
|
||||||
|
void stop(void) { is_running = false; }
|
||||||
|
bool running(void) { return is_running; }
|
||||||
|
|
||||||
|
void read_startup(void);
|
||||||
|
void run_startup(bool splash, bool dryrun);
|
||||||
|
int handle(const XEvent* xev);
|
||||||
|
|
||||||
|
void start_xsettings_manager(void);
|
||||||
|
void stop_xsettings_manager(bool serialize);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
31
evoke/Jamfile
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# Part of Equinox Desktop Environment (EDE).
|
||||||
|
# Copyright (c) 2009 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 ;
|
||||||
|
|
||||||
|
SOURCE = evoke.cpp
|
||||||
|
EvokeService.cpp
|
||||||
|
Splash.cpp
|
||||||
|
Xsm.cpp
|
||||||
|
Logout.cpp
|
||||||
|
Autostart.cpp ;
|
||||||
|
|
||||||
|
#ObjectC++Flags $(SOURCE) : -DUSE_LOCAL_CONFIG ;
|
||||||
|
|
||||||
|
EdeProgram evoke : $(SOURCE) ;
|
||||||
|
TranslationStrings locale : $(SOURCE) ;
|
||||||
|
EdeManual doc/evoke.txt ;
|
||||||
|
|
||||||
|
FltkProgramBare test/evoke_test : test/evoke_test.cpp : "noinstall" ;
|
||||||
|
|
||||||
|
SubInclude TOP evoke splash-themes ;
|
95
evoke/Logout.cpp
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2008-2009 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_show(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 EDE?"));
|
||||||
|
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;
|
||||||
|
}
|
26
evoke/Logout.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2008-2009 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_show(int screen_w, int screen_h, int opt);
|
||||||
|
|
||||||
|
#endif
|
311
evoke/Splash.cpp
Normal file
@ -0,0 +1,311 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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/Debug.h>
|
||||||
|
#include <edelib/Nls.h>
|
||||||
|
#include <edelib/Util.h>
|
||||||
|
#include <edelib/Directory.h>
|
||||||
|
#include <edelib/Resource.h>
|
||||||
|
#include <edelib/Run.h>
|
||||||
|
|
||||||
|
#include "Splash.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 */
|
||||||
|
|
||||||
|
EDELIB_NS_USING(String)
|
||||||
|
EDELIB_NS_USING(Resource)
|
||||||
|
EDELIB_NS_USING(build_filename)
|
||||||
|
EDELIB_NS_USING(dir_exists)
|
||||||
|
EDELIB_NS_USING(run_program)
|
||||||
|
EDELIB_NS_USING(RES_SYS_ONLY)
|
||||||
|
|
||||||
|
#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() until 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(StartupItemList& s, String& theme, bool show_it, bool dr) : Fl_Double_Window(480, 365) {
|
||||||
|
slist = &s;
|
||||||
|
splash_theme = &theme;
|
||||||
|
show_splash = show_it;
|
||||||
|
dryrun = dr;
|
||||||
|
icons = NULL;
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
box(FL_BORDER_BOX);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Splash::~Splash() {
|
||||||
|
E_DEBUG(E_STRLOC ": 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(slist != NULL);
|
||||||
|
|
||||||
|
if(!show_splash) {
|
||||||
|
while(next_client_nosplash())
|
||||||
|
;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fl_register_images();
|
||||||
|
|
||||||
|
String path, splash_theme_path;
|
||||||
|
|
||||||
|
#ifdef USE_LOCAL_CONFIG
|
||||||
|
splash_theme_path = "splash-themes/";
|
||||||
|
#else
|
||||||
|
splash_theme_path = Resource::find_data("ede/splash-themes", RES_SYS_ONLY);
|
||||||
|
if(splash_theme_path.empty()) {
|
||||||
|
E_WARNING(E_STRLOC ": Unable to locate splash themes in $XDG_DATA_DIRS directories\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
splash_theme_path += E_DIR_SEPARATOR;
|
||||||
|
splash_theme_path += *splash_theme;
|
||||||
|
|
||||||
|
if(!dir_exists(splash_theme_path.c_str())) {
|
||||||
|
E_WARNING(E_STRLOC ": Unable to locate '%s' in '%s' theme directory\n",
|
||||||
|
splash_theme->c_str(), splash_theme_path.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup widgets */
|
||||||
|
begin();
|
||||||
|
Fl_Box* bimg = new Fl_Box(0, 0, w(), h());
|
||||||
|
Fl_Image* splash_img = 0;
|
||||||
|
|
||||||
|
path = build_filename(splash_theme_path.c_str(), "background.png");
|
||||||
|
splash_img = Fl_Shared_Image::get(path.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*[slist->size()];
|
||||||
|
|
||||||
|
icon_group->begin();
|
||||||
|
int i = 0;
|
||||||
|
const char* imgpath;
|
||||||
|
Fl_Image* iconimg = 0;
|
||||||
|
|
||||||
|
for(StartupItemListIter it = slist->begin(); it != slist->end(); ++it, ++i) {
|
||||||
|
Fl_Box* bb = new Fl_Box(X, Y, 64, 64);
|
||||||
|
|
||||||
|
path = build_filename(splash_theme_path.c_str(), (*it)->icon.c_str());
|
||||||
|
imgpath = path.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 EDEWM_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(slist->empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(counter == 0)
|
||||||
|
slist_it = slist->begin();
|
||||||
|
|
||||||
|
if(slist_it == slist->end()) {
|
||||||
|
counter = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
E_ASSERT(counter < slist->size() && "Internal error; 'counter' out of bounds");
|
||||||
|
|
||||||
|
char buff[1024];
|
||||||
|
const char* msg = (*slist_it)->description.c_str();
|
||||||
|
const char* cmd = (*slist_it)->exec.c_str();
|
||||||
|
snprintf(buff, sizeof(buff), _("Starting %s..."), msg);
|
||||||
|
|
||||||
|
icons[counter]->show();
|
||||||
|
msgbox->copy_label(buff);
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
/* run command */
|
||||||
|
if(!dryrun)
|
||||||
|
run_program(cmd, false);
|
||||||
|
|
||||||
|
++slist_it;
|
||||||
|
++counter;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* called when splash option is off */
|
||||||
|
bool Splash::next_client_nosplash(void) {
|
||||||
|
if(slist->empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(counter == 0)
|
||||||
|
slist_it = slist->begin();
|
||||||
|
|
||||||
|
if(slist_it == slist->end()) {
|
||||||
|
counter = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
E_ASSERT(counter < slist->size() && "Internal error; 'counter' out of bounds");
|
||||||
|
|
||||||
|
char buff[1024];
|
||||||
|
const char* msg = (*slist_it)->description.c_str();
|
||||||
|
const char* cmd = (*slist_it)->exec.c_str();
|
||||||
|
snprintf(buff, sizeof(buff), _("Starting %s..."), msg);
|
||||||
|
|
||||||
|
printf("%s\n", buff);
|
||||||
|
|
||||||
|
/* run command */
|
||||||
|
if(!dryrun)
|
||||||
|
run_program(cmd, false);
|
||||||
|
|
||||||
|
++slist_it;
|
||||||
|
++counter;
|
||||||
|
return true;
|
||||||
|
}
|
48
evoke/Splash.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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:
|
||||||
|
StartupItemList* slist;
|
||||||
|
StartupItemListIter slist_it;
|
||||||
|
edelib::String* splash_theme;
|
||||||
|
|
||||||
|
unsigned int counter;
|
||||||
|
bool show_splash;
|
||||||
|
bool dryrun;
|
||||||
|
|
||||||
|
Fl_Box* msgbox;
|
||||||
|
Fl_Box** icons;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Splash(StartupItemList& s, edelib::String& theme, bool show_it, bool dr);
|
||||||
|
~Splash();
|
||||||
|
|
||||||
|
bool next_client(void);
|
||||||
|
bool next_client_nosplash(void);
|
||||||
|
|
||||||
|
void run(void);
|
||||||
|
|
||||||
|
#if EDEWM_HAVE_NET_SPLASH
|
||||||
|
virtual void show(void);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
375
evoke/Xsm.cpp
Normal file
@ -0,0 +1,375 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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 <stdio.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <FL/x.H>
|
||||||
|
#include <X11/Xresource.h>
|
||||||
|
|
||||||
|
#include <edelib/Debug.h>
|
||||||
|
#include <edelib/TiXml.h>
|
||||||
|
#include <edelib/Color.h>
|
||||||
|
#include <edelib/String.h>
|
||||||
|
#include <edelib/Util.h>
|
||||||
|
#include <edelib/Directory.h>
|
||||||
|
#include <edelib/XSettingsCommon.h>
|
||||||
|
#include <edelib/File.h>
|
||||||
|
#include <edelib/Resource.h>
|
||||||
|
|
||||||
|
#include "Xsm.h"
|
||||||
|
|
||||||
|
#define USER_XRESOURCE ".Xdefaults"
|
||||||
|
#define USER_XRESOURCE_TMP ".Xdefaults-tmp"
|
||||||
|
#define USER_XRESOURCE_SAVED ".Xdefaults-ede-saved"
|
||||||
|
|
||||||
|
#define SETTINGS_FILENAME "ede-settings"
|
||||||
|
|
||||||
|
EDELIB_NS_USING(String)
|
||||||
|
EDELIB_NS_USING(Resource)
|
||||||
|
EDELIB_NS_USING(XSettingsSetting)
|
||||||
|
EDELIB_NS_USING(XSettingsList)
|
||||||
|
EDELIB_NS_USING(dir_home)
|
||||||
|
EDELIB_NS_USING(file_remove)
|
||||||
|
EDELIB_NS_USING(file_rename)
|
||||||
|
EDELIB_NS_USING(build_filename)
|
||||||
|
EDELIB_NS_USING(user_config_dir)
|
||||||
|
EDELIB_NS_USING(xsettings_list_find)
|
||||||
|
EDELIB_NS_USING(xsettings_list_free)
|
||||||
|
EDELIB_NS_USING(xsettings_decode)
|
||||||
|
EDELIB_NS_USING(color_rgb_to_fltk)
|
||||||
|
EDELIB_NS_USING(color_fltk_to_html)
|
||||||
|
EDELIB_NS_USING(XSETTINGS_TYPE_COLOR)
|
||||||
|
EDELIB_NS_USING(XSETTINGS_TYPE_INT)
|
||||||
|
EDELIB_NS_USING(XSETTINGS_TYPE_STRING)
|
||||||
|
|
||||||
|
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() {
|
||||||
|
E_DEBUG(E_STRLOC ": 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;
|
||||||
|
|
||||||
|
String home = dir_home();
|
||||||
|
|
||||||
|
// try to open ~/.Xdefaults; if failed, X Resource will not complain
|
||||||
|
String db_file = build_filename(home.c_str(), USER_XRESOURCE);
|
||||||
|
|
||||||
|
// initialize XResource manager
|
||||||
|
XrmInitialize();
|
||||||
|
|
||||||
|
// load XResource database
|
||||||
|
XrmDatabase db = XrmGetFileDatabase(db_file.c_str());
|
||||||
|
|
||||||
|
XSettingsSetting* s;
|
||||||
|
int status;
|
||||||
|
char* type, *value;
|
||||||
|
XrmValue xrmv;
|
||||||
|
char color_val[8];
|
||||||
|
|
||||||
|
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 = xsettings_list_find(manager_data->settings, resource_map[i].name);
|
||||||
|
if(!s)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// assure that XSETTINGS key is color type
|
||||||
|
if(s->type != XSETTINGS_TYPE_COLOR) {
|
||||||
|
E_WARNING(E_STRLOC ": 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) {
|
||||||
|
E_DEBUG(E_STRLOC ": %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 = color_rgb_to_fltk(s->data.v_color.red, s->data.v_color.green, s->data.v_color.blue);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
String tmp_db_file = 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());
|
||||||
|
XrmDestroyDatabase(db);
|
||||||
|
|
||||||
|
if(status) {
|
||||||
|
String db_backup = build_filename(home.c_str(), USER_XRESOURCE_SAVED);
|
||||||
|
file_rename(db_file.c_str(), db_backup.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
file_rename(tmp_db_file.c_str(), db_file.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Xsm::xresource_undo(void) {
|
||||||
|
String home, db_file_backup, db_file;
|
||||||
|
|
||||||
|
home = dir_home();
|
||||||
|
db_file_backup = build_filename(home.c_str(), USER_XRESOURCE_SAVED);
|
||||||
|
db_file = 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(!file_rename(db_file_backup.c_str(), db_file.c_str()))
|
||||||
|
file_remove(db_file.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Xsm::load_serialized(void) {
|
||||||
|
#ifdef USE_LOCAL_CONFIG
|
||||||
|
/*
|
||||||
|
* this will load SETTINGS_FILENAME only from local directory;
|
||||||
|
* intended for development and testing only
|
||||||
|
*/
|
||||||
|
String file = SETTINGS_FILENAME".conf";
|
||||||
|
#else
|
||||||
|
/* try to find it in home directory, then will scan for the system one */
|
||||||
|
String file = Resource::find_config("ede/"SETTINGS_FILENAME);
|
||||||
|
if(file.empty()) {
|
||||||
|
E_WARNING(E_STRLOC ": Unable to load XSETTINGS data from '%s'\n", file.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
TiXmlDocument doc(file.c_str());
|
||||||
|
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) {
|
||||||
|
E_WARNING(E_STRLOC ": Got unknown child in 'ede-setting' %s\n", elem->Value());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = elem->ToElement()->Attribute("name");
|
||||||
|
if(!name) {
|
||||||
|
E_WARNING(E_STRLOC ": Missing name key\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = elem->ToElement()->Attribute("type");
|
||||||
|
if(!type) {
|
||||||
|
E_WARNING(E_STRLOC ": 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 {
|
||||||
|
E_WARNING(E_STRLOC ": Unknown type %s\n", type);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(cmp) {
|
||||||
|
case 1:
|
||||||
|
if(elem->ToElement()->QueryIntAttribute("value", &v_int) == TIXML_SUCCESS)
|
||||||
|
set(name, v_int);
|
||||||
|
else
|
||||||
|
E_WARNING(E_STRLOC ": 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(void) {
|
||||||
|
Atom type;
|
||||||
|
int format;
|
||||||
|
unsigned long n_items, bytes_after;
|
||||||
|
unsigned char* data;
|
||||||
|
int result;
|
||||||
|
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)
|
||||||
|
E_WARNING(E_STRLOC ": Invalid type for XSETTINGS property\n");
|
||||||
|
else if(format != 8)
|
||||||
|
E_WARNING(E_STRLOC ": Invalid format for XSETTINGS property\n");
|
||||||
|
else
|
||||||
|
settings = xsettings_decode(data, n_items, NULL);
|
||||||
|
XFree(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!settings)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef USE_LOCAL_CONFIG
|
||||||
|
/*
|
||||||
|
* this will load SETTINGS_FILENAME only from local directory;
|
||||||
|
* intended for development and testing only
|
||||||
|
*/
|
||||||
|
String file = SETTINGS_FILENAME".conf";
|
||||||
|
#else
|
||||||
|
String file = user_config_dir();
|
||||||
|
file += "/ede/"SETTINGS_FILENAME".conf";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FILE* setting_file = fopen(file.c_str(), "w");
|
||||||
|
if(!setting_file) {
|
||||||
|
E_WARNING(E_STRLOC ": Unable to write to %s\n", file.c_str());
|
||||||
|
xsettings_list_free(settings);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(setting_file, "<? xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
|
||||||
|
fprintf(setting_file, "<ede-settings>\n");
|
||||||
|
|
||||||
|
iter = settings;
|
||||||
|
while(iter) {
|
||||||
|
fprintf(setting_file, " <setting name=\"%s\" ", iter->setting->name);
|
||||||
|
switch(iter->setting->type) {
|
||||||
|
case XSETTINGS_TYPE_INT:
|
||||||
|
fprintf(setting_file, "type=\"int\" value=\"%i\" />\n", iter->setting->data.v_int);
|
||||||
|
break;
|
||||||
|
case XSETTINGS_TYPE_STRING:
|
||||||
|
fprintf(setting_file, "type=\"string\" value=\"%s\" />\n", iter->setting->data.v_string);
|
||||||
|
break;
|
||||||
|
case XSETTINGS_TYPE_COLOR:
|
||||||
|
fprintf(setting_file, "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;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(setting_file, "</ede-settings>\n");
|
||||||
|
|
||||||
|
fclose(setting_file);
|
||||||
|
xsettings_list_free(settings);
|
||||||
|
xresource_undo();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
36
evoke/Xsm.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 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(void);
|
||||||
|
bool save_serialized(void);
|
||||||
|
|
||||||
|
/* replace XResource values from one from XSETTINGS */
|
||||||
|
void xresource_replace(void);
|
||||||
|
/* undo old XResource values */
|
||||||
|
void xresource_undo(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
121
evoke/doc/evoke.txt
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
evoke documentation
|
||||||
|
===================
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
.TODO
|
||||||
|
=====================
|
||||||
|
Add info about splash themes; reorder document
|
||||||
|
=====================
|
||||||
|
|
||||||
|
evoke is EDE service responsible for starting and quitting desktop, including
|
||||||
|
all needed prerequisites. Also, it will autostart programs (run programs using
|
||||||
|
http://www.freedesktop.org/wiki/Specifications/autostart-spec[autostart specification])
|
||||||
|
and behave as http://www.freedesktop.org/wiki/Specifications/xsettings-spec[XSETTINGS] manager.
|
||||||
|
|
||||||
|
It is usually started at EDE startup, from '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 'ede-startup.conf' file looking for components 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 useful in startup mode (if '-s' or '--startup' are given). Mainly to test
|
||||||
|
splash screen themes
|
||||||
|
|
||||||
|
-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.
|
||||||
|
|
||||||
|
-h, --help::
|
||||||
|
This help.
|
||||||
|
|
||||||
|
|
||||||
|
Details
|
||||||
|
-------
|
||||||
|
|
||||||
|
evoke can be started with or without options. If started without options, it will behave
|
||||||
|
as XSETTINGS manager, reading options from 'ede-settings.conf'.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
.XSETTINGS support
|
||||||
|
==================================
|
||||||
|
Not all toolkits supports XSETTINGS protocol; currently only Gtk+ and edelib apps understainds
|
||||||
|
it (as I know).
|
||||||
|
==================================
|
||||||
|
|
||||||
|
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 'ede-startup.conf' (or file specified with '-c' option). This configuration file must be in the following form:
|
||||||
|
--------------
|
||||||
|
[Startup]
|
||||||
|
# start_order key is used to notify evoke what to start
|
||||||
|
# and program keys must be separated with comma (if multiple ones are given)
|
||||||
|
start_order = program1, program2, program3
|
||||||
|
|
||||||
|
# splash_data is directory with icons used for splash screen
|
||||||
|
splash_data = /some/path/some_dir_name
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
...
|
||||||
|
--------------
|
19
evoke/ede-settings.conf
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<? 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>
|
24
evoke/ede-startup.conf
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# ede-startup configuration sample
|
||||||
|
[Startup]
|
||||||
|
start_order = edewm,eiconman,eworkpanel,xscreensaver
|
||||||
|
splash_theme = scape
|
||||||
|
|
||||||
|
[edewm]
|
||||||
|
exec = edewm
|
||||||
|
icon = edewm.png
|
||||||
|
description = window manager
|
||||||
|
|
||||||
|
[eiconman]
|
||||||
|
exec = eiconman
|
||||||
|
icon = eiconman.png
|
||||||
|
description = desktop
|
||||||
|
|
||||||
|
[eworkpanel]
|
||||||
|
exec = eworkpanel
|
||||||
|
icon = eworkpanel.png
|
||||||
|
description = panel
|
||||||
|
|
||||||
|
[xscreensaver]
|
||||||
|
exec = xscreensaver -nosplash
|
||||||
|
icon = xscreensaver.png
|
||||||
|
description = screensaver
|
153
evoke/evoke.cpp
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Evoke, head honcho of everything
|
||||||
|
* Part of Equinox Desktop Environment (EDE).
|
||||||
|
* Copyright (c) 2007-2009 EDE Authors.
|
||||||
|
*
|
||||||
|
* This program is licensed under terms of the
|
||||||
|
* GNU General Public License version 2 or newer.
|
||||||
|
* See COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <FL/x.H>
|
||||||
|
|
||||||
|
#include "EvokeService.h"
|
||||||
|
#include "Autostart.h"
|
||||||
|
|
||||||
|
#define FOREVER 1e20
|
||||||
|
#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) {
|
||||||
|
EvokeService::instance()->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int xmessage_handler(int) {
|
||||||
|
return EvokeService::instance()->handle(fl_xevent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void help(void) {
|
||||||
|
puts("Usage: evoke [OPTIONS]");
|
||||||
|
puts("EDE startup manager responsible for desktop starting and quitting");
|
||||||
|
puts("(including various bits and pieces desktop needs)");
|
||||||
|
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\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
bool do_startup = false;
|
||||||
|
bool do_dryrun = false;
|
||||||
|
bool show_splash = true;
|
||||||
|
bool do_autostart = false;
|
||||||
|
bool do_autostart_safe = false;
|
||||||
|
|
||||||
|
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, "-s", "--starup"))
|
||||||
|
do_startup = true;
|
||||||
|
else if(CHECK_ARGV(a, "-d", "--dry-run"))
|
||||||
|
do_dryrun = true;
|
||||||
|
else if(CHECK_ARGV(a, "-n", "--no-splash"))
|
||||||
|
show_splash = false;
|
||||||
|
else if(CHECK_ARGV(a, "-a", "--autostart"))
|
||||||
|
do_autostart = true;
|
||||||
|
else if(CHECK_ARGV(a, "-u", "--autostart-safe"))
|
||||||
|
do_autostart_safe = true;
|
||||||
|
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();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Main loop is not initialized before startup (and splash) are finished;
|
||||||
|
* this is intentional so we could use 'dryrun' to test a splash theme and startup items
|
||||||
|
* without interfering with already running evoke instance (and getting lock error)
|
||||||
|
*
|
||||||
|
* TODO: dryrun option is pretty dummy; better to use "test-splash" or similar
|
||||||
|
*/
|
||||||
|
if(do_startup) {
|
||||||
|
service->read_startup();
|
||||||
|
service->run_startup(show_splash, do_dryrun);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* only testing, quit nicely */
|
||||||
|
if(do_dryrun)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(!service->setup_lock(LOCK_FILE)) {
|
||||||
|
printf("Either another evoke instance is running or I can't create lock file\n");
|
||||||
|
printf("If program abnormaly crashed before, just remove '%s' and start it again\n", LOCK_FILE);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(do_autostart || do_autostart_safe)
|
||||||
|
perform_autostart(do_autostart_safe);
|
||||||
|
|
||||||
|
service->start_xsettings_manager();
|
||||||
|
|
||||||
|
/* set stuff so xsettings manager can receive events */
|
||||||
|
XSelectInput(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
PropertyChangeMask | SubstructureNotifyMask | ClientMessage);
|
||||||
|
Fl::add_handler(xmessage_handler);
|
||||||
|
|
||||||
|
service->start();
|
||||||
|
|
||||||
|
while(service->running()) {
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
|
||||||
|
Fl::wait(FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
33
evoke/fl/autostart.fl
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
evoke/fl/logout.fl
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# 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}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
319
evoke/icons/warning.xpm
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
/* 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+#@$@%@%@%@+ + &@ ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" ",
|
||||||
|
" "};
|
14
evoke/splash-themes/Jamfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# Part of Equinox Desktop Environment (EDE).
|
||||||
|
# Copyright (c) 2009 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 splash-themes ;
|
||||||
|
|
||||||
|
SubInclude TOP evoke splash-themes scape ;
|
||||||
|
SubInclude TOP evoke splash-themes standard ;
|
14
evoke/splash-themes/scape/Jamfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# Part of Equinox Desktop Environment (EDE).
|
||||||
|
# Copyright (c) 2009 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 splash-themes scape ;
|
||||||
|
|
||||||
|
DATA = background.png background.xcf edewm.png eiconman.png eworkpanel.png xscreensaver.png ;
|
||||||
|
InstallData $(datarootdir)/splash-themes/scape : $(DATA) ;
|
BIN
evoke/splash-themes/scape/background.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
evoke/splash-themes/scape/background.xcf
Normal file
BIN
evoke/splash-themes/scape/edewm.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
evoke/splash-themes/scape/eiconman.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
evoke/splash-themes/scape/eworkpanel.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
evoke/splash-themes/scape/xscreensaver.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
14
evoke/splash-themes/standard/Jamfile
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#
|
||||||
|
# $Id$
|
||||||
|
#
|
||||||
|
# Part of Equinox Desktop Environment (EDE).
|
||||||
|
# Copyright (c) 2009 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 splash-themes standard ;
|
||||||
|
|
||||||
|
DATA = background.png edewm.png eiconman.png eworkpanel.png xscreensaver.png ;
|
||||||
|
InstallData $(datarootdir)/splash-themes/standard : $(DATA) ;
|
BIN
evoke/splash-themes/standard/background.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
evoke/splash-themes/standard/edewm.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
evoke/splash-themes/standard/eiconman.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
evoke/splash-themes/standard/eworkpanel.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
evoke/splash-themes/standard/xscreensaver.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
63
evoke/test/evoke_test.cpp
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <FL/Fl.H>
|
||||||
|
#include <FL/Fl_Double_Window.H>
|
||||||
|
#include <FL/Fl_Input.H>
|
||||||
|
#include <FL/Fl_Button.H>
|
||||||
|
#include <FL/x.H>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Fl_Input* inp;
|
||||||
|
Fl_Double_Window* win;
|
||||||
|
|
||||||
|
void run_cb(Fl_Widget*, void*) {
|
||||||
|
Atom _XA_EDE_EVOKE_SPAWN = XInternAtom(fl_display, "_EDE_EVOKE_SPAWN", False);
|
||||||
|
// max size
|
||||||
|
unsigned char txt_send[8192];
|
||||||
|
int i;
|
||||||
|
const char* txt_val = inp->value() ? inp->value() : "(none)";
|
||||||
|
int len = strlen(txt_val);
|
||||||
|
|
||||||
|
for(i = 0; i < 8192-2 && i < len; i++)
|
||||||
|
txt_send[i] = txt_val[i];
|
||||||
|
|
||||||
|
txt_send[i] = '\0';
|
||||||
|
|
||||||
|
// send text
|
||||||
|
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
_XA_EDE_EVOKE_SPAWN, XA_STRING, 8, PropModeReplace,
|
||||||
|
txt_send, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void evoke_quit_cb(Fl_Widget*, void*) {
|
||||||
|
Atom _XA_EDE_EVOKE_QUIT = XInternAtom(fl_display, "_EDE_EVOKE_QUIT", False);
|
||||||
|
|
||||||
|
int dummy = 1;
|
||||||
|
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
_XA_EDE_EVOKE_QUIT, XA_CARDINAL, 32, PropModeReplace,
|
||||||
|
(unsigned char*)&dummy, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
void quit_all_cb(Fl_Widget*, void*) {
|
||||||
|
Atom _XA_EDE_EVOKE_SHUTDOWN_ALL = XInternAtom(fl_display, "_EDE_EVOKE_SHUTDOWN_ALL", False);
|
||||||
|
|
||||||
|
int dummy = 1;
|
||||||
|
XChangeProperty(fl_display, RootWindow(fl_display, fl_screen),
|
||||||
|
_XA_EDE_EVOKE_SHUTDOWN_ALL, XA_CARDINAL, 32, PropModeReplace,
|
||||||
|
(unsigned char*)&dummy, sizeof(int));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
win = new Fl_Double_Window(355, 94, "Evoke test");
|
||||||
|
win->begin();
|
||||||
|
inp = new Fl_Input(10, 25, 335, 25, "Program to run:");
|
||||||
|
inp->align(FL_ALIGN_TOP_LEFT);
|
||||||
|
Fl_Button* b1 = new Fl_Button(255, 60, 90, 25, "&Run");
|
||||||
|
b1->callback(run_cb);
|
||||||
|
Fl_Button* b2 = new Fl_Button(150, 60, 90, 25, "&Quit evoke");
|
||||||
|
b2->callback(evoke_quit_cb);
|
||||||
|
Fl_Button* b3 = new Fl_Button(55, 60, 90, 25, "&Quit all");
|
||||||
|
b3->callback(quit_all_cb);
|
||||||
|
win->end();
|
||||||
|
win->show(argc, argv);
|
||||||
|
return Fl::run();
|
||||||
|
}
|
28
evoke/test/evoke_test.fl
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# data file for the Fltk User Interface Designer (fluid)
|
||||||
|
version 1.0108
|
||||||
|
header_name {.h}
|
||||||
|
code_name {.cxx}
|
||||||
|
Function {} {open
|
||||||
|
} {
|
||||||
|
Fl_Window {} {
|
||||||
|
label {Evoke test} open
|
||||||
|
xywh {493 478 355 94} type Double visible
|
||||||
|
} {
|
||||||
|
Fl_Input {} {
|
||||||
|
label {Program to run:} selected
|
||||||
|
xywh {10 25 335 25} labelsize 14 align 5 textsize 14
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label {&Run}
|
||||||
|
xywh {255 60 90 25} labelsize 14
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label {&Quit evoke}
|
||||||
|
xywh {150 60 90 25} labelsize 14
|
||||||
|
}
|
||||||
|
Fl_Button {} {
|
||||||
|
label {&Quit all}
|
||||||
|
xywh {55 60 90 25} labelsize 14
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|