Launcher: Add support for Terminal=true

This commit is contained in:
o9000 2017-09-02 10:53:20 +02:00
parent eb93af3622
commit 14c3824632
12 changed files with 105 additions and 30 deletions

View file

@ -464,5 +464,5 @@ void battery_action(void *obj, int button, int x, int y, Time time)
command = battery_dwheel_command;
break;
}
tint_exec(command, NULL, NULL, time, obj, x, y);
tint_exec(command, NULL, NULL, time, obj, x, y, FALSE, TRUE);
}

View file

@ -530,7 +530,7 @@ void button_action(void *obj, int mouse_button, int x, int y, Time time)
command = button->backend->dwheel_command;
break;
}
tint_exec(command, NULL, NULL, time, obj, x, y);
tint_exec(command, NULL, NULL, time, obj, x, y, FALSE, TRUE);
}
char *button_get_tooltip(void *obj)

View file

@ -353,5 +353,5 @@ void clock_action(void *obj, int button, int x, int y, Time time)
command = clock_dwheel_command;
break;
}
tint_exec(command, NULL, NULL, time, obj, x, y);
tint_exec(command, NULL, NULL, time, obj, x, y, FALSE, TRUE);
}

View file

@ -30,7 +30,7 @@ static int dnd_version;
static Atom dnd_selection;
static Atom dnd_atom;
static int dnd_sent_request;
static char *dnd_launcher_exec;
static LauncherIcon *dnd_launcher_icon;
static gboolean dnd_debug = FALSE;
gboolean hidden_panel_shown_for_dnd;
@ -43,7 +43,7 @@ void dnd_init()
dnd_selection = XInternAtom(server.display, "PRIMARY", 0);
dnd_atom = None;
dnd_sent_request = 0;
dnd_launcher_exec = 0;
dnd_launcher_icon = NULL;
hidden_panel_shown_for_dnd = FALSE;
}
@ -62,9 +62,21 @@ void handle_dnd_enter(XClientMessageEvent *e)
__LINE__,
more_than_3 ? "yes" : "no");
fprintf(stderr, "tint2: DnD %s:%d: Protocol version = %d\n", __FILE__, __LINE__, dnd_version);
fprintf(stderr, "tint2: DnD %s:%d: Type 1 = %s\n", __FILE__, __LINE__, GetAtomName(server.display, e->data.l[2]));
fprintf(stderr, "tint2: DnD %s:%d: Type 2 = %s\n", __FILE__, __LINE__, GetAtomName(server.display, e->data.l[3]));
fprintf(stderr, "tint2: DnD %s:%d: Type 3 = %s\n", __FILE__, __LINE__, GetAtomName(server.display, e->data.l[4]));
fprintf(stderr,
"tint2: DnD %s:%d: Type 1 = %s\n",
__FILE__,
__LINE__,
GetAtomName(server.display, e->data.l[2]));
fprintf(stderr,
"tint2: DnD %s:%d: Type 2 = %s\n",
__FILE__,
__LINE__,
GetAtomName(server.display, e->data.l[3]));
fprintf(stderr,
"tint2: DnD %s:%d: Type 3 = %s\n",
__FILE__,
__LINE__,
GetAtomName(server.display, e->data.l[4]));
}
// Query which conversions are available and pick the best
@ -80,7 +92,11 @@ void handle_dnd_enter(XClientMessageEvent *e)
}
if (dnd_debug)
fprintf(stderr, "tint2: DnD %s:%d: Requested type = %s\n", __FILE__, __LINE__, GetAtomName(server.display, dnd_atom));
fprintf(stderr,
"tint2: DnD %s:%d: Requested type = %s\n",
__FILE__,
__LINE__,
GetAtomName(server.display, dnd_atom));
}
void handle_dnd_position(XClientMessageEvent *e)
@ -102,9 +118,9 @@ void handle_dnd_position(XClientMessageEvent *e)
LauncherIcon *icon = click_launcher_icon(panel, mapX, mapY);
if (icon) {
accept = 1;
dnd_launcher_exec = icon->cmd;
dnd_launcher_icon = icon;
} else {
dnd_launcher_exec = 0;
dnd_launcher_icon = NULL;
}
}
@ -129,7 +145,7 @@ void handle_dnd_position(XClientMessageEvent *e)
void handle_dnd_drop(XClientMessageEvent *e)
{
if (dnd_target_window && dnd_launcher_exec) {
if (dnd_target_window && dnd_launcher_icon) {
if (dnd_version >= 1) {
XConvertSelection(server.display,
server.atom.XdndSelection,
@ -173,7 +189,11 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
__FILE__,
__LINE__,
GetAtomName(server.display, e->selection));
fprintf(stderr, "tint2: DnD %s:%d: Target atom = %s\n", __FILE__, __LINE__, GetAtomName(server.display, target));
fprintf(stderr,
"tint2: DnD %s:%d: Target atom = %s\n",
__FILE__,
__LINE__,
GetAtomName(server.display, target));
fprintf(stderr,
"DnD %s:%d: Property atom = %s\n",
__FILE__,
@ -181,7 +201,7 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
GetAtomName(server.display, e->property));
}
if (e->property != None && dnd_launcher_exec) {
if (e->property != None && dnd_launcher_icon) {
Property prop = read_property(server.display, dnd_target_window, dnd_selection);
// If we're being given a list of targets (possible conversions)
@ -213,10 +233,12 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
fprintf(stderr, "tint2: --------\n");
}
// TODO replace this with exec*(...)
int cmd_length = 0;
cmd_length += 1; // (
cmd_length += strlen(dnd_launcher_exec) + 1; // exec + space
cmd_length += 1; // open double quotes
cmd_length += 1; // (
cmd_length += strlen(dnd_launcher_icon->cmd) + 1; // exec + space
cmd_length += 1; // open double quotes
for (int i = 0; i < prop.nitems * prop.format / 8; i++) {
char c = ((char *)prop.data)[i];
if (c == '\n') {
@ -239,7 +261,7 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
char *cmd = (char *)calloc(cmd_length, 1);
cmd[0] = '\0';
strcat(cmd, "(");
strcat(cmd, dnd_launcher_exec);
strcat(cmd, dnd_launcher_icon->cmd);
strcat(cmd, " \"");
for (int i = 0; i < prop.nitems * prop.format / 8; i++) {
char c = ((char *)prop.data)[i];
@ -263,7 +285,15 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
strcat(cmd, "&)");
if (dnd_debug)
fprintf(stderr, "tint2: DnD %s:%d: Running command: %s\n", __FILE__, __LINE__, cmd);
tint_exec(cmd, NULL, NULL, e->time, NULL, 0, 0);
tint_exec(cmd,
NULL,
NULL,
e->time,
NULL,
0,
0,
dnd_launcher_icon->start_in_terminal,
dnd_launcher_icon->startup_notification);
free(cmd);
// Reply OK.

View file

@ -577,7 +577,7 @@ void execp_action(void *obj, int button, int x, int y, Time time)
setenvd("EXECP_Y", y);
setenvd("EXECP_W", execp->area.width);
setenvd("EXECP_H", execp->area.height);
pid_t pid = tint_exec(command, NULL, NULL, time, obj, x, y);
pid_t pid = tint_exec(command, NULL, NULL, time, obj, x, y, FALSE, TRUE);
unsetenv("EXECP_X");
unsetenv("EXECP_Y");
unsetenv("EXECP_W");

View file

@ -113,6 +113,8 @@ gboolean read_desktop_file_full_path(const char *path, DesktopEntry *entry)
{
entry->name = entry->generic_name = entry->icon = entry->exec = entry->cwd = NULL;
entry->hidden_from_menus = FALSE;
entry->start_in_terminal = FALSE;
entry->startup_notification = TRUE;
FILE *fp = fopen(path, "rt");
if (fp == NULL) {
@ -192,6 +194,10 @@ gboolean read_desktop_file_full_path(const char *path, DesktopEntry *entry)
entry->icon = strdup(value);
} else if (strcmp(key, "NoDisplay") == 0) {
entry->hidden_from_menus = strcasecmp(value, "true") == 0;
} else if (strcmp(key, "Terminal") == 0) {
entry->start_in_terminal = strcasecmp(value, "true") == 0;
} else if (strcmp(key, "StartupNotify") == 0) {
entry->startup_notification = strcasecmp(value, "true") == 0;
}
}
}

View file

@ -17,6 +17,8 @@ typedef struct DesktopEntry {
char *path;
char *cwd;
gboolean hidden_from_menus;
gboolean start_in_terminal;
gboolean startup_notification;
} DesktopEntry;
// Parses a line of the form "key = value". Modifies the line.

View file

@ -435,7 +435,7 @@ void launcher_action(LauncherIcon *icon, XEvent *evt, int x, int y)
launcher_reload_hidden_icons((Launcher *)icon->area.parent);
if (evt->type == ButtonPress || evt->type == ButtonRelease)
tint_exec(icon->cmd, icon->cwd, icon->icon_tooltip, evt->xbutton.time, &icon->area, x, y);
tint_exec(icon->cmd, icon->cwd, icon->icon_tooltip, evt->xbutton.time, &icon->area, x, y, icon->start_in_terminal, icon->startup_notification);
}
// Populates the list_icons list from the list_apps list
@ -490,6 +490,8 @@ void launcher_reload_icon(Launcher *launcher, LauncherIcon *launcherIcon)
launcherIcon->cwd = strdup(entry.cwd);
else
launcherIcon->cwd = NULL;
launcherIcon->start_in_terminal = entry.start_in_terminal;
launcherIcon->startup_notification = entry.startup_notification;
if (launcherIcon->icon_name)
free(launcherIcon->icon_name);
launcherIcon->icon_name = entry.icon ? strdup(entry.icon) : strdup(DEFAULT_ICON);

View file

@ -33,6 +33,8 @@ typedef struct LauncherIcon {
Imlib_Image image_pressed;
char *cmd;
char *cwd;
gboolean start_in_terminal;
gboolean startup_notification;
char *icon_name;
char *icon_path;
char *icon_tooltip;

View file

@ -536,6 +536,7 @@ void handle_x_event(XEvent *e)
emit_self_restart("compositor changed");
}
}
fprintf(stderr, "tint2: ClientMessage %s\n", GetAtomName(server.display, ev->message_type));
if (systray_enabled && e->xclient.message_type == server.atom._NET_SYSTEM_TRAY_OPCODE &&
e->xclient.format == 32 && e->xclient.window == net_sel_win) {
handle_systray_event(&e->xclient);

View file

@ -40,6 +40,7 @@
#include <sys/time.h>
#include <errno.h>
#include <dirent.h>
#include <wordexp.h>
#ifdef HAVE_RSVG
#include <librsvg/rsvg.h>
@ -267,7 +268,15 @@ int setenvd(const char *name, const int value)
}
#ifndef TINT2CONF
pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time time, Area *area, int x, int y)
pid_t tint_exec(const char *command,
const char *dir,
const char *tooltip,
Time time,
Area *area,
int x,
int y,
gboolean terminal,
gboolean startup_notification)
{
if (!command || strlen(command) == 0)
return -1;
@ -362,7 +371,7 @@ pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time
#if HAVE_SN
SnLauncherContext *ctx = 0;
if (startup_notifications && time) {
if (startup_notifications && startup_notification && time) {
ctx = sn_launcher_context_new(server.sn_display, server.screen);
sn_launcher_context_set_name(ctx, tooltip);
sn_launcher_context_set_description(ctx, "Application launched from tint2");
@ -377,7 +386,7 @@ pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time
} else if (pid == 0) {
// Child process
#if HAVE_SN
if (startup_notifications && time) {
if (startup_notifications && startup_notification && time) {
sn_launcher_context_setup_child_process(ctx);
}
#endif // HAVE_SN
@ -387,10 +396,25 @@ pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time
if (dir)
chdir(dir);
close_all_fds();
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
fprintf(stderr, "tint2: Failed to execlp %s\n", command);
if (terminal) {
fprintf(stderr, "tint2: executing in x-terminal-emulator: %s\n", command);
wordexp_t words;
words.we_offs = 2;
wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR);
words.we_wordv[0] = (char*)"x-terminal-emulator";
words.we_wordv[1] = (char*)"-e";
execvp("x-terminal-emulator", words.we_wordv);
}
fprintf(stderr, "tint2: could not execute command in x-terminal-emulator: %s, executting in shell\n", command);
wordexp_t words;
words.we_offs = 2;
wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR);
words.we_wordv[0] = (char*)"sh";
words.we_wordv[1] = (char*)"-c";
execvp("sh", words.we_wordv);
fprintf(stderr, "tint2: Failed to execute %s\n", command);
#if HAVE_SN
if (startup_notifications && time) {
if (startup_notifications && startup_notification && time) {
sn_launcher_context_unref(ctx);
}
#endif // HAVE_SN
@ -398,7 +422,7 @@ pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time
} else {
// Parent process
#if HAVE_SN
if (startup_notifications && time) {
if (startup_notifications && startup_notification && time) {
g_tree_insert(server.pids, GINT_TO_POINTER(pid), ctx);
}
#endif // HAVE_SN
@ -425,7 +449,7 @@ pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time
void tint_exec_no_sn(const char *command)
{
tint_exec(command, NULL, NULL, 0, NULL, 0, 0);
tint_exec(command, NULL, NULL, 0, NULL, 0, 0, FALSE, FALSE);
}
#endif

View file

@ -66,7 +66,15 @@ void extract_values(const char *value, char **value1, char **value2, char **valu
void extract_values_4(const char *value, char **value1, char **value2, char **value3, char **value4);
// Executes a command in a shell.
pid_t tint_exec(const char *command, const char *dir, const char *tooltip, Time time, Area *area, int x, int y);
pid_t tint_exec(const char *command,
const char *dir,
const char *tooltip,
Time time,
Area *area,
int x,
int y,
gboolean terminal,
gboolean startup_notification);
void tint_exec_no_sn(const char *command);
int setenvd(const char *name, const int value);