mirror of
https://github.com/edeproject/ede.git
synced 2023-08-10 21:13:03 +03:00
Improved launch tool with preferred applications support.
This commit is contained in:
parent
f0acacfd89
commit
c0f1ca1c44
@ -44,42 +44,27 @@
|
|||||||
#include <edelib/WindowUtils.h>
|
#include <edelib/WindowUtils.h>
|
||||||
#include <edelib/DesktopFile.h>
|
#include <edelib/DesktopFile.h>
|
||||||
#include <edelib/StrUtil.h>
|
#include <edelib/StrUtil.h>
|
||||||
|
#include <edelib/Debug.h>
|
||||||
#include <edelib/Ede.h>
|
#include <edelib/Ede.h>
|
||||||
#include "StartupNotify.h"
|
#include "StartupNotify.h"
|
||||||
|
|
||||||
#include "icons/run.xpm"
|
#include "icons/run.xpm"
|
||||||
|
|
||||||
/*
|
/* so value could be directed returned to shell */
|
||||||
* Window from X11 is alread included with Fl.H so we can't use EDELIB_NS_USING(Window) here.
|
#define RETURN_FROM_BOOL(v) (v != false)
|
||||||
* Stupid C++ namespaces
|
|
||||||
*/
|
|
||||||
#define LaunchWindow edelib::Window
|
|
||||||
|
|
||||||
EDELIB_NS_USING(Resource)
|
/* config name where all things are stored and read from */
|
||||||
EDELIB_NS_USING(String)
|
#define EDE_LAUNCH_CONFIG "ede-launch"
|
||||||
EDELIB_NS_USING(DesktopFile)
|
|
||||||
EDELIB_NS_USING(RES_USER_ONLY)
|
EDELIB_NS_USING_LIST(11, (Resource, String, DesktopFile, RES_USER_ONLY, DESK_FILE_TYPE_APPLICATION, run_sync, run_async, alert, file_path, window_center_on_screen, str_ends))
|
||||||
EDELIB_NS_USING(DESK_FILE_TYPE_APPLICATION)
|
EDELIB_NS_USING_AS(Window, LaunchWindow)
|
||||||
EDELIB_NS_USING(run_sync)
|
|
||||||
EDELIB_NS_USING(run_async)
|
|
||||||
EDELIB_NS_USING(alert)
|
|
||||||
EDELIB_NS_USING(file_path)
|
|
||||||
EDELIB_NS_USING(window_center_on_screen)
|
|
||||||
EDELIB_NS_USING(str_ends)
|
|
||||||
|
|
||||||
static Fl_Pixmap image_run((const char**)run_xpm);
|
static Fl_Pixmap image_run((const char**)run_xpm);
|
||||||
static Fl_Input* dialog_input;
|
static Fl_Input* dialog_input;
|
||||||
static Fl_Check_Button* in_term;
|
static Fl_Check_Button* in_term;
|
||||||
static const char *launch_type[] = {
|
|
||||||
"browser",
|
|
||||||
"mail",
|
|
||||||
"terminal",
|
|
||||||
"file_manager",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
static void help(void) {
|
static void help(void) {
|
||||||
puts("Usage: ede-launch [OPTIONS] [URLs...]");
|
puts("Usage: ede-launch [OPTIONS] [PROGRAM]");
|
||||||
puts("EDE program launcher");
|
puts("EDE program launcher");
|
||||||
puts("Options:");
|
puts("Options:");
|
||||||
puts(" -h, --help show this help");
|
puts(" -h, --help show this help");
|
||||||
@ -94,6 +79,7 @@ static void help(void) {
|
|||||||
puts("Example:");
|
puts("Example:");
|
||||||
puts(" ede-launch --launch browser http://www.foo.com");
|
puts(" ede-launch --launch browser http://www.foo.com");
|
||||||
puts(" ede-launch gvim");
|
puts(" ede-launch gvim");
|
||||||
|
puts(" ede-launch ~/Desktop/foo.desktop");
|
||||||
}
|
}
|
||||||
|
|
||||||
static char* get_basename(const char* path) {
|
static char* get_basename(const char* path) {
|
||||||
@ -125,13 +111,33 @@ static char** cmd_split(const char* cmd) {
|
|||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool allowed_launch_type(const char *t) {
|
||||||
|
E_RETURN_VAL_IF_FAIL(t != 0, false);
|
||||||
|
|
||||||
|
/* should be synced with keys from ede-preferred-applications */
|
||||||
|
static const char *launch_types[] = {
|
||||||
|
"browser",
|
||||||
|
"mail",
|
||||||
|
"terminal",
|
||||||
|
"file_manager",
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int i = 0; launch_types[i]; i++) {
|
||||||
|
/* we do not allow >= 64 chars from user input */
|
||||||
|
if(strncmp(t, launch_types[i], 64) == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void start_crasher(const char* cmd, int sig) {
|
static void start_crasher(const char* cmd, int sig) {
|
||||||
const char* base = get_basename(cmd);
|
const char* base = get_basename(cmd);
|
||||||
const char* ede_app_flag = "";
|
const char* ede_app_flag = "";
|
||||||
|
|
||||||
/* this means the app was called without full path */
|
/* this means the app was called without full path */
|
||||||
if(!base)
|
if(!base) base = cmd;
|
||||||
base = cmd;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* determine is our app by checking the prefix; we don't want user to send bug reports about crashes
|
* determine is our app by checking the prefix; we don't want user to send bug reports about crashes
|
||||||
@ -141,7 +147,7 @@ static void start_crasher(const char* cmd, int sig) {
|
|||||||
ede_app_flag = "--edeapp";
|
ede_app_flag = "--edeapp";
|
||||||
|
|
||||||
/* call edelib implementation instead start_child_process() to prevents loops if 'ede-crasher' crashes */
|
/* call edelib implementation instead start_child_process() to prevents loops if 'ede-crasher' crashes */
|
||||||
run_sync("ede-crasher %s --appname %s --apppath %s --signal %i", ede_app_flag, base, cmd, sig);
|
run_sync(PREFIX "/bin/ede-crasher %s --appname %s --apppath %s --signal %i", ede_app_flag, base, cmd, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int start_child_process(const char* cmd) {
|
static int start_child_process(const char* cmd) {
|
||||||
@ -288,7 +294,7 @@ static bool start_desktop_file(const char *cmd) {
|
|||||||
DesktopFile d;
|
DesktopFile d;
|
||||||
|
|
||||||
if(!d.load(cmd)) {
|
if(!d.load(cmd)) {
|
||||||
alert(d.strerror());
|
alert(_("Unable to load .desktop file '%s'. Got: %s"), cmd, d.strerror());
|
||||||
goto FAIL;
|
goto FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,15 +304,58 @@ static bool start_desktop_file(const char *cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char buf[PATH_MAX];
|
char buf[PATH_MAX];
|
||||||
if(d.exec(buf, PATH_MAX))
|
if(d.exec(buf, PATH_MAX)) {
|
||||||
return start_child_process(buf);
|
|
||||||
else
|
|
||||||
alert(_("Unable to run '%s'.\nProbably this file is malformed or 'Exec' key has non-installed program"), cmd);
|
alert(_("Unable to run '%s'.\nProbably this file is malformed or 'Exec' key has non-installed program"), cmd);
|
||||||
|
goto FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return start_child(buf);
|
||||||
|
|
||||||
FAIL:
|
FAIL:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* concat all arguments preparing it for start_child() */
|
||||||
|
static void join_args(int start, int argc, char **argv, const char *program, String &ret) {
|
||||||
|
String args;
|
||||||
|
unsigned int alen;
|
||||||
|
|
||||||
|
/* append program if given */
|
||||||
|
if(program) {
|
||||||
|
args = program;
|
||||||
|
args += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = start; i < argc; i++) {
|
||||||
|
args += argv[i];
|
||||||
|
args += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
alen = args.length();
|
||||||
|
|
||||||
|
/* remove start/ending quotes and spaces */
|
||||||
|
if((args[0] == '"') || isspace(args[0]) || (args[alen - 1] == '"') || isspace(args[alen - 1])) {
|
||||||
|
int i;
|
||||||
|
char *copy = strdup(args.c_str());
|
||||||
|
char *ptr = copy;
|
||||||
|
|
||||||
|
/* remove ending first */
|
||||||
|
for(i = (int)alen - 1; i > 0 && (ptr[i] == '"' || isspace(ptr[i])); i--)
|
||||||
|
;
|
||||||
|
|
||||||
|
ptr[i + 1] = 0;
|
||||||
|
|
||||||
|
/* remove then starting */
|
||||||
|
for(; *ptr && (*ptr == '"' || isspace(*ptr)); ptr++)
|
||||||
|
;
|
||||||
|
|
||||||
|
ret = copy;
|
||||||
|
free(copy);
|
||||||
|
} else {
|
||||||
|
ret = args;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void cancel_cb(Fl_Widget*, void* w) {
|
static void cancel_cb(Fl_Widget*, void* w) {
|
||||||
LaunchWindow* win = (LaunchWindow*)w;
|
LaunchWindow* win = (LaunchWindow*)w;
|
||||||
win->hide();
|
win->hide();
|
||||||
@ -321,6 +370,16 @@ do { \
|
|||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static bool find_terminal(String &ret) {
|
static bool find_terminal(String &ret) {
|
||||||
|
/* before goint to list, try to read it from config file */
|
||||||
|
Resource rc;
|
||||||
|
if(rc.load(EDE_LAUNCH_CONFIG)) {
|
||||||
|
char buf[64];
|
||||||
|
if(rc.get("Preferred", "terminal", buf, sizeof(buf))) {
|
||||||
|
ret = buf;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* list of known terminals */
|
/* list of known terminals */
|
||||||
static const char *terms[] = {
|
static const char *terms[] = {
|
||||||
"xterm",
|
"xterm",
|
||||||
@ -379,8 +438,10 @@ static void ok_cb(Fl_Widget*, void* w) {
|
|||||||
dialog_input->position(0, dialog_input->size());
|
dialog_input->position(0, dialog_input->size());
|
||||||
} else {
|
} else {
|
||||||
Resource rc;
|
Resource rc;
|
||||||
|
/* so could load previous content */
|
||||||
|
rc.load(EDE_LAUNCH_CONFIG);
|
||||||
rc.set("History", "open", cmd);
|
rc.set("History", "open", cmd);
|
||||||
rc.save("ede-launch-history");
|
rc.save(EDE_LAUNCH_CONFIG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -398,7 +459,7 @@ static int start_dialog(int argc, char** argv) {
|
|||||||
Resource rc;
|
Resource rc;
|
||||||
char buf[128];
|
char buf[128];
|
||||||
|
|
||||||
if(rc.load("ede-launch-history") && rc.get("History", "open", buf, sizeof(buf))) {
|
if(rc.load(EDE_LAUNCH_CONFIG) && rc.get("History", "open", buf, sizeof(buf))) {
|
||||||
dialog_input->value(buf);
|
dialog_input->value(buf);
|
||||||
|
|
||||||
/* make text appear selected */
|
/* make text appear selected */
|
||||||
@ -414,61 +475,109 @@ static int start_dialog(int argc, char** argv) {
|
|||||||
cancel->callback(cancel_cb, win);
|
cancel->callback(cancel_cb, win);
|
||||||
win->end();
|
win->end();
|
||||||
win->window_icon(run_xpm);
|
win->window_icon(run_xpm);
|
||||||
|
|
||||||
window_center_on_screen(win);
|
window_center_on_screen(win);
|
||||||
win->show(argc, argv);
|
win->show(argc, argv);
|
||||||
|
|
||||||
return Fl::run();
|
return Fl::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK_ARGV(argv, pshort, plong) ((strcmp(argv, pshort) == 0) || (strcmp(argv, plong) == 0))
|
||||||
|
|
||||||
|
static const char* next_param(int curr, char **argv, int argc) {
|
||||||
|
int j = curr + 1;
|
||||||
|
if(j >= argc)
|
||||||
|
return NULL;
|
||||||
|
if(argv[j][0] == '-')
|
||||||
|
return NULL;
|
||||||
|
return argv[j];
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
EDE_APPLICATION("ede-launch");
|
EDE_APPLICATION("ede-launch");
|
||||||
|
|
||||||
|
/* start dialog if we have nothing */
|
||||||
if(argc <= 1)
|
if(argc <= 1)
|
||||||
return start_dialog(argc, argv);
|
return start_dialog(argc, argv);
|
||||||
|
|
||||||
/* do not see possible flags as commands */
|
int ca = 1; /* current argument index */
|
||||||
if(argv[1][0] == '-') {
|
const char *cwd, *launch_type;
|
||||||
|
cwd = launch_type = 0;
|
||||||
|
|
||||||
|
/* parse args and stop as soon as detected first non-parameter value (not counting parameter values) */
|
||||||
|
for(; ca < argc; ca++) {
|
||||||
|
if(argv[ca][0] != '-') break;
|
||||||
|
|
||||||
|
if(CHECK_ARGV(argv[ca], "-h", "--help")) {
|
||||||
help();
|
help();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(CHECK_ARGV(argv[ca], "-l", "--launch")) {
|
||||||
|
launch_type = next_param(ca, argv, argc);
|
||||||
|
if(!launch_type) {
|
||||||
|
puts("Missing lauch type. Run program with '-h' to see options");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!allowed_launch_type(launch_type)) {
|
||||||
|
puts("This is not allowed launch type. Run program with '-h' to see options");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ca++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(CHECK_ARGV(argv[ca], "-w", "--working-dir")) {
|
||||||
|
cwd = next_param(ca, argv, argc);
|
||||||
|
if(!cwd) {
|
||||||
|
puts("Missing working directory parameter. Run program with '-h' to see options");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ca++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Bad parameter '%s'. Run program with '-h' to see options\n", argv[ca]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure we have something to run */
|
||||||
|
if(!argv[ca]) {
|
||||||
|
puts("Missing execution parameter(s). Run program with '-h' to see options");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* setup working dir */
|
||||||
|
if(cwd) {
|
||||||
|
errno = 0;
|
||||||
|
if(chdir(cwd) != 0) {
|
||||||
|
alert(_("Unable to change directory to '%s'. Got '%s' (%i)"), cwd, strerror(errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* check if we have .desktop file */
|
/* check if we have .desktop file */
|
||||||
if(argc == 2 && str_ends(argv[1], ".desktop")) {
|
if(str_ends(argv[ca], ".desktop"))
|
||||||
start_desktop_file(argv[1]);
|
return RETURN_FROM_BOOL(start_desktop_file(argv[ca]));
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/* make arguments and exec program */
|
||||||
String args;
|
String args;
|
||||||
unsigned int alen;
|
if(launch_type) {
|
||||||
|
Resource rc;
|
||||||
|
char buf[64];
|
||||||
|
|
||||||
for(int i = 1; i < argc; i++) {
|
if(!rc.load(EDE_LAUNCH_CONFIG) || !rc.get("Preferred", launch_type, buf, sizeof(buf))) {
|
||||||
args += argv[i];
|
E_WARNING("Unable to find out launch type. Balling out...\n");
|
||||||
args += ' ';
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
alen = args.length();
|
join_args(ca, argc, argv, buf, args);
|
||||||
|
|
||||||
/* remove start/ending quotes and spaces */
|
|
||||||
if((args[0] == '"') || isspace(args[0]) || (args[alen - 1] == '"') || isspace(args[alen - 1])) {
|
|
||||||
int i;
|
|
||||||
char *copy = strdup(args.c_str());
|
|
||||||
char *ptr = copy;
|
|
||||||
|
|
||||||
/* remove ending first */
|
|
||||||
for(i = (int)alen - 1; i > 0 && (ptr[i] == '"' || isspace(ptr[i])); i--)
|
|
||||||
;
|
|
||||||
|
|
||||||
ptr[i + 1] = 0;
|
|
||||||
|
|
||||||
/* remove then starting */
|
|
||||||
for(; *ptr && (*ptr == '"' || isspace(*ptr)); ptr++)
|
|
||||||
;
|
|
||||||
|
|
||||||
start_child(ptr);
|
|
||||||
free(copy);
|
|
||||||
} else {
|
} else {
|
||||||
start_child(args.c_str());
|
join_args(ca, argc, argv, 0, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return RETURN_FROM_BOOL(start_child(args.c_str()));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user