mirror of
https://codeberg.org/dwl/dwl-patches.git
synced 2025-09-06 19:24:51 +00:00
update hot-reload README with a more comprehensive explanation of how to integrate it with other patches.
This commit is contained in:
parent
83b68bee53
commit
50c6a46c35
@ -19,7 +19,8 @@ Note that you're responsible yourself for reloading ressources like fonts, which
|
||||
A lot of components of dwl will also only get run on a trigger (the tiling for example).
|
||||
So not every change will be immediate.
|
||||
Furthermore, any patch adding more global state to dwl cannot currently be reloaded properly since
|
||||
we keep state in the cold part.
|
||||
we keep state in the cold part. These patches will still work and their functionality will (hopefully) be
|
||||
reloadable but you will need to restart the compositor once.
|
||||
|
||||
#### Notes
|
||||
##### reduce compile errors
|
||||
@ -30,9 +31,71 @@ So you may want to disable this compile option in order to get readable compiler
|
||||
This does depend on you having a notification daemon like `dunst` or `mako` running as well as
|
||||
having `notify-send` installed in order for the compositor to inform you of the reload.
|
||||
|
||||
|
||||
#### How?
|
||||
Most of all dwl functionality is moved into a shared object file `dwl.so`, which can be reloaded at runtime.
|
||||
|
||||
#### How do I make this work with other patches?
|
||||
Most patches should already put everything in more or less the correct place but if they don't, then here is
|
||||
where you learn how to fix it.
|
||||
|
||||
The concept itself is quite simple. We compile dwl.c twice once normally and once with the `HOT` macro defined.
|
||||
The first run will yield the executable and the second will yield a shared object file to be reloaded at runtime.
|
||||
From the cold part there are some newly available macros:
|
||||
> symbol names are written as-is, never as string literals
|
||||
* `TSYM(T, s)` dynamically loads the symbol `s` with type `T` from the shared object file use this if you need to call functions in the cold part (i.e. the `setup` function).
|
||||
* `CSYM(T, v)` dynamically accesses the value of the symbol `v` of type `T` from the shared object. Use this to query values from config.h for example.
|
||||
* `LISTEN_GLOBAL(E, L)` is similar to the `LISTEN` macro. `E` is an event and `L` the name of a global
|
||||
listener. Current implementation is a bit messy and I may fix it if someone bothers me about it.
|
||||
* `UNLISTEN(L)` takes a listener and unregisteres it. This is important for reloading.
|
||||
|
||||
When adding new code there are some considerations to be made. Since dwl decorates all symbols with `static` by default, we cannot access them as-is.
|
||||
C's macro system is a bit too powerful though and we use this to our advantage. We will repeatedly define and
|
||||
undefine a macro called `static` in order to replace the `static` keyword inside some sections.
|
||||
This allows us to do less refactoring and preserve a lot of the original patch compatability since we're only
|
||||
strategically adding lines.
|
||||
As a general guide:
|
||||
* global state should be global for the cold part and `extern` in the cold part meaning it should be inside a block like this:
|
||||
```C
|
||||
#ifdef HOT
|
||||
#define static extern
|
||||
#else
|
||||
#define static
|
||||
#endif
|
||||
... // your global variables go here
|
||||
#undef static
|
||||
```
|
||||
* function declarations should be visible in the hot part but not included in the cold part meaning they should be enclosed like this:
|
||||
```C
|
||||
#ifdef HOT
|
||||
#define static
|
||||
... // your function declarations go here
|
||||
#undef static
|
||||
#endif
|
||||
```
|
||||
* static data like the event handler structs in the current `main` branch are a bit more difficult but we will let them reside inside the hot part.
|
||||
Thus, we enclose them the same way we do functions:
|
||||
```C
|
||||
#ifdef HOT
|
||||
#define static
|
||||
... // your struct wl_listener event handlers go here
|
||||
#undef static
|
||||
#endif
|
||||
```
|
||||
* function definitions should go in the hot part, so they need to be inside a big block like this:
|
||||
```C
|
||||
#ifdef HOT
|
||||
... // function definitions here
|
||||
#endif
|
||||
* enfore use of the `LISTEN_GLOBAL` and `UNLISTEN` macros (I know this sucks but what can I do, I need to get
|
||||
access to the callbacks somehow). So you want
|
||||
* `wl_list_remove(listener.link)` to become `UNLISTEN(listener)` and
|
||||
* `wl_signal_add(event, global_listener)` to become `LISTEN_GLOBAL(event, global)listener`.
|
||||
* Make sure that any patch you're using also uses static everywhere.
|
||||
Note that you do not have to create additional such feature blocks most of the time (there's a huge
|
||||
`#ifdef HOT`-delimited codeblock at the bottom of dwl.c where all the function definitions go for example).
|
||||
If you have any troubles, feel free to reach out.
|
||||
|
||||
### Download
|
||||
- [0.7](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload-0.7.patch)
|
||||
- [main 2025-05-30](/dwl/dwl-patches/raw/branch/main/patches/hot-reload/hot-reload.patch)
|
||||
|
Loading…
x
Reference in New Issue
Block a user