diff options
Diffstat (limited to 'dwl-patches/patches/hot-reload/hot-reload-0.7.patch')
-rw-r--r-- | dwl-patches/patches/hot-reload/hot-reload-0.7.patch | 770 |
1 files changed, 770 insertions, 0 deletions
diff --git a/dwl-patches/patches/hot-reload/hot-reload-0.7.patch b/dwl-patches/patches/hot-reload/hot-reload-0.7.patch new file mode 100644 index 0000000..c8a8cce --- /dev/null +++ b/dwl-patches/patches/hot-reload/hot-reload-0.7.patch @@ -0,0 +1,770 @@ +From caa1adaf02ab4f9a326761ade5d1346149bc7c59 Mon Sep 17 00:00:00 2001 +From: Sivecano <sivecano@gmail.com> +Date: Sun, 26 Jan 2025 18:30:02 +0100 +Subject: [PATCH] redo hot-reloading in one file + +--- + Makefile | 19 ++- + config.def.h | 5 +- + dwl.c | 337 ++++++++++++++++++++++++++++++++++++++++++++------- + util.c | 34 ++++++ + util.h | 6 + + 5 files changed, 351 insertions(+), 50 deletions(-) + +diff --git a/Makefile b/Makefile +index 3358bae..70d3d0f 100644 +--- a/Makefile ++++ b/Makefile +@@ -13,13 +13,16 @@ DWLDEVCFLAGS = -g -pedantic -Wall -Wextra -Wdeclaration-after-statement \ + + # CFLAGS / LDFLAGS + PKGS = wlroots-0.18 wayland-server xkbcommon libinput $(XLIBS) +-DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) ++DWLCFLAGS = `$(PKG_CONFIG) --cflags $(PKGS)` $(DWLCPPFLAGS) $(DWLDEVCFLAGS) $(CFLAGS) -fPIC -rdynamic + LDLIBS = `$(PKG_CONFIG) --libs $(PKGS)` -lm $(LIBS) + +-all: dwl ++all: dwl dwl.so + dwl: dwl.o util.o + $(CC) dwl.o util.o $(DWLCFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ +-dwl.o: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ ++dwl.o: dwl.c cursor-shape-v1-protocol.h \ ++ pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ ++ wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h ++dwl.so: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \ + pointer-constraints-unstable-v1-protocol.h wlr-layer-shell-unstable-v1-protocol.h \ + wlr-output-power-management-unstable-v1-protocol.h xdg-shell-protocol.h + util.o: util.c util.h +@@ -49,7 +52,7 @@ xdg-shell-protocol.h: + config.h: + cp config.def.h $@ + clean: +- rm -f dwl *.o *-protocol.h ++ rm -f dwl *.o *-protocol.h *.so + + dist: clean + mkdir -p dwl-$(VERSION) +@@ -63,6 +66,8 @@ install: dwl + mkdir -p $(DESTDIR)$(PREFIX)/bin + cp -f dwl $(DESTDIR)$(PREFIX)/bin + chmod 755 $(DESTDIR)$(PREFIX)/bin/dwl ++ mkdir -p $(DESTDIR)$(PREFIX)/lib ++ install -m 744 dwl.so $(DESTDIR)$(PREFIX)/lib + mkdir -p $(DESTDIR)$(MANDIR)/man1 + cp -f dwl.1 $(DESTDIR)$(MANDIR)/man1 + chmod 644 $(DESTDIR)$(MANDIR)/man1/dwl.1 +@@ -70,9 +75,13 @@ install: dwl + cp -f dwl.desktop $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + chmod 644 $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + uninstall: +- rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(MANDIR)/man1/dwl.1 \ ++ rm -f $(DESTDIR)$(PREFIX)/bin/dwl $(DESTDIR)$(PREFIX)/lib/dwl.so $(DESTDIR)$(MANDIR)/man1/dwl.1 \ + $(DESTDIR)$(DATADIR)/wayland-sessions/dwl.desktop + + .SUFFIXES: .c .o + .c.o: + $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -c $< ++ ++.SUFFIXES: .c .so ++.c.so: ++ $(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -shared -DHOT $< +diff --git a/config.def.h b/config.def.h +index 22d2171..6e3dda1 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -7,7 +7,7 @@ + static const int sloppyfocus = 1; /* focus follows mouse */ + static const int bypass_surface_visibility = 0; /* 1 means idle inhibitors will disable idle tracking even if it's surface isn't visible */ + static const unsigned int borderpx = 1; /* border pixel of windows */ +-static const float rootcolor[] = COLOR(0x222222ff); ++const float rootcolor[] = COLOR(0x222222ff); + static const float bordercolor[] = COLOR(0x444444ff); + static const float focuscolor[] = COLOR(0x005577ff); + static const float urgentcolor[] = COLOR(0xff0000ff); +@@ -18,7 +18,7 @@ static const float fullscreen_bg[] = {0.1f, 0.1f, 0.1f, 1.0f}; /* You ca + #define TAGCOUNT (9) + + /* logging */ +-static int log_level = WLR_ERROR; ++int log_level = WLR_ERROR; + + /* NOTE: ALWAYS keep a rule declared even if you don't use rules (e.g leave at least one example) */ + static const Rule rules[] = { +@@ -127,6 +127,7 @@ static const Key keys[] = { + /* modifier key function argument */ + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_R, reload, {0} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, +diff --git a/dwl.c b/dwl.c +index def2562..7e059ad 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -1,6 +1,15 @@ + /* + * See LICENSE file for copyright and license details. + */ ++ ++/* stuff for hot-reload */ ++#define _GNU_SOURCE ++#include <dlfcn.h> ++#include <limits.h> ++#include <unistd.h> ++#include <libgen.h> ++#include <errno.h> ++ + #include <getopt.h> + #include <libinput.h> + #include <linux/input-event-codes.h> +@@ -67,6 +76,7 @@ + #include <xcb/xcb_icccm.h> + #endif + ++ + #include "util.h" + + /* macros */ +@@ -77,8 +87,34 @@ + #define LENGTH(X) (sizeof X / sizeof X[0]) + #define END(A) ((A) + LENGTH(A)) + #define TAGMASK ((1u << TAGCOUNT) - 1) +-#define LISTEN(E, L, H) wl_signal_add((E), ((L)->notify = (H), (L))) +-#define LISTEN_STATIC(E, H) do { static struct wl_listener _l = {.notify = (H)}; wl_signal_add((E), &_l); } while (0) ++ ++#define SYM(a) dlsym(dwl_module, #a) ++#define TSYM(T, a) ((T)SYM(a)) ++#define CSYM(T, a) *(TSYM(T*, a)) ++ ++#define LISTEN(E, L, H) do { \ ++ (L)->notify = SYM(H); \ ++ listeners = append_listener((L), listeners); \ ++ wl_signal_add((E), (L)); \ ++ } while(0) ++ ++#define LISTEN_GLOBAL(E, L) do { \ ++ struct wl_listener* l = SYM(L); \ ++ listeners = append_listener(l, listeners); \ ++ wl_signal_add((E), l); \ ++ } while (0) ++ ++#define LISTEN_STATIC(E, H) do { \ ++ struct wl_listener* _l = malloc(sizeof(struct wl_listener)); \ ++ _l->notify = SYM(H); \ ++ listeners = append_listener(_l, listeners); \ ++ wl_signal_add((E), _l); \ ++ } while (0) ++ ++#define UNLISTEN(L) do { \ ++ wl_list_remove(&(L)->link); \ ++ listeners = remove_listener((L), listeners);\ ++ } while (0) + + /* enums */ + enum { CurNormal, CurPressed, CurMove, CurResize }; /* cursor */ +@@ -242,6 +278,9 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++#define static ++ ++#ifdef HOT + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -253,7 +292,18 @@ static void axisnotify(struct wl_listener *listener, void *data); + static void buttonpress(struct wl_listener *listener, void *data); + static void chvt(const Arg *arg); + static void checkidleinhibitor(struct wlr_surface *exclude); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void cleanup(void); ++ ++#undef static ++#define static ++#ifdef HOT ++ + static void cleanupmon(struct wl_listener *listener, void *data); + static void closemon(Monitor *m); + static void commitlayersurfacenotify(struct wl_listener *listener, void *data); +@@ -321,7 +371,18 @@ static void requestdecorationmode(struct wl_listener *listener, void *data); + static void requeststartdrag(struct wl_listener *listener, void *data); + static void requestmonstate(struct wl_listener *listener, void *data); + static void resize(Client *c, struct wlr_box geo, int interact); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void run(char *startup_cmd); ++ ++#ifdef HOT ++#undef static ++#define static ++ + static void setcursor(struct wl_listener *listener, void *data); + static void setcursorshape(struct wl_listener *listener, void *data); + static void setfloating(Client *c, int floating); +@@ -332,7 +393,18 @@ static void setmfact(const Arg *arg); + static void setmon(Client *c, Monitor *m, uint32_t newtags); + static void setpsel(struct wl_listener *listener, void *data); + static void setsel(struct wl_listener *listener, void *data); ++ ++#undef static ++#define static extern ++#endif ++ ++/* this is cold */ + static void setup(void); ++ ++#ifdef HOT ++#undef static ++#define static ++ + static void spawn(const Arg *arg); + static void startdrag(struct wl_listener *listener, void *data); + static void tag(const Arg *arg); +@@ -356,6 +428,16 @@ static void xytonode(double x, double y, struct wlr_surface **psurface, + Client **pc, LayerSurface **pl, double *nx, double *ny); + static void zoom(const Arg *arg); + ++#endif ++ ++#ifdef HOT ++ #undef static ++ #define static extern ++#else ++ #undef static ++ #define static ++#endif ++ + /* variables */ + static const char broken[] = "broken"; + static pid_t child_pid = -1; +@@ -400,7 +482,9 @@ static struct wlr_scene_rect *root_bg; + static struct wlr_session_lock_manager_v1 *session_lock_mgr; + static struct wlr_scene_rect *locked_bg; + static struct wlr_session_lock_v1 *cur_lock; ++#ifdef HOT + static struct wl_listener lock_listener = {.notify = locksession}; ++#endif + + static struct wlr_seat *seat; + static KeyboardGroup *kb_group; +@@ -426,6 +510,33 @@ static struct wlr_xwayland *xwayland; + static xcb_atom_t netatom[NetLast]; + #endif + ++/* undoes the shadowing of static from above */ ++#undef static ++ ++/* this is where we put global hot-reload state */ ++#ifdef HOT ++#define COLD extern ++#else ++#define COLD ++ ++static void* load(void); ++static const char* get_module_path(void); ++ ++#endif ++ ++COLD void * dwl_module = NULL; ++COLD void * last_module = NULL; ++COLD struct listens* listeners = NULL; ++COLD void reload(const Arg* arg); ++ ++#ifndef HOT ++static char* runpath; ++ ++#endif ++ ++ ++#ifdef HOT ++ + /* configuration, allows nested code to access above variables */ + #include "config.h" + +@@ -673,6 +784,8 @@ checkidleinhibitor(struct wlr_surface *exclude) + wlr_idle_notifier_v1_set_inhibited(idle_notifier, inhibited); + } + ++#endif ++ + void + cleanup(void) + { +@@ -687,7 +800,7 @@ cleanup(void) + } + wlr_xcursor_manager_destroy(cursor_mgr); + +- destroykeyboardgroup(&kb_group->destroy, NULL); ++ TSYM(void (*)(struct wl_listener*, void*), destroykeyboardgroup)(&kb_group->destroy, NULL); + + /* If it's not destroyed manually it will cause a use-after-free of wlr_seat. + * Destroy it until it's fixed in the wlroots side */ +@@ -699,6 +812,8 @@ cleanup(void) + wlr_scene_node_destroy(&scene->tree.node); + } + ++#ifdef HOT ++ + void + cleanupmon(struct wl_listener *listener, void *data) + { +@@ -712,10 +827,10 @@ cleanupmon(struct wl_listener *listener, void *data) + wlr_layer_surface_v1_destroy(l->layer_surface); + } + +- wl_list_remove(&m->destroy.link); +- wl_list_remove(&m->frame.link); ++ UNLISTEN(&m->destroy); ++ UNLISTEN(&m->frame); + wl_list_remove(&m->link); +- wl_list_remove(&m->request_state.link); ++ UNLISTEN(&m->request_state); + m->wlr_output->data = NULL; + wlr_output_layout_remove(output_layout, m->wlr_output); + wlr_scene_output_destroy(m->scene_output); +@@ -848,7 +963,7 @@ commitpopup(struct wl_listener *listener, void *data) + box.x -= (type == LayerShell ? l->geom.x : c->geom.x); + box.y -= (type == LayerShell ? l->geom.y : c->geom.y); + wlr_xdg_popup_unconstrain_from_box(popup, &box); +- wl_list_remove(&listener->link); ++ UNLISTEN(listener); + } + + void +@@ -1179,8 +1294,8 @@ destroydecoration(struct wl_listener *listener, void *data) + Client *c = wl_container_of(listener, c, destroy_decoration); + c->decoration = NULL; + +- wl_list_remove(&c->destroy_decoration.link); +- wl_list_remove(&c->set_decoration_mode.link); ++ UNLISTEN(&c->destroy_decoration); ++ UNLISTEN(&c->set_decoration_mode); + } + + void +@@ -1205,9 +1320,9 @@ destroylayersurfacenotify(struct wl_listener *listener, void *data) + LayerSurface *l = wl_container_of(listener, l, destroy); + + wl_list_remove(&l->link); +- wl_list_remove(&l->destroy.link); +- wl_list_remove(&l->unmap.link); +- wl_list_remove(&l->surface_commit.link); ++ UNLISTEN(&l->destroy); ++ UNLISTEN(&l->unmap); ++ UNLISTEN(&l->surface_commit); + wlr_scene_node_destroy(&l->scene->node); + wlr_scene_node_destroy(&l->popups->node); + free(l); +@@ -1226,9 +1341,9 @@ destroylock(SessionLock *lock, int unlock) + motionnotify(0, NULL, 0, 0, 0, 0); + + destroy: +- wl_list_remove(&lock->new_surface.link); +- wl_list_remove(&lock->unlock.link); +- wl_list_remove(&lock->destroy.link); ++ UNLISTEN(&lock->new_surface); ++ UNLISTEN(&lock->unlock); ++ UNLISTEN(&lock->destroy); + + wlr_scene_node_destroy(&lock->scene->node); + cur_lock = NULL; +@@ -1242,7 +1357,7 @@ destroylocksurface(struct wl_listener *listener, void *data) + struct wlr_session_lock_surface_v1 *surface, *lock_surface = m->lock_surface; + + m->lock_surface = NULL; +- wl_list_remove(&m->destroy_lock_surface.link); ++ UNLISTEN(&m->destroy_lock_surface); + + if (lock_surface->surface != seat->keyboard_state.focused_surface) + return; +@@ -1262,22 +1377,22 @@ destroynotify(struct wl_listener *listener, void *data) + { + /* Called when the xdg_toplevel is destroyed. */ + Client *c = wl_container_of(listener, c, destroy); +- wl_list_remove(&c->destroy.link); +- wl_list_remove(&c->set_title.link); +- wl_list_remove(&c->fullscreen.link); ++ UNLISTEN(&c->destroy); ++ UNLISTEN(&c->set_title); ++ UNLISTEN(&c->fullscreen); + #ifdef XWAYLAND + if (c->type != XDGShell) { +- wl_list_remove(&c->activate.link); +- wl_list_remove(&c->associate.link); +- wl_list_remove(&c->configure.link); +- wl_list_remove(&c->dissociate.link); +- wl_list_remove(&c->set_hints.link); ++ UNLISTEN(&c->activate); ++ UNLISTEN(&c->associate); ++ UNLISTEN(&c->configure); ++ UNLISTEN(&c->dissociate); ++ UNLISTEN(&c->set_hints); + } else + #endif + { +- wl_list_remove(&c->commit.link); +- wl_list_remove(&c->map.link); +- wl_list_remove(&c->unmap.link); ++ UNLISTEN(&c->commit); ++ UNLISTEN(&c->map); ++ UNLISTEN(&c->unmap); + } + free(c); + } +@@ -1292,7 +1407,7 @@ destroypointerconstraint(struct wl_listener *listener, void *data) + active_constraint = NULL; + } + +- wl_list_remove(&pointer_constraint->destroy.link); ++ UNLISTEN(&pointer_constraint->destroy); + free(pointer_constraint); + } + +@@ -1306,8 +1421,8 @@ destroysessionlock(struct wl_listener *listener, void *data) + void + destroysessionmgr(struct wl_listener *listener, void *data) + { +- wl_list_remove(&lock_listener.link); +- wl_list_remove(&listener->link); ++ UNLISTEN(&lock_listener); ++ UNLISTEN(listener); + } + + void +@@ -1315,10 +1430,10 @@ destroykeyboardgroup(struct wl_listener *listener, void *data) + { + KeyboardGroup *group = wl_container_of(listener, group, destroy); + wl_event_source_remove(group->key_repeat_source); ++ UNLISTEN(&group->key); ++ UNLISTEN(&group->modifiers); ++ UNLISTEN(&group->destroy); + wlr_keyboard_group_destroy(group->wlr_group); +- wl_list_remove(&group->key.link); +- wl_list_remove(&group->modifiers.link); +- wl_list_remove(&group->destroy.link); + free(group); + } + +@@ -2212,6 +2327,8 @@ resize(Client *c, struct wlr_box geo, int interact) + wlr_scene_subsurface_tree_set_clip(&c->scene_surface->node, &clip); + } + ++#else /*HOT*/ ++ + void + run(char *startup_cmd) + { +@@ -2251,11 +2368,11 @@ run(char *startup_cmd) + if (fd_set_nonblock(STDOUT_FILENO) < 0) + close(STDOUT_FILENO); + +- printstatus(); ++ TSYM(void (*)(void), printstatus)(); + + /* At this point the outputs are initialized, choose initial selmon based on + * cursor position, and set default cursor image */ +- selmon = xytomon(cursor->x, cursor->y); ++ selmon = TSYM(Monitor* (*)(double x, double y), xytomon)(cursor->x, cursor->y); + + /* TODO hack to get cursor to display in its initial location (100, 100) + * instead of (0, 0) and then jumping. still may not be fully +@@ -2271,6 +2388,9 @@ run(char *startup_cmd) + wl_display_run(dpy); + } + ++#endif ++#ifdef HOT ++ + void + setcursor(struct wl_listener *listener, void *data) + { +@@ -2428,17 +2548,19 @@ setsel(struct wl_listener *listener, void *data) + wlr_seat_set_selection(seat, event->source, event->serial); + } + ++#else /*HOT*/ ++ + void + setup(void) + { + int i, sig[] = {SIGCHLD, SIGINT, SIGTERM, SIGPIPE}; +- struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = handlesig}; ++ struct sigaction sa = {.sa_flags = SA_RESTART, .sa_handler = SYM(handlesig)}; + sigemptyset(&sa.sa_mask); + + for (i = 0; i < (int)LENGTH(sig); i++) + sigaction(sig[i], &sa, NULL); + +- wlr_log_init(log_level, NULL); ++ wlr_log_init(CSYM(enum wlr_log_importance, log_level), NULL); + + /* The Wayland display is managed by libwayland. It handles accepting + * clients from the Unix socket, manging Wayland globals, and so on. */ +@@ -2454,7 +2576,7 @@ setup(void) + + /* Initialize the scene graph used to lay out windows */ + scene = wlr_scene_create(); +- root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, rootcolor); ++ root_bg = wlr_scene_rect_create(&scene->tree, 0, 0, TSYM(float*, rootcolor)); + for (i = 0; i < NUM_LAYERS; i++) + layers[i] = wlr_scene_tree_create(&scene->tree); + drag_icon = wlr_scene_tree_create(&scene->tree); +@@ -2550,7 +2672,7 @@ setup(void) + LISTEN_STATIC(&idle_inhibit_mgr->events.new_inhibitor, createidleinhibitor); + + session_lock_mgr = wlr_session_lock_manager_v1_create(dpy); +- wl_signal_add(&session_lock_mgr->events.new_lock, &lock_listener); ++ LISTEN_GLOBAL(&session_lock_mgr->events.new_lock, lock_listener); + LISTEN_STATIC(&session_lock_mgr->events.destroy, destroysessionmgr); + locked_bg = wlr_scene_rect_create(layers[LyrBlock], sgeom.width, sgeom.height, + (float [4]){0.1f, 0.1f, 0.1f, 1.0f}); +@@ -2620,7 +2742,7 @@ setup(void) + LISTEN_STATIC(&seat->events.request_start_drag, requeststartdrag); + LISTEN_STATIC(&seat->events.start_drag, startdrag); + +- kb_group = createkeyboardgroup(); ++ kb_group = TSYM(KeyboardGroup *(*)(void), createkeyboardgroup)(); + wl_list_init(&kb_group->destroy.link); + + output_mgr = wlr_output_manager_v1_create(dpy); +@@ -2647,6 +2769,9 @@ setup(void) + #endif + } + ++#endif ++#ifdef HOT ++ + void + spawn(const Arg *arg) + { +@@ -3121,8 +3246,8 @@ void + dissociatex11(struct wl_listener *listener, void *data) + { + Client *c = wl_container_of(listener, c, dissociate); +- wl_list_remove(&c->map.link); +- wl_list_remove(&c->unmap.link); ++ UNLISTEN(&c->map); ++ UNLISTEN(&c->unmap); + } + + xcb_atom_t +@@ -3185,17 +3310,141 @@ xwaylandready(struct wl_listener *listener, void *data) + } + #endif + ++#else /* HOT */ ++void* ++load(void) ++{ ++ const char* path = get_module_path(); ++ char load[PATH_MAX] = "/tmp/dwl.soXXXXXX"; ++ void* new; ++ ++ if (!path) { ++ fprintf(stderr, "cannot find dwl.so\n"); ++ } ++ ++ do { ++ mktemp(load); ++ errno = 0; ++ symlink(path, load); ++ } while(errno == EEXIST); ++ ++ new = dlopen(load, RTLD_NOW|RTLD_LOCAL); ++ ++ unlink(load); ++ if (new == NULL) ++ fprintf(stderr, "error while loading %s: %s\n", path, dlerror()); ++ else ++ printf("loaded: %s\n", path); ++ ++ return new; ++} ++ ++const char * ++get_module_path(void) { ++ char home[PATH_MAX]; ++ strcpy(home, getenv("HOME")); ++ strcat(home, "/.local/lib"); ++ const char* abspaths[] = {".", home, "/usr/share/lib", "/usr/local/lib", "/usr/local/share/lib"}; ++ const char* relpaths[] = {"", "/../lib"}; ++ char paths[LENGTH(abspaths) + LENGTH(relpaths)][PATH_MAX]; ++ static char out[PATH_MAX] = "./"; ++ ++ for (size_t i = 0; i < LENGTH(abspaths); i++) ++ realpath(abspaths[i], paths[i]); ++ ++ for (size_t i = 0; i < LENGTH(relpaths); i++) ++ { ++ char tmp[PATH_MAX]; ++ strcpy(tmp, runpath); ++ strcat(tmp, relpaths[i]); ++ realpath(tmp, paths[LENGTH(abspaths) + i]); ++ } ++ ++ ++ ++ for (size_t i = 0; i < LENGTH(paths); i++) ++ { ++ char tmp[PATH_MAX]; ++ printf("checking path: %s\n", paths[i]); ++ strcpy(tmp, paths[i]); ++ strcat(tmp, "/dwl.so"); ++ if (access(tmp, F_OK|R_OK) == 0) ++ { ++ strcpy(out, tmp); ++ return out; ++ } ++ } ++ ++ return NULL; ++} ++ ++void ++reload(const Arg* arg) ++{ ++ char* error; ++ void* new; ++ size_t i = 0; ++ ++ // deinitialize previous module ++ if (last_module) { ++ // dlclose(last_module); ++ last_module = NULL; ++ } ++ ++ wlr_log(WLR_INFO, "reloading"); ++ ++ new = load(); ++ ++ if (new == NULL) ++ { ++ wlr_log(WLR_ERROR, "couldn't load new dwl module from %s", get_module_path()); ++ ++ if (fork() == 0) ++ execl("/bin/env", "--", "Notify-send", "-u", "low", "failed to reload dwl", NULL); ++ return; ++ } ++ ++ wlr_log(WLR_DEBUG, "---------- listens ---------"); ++ for(listens* a = listeners; a != NULL; a = a->next) ++ { ++ Dl_info info; ++ void* old = a->listen->notify; ++ dladdr(a->listen->notify, &info); ++ a->listen->notify = dlsym(new, info.dli_sname); ++ if ((error = dlerror()) != NULL){ ++ fprintf(stderr, "reload failure: %s", error); ++ a->listen->notify = old; ++ return; ++ } ++ wlr_log(WLR_DEBUG, "replaced listener: %s", info.dli_sname); ++ i++; ++ } ++ ++ wlr_log(WLR_DEBUG, "---------- done! ---------"); ++ wlr_log(WLR_DEBUG, "replaced %zu listeners", i); ++ ++ last_module = dwl_module; ++ dwl_module = new; ++ ++ if (fork() == 0) ++ execl("/bin/env", "--", "notify-send", "-u", "low", "reloaded dwl", NULL); ++ ++} ++ + int + main(int argc, char *argv[]) + { + char *startup_cmd = NULL; + int c; + ++ runpath = dirname(argv[0]); ++ dwl_module = load(); ++ + while ((c = getopt(argc, argv, "s:hdv")) != -1) { + if (c == 's') + startup_cmd = optarg; + else if (c == 'd') +- log_level = WLR_DEBUG; ++ CSYM(enum wlr_log_importance, log_level) = WLR_DEBUG; + else if (c == 'v') + die("dwl " VERSION); + else +@@ -3215,3 +3464,5 @@ main(int argc, char *argv[]) + usage: + die("Usage: %s [-v] [-d] [-s startup command]", argv[0]); + } ++ ++#endif +diff --git a/util.c b/util.c +index 51130af..2000731 100644 +--- a/util.c ++++ b/util.c +@@ -49,3 +49,37 @@ fd_set_nonblock(int fd) { + + return 0; + } ++ ++struct listens* ++append_listener(struct wl_listener* new, struct listens* list) ++{ ++ struct listens* l = malloc(sizeof(struct listens)); ++ l->listen = new; ++ l->next = list; ++ return l; ++} ++ ++struct listens* ++remove_listener(struct wl_listener* l, struct listens* ls) ++{ ++ struct listens* out = ls; ++ struct listens* f = NULL; ++ for(struct listens* last = NULL; ls != NULL; ls = ls->next) ++ { ++ if (ls->listen == l) ++ { ++ if (last != NULL) ++ last->next = ls->next; ++ else ++ out = ls->next; ++ ++ f = ls; ++ } ++ else ++ last = ls; ++ } ++ ++ free(f); ++ ++ return out; ++} +diff --git a/util.h b/util.h +index 226980d..11aab34 100644 +--- a/util.h ++++ b/util.h +@@ -1,5 +1,11 @@ + /* See LICENSE.dwm file for copyright and license details. */ ++typedef struct listens { ++ struct wl_listener* listen; ++ struct listens* next; ++} listens; + + void die(const char *fmt, ...); + void *ecalloc(size_t nmemb, size_t size); + int fd_set_nonblock(int fd); ++struct listens* append_listener(struct wl_listener* l, struct listens* ls); ++struct listens* remove_listener(struct wl_listener* l, struct listens* ls); +-- +2.48.1 + |