SXB57HHWBQQIOEUXK65JKGXX4ZNSGXU55XHSEXU2YZSTFH3PYZRQC DPRID5UEAF6C2TPMTRPE2CQBGPQWXBRBIUOMABSJ7AICLMHYZPVAC TRGHSV7WZDJK4N2GYF54ZPP3SQKRN3L3XAPZ2NCAZU4SVMBCD2YQC SUD4YYZJGWJTQUBNBSYIPYSO22NCRI6MYTIUVNGTY5TD7FWKZ5UQC CGFALGMDL4Y5V4G7RY2ISQAWZTDXTE4CVDJL3EWSMGTE5CXGVWTQC GLMJBCVZQV44EBKNLIBESMJGWIG2QEU4F4L5KJ7IO4ALSM6LX4KQC N3SL4BMZY4QLRU6GRFT33T6TQKSBKXD5GYEFCHAXUJBH7XQPBBIAC 7EL6M5JX7NETLCKWGFWXU3ADIHQ2EKPCFHDMMDNFF5Y7WXHYG3ZAC TINMCJXVMLM3X5UM677SJNA6UGI3XCNMZ4ZOLQPBSRAOOY2USOSQC 7RLLU52RCOT2MQY4CPZTCDIA3FXETNPAISE5F2I7CI7TZW2SZVHAC PRKNMJFY3IHIRZH2QSJKLEAXQOONJITGHAZ4HOJTC35V2PPR2POAC HFIKAPN3TBMDVBDG7SZLX4ZJMSFFDGINTO6C2SKO5IVYUILGCQEQC 7B74AT3BXYB7PVW4F6SGQNPMHOU5TEV5TZ54CG6VSQI46XSEKWXQC GGAF2M67EYKDSJFLXEZ6TJ3FC2LDKTDD2TFBM3YRQDWI6ON3FV6AC ERBETXYU7NGSWW5LHQ3NSJA2N27JNMDDYMZ74B6IVQTEQMLRP6PAC R2ACAAQNXWMD77ITUPIXPHB6ZQH4PCXNFEK5L64HEXU3ETFZAHDAC AMKI4S66JRI3L5BH2A2BTQZKGJW2OFKUMOPSXT5EHP6LHLACLDEAC ZTOYJ4G4UQ665FKUH376KJOOO5GXHI62SWVXNZS7X6F2Y4GG2FSQC YCC55JJHQR3BEO3ZTP6NVDKTFU4NNNJP2SW755QMMUAIEBMXXIRAC CN4FS77B6FLSEDGAQ4R5YGHS56TNW7IGUR7RK4HKCLDX2627VBKAC JTZBFGPCDJDJWECXH2LLXY3SUAQNCP45HLJQKG3V7XGTPLD634WAC 7XCGFU3GX4TQXZBOU7GFAQ62EEOTVRNWFYQGI3XULFPSUKDZ2EYAC D425ND7AT3F7QJ3CCSESMVDOC3J5C5P32M5SJDBHECZJXLHNQ2FAC QKVRBSFOOQUQMZ3P7CMPA7QCVQW5TXAKWH6NDL3K7Q3Z4GMXOVPQC WMNBUD2PGH4XJP7UJNQXULQ475EIQUPEDPZOVU4AT2ALU3FHKFEQC HIFS24I32X4DPDLGVEK47AC3N2TRDUANPWFOZ5C52K4AGSITZLHAC 6XZIQSMIVP2GZ5S3UCKEVNDSLTHSQEVSXLV4UIFF3G3SRCGJPXYAC 6US7XFRJWUNIUZHKTODZDU3DX6WO5K3J2G3ECIQYSVBDII3DXGWAC S7RXJJZG4IEIVLPHEWFT5M2T3SRRO5US5SYBPXSYSWJJLXAKNNPAC 4WVZ2LAGAIQ2EROHNA4T5PWQEEIPJRTA3CBHGAO55NACCUGLKEZQC E7UO6NRGXFDMBU3BSJYRDNOA3Y7VHD7NWPHI5PHCPHQF6ZNOPZLQC CRDMPMNSQ5IALD7Y5TVHZE6KFFTWFPP33DWMBVRPDHP7HD2SLTPAC 4QUF4MKRSB5LYYS5FSYTCDSIEMYIERI2BQZLRGJ3GIGVYCPJVEPAC UXGT6OW6ENH6SWLVRF3JVS3WGTXPTKZPVOESJAGUSSLZT2WRASBAC QAPSVUOF7DV6R2PSLKLZUKC5TMB62ZYOUZ2NA6CHFOU6PSTJULWAC RKY73PZWOR4BJ7HARRPKL6X5VBP2UOMYUWHPNO5G5754XML75ZHQC YQQETCXBXPPLXBU3UPUIIKB3JZCHRFSW7PPP2DR436WVIXNXFUHAC 7HUMD4TAMWWBQDOZYCMWQXR66G3IU5WU3IVKTPCSMETSB6VREWTAC XXOC2AY53ZWML6TVPKX6BHGKZJNRET4IWRSTCVMJQJZMK3MFD3TQC PYI6X6HN7VRPTRIMCETLC7MOERACNHLMUJ3F5OMLLMFGTFT5F2IQC CENV55CAVVS7AIEOACYGIHLOJBGBX7GGSYJRU6GZ2XEMKYNUWGLQC KTZQPN4Y5YMJV72M54WVFCA6ZL6MIEMARZRIJBWQV5FY3A6S7OGAC RLFTJX3XEX5I2N5JDVBBYRN4INKH7MQGKC5SNJ4QFR243TRYKDXQC EQRGODLKSVSPFSUZU7BV5ER72U4QS4ATSBKV544XXQVKKTOSC7EAC 34TOMU43GSVTGKBSPBPRFLQYCJZ35HV2BNHKUAJ6CPE4XZLADCLQC AW7XCEBTLPKA5YP4T5P5SXX47QVPYETDFBSLV6KMJZNKN7BLO2EQC DVIBBDIRHCREHHOHZNQ2L3JJTW6GRSUGBHDJD2OKUBHWIBJ5WJUQC HGITBD7RZVPMWWPLFXDXW53LO5MWD4RVS77ZBFLORUIJMJ35IVDQC N54JKDQTHG2GSXAXR6PGMVVEKAHLKENNDSQ2IUGKQUDHGA72J4XQC HQ7H76DZBXQOQEYAB7WD76B5R6KSY65ANHC5XTLDDMPJ7KPYCOAAC DI2TRANVC5E5BKZAW2LTC355YI7O3VI32XB3PGBHU4V4X75325EQC CFECX3NOTBCQGTC7ZJOF2IAEJF55SZPHZJN57OZLPMZT24ERFIXQC ZEKBZDRVZJFHG75HZQVVQHO4G7RIY5OZTSI5G3BWIF566BRQBXHAC CD2JEM3MH5BXN7ADZAWLJFTRZG7PMDCKISDNJEO472PIBEJHBH2AC 3ZTG6CX4LPFTAV4AKALPCMGUCEA3XDE3O4LVTCBAQJDTBYO5ABCAC WWZVYE7LMUCWGQVPLJQQBD3ZNLJHGMMQJTLXXOAEXA7ETSXIHCQAC HONIZT6S2TNUT5XHRNWAJELT244HYO2WXYGRINBT6OONLTQ52JOQC V27TVOIQEKBQ5YYJUV4F762WEDPB2XYPWDYZRCAR5B65F3NDFTKAC HSAZJTBIAQFXHRMPSE6VZXIJFJTHG2LWAIPKIOER2NKCEMFHQMOQC YDFL47ANP2XUUHFLKSWQNG6FTRQAOYQMRE5DPGEDFKDHKZEEMLCQC WMN7AWGSUJORMCEMVPKDN22OK5WXUMLOKOG55RGBVPUIPSADXFZAC struct listens* append_listener(struct wl_listener* l, struct listens* ls);struct listens* remove_listener(struct wl_listener* l, struct listens* ls);
}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;elseout = ls->next;f = ls;}elselast = ls;}free(f);return out;
#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)
#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 COLDstatic void* load(void);static const char* get_module_path(void);#endifCOLD void * dwl_module = NULL;COLD void * last_module = NULL;COLD struct listens* listeners = NULL;COLD void reload(const Arg* arg);#ifndef HOTstatic char* runpath;
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 /* 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());elseprintf("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]);// printf("tmp: %s\n", tmp);strcat(tmp, "/dwl.so");if (access(tmp, F_OK|R_OK) == 0){strcpy(out, tmp);return out;}}return NULL;}voidreload(const Arg* arg){char* error;void* new;size_t i = 0;// deinitialize previous moduleif (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());system("notify-send -u low \"failed to reload dwl\"");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;system("notify-send -u low \"reloaded dwl\"");}
#endif
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.hdwl.so: dwl.c client.h config.h config.mk cursor-shape-v1-protocol.h \
.SUFFIXES: .c .so.c.so:$(CC) $(CPPFLAGS) $(DWLCFLAGS) -o $@ -shared -DHOT $<