diff --git a/evoke/Autostart.cpp b/evoke/Autostart.cpp new file mode 100644 index 0000000..c57190f --- /dev/null +++ b/evoke/Autostart.cpp @@ -0,0 +1,71 @@ +/* + * $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 +#include +#include + +Fl_Pixmap warnpix(warning_xpm); + +void closeit_cb(Fl_Widget*, void* w) { + AstartDialog* win = (AstartDialog*)w; + win->hide(); +} + +AstartDialog::AstartDialog(unsigned int sz) : Fl_Window(370, 305, _("Autostart warning")), + curr(0), lst_sz(sz), lst(0) { + + if(lst_sz) + lst = new AstartItem[lst_sz]; + + 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); + run_sel = new Fl_Button(45, 270, 125, 25, _("Run &selected")); + run_all = new Fl_Button(175, 270, 90, 25, _("&Run all")); + 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; + AstartItem it; + it.name = n; + it.exec = e; + + lst[curr++] = it; +} + +void AstartDialog::run(void) { + for(unsigned int i = 0; i < curr; i++) + cbrowser->add(lst[i].name.c_str()); + + if(!shown()) + show(); + + while(shown()) + Fl::wait(); +} diff --git a/evoke/Autostart.h b/evoke/Autostart.h new file mode 100644 index 0000000..6300240 --- /dev/null +++ b/evoke/Autostart.h @@ -0,0 +1,50 @@ +/* + * $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 +#include +#include +#include + +#include + +struct AstartItem { + edelib::String name; + edelib::String exec; +}; + +class AstartDialog : public Fl_Window { + private: + unsigned int curr; + unsigned int lst_sz; + AstartItem* lst; + + Fl_Box* img; + Fl_Box* txt; + Fl_Check_Browser* cbrowser; + Fl_Button* run_sel; + Fl_Button* run_all; + Fl_Button* cancel; + + public: + AstartDialog(unsigned int sz); + ~AstartDialog(); + + unsigned int list_size(void) { return curr; } + void add_item(const edelib::String& n, const edelib::String& e); + void run(void); +}; + +#endif diff --git a/evoke/EvokeService.cpp b/evoke/EvokeService.cpp index bba8bc1..98c8bce 100644 --- a/evoke/EvokeService.cpp +++ b/evoke/EvokeService.cpp @@ -16,6 +16,7 @@ #include "Splash.h" #include "Spawn.h" #include "Crash.h" +#include "Autostart.h" #include #include @@ -24,10 +25,9 @@ #include #include #include +#include #include -#include - #include // getpid #include // #include // free @@ -50,6 +50,50 @@ void resolve_path(const edelib::String& imgdir, edelib::String& img, bool have_i } } +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 ? + */ +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(); + } + } +} + int get_int_property_value(Atom at) { Atom real; int format; @@ -249,9 +293,75 @@ bool EvokeService::init_splash(const char* config, bool no_splash, bool dry_run) * TryExec is same as for .desktop spec. */ void EvokeService::init_autostart(void) { - edelib::String home = edelib::user_config_dir(); - home += "/autostart/"; - // TODO + edelib::String adir = edelib::user_config_dir(); + adir += "/autostart/"; + + StringList dfiles, sysdirs; + StringListIter it, 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/"; + + // append content + edelib::dir_list((*it).c_str(), dfiles, true, false, false); + } + } + + 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()); + + 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::setup_atoms(Display* d) { @@ -263,7 +373,7 @@ void EvokeService::setup_atoms(Display* d) { } void EvokeService::quit_x11(void) { - int ret = fl_ask(_("Nice quitting is not implemented yet and this will forcefully kill\nall running applications. Make sure to save what needs to be saved.\nSo, would you like to continue ?")); + int ret = edelib::ask(_("Nice quitting is not implemented yet and this will forcefully kill\nall running applications. Make sure to save what needs to be saved.\nSo, would you like to continue ?")); if(ret) stop(); #if 0 @@ -362,7 +472,7 @@ void EvokeService::run_program(const char* cmd) { int r = spawn_program_with_core(cmd, service_watcher_cb, &child); if(r != 0) - fl_alert("Unable to start %s. Got code %i", cmd, r); + edelib::alert("Unable to start %s. Got code %i", cmd, r); else register_process(cmd, child); } diff --git a/evoke/Jamfile b/evoke/Jamfile index 35202da..8bec22a 100644 --- a/evoke/Jamfile +++ b/evoke/Jamfile @@ -10,7 +10,7 @@ SubDir TOP evoke ; -SOURCE = evoke.cpp EvokeService.cpp Spawn.cpp Splash.cpp Log.cpp Logout.cpp Crash.cpp ; +SOURCE = evoke.cpp EvokeService.cpp Spawn.cpp Splash.cpp Log.cpp Logout.cpp Crash.cpp Autostart.cpp ; EdeProgram evoke : $(SOURCE) ; FltkProgramBare test/evoke_test : test/evoke_test.cpp ; diff --git a/evoke/fl/autostart.fl b/evoke/fl/autostart.fl new file mode 100644 index 0000000..dee328e --- /dev/null +++ b/evoke/fl/autostart.fl @@ -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 + } + } +} diff --git a/evoke/icons/warning.xpm b/evoke/icons/warning.xpm new file mode 100644 index 0000000..447467b --- /dev/null +++ b/evoke/icons/warning.xpm @@ -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+#@$@%@%@%@+ + &@ ", +" ", +" ", +" ", +" "};