From ef89c2dac9d744af69b9080b2d8d674fad8b3994 Mon Sep 17 00:00:00 2001 From: NishiOwO Date: Sun, 28 Dec 2025 17:29:00 +0900 Subject: [PATCH] add reload --- mpanel/launcher/module.c | 53 +++++++++--- mpanel/main.c | 7 ++ mpanel/module.c | 122 +++++++++++++++++++++----- mpanel/mpanel.h | 2 + mpanel/mpanelrc.in | 14 +-- mpanel/separator/module.c | 10 +-- mpanel/startbutton/module.c | 165 +++++++++++++++++++++--------------- mpanel/stb_ds.c | 2 + mpanel/taskbar/module.c | 4 +- mpanel/time/module.c | 4 +- startmde/startmde.in | 25 ++++-- 11 files changed, 285 insertions(+), 123 deletions(-) create mode 100644 mpanel/stb_ds.c diff --git a/mpanel/launcher/module.c b/mpanel/launcher/module.c index f26a9ab..fcf1470 100644 --- a/mpanel/launcher/module.c +++ b/mpanel/launcher/module.c @@ -2,14 +2,15 @@ #include #include -void module(MwWidget box, xl_node_t* node) { - MwWidget f; - xl_node_t* n; - int c; - int w; - int gap = (MwGetInteger(box, MwNheight) - 18 * 2); +static int calc_gap(MwWidget box) { + return MwGetInteger(box, MwNheight) - 18 * 2; +} + +static int calc_size(MwWidget box, xl_node_t* node) { + xl_node_t* n; + int gap = calc_gap(box); + int c = 0; - c = 0; n = node->first_child; while(n != NULL) { if(n->type == XL_NODE_NODE && strcmp(n->name, "Execute") == 0 && n->text != NULL) { @@ -19,11 +20,26 @@ void module(MwWidget box, xl_node_t* node) { n = n->next; } - w = (c + (c % 2)) / 2; + return (gap + 18) * ((c + (c % 2)) / 2) - gap; +} - f = MwVaCreateWidget(MwFrameClass, "launcher", box, 0, 0, 0, 0, - MwNfixedSize, (gap + 18) * w - gap, - NULL); +void module_reload(MwWidget box, MwWidget user, xl_node_t* node) { + int w = calc_size(box, node); + int gap = calc_gap(box); + xl_node_t* n; + int c; + MwWidget* children; + + children = MwGetChildren(user); + if(children != NULL) { + int i; + for(i = 0; children[i] != NULL; i++) MwDestroyWidget(children[i]); + free(children); + } + + MwVaApply(user, + MwNfixedSize, w, + NULL); c = 0; n = node->first_child; @@ -55,7 +71,7 @@ void module(MwWidget box, xl_node_t* node) { } } - btn = MwVaCreateWidget(MwButtonClass, "button", f, x, y, 18, 18, + btn = MwVaCreateWidget(MwButtonClass, "button", user, x, y, 18, 18, MwNflat, 1, MwNpixmap, px, NULL); @@ -66,3 +82,16 @@ void module(MwWidget box, xl_node_t* node) { n = n->next; } } + +MwWidget module(MwWidget box, xl_node_t* node) { + MwWidget f; + int w = calc_size(box, node); + + f = MwVaCreateWidget(MwFrameClass, "launcher", box, 0, 0, 0, 0, + MwNfixedSize, w, + NULL); + + module_reload(box, f, node); + + return f; +} diff --git a/mpanel/main.c b/mpanel/main.c index 069aa0f..ab1a03f 100644 --- a/mpanel/main.c +++ b/mpanel/main.c @@ -5,6 +5,10 @@ MwWidget window, box; static int first = 1; +static void sig_hup(int sig) { + reload_modules(); +} + static void resize(MwWidget handle, void* user, void* client) { int bw = MwDefaultBorderWidth(window) + 2; @@ -19,6 +23,8 @@ static void resize(MwWidget handle, void* user, void* client) { first = 0; load_modules(); + + signal(SIGHUP, sig_hup); } } @@ -26,6 +32,7 @@ int main() { MwRect rc; signal(SIGCHLD, SIG_IGN); + signal(SIGHUP, SIG_IGN); MwLibraryInit(); diff --git a/mpanel/module.c b/mpanel/module.c index 29e023e..993238c 100644 --- a/mpanel/module.c +++ b/mpanel/module.c @@ -1,5 +1,14 @@ #include "mpanel.h" +#include + +typedef struct module { + char* key; + void* value; + MwWidget user; +} module_t; +module_t* modules = NULL; + static void read_config(xemil_t** cfg, const char* path) { xemil_t* tmp; @@ -13,44 +22,115 @@ static void read_config(xemil_t** cfg, const char* path) { } } +static void init_module(xl_node_t* node) { + char* p = MDEStringConcatenate("lib", node->name); + char* p2 = MDEStringConcatenate(p, "Module.so"); + char* s = MwDirectoryJoin(LIBDIR "/mpanel", p2); + void* lib; + char* id = NULL; + xl_attribute_t* a = node->first_attribute; + int ind; + + while(a != NULL) { + if(strcmp(a->key, "ID") == 0 && a->value != NULL) { + id = a->value; + } + a = a->next; + } + + if(id == NULL) return; + + lib = dlopen(s, RTLD_LAZY | RTLD_LOCAL); + + if(lib != NULL) { + if((ind = shgeti(modules, id)) == -1) { + MwWidget (*module)(MwWidget box, xl_node_t* node) = dlsym(lib, "module"); + void* ret = NULL; + + if(module != NULL) { + ret = module(box, node); + + shput(modules, id, lib); + + ind = shgeti(modules, id); + modules[ind].user = ret; + } + } else { + void (*module)(MwWidget box, MwWidget user, xl_node_t* node); + void* ret = NULL; + + dlclose(lib); + lib = modules[ind].value; + + module = dlsym(lib, "module_reload"); + + if(module != NULL) { + module(box, modules[ind].user, node); + } + } + } + + free(s); + free(p2); + free(p); +} + static void module_scan(xl_node_t* node) { xl_node_t* n = node->first_child; while(n != NULL) { if(n->type == XL_NODE_NODE) { - char* p = MDEStringConcatenate("lib", n->name); - char* p2 = MDEStringConcatenate(p, "Module.so"); - char* s = MwDirectoryJoin(LIBDIR "/mpanel", p2); - void* lib = dlopen(s, RTLD_LAZY | RTLD_LOCAL); - - if(lib != NULL) { - void (*module)(MwWidget box, xl_node_t* node) = dlsym(lib, "module"); - - if(module != NULL) module(box, n); - } - - free(s); - free(p2); - free(p); + init_module(n); } n = n->next; } } -void load_modules(void) { - xemil_t* cfg = NULL; - char* conf = MDEDirectoryConfigPath(); - char* dir = MwDirectoryJoin(conf, "mpanel"); - char* path = MwDirectoryJoin(dir, "mpanelrc"); +static void prepare_config(xemil_t** cfg) { + char* conf = MDEDirectoryConfigPath(); + char* dir = MwDirectoryJoin(conf, "mpanel"); + char* path = MwDirectoryJoin(dir, "mpanelrc"); free(dir); free(conf); - read_config(&cfg, SYSCONFDIR "/mpanel/mpanelrc"); - read_config(&cfg, path); + read_config(cfg, SYSCONFDIR "/mpanel/mpanelrc"); + read_config(cfg, path); free(path); +} + +void load_modules(void) { + xemil_t* cfg = NULL; + + prepare_config(&cfg); + + sh_new_strdup(modules); + + if(cfg != NULL && cfg->root != NULL) { + xl_node_t* n = cfg->root->first_child; + if(strcmp(cfg->root->name, "Panel") != 0) { + fprintf(stderr, "MPanel config error: Root element has to be Panel\n"); + return; + } + + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "Module") == 0) { + module_scan(n); + } + + n = n->next; + } + + xl_close(cfg); + } +} + +void reload_modules(void) { + xemil_t* cfg = NULL; + + prepare_config(&cfg); if(cfg != NULL && cfg->root != NULL) { xl_node_t* n = cfg->root->first_child; diff --git a/mpanel/mpanel.h b/mpanel/mpanel.h index 2e779f6..b574042 100644 --- a/mpanel/mpanel.h +++ b/mpanel/mpanel.h @@ -13,11 +13,13 @@ /* Standard */ #include #include +#include /* main.c */ extern MwWidget window, box; /* module.c */ void load_modules(void); +void reload_modules(void); #endif diff --git a/mpanel/mpanelrc.in b/mpanel/mpanelrc.in index 5a8e0b9..02b406b 100644 --- a/mpanel/mpanelrc.in +++ b/mpanel/mpanelrc.in @@ -2,7 +2,7 @@ - + @CMAKE_INSTALL_FULL_DATAROOTDIR@/mpanel/mde-stripe.png @@ -17,9 +17,9 @@ - + - + uxterm uxterm uxterm @@ -31,13 +31,13 @@ uxterm - + - + - + - diff --git a/mpanel/separator/module.c b/mpanel/separator/module.c index 72b045a..f0d14eb 100644 --- a/mpanel/separator/module.c +++ b/mpanel/separator/module.c @@ -1,9 +1,9 @@ #include #include -void module(MwWidget box, xl_node_t* node) { - MwVaCreateWidget(MwSeparatorClass, "separator", box, 0, 0, 0, 0, - MwNfixedSize, 10, - MwNorientation, MwVERTICAL, - NULL); +MwWidget module(MwWidget box, xl_node_t* node) { + return MwVaCreateWidget(MwSeparatorClass, "separator", box, 0, 0, 0, 0, + MwNfixedSize, 10, + MwNorientation, MwVERTICAL, + NULL); } diff --git a/mpanel/startbutton/module.c b/mpanel/startbutton/module.c index 5eddb98..a509032 100644 --- a/mpanel/startbutton/module.c +++ b/mpanel/startbutton/module.c @@ -36,11 +36,11 @@ static int dumper(void* user, const char* section, const char* name, const char* if(strcmp(section, "Desktop Entry") != 0) return 1; if(strcmp(name, "Name") == 0) { - opaque->name = MwStringDuplicate(value); + opaque->name = MDEStringDuplicate(value); } else if(strcmp(name, "Categories") == 0) { - opaque->category = MwStringDuplicate(value); + opaque->category = MDEStringDuplicate(value); } else if(strcmp(name, "Exec") == 0) { - opaque->exec = MwStringDuplicate(value); + opaque->exec = MDEStringDuplicate(value); } return 1; @@ -143,11 +143,12 @@ static void call(const char* name, int dir, int symlink, void* user) { } } if(mc == NULL) { - mc = malloc(sizeof(*mc)); - mc->name = (char*)category_mapping[c]; - mc->keep = 0; - mc->sub = NULL; - mc->wsub = NULL; + mc = malloc(sizeof(*mc)); + mc->name = MDEStringDuplicate(category_mapping[c]); + mc->keep = 0; + mc->sub = NULL; + mc->wsub = NULL; + mc->opaque = NULL; arrput(opaque->current->sub, mc); } @@ -313,35 +314,37 @@ static void menu_scan(opaque_t* opaque, xl_node_t* node) { MwMenu m = NULL; if(n->type == XL_NODE_NODE && strcmp(n->name, "Application") == 0 && name != NULL) { - m = malloc(sizeof(*m)); - m->name = MwStringDuplicate(name); - m->keep = 0; - m->wsub = NULL; - m->sub = NULL; + m = malloc(sizeof(*m)); + m->name = MDEStringDuplicate(name); + m->keep = 0; + m->wsub = NULL; + m->sub = NULL; + m->opaque = NULL; opaque->current = m; MDEDirectoryScan(DATAROOTDIR "/applications", call, opaque); - MDEDirectoryScan("/usr/share/applications", call, opaque); #if defined(__NetBSD__) MDEDirectoryScan("/usr/pkg/share/applications", call, opaque); #endif + MDEDirectoryScan("/usr/share/applications", call, opaque); } else if(n->type == XL_NODE_NODE && strcmp(n->name, "Separator") == 0) { - m = malloc(sizeof(*m)); - m->name = MwStringDuplicate("----"); - m->keep = 0; - m->wsub = NULL; - m->sub = NULL; - } else if(n->type == XL_NODE_NODE && strcmp(n->name, "Execute") == 0 && name != NULL) { m = malloc(sizeof(*m)); - m->name = MwStringDuplicate(name); + m->name = MDEStringDuplicate("----"); m->keep = 0; m->wsub = NULL; m->sub = NULL; - m->opaque = MwStringDuplicate(n->text == NULL ? "" : n->text); + m->opaque = NULL; + } else if(n->type == XL_NODE_NODE && strcmp(n->name, "Execute") == 0 && name != NULL) { + m = malloc(sizeof(*m)); + m->name = MDEStringDuplicate(name); + m->keep = 0; + m->wsub = NULL; + m->sub = NULL; + m->opaque = MDEStringDuplicate(n->text == NULL ? "" : n->text); } else if(n->type == XL_NODE_NODE && strcmp(n->name, "EndSession") == 0 && name != NULL) { m = malloc(sizeof(*m)); - m->name = MwStringDuplicate(name); + m->name = MDEStringDuplicate(name); m->keep = 0; m->wsub = NULL; m->sub = NULL; @@ -350,18 +353,18 @@ static void menu_scan(opaque_t* opaque, xl_node_t* node) { sprintf(m->opaque, "kill %ld", (long)getppid()); } else if(n->type == XL_NODE_NODE && strcmp(n->name, "ShutDown") == 0 && name != NULL) { m = malloc(sizeof(*m)); - m->name = MwStringDuplicate(name); + m->name = MDEStringDuplicate(name); m->keep = 0; m->wsub = NULL; m->sub = NULL; - m->opaque = MwStringDuplicate(""); /* TODO */ + m->opaque = MDEStringDuplicate(""); /* TODO */ } else if(n->type == XL_NODE_NODE && strcmp(n->name, "Reboot") == 0 && name != NULL) { m = malloc(sizeof(*m)); - m->name = MwStringDuplicate(name); + m->name = MDEStringDuplicate(name); m->keep = 0; m->wsub = NULL; m->sub = NULL; - m->opaque = MwStringDuplicate(""); /* TODO */ + m->opaque = MDEStringDuplicate(""); /* TODO */ } if(m != NULL) { @@ -372,7 +375,65 @@ static void menu_scan(opaque_t* opaque, xl_node_t* node) { } } -void module(MwWidget box, xl_node_t* node) { +static void recursive_free(MwMenu menu) { + int i; + + for(i = 0; i < arrlen(menu->sub); i++) recursive_free(menu->sub[i]); + if(menu->opaque != NULL) free(menu->opaque); + if(menu->name != NULL) free(menu->name); + if(menu->wsub != NULL) MwDestroyWidget(menu->wsub); + free(menu); +} + +void module_reload(MwWidget box, MwWidget user, xl_node_t* node) { + xl_node_t* n; + opaque_t* opaque = user->opaque; + int i; + + if(opaque->menu != NULL) recursive_free(opaque->menu); + + opaque->menu = malloc(sizeof(*opaque->menu)); + opaque->menu->name = NULL; + opaque->menu->keep = 0; + opaque->menu->wsub = NULL; + opaque->menu->sub = NULL; + opaque->menu->opaque = NULL; + + n = node->first_child; + + while(n != NULL) { + if(n->type == XL_NODE_NODE && strcmp(n->name, "Menu") == 0) { + menu_scan(opaque, n); + } else if(n->type == XL_NODE_NODE && strcmp(n->name, "Stripe") == 0) { + xl_attribute_t* a; + + if(opaque->stripe != NULL) MwLLDestroyPixmap(opaque->stripe); + opaque->stripe = MwLoadImage(box, n->text == NULL ? "" : n->text); + + a = n->first_attribute; + while(a != NULL) { + if(strcmp(a->key, "Color") == 0 && a->value != NULL) { + if(opaque->stripe_color != NULL) free(opaque->stripe_color); + + opaque->stripe_color = MDEStringDuplicate(a->value); + } + + a = a->next; + } + } + + n = n->next; + } + + if(arrlen(opaque->menu->sub[0]->sub) > 0) { + qsort(opaque->menu->sub[0]->sub, arrlen(opaque->menu->sub[0]->sub), sizeof(MwMenu), sort_alphabet); + for(i = 0; i < arrlen(opaque->menu->sub[0]->sub); i++) { + qsort(opaque->menu->sub[0]->sub[i]->sub, arrlen(opaque->menu->sub[0]->sub[i]->sub), sizeof(MwMenu), sort_alphabet); + } + } +} + +MwWidget module(MwWidget box, xl_node_t* node) { MwLLPixmap closed = NULL; MwLLPixmap opened = NULL; MwWidget btn; @@ -380,8 +441,6 @@ void module(MwWidget box, xl_node_t* node) { unsigned int ch; unsigned char* rgb; opaque_t* opaque = malloc(sizeof(*opaque)); - int i; - xl_node_t* n; if((rgb = stbi_load(ICON64DIR "/apps/mde.png", &w, &h, &ch, 4)) != NULL) { int bw = MwGetInteger(box, MwNheight) - MwDefaultBorderWidth(box) * 2; @@ -434,57 +493,23 @@ void module(MwWidget box, xl_node_t* node) { MwNpixmap, closed, NULL); + btn->opaque = opaque; + opaque->closed = closed; opaque->opened = opened; opaque->submenu = NULL; opaque->is_opened = 0; - opaque->menu = malloc(sizeof(*opaque->menu)); - opaque->menu->name = NULL; - opaque->menu->keep = 0; - opaque->menu->wsub = NULL; - opaque->menu->sub = NULL; - opaque->stripe_color = NULL; opaque->stripe = NULL; - n = node->first_child; + opaque->menu = NULL; - while(n != NULL) { - if(n->type == XL_NODE_NODE && strcmp(n->name, "Menu") == 0) { - menu_scan(opaque, n); - } else if(n->type == XL_NODE_NODE && strcmp(n->name, "Stripe") == 0) { - xl_attribute_t* a; - - if(opaque->stripe != NULL) MwLLDestroyPixmap(opaque->stripe); - - opaque->stripe = MwLoadImage(box, n->text == NULL ? "" : n->text); - - a = n->first_attribute; - while(a != NULL) { - if(strcmp(a->key, "Color") == 0 && a->value != NULL) { - if(opaque->stripe_color != NULL) free(opaque->stripe_color); - - opaque->stripe_color = MwStringDuplicate(a->value); - } - - a = a->next; - } - } - - n = n->next; - } - - if(arrlen(opaque->menu->sub[0]->sub) > 0) { - qsort(opaque->menu->sub[0]->sub, arrlen(opaque->menu->sub[0]->sub), sizeof(MwMenu), sort_alphabet); - for(i = 0; i < arrlen(opaque->menu->sub[0]->sub); i++) { - qsort(opaque->menu->sub[0]->sub[i]->sub, arrlen(opaque->menu->sub[0]->sub[i]->sub), sizeof(MwMenu), sort_alphabet); - } - } - - btn->opaque = opaque; + module_reload(box, btn, node); MwAddUserHandler(btn, MwNactivateHandler, activate, NULL); MwAddUserHandler(btn, MwNmenuHandler, menu, NULL); + + return btn; } diff --git a/mpanel/stb_ds.c b/mpanel/stb_ds.c new file mode 100644 index 0000000..689615c --- /dev/null +++ b/mpanel/stb_ds.c @@ -0,0 +1,2 @@ +#define STB_DS_IMPLEMENTATION +#include diff --git a/mpanel/taskbar/module.c b/mpanel/taskbar/module.c index d55a6c3..d24443b 100644 --- a/mpanel/taskbar/module.c +++ b/mpanel/taskbar/module.c @@ -1,6 +1,8 @@ #include #include -void module(MwWidget box, xl_node_t* node) { +MwWidget module(MwWidget box, xl_node_t* node) { MwWidget b = MwCreateWidget(MwFrameClass, "taskbar", box, 0, 0, 0, 0); + + return b; } diff --git a/mpanel/time/module.c b/mpanel/time/module.c index 7f36cc5..65ed1ac 100644 --- a/mpanel/time/module.c +++ b/mpanel/time/module.c @@ -54,7 +54,7 @@ static void tick(MwWidget handle, void* user, void* client) { free(children); } -void module(MwWidget box, xl_node_t* node) { +MwWidget module(MwWidget box, xl_node_t* node) { MwWidget b = MwVaCreateWidget(MwBoxClass, "time", box, 0, 0, 0, 0, MwNfixedSize, 64, MwNbackground, "#bebdb2", @@ -80,4 +80,6 @@ void module(MwWidget box, xl_node_t* node) { MwAddUserHandler(b, MwNtickHandler, tick, NULL); MwAddTickList(b); + + return b; } diff --git a/startmde/startmde.in b/startmde/startmde.in index 20cc965..c476d9e 100755 --- a/startmde/startmde.in +++ b/startmde/startmde.in @@ -1,18 +1,31 @@ #!/bin/sh +kill_all () { + kill $1 $PANEL $WM +} + stop_all () { - kill $PANEL $WM + kill_all exit } +reload_all () { + kill_all -HUP +} + +start_all () { + "@CMAKE_INSTALL_FULL_BINDIR@/mpanel" & + PANEL="$!" + + "@CMAKE_INSTALL_FULL_BINDIR@/milkwm" & + WM="$!" +} + trap "stop_all" INT trap "stop_all" TERM +trap "reload_all" HUP -"@CMAKE_INSTALL_FULL_BINDIR@/mpanel" & -PANEL="$!" - -"@CMAKE_INSTALL_FULL_BINDIR@/milkwm" & -WM="$!" +start_all while true; do wait