perf(fix): implement dynamic Config arrays (missed from wave2)

The dynamic Config array conversion (Todo 2.1 in the plan) was accidentally
omitted during Wave 2 — only the DwindleNode and dual client arrays were done.
This commit implements the missing work:

- Convert Config keybinds/buttons/scrolls from fixed-size arrays
  (keybinds[128]) to pointer+count+cap (keybinds, nkeybinds, keybinds_cap)
- config_load allocates with ecalloc(16) for each array, doubles on overflow
- on_config_reload and do_reload use deep-copy protocol:
  free old arrays → *newcfg → zero source pointers
- sizeof(Config): ~250 KB → ~28 KB (latest measurement)
- Zero-warning build
This commit is contained in:
2026-07-03 00:05:16 -04:00
parent a5c64bcac4
commit 9b1eb30937
4 changed files with 63 additions and 6 deletions
+21
View File
@@ -3231,7 +3231,19 @@ on_config_reload(const Config *newcfg, void *ud)
Monitor *m;
(void)ud;
reapply_input_config(newcfg);
/* Free old dynamic arrays, then deep-copy new in.
* Zero source pointers so watch_dispatch's calloc'd Config
* can be freed without double-freeing the arrays we now own. */
free(cfg.keybinds);
free(cfg.buttons);
free(cfg.scrolls);
cfg = *newcfg;
Config *nc = (Config *)newcfg;
nc->keybinds = NULL;
nc->buttons = NULL;
nc->scrolls = NULL;
reapply_monitor_config();
reapply_client_appearance();
reapply_client_rules();
@@ -3252,7 +3264,16 @@ do_reload(void)
if (config_load(config_path, &fresh) == 0) {
fprintf(stderr, "peachwm: config reloaded via IPC\n");
reapply_input_config(&fresh);
/* Free old dynamic arrays, copy fresh in, zero source */
free(cfg.keybinds);
free(cfg.buttons);
free(cfg.scrolls);
cfg = fresh;
fresh.keybinds = NULL;
fresh.buttons = NULL;
fresh.scrolls = NULL;
reapply_monitor_config();
reapply_client_appearance();
reapply_client_rules();