Launcher: Support %f and %F

This commit is contained in:
o9000 2017-09-02 13:04:01 +02:00
parent 498b665c8a
commit d49adfdef3
6 changed files with 82 additions and 36 deletions

View file

@ -298,23 +298,6 @@ void handle_dnd_drop(XClientMessageEvent *e)
}
}
GString *tint2_g_string_replace(GString *s, const char *from, const char *to)
{
GString *result = g_string_new("");
for (char *p = s->str; *p;) {
if (strstr(p, from) == p) {
g_string_append(result, to);
p += strlen(from);
} else {
g_string_append_c(result, *p);
p += 1;
}
}
g_string_assign(s, result->str);
g_string_free(result, TRUE);
return s;
}
void handle_dnd_selection_notify(XSelectionEvent *e)
{
Atom target = e->target;
@ -326,11 +309,7 @@ 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__,
@ -371,25 +350,49 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
fprintf(stderr, "tint2: --------\n");
}
// TODO: support %r nd %F
// https://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables
GString *cmd = g_string_new(dnd_launcher_icon->cmd);
const char *atom_name = GetAtomName(server.display, prop.type);
if (strcasecmp(atom_name, "STRING") == 0 ||
strcasecmp(atom_name, "text/uri-list") == 0) {
if (strcasecmp(atom_name, "STRING") == 0 || strcasecmp(atom_name, "text/uri-list") == 0) {
GString *url = g_string_new("");
GString *prev_url = g_string_new("");
gboolean must_unescape = strcasecmp(atom_name, "text/uri-list") == 0;
for (int i = 0; i < prop.nitems * prop.format / 8; i++) {
char c = ((char *)prop.data)[i];
if (c == '\n') {
if (must_unescape) {
char *raw = g_uri_unescape_string(url->str, NULL);
if (raw) {
g_string_assign(url, raw);
}
free(raw);
}
// Many programs cannot handle this prefix
tint2_g_string_replace(url, "file://", "");
// Some programs put duplicates in the list, we remove them
if (strcmp(url->str, prev_url->str) != 0) {
g_string_append(cmd, " \"");
g_string_append(cmd, url->str);
g_string_append(cmd, "\"");
if (strstr(cmd->str, "%F")) {
GString *piece = g_string_new("");
g_string_append(piece, " \"");
g_string_append(piece, url->str);
g_string_append(piece, "\"");
g_string_append(piece, " %F");
tint2_g_string_replace(cmd, "%F", piece->str);
g_string_free(piece, TRUE);
} else if (strstr(cmd->str, "%f")) {
GString *piece = g_string_new("");
g_string_append(piece, " \"");
g_string_append(piece, url->str);
g_string_append(piece, "\"");
tint2_g_string_replace(cmd, "%f", piece->str);
g_string_free(piece, TRUE);
break;
} else {
g_string_append(cmd, " \"");
g_string_append(cmd, url->str);
g_string_append(cmd, "\"");
}
}
g_string_assign(prev_url, url->str);
g_string_assign(url, "");
@ -405,6 +408,8 @@ void handle_dnd_selection_notify(XSelectionEvent *e)
g_string_free(url, TRUE);
g_string_free(prev_url, TRUE);
}
tint2_g_string_replace(cmd, "%F", "");
tint2_g_string_replace(cmd, "%f", "");
if (debug_dnd)
fprintf(stderr, "tint2: DnD %s:%d: Running command: %s\n", __FILE__, __LINE__, cmd->str);
tint_exec(cmd->str,

View file

@ -96,6 +96,10 @@ void expand_exec(DesktopEntry *entry, const char *path)
q += strlen("''");
q += strlen(path);
q--; // To balance the q++ in the for
} else if (*p == 'f' || *p == 'F') {
sprintf(q, "%c%c", '%', *p);
q += 2;
q--; // To balance the q++ in the for
} else {
// We don't care about other expansions
q--; // Delete the last % from q

View file

@ -385,7 +385,12 @@ void draw_launcher_icon(void *obj, cairo_t *c)
void launcher_icon_dump_geometry(void *obj, int indent)
{
LauncherIcon *launcherIcon = (LauncherIcon *)obj;
fprintf(stderr, "tint2: %*sIcon: w = h = %d, name = %s\n", indent, "", launcherIcon->icon_size, launcherIcon->icon_name);
fprintf(stderr,
"tint2: %*sIcon: w = h = %d, name = %s\n",
indent,
"",
launcherIcon->icon_size,
launcherIcon->icon_name);
}
Imlib_Image scale_icon(Imlib_Image original, int icon_size)
@ -434,8 +439,21 @@ void launcher_action(LauncherIcon *icon, XEvent *evt, int x, int y)
launcher_reload_icon((Launcher *)icon->area.parent, icon);
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, icon->start_in_terminal, icon->startup_notification);
if (evt->type == ButtonPress || evt->type == ButtonRelease) {
GString *cmd = g_string_new(icon->cmd);
tint2_g_string_replace(cmd, "%f", "");
tint2_g_string_replace(cmd, "%F", "");
tint_exec(cmd->str,
icon->cwd,
icon->icon_tooltip,
evt->xbutton.time,
&icon->area,
x,
y,
icon->start_in_terminal,
icon->startup_notification);
g_string_free(cmd, TRUE);
}
}
// Populates the list_icons list from the list_apps list

View file

@ -536,7 +536,6 @@ 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

@ -400,10 +400,11 @@ pid_t tint_exec(const char *command,
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);
if (wordexp(command, &words, WRDE_DOOFFS | WRDE_SHOWERR) == 0) {
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);
}
execlp("sh", "sh", "-c", command, NULL);
@ -1033,3 +1034,20 @@ void close_all_fds()
close(fd);
}
}
GString *tint2_g_string_replace(GString *s, const char *from, const char *to)
{
GString *result = g_string_new("");
for (char *p = s->str; *p;) {
if (strstr(p, from) == p) {
g_string_append(result, to);
p += strlen(from);
} else {
g_string_append_c(result, *p);
p += 1;
}
}
g_string_assign(s, result->str);
g_string_free(result, TRUE);
return s;
}

View file

@ -148,6 +148,8 @@ GSList *slist_remove_duplicates(GSList *list, GCompareFunc eq, GDestroyNotify fr
// A trivial pointer comparator.
gint cmp_ptr(gconstpointer a, gconstpointer b);
GString *tint2_g_string_replace(GString *s, const char *from, const char *to);
#define free_and_null(p) \
{ \
free(p); \