diff --git a/mpanel/main.c b/mpanel/main.c index 908ce80..069aa0f 100644 --- a/mpanel/main.c +++ b/mpanel/main.c @@ -25,6 +25,8 @@ static void resize(MwWidget handle, void* user, void* client) { int main() { MwRect rc; + signal(SIGCHLD, SIG_IGN); + MwLibraryInit(); window = MwVaCreateWidget(MwWindowClass, "window", NULL, MwDEFAULT, MwDEFAULT, 0, 0, diff --git a/mpanel/mpanel.h b/mpanel/mpanel.h index 71f7312..fca3f8f 100644 --- a/mpanel/mpanel.h +++ b/mpanel/mpanel.h @@ -12,6 +12,7 @@ /* Standard */ #include +#include /* main.c */ extern MwWidget window, box; diff --git a/mpanel/startbutton/module.c b/mpanel/startbutton/module.c index 2d5960b..47c9340 100644 --- a/mpanel/startbutton/module.c +++ b/mpanel/startbutton/module.c @@ -11,6 +11,7 @@ #include #include +#include #define TriW 5 @@ -23,16 +24,19 @@ typedef struct opaque { char* name; char* category; + char* exec; } opaque_t; static int dumper(void* user, const char* section, const char* name, const char* value) { opaque_t* opaque = user; if(strcmp(section, "Desktop Entry") != 0) return 1; - if(strcmp(name, "Name") == 0){ + if(strcmp(name, "Name") == 0) { opaque->name = MwStringDuplicate(value); - }else if(strcmp(name, "Categories") == 0){ + } else if(strcmp(name, "Categories") == 0) { opaque->category = MwStringDuplicate(value); + } else if(strcmp(name, "Exec") == 0) { + opaque->exec = MwStringDuplicate(value); } return 1; @@ -56,65 +60,65 @@ enum CATEGORY { }; static const char* category_mapping[] = { - "Lost & Found", - "Multimedia", - "Audio", - "Video", - "Development", - "Education", - "Game", - "Graphics", - "Network", - "Office", - "Science", - "Settings", - "System", - "Utility" -}; + "Lost & Found", + "Multimedia", + "Audio", + "Video", + "Development", + "Education", + "Game", + "Graphics", + "Network", + "Office", + "Science", + "Settings", + "System", + "Utility"}; -static void call(const char* name, int dir, int symlink, void* user){ +static void call(const char* name, int dir, int symlink, void* user) { opaque_t* opaque = user; - int c = C_UNKNOWN; + int c = C_UNKNOWN; - opaque->name = NULL; + opaque->name = NULL; opaque->category = NULL; + opaque->exec = NULL; ini_parse(name, dumper, user); - if(opaque->category != NULL){ + if(opaque->category != NULL) { char* str = opaque->category; - while(str != NULL){ + while(str != NULL) { char* s = strchr(str, ';'); - if(s != NULL){ + if(s != NULL) { s[0] = 0; } - if(strcasecmp(str, "AudioVideo") == 0){ + if(strcasecmp(str, "AudioVideo") == 0) { c = C_AUDIOVIDEO; - }else if(strcasecmp(str, "Audio") == 0){ + } else if(strcasecmp(str, "Audio") == 0) { c = C_AUDIO; - }else if(strcasecmp(str, "Video") == 0){ + } else if(strcasecmp(str, "Video") == 0) { c = C_VIDEO; - }else if(strcasecmp(str, "Development") == 0){ + } else if(strcasecmp(str, "Development") == 0) { c = C_DEVELOPMENT; - }else if(strcasecmp(str, "Education") == 0){ + } else if(strcasecmp(str, "Education") == 0) { c = C_EDUCATION; - }else if(strcasecmp(str, "Game") == 0){ + } else if(strcasecmp(str, "Game") == 0) { c = C_GAME; - }else if(strcasecmp(str, "Graphics") == 0){ + } else if(strcasecmp(str, "Graphics") == 0) { c = C_GRAPHICS; - }else if(strcasecmp(str, "Network") == 0){ + } else if(strcasecmp(str, "Network") == 0) { c = C_NETWORK; - }else if(strcasecmp(str, "Office") == 0){ + } else if(strcasecmp(str, "Office") == 0) { c = C_OFFICE; - }else if(strcasecmp(str, "Science") == 0){ + } else if(strcasecmp(str, "Science") == 0) { c = C_SCIENCE; - }else if(strcasecmp(str, "Settings") == 0){ + } else if(strcasecmp(str, "Settings") == 0) { c = C_SETTINGS; - }else if(strcasecmp(str, "System") == 0){ + } else if(strcasecmp(str, "System") == 0) { c = C_SYSTEM; - }else if(strcasecmp(str, "Utility") == 0){ + } else if(strcasecmp(str, "Utility") == 0) { c = C_UTILITY; } @@ -125,45 +129,108 @@ static void call(const char* name, int dir, int symlink, void* user){ free(opaque->category); } - if(opaque->name != NULL){ - int i; + if(opaque->name != NULL) { + int i; MwMenu mc = NULL, m; - for(i = 0; i < arrlen(opaque->menu->sub); i++){ - if(strcmp(opaque->menu->sub[i]->name, category_mapping[c]) == 0){ + for(i = 0; i < arrlen(opaque->menu->sub); i++) { + if(strcmp(opaque->menu->sub[i]->name, category_mapping[c]) == 0) { mc = opaque->menu->sub[i]; break; } } - if(mc == NULL){ - mc = malloc(sizeof(*mc)); + if(mc == NULL) { + mc = malloc(sizeof(*mc)); mc->name = (char*)category_mapping[c]; mc->keep = 0; - mc->sub = NULL; + mc->sub = NULL; mc->wsub = NULL; arrput(opaque->menu->sub, mc); } - for(i = 0; i < arrlen(mc->sub); i++){ - if(strcmp(mc->sub[i]->name, opaque->name) == 0){ + for(i = 0; i < arrlen(mc->sub); i++) { + if(strcmp(mc->sub[i]->name, opaque->name) == 0) { break; } } - if(i == arrlen(mc->sub)){ - m = malloc(sizeof(*m)); - m->name = opaque->name; - m->keep = 0; - m->sub = NULL; - m->wsub = NULL; + if(i == arrlen(mc->sub)) { + m = malloc(sizeof(*m)); + m->name = opaque->name; + m->keep = 0; + m->sub = NULL; + m->wsub = NULL; + m->opaque = opaque->exec; arrput(mc->sub, m); } } } +static char** desktop_exec(const char* exec, const char* file) { + char** a = NULL; + int i; + char* buf = malloc(1); + + buf[0] = 0; + + for(i = 0;; i++) { + if(exec[i] == ' ' || exec[i] == 0) { + if(strlen(buf) > 0) arrput(a, buf); + + buf = malloc(1); + buf[0] = 0; + + if(exec[i] == 0) break; + } else if(exec[i] == '%') { + char c = exec[++i]; + + if(c == 'f' && file != NULL) { + char* old = buf; + + buf = malloc(strlen(old) + strlen(file) + 1); + strcpy(buf, old); + strcpy(buf + strlen(old), file); + + free(old); + } + } else { + char* old = buf; + + buf = malloc(strlen(old) + 2); + strcpy(buf, old); + buf[strlen(old)] = exec[i]; + buf[strlen(old) + 1] = 0; + + free(old); + } + } + + arrput(a, NULL); + + return a; +} + static void menu(MwWidget handle, void* user, void* client) { opaque_t* opaque = handle->opaque; + char* s = NULL; + MwMenu m = client; + + if(m->opaque != NULL) { + char** args = desktop_exec(m->opaque, NULL); + int i; + + if(fork() == 0) { + execvp(args[0], args); + + _exit(-1); + } + + for(i = 0; i < arrlen(args); i++) { + if(args[i] != NULL) free(args[i]); + } + arrfree(args); + } if(opaque->is_opened) { opaque->is_opened = 0; @@ -204,7 +271,7 @@ static void activate(MwWidget handle, void* user, void* client) { } } -int sort_alphabet(const void* a, const void* b){ +int sort_alphabet(const void* a, const void* b) { return strcmp((*((MwMenu*)a))->name, (*((MwMenu*)b))->name); } @@ -217,7 +284,7 @@ void module(MwWidget box, config_setting_t* setting) { unsigned char* rgb; opaque_t* opaque = malloc(sizeof(*opaque)); MwMenu m; - int i; + int i; if((rgb = stbi_load(ICON64DIR "/logo.png", &w, &h, &ch, 4)) != NULL) { int bw = MwGetInteger(box, MwNheight) - MwDefaultBorderWidth(box) * 2; @@ -283,9 +350,12 @@ void module(MwWidget box, config_setting_t* setting) { MDEDirectoryScan(DATAROOTDIR "/applications", call, opaque); MDEDirectoryScan("/usr/share/applications", call, opaque); +#if defined(__NetBSD__) + MDEDirectoryScan("/usr/pkg/share/applications", call, opaque); +#endif qsort(opaque->menu->sub, arrlen(opaque->menu->sub), sizeof(MwMenu), sort_alphabet); - for(i = 0; i < arrlen(opaque->menu->sub); i++){ + for(i = 0; i < arrlen(opaque->menu->sub); i++) { qsort(opaque->menu->sub[i]->sub, arrlen(opaque->menu->sub[i]->sub), sizeof(MwMenu), sort_alphabet); }