mirror of
				https://codeberg.org/dwl/dwl-patches.git
				synced 2025-10-31 12:04:23 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			771 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			771 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| 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
 | |
| 
 | 
