dwl-patches/patches/hot-reload/hot-reload-0.7.patch

771 lines
23 KiB
Diff

From 559c635056f23d55df3f83c12d1201a7328f648f 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..e7ee9ff 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 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
+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..1c9ab67 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.49.0