commit 5cca9b2
0uppy
·
2026-03-13 15:38:14 +0000 UTC
parent 4af3e85
slgro 1.0 - Source directory
3 files changed,
+758,
-0
+57,
-0
1@@ -0,0 +1,57 @@
2+#ifndef CONFIG_H
3+#define CONFIG_H
4+
5+#include <xkbcommon/xkbcommon-keysyms.h>
6+
7+
8+#include "include/types.h"
9+#include "include/slgro.h"
10+
11+static const struct config cfg = {
12+ .motion_throttle_hz = 85,
13+ .border_col_active = 0xffed953e,
14+ .border_col_normal = 0xff444444,
15+ .border_width = 1,
16+ .gaps = 0,
17+};
18+
19+static const char* termcmd[] = { "havoc", NULL };
20+static struct bind binds[] = {
21+ { SWC_BINDING_KEY, MOD4, XKB_KEY_Return, { .v = termcmd }, spawn },
22+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_q, { .v = NULL }, quit },
23+ { SWC_BINDING_KEY, MOD4, XKB_KEY_Tab, { .v = NULL }, focus_next },
24+ { SWC_BINDING_KEY, MOD4, XKB_KEY_f, { .v = NULL }, fullscreen },
25+ { SWC_BINDING_KEY, MOD4, XKB_KEY_q, { .v = NULL }, kill_sel },
26+ { SWC_BINDING_KEY, MOD4, XKB_KEY_Right, { .i = 100 }, kb_move_x },
27+ { SWC_BINDING_KEY, MOD4, XKB_KEY_Left, { .i = -100 }, kb_move_x },
28+ { SWC_BINDING_KEY, MOD4, XKB_KEY_Down, { .i = 100 }, kb_move_y },
29+ { SWC_BINDING_KEY, MOD4, XKB_KEY_Up, { .i = -100 }, kb_move_y },
30+ { SWC_BINDING_KEY, MOD4, XKB_KEY_space, { .v = NULL }, center_window },
31+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_Right, { .i = 50 }, kb_resize_width },
32+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_Left, { .i = -50 }, kb_resize_width },
33+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_Down, { .i = 50 }, kb_resize_height },
34+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_Up, { .i = -50 }, kb_resize_height },
35+ { SWC_BINDING_KEY, MOD4, XKB_KEY_h, { .v = NULL }, snap_left_half },
36+ { SWC_BINDING_KEY, MOD4, XKB_KEY_l, { .v = NULL }, snap_right_half },
37+ { SWC_BINDING_KEY, MOD4, XKB_KEY_1, { .ui = 1 }, workspace_goto },
38+ { SWC_BINDING_KEY, MOD4, XKB_KEY_2, { .ui = 2 }, workspace_goto },
39+ { SWC_BINDING_KEY, MOD4, XKB_KEY_3, { .ui = 3 }, workspace_goto },
40+ { SWC_BINDING_KEY, MOD4, XKB_KEY_4, { .ui = 4 }, workspace_goto },
41+ { SWC_BINDING_KEY, MOD4, XKB_KEY_5, { .ui = 5 }, workspace_goto },
42+ { SWC_BINDING_KEY, MOD4, XKB_KEY_6, { .ui = 6 }, workspace_goto },
43+ { SWC_BINDING_KEY, MOD4, XKB_KEY_7, { .ui = 7 }, workspace_goto },
44+ { SWC_BINDING_KEY, MOD4, XKB_KEY_8, { .ui = 8 }, workspace_goto },
45+ { SWC_BINDING_KEY, MOD4, XKB_KEY_9, { .ui = 9 }, workspace_goto },
46+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_1, { .ui = 1 }, workspace_moveto },
47+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_2, { .ui = 2 }, workspace_moveto },
48+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_3, { .ui = 3 }, workspace_moveto },
49+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_4, { .ui = 4 }, workspace_moveto },
50+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_5, { .ui = 5 }, workspace_moveto },
51+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_6, { .ui = 6 }, workspace_moveto },
52+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_7, { .ui = 7 }, workspace_moveto },
53+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_8, { .ui = 8 }, workspace_moveto },
54+ { SWC_BINDING_KEY, MOD4|SHFT, XKB_KEY_9, { .ui = 9 }, workspace_moveto },
55+
56+};
57+
58+#endif /* CONFIG_H */
+657,
-0
1@@ -0,0 +1,657 @@
2+#include <asm-generic/errno.h>
3+#include <signal.h>
4+#include <stdio.h>
5+#include <stdlib.h>
6+#include <unistd.h>
7+
8+#include <swc.h>
9+#include <wayland-server.h>
10+#include <wayland-util.h>
11+#include <xkbcommon/xkbcommon-keysyms.h>
12+
13+#include "config.h"
14+#include "include/types.h"
15+#include "include/util.h"
16+#include "include/slgro.h"
17+
18+static void focus(struct client* c);
19+static struct client* first_client(struct screen* s);
20+static bool is_ws_client(const struct client* c, const struct screen* s);
21+static void on_screen_destroy(void* data);
22+static void on_win_destroy(void* data);
23+static void on_win_entered(void* data);
24+static void setup(void);
25+static void setup_binds(void);
26+static void sync_window_visibility(void);
27+
28+struct wm wm;
29+const struct swc_manager manager = {
30+ .new_screen = new_screen, .new_window = new_window, .new_device = new_device,
31+};
32+struct swc_window_handler window_handler = {
33+ .destroy = on_win_destroy, .entered = on_win_entered,
34+};
35+struct swc_screen_handler screen_handler = {
36+ .destroy = on_screen_destroy,
37+};
38+
39+static void focus(struct client* c)
40+{
41+ if (wm.sel_client)
42+ swc_window_set_border(
43+ wm.sel_client->win,
44+ cfg.border_col_normal, cfg.border_width,
45+ 0, 0
46+ );
47+
48+ if (c)
49+ swc_window_set_border(
50+ c->win,
51+ cfg.border_col_active, cfg.border_width,
52+ 0, 0
53+ );
54+
55+ swc_window_focus(c ? c->win : NULL);
56+ wm.sel_client = c;
57+}
58+
59+static struct client* first_client(struct screen* s)
60+{
61+ struct client* c;
62+
63+ wl_list_for_each(c, &wm.clients, link) {
64+ if (is_ws_client(c, s))
65+ return c;
66+ }
67+
68+ return NULL;
69+}
70+
71+static bool is_ws_client(const struct client* c, const struct screen* s)
72+{
73+ return c && c->ws == wm.ws && (!s || c->scr == s);
74+}
75+
76+static void on_screen_destroy(void* data)
77+{
78+ struct screen* s = data;
79+
80+ if (!s)
81+ return;
82+
83+ wl_list_remove(&s->link);
84+
85+ if (wm.sel_screen == s) {
86+ if (wl_list_empty(&wm.screens))
87+ wm.sel_screen = NULL;
88+ else
89+ wm.sel_screen = wl_container_of(wm.screens.next, wm.sel_screen, link);
90+ }
91+
92+ free(s);
93+}
94+
95+static void on_win_destroy(void* data)
96+{
97+ struct client* c = data;
98+ struct client* next;
99+
100+ if (!c)
101+ return;
102+
103+ if (wm.grab.active && wm.grab.c == c) {
104+ wm.grab.active = false;
105+ wm.grab.c = NULL;
106+ }
107+
108+ if (wm.sel_client == c) {
109+ wm.sel_client = NULL;
110+ }
111+
112+ wl_list_remove(&c->link);
113+ free(c);
114+
115+ next = first_client(wm.sel_screen);
116+ if (!next)
117+ next = first_client(NULL);
118+ focus(next);
119+}
120+
121+static void on_win_entered(void* data)
122+{
123+ if (wm.grab.active)
124+ return;
125+
126+ struct client* c = data;
127+ if (!is_ws_client(c, NULL))
128+ return;
129+
130+ focus(c);
131+}
132+
133+static void setup(void)
134+{
135+ /* display */
136+ wm.dpy = wl_display_create();
137+ if (!wm.dpy)
138+ die(EXIT_FAILURE, "wl_display_create failed");
139+
140+ /* variables */
141+ wl_list_init(&wm.screens);
142+ wl_list_init(&wm.clients);
143+ wm.sel_client = NULL;
144+ wm.sel_screen = NULL;
145+ wm.grab.active = false;
146+ wm.grab.resize = false;
147+ wm.grab.c = NULL;
148+ wm.ws = 1;
149+
150+ /* event loop */
151+ wm.ev_loop = wl_display_get_event_loop(wm.dpy);
152+ if (!swc_initialize(wm.dpy, wm.ev_loop, &manager))
153+ die(EXIT_FAILURE, "swc_initialize failed\n");
154+
155+ setup_binds();
156+
157+ /* display socket */
158+ const char* sock;
159+ sock = wl_display_add_socket_auto(wm.dpy);
160+ if (!sock)
161+ die(EXIT_FAILURE, "wl_display_add_socket_auto failed\n");
162+ setenv("WAYLAND_DISPLAY", sock, 1);
163+ _log(stderr, "WAYLAND_DISPLAY=%s\n", sock);
164+
165+ /* signals */
166+ signal(SIGINT, sig_handler);
167+ signal(SIGTERM, sig_handler);
168+ signal(SIGQUIT, sig_handler);
169+}
170+
171+static void setup_binds(void)
172+{
173+ for (size_t i = 0; i < LENGTH(binds); i++) {
174+ const struct bind* b = &binds[i];
175+ swc_add_binding(b->type, b->mods, b->ksym, b->fn, (void*)&b->arg);
176+ }
177+}
178+
179+static void sync_window_visibility(void)
180+{
181+ struct client* c;
182+
183+ wl_list_for_each(c, &wm.clients, link) {
184+ if (c->ws == wm.ws)
185+ swc_window_show(c->win);
186+ else
187+ swc_window_hide(c->win);
188+ }
189+}
190+
191+void focus_next(void* data, uint32_t time, uint32_t value, uint32_t state)
192+{
193+ (void)data;
194+ (void)time;
195+ (void)value;
196+
197+ struct client* c = NULL;
198+
199+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
200+ return;
201+
202+ if (wl_list_empty(&wm.clients))
203+ return;
204+
205+ if (!wm.sel_client || !is_ws_client(wm.sel_client, wm.sel_screen)) {
206+ c = first_client(wm.sel_screen);
207+ if (!c)
208+ c = first_client(NULL);
209+ focus(c);
210+ return;
211+ }
212+
213+ struct wl_list* start = wm.sel_client->link.next;
214+ struct wl_list* it = start;
215+
216+ do {
217+ if (it == &wm.clients)
218+ it = wm.clients.next;
219+ if (it == &wm.clients)
220+ break;
221+
222+ c = wl_container_of(it, c, link);
223+ if (is_ws_client(c, wm.sel_screen)) {
224+ focus(c);
225+ return;
226+ }
227+ it = it->next;
228+ } while (it != start);
229+
230+ c = first_client(wm.sel_screen);
231+ if (!c)
232+ c = first_client(NULL);
233+ focus(c);
234+}
235+
236+void focus_prev(void* data, uint32_t time, uint32_t value, uint32_t state)
237+{
238+ struct client* c = NULL;
239+
240+ (void)data;
241+ (void)time;
242+ (void)value;
243+
244+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
245+ return;
246+
247+ if (wl_list_empty(&wm.clients))
248+ return;
249+
250+ if (!wm.sel_client || !is_ws_client(wm.sel_client, wm.sel_screen)) {
251+ c = first_client(wm.sel_screen);
252+ if (!c)
253+ c = first_client(NULL);
254+ focus(c);
255+ return;
256+ }
257+
258+ struct wl_list* start = wm.sel_client->link.prev;
259+ struct wl_list* it = start;
260+
261+ do {
262+ if (it == &wm.clients)
263+ it = wm.clients.prev;
264+ if (it == &wm.clients)
265+ break;
266+
267+ c = wl_container_of(it, c, link);
268+ if (is_ws_client(c, wm.sel_screen)) {
269+ focus(c);
270+ return;
271+ }
272+ it = it->prev;
273+ } while (it != start);
274+
275+ c = first_client(wm.sel_screen);
276+ if (!c)
277+ c = first_client(NULL);
278+ focus(c);
279+}
280+
281+void kill_sel(void* data, uint32_t time, uint32_t value, uint32_t state)
282+{
283+ (void)data;
284+ (void)time;
285+ (void)value;
286+
287+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
288+ return;
289+
290+ if (!wm.sel_client)
291+ return;
292+
293+ swc_window_close(wm.sel_client->win);
294+}
295+
296+void fullscreen(void* data, uint32_t time, uint32_t value, uint32_t state)
297+{
298+ struct swc_rectangle geom;
299+
300+ (void)data;
301+ (void)time;
302+ (void)value;
303+
304+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
305+ return;
306+
307+ if (!wm.sel_client)
308+ return;
309+
310+ if (wm.sel_client->fullscreen) {
311+ wm.sel_client->fullscreen = false;
312+ swc_window_set_stacked(wm.sel_client->win);
313+
314+ if (wm.sel_client->w > 0 && wm.sel_client->h > 0) {
315+ geom.x = wm.sel_client->x;
316+ geom.y = wm.sel_client->y;
317+ geom.width = wm.sel_client->w;
318+ geom.height = wm.sel_client->h;
319+ swc_window_set_geometry(wm.sel_client->win, &geom);
320+ }
321+ return;
322+ }
323+
324+ if (!wm.sel_client->scr || !wm.sel_client->scr->scr)
325+ return;
326+
327+ if (swc_window_get_geometry(wm.sel_client->win, &geom)) {
328+ wm.sel_client->x = geom.x;
329+ wm.sel_client->y = geom.y;
330+ wm.sel_client->w = geom.width;
331+ wm.sel_client->h = geom.height;
332+ }
333+
334+ wm.sel_client->fullscreen = true;
335+ swc_window_set_fullscreen(wm.sel_client->win, wm.sel_client->scr->scr);
336+}
337+
338+/* slgro - im sure i could have made this better but atleast this works rn so ig that's what matters,, ill work on simplifying this another time,.,.*/
339+void kb_move_x(void* data, uint32_t time, uint32_t value, uint32_t state) {
340+
341+ (void)time;
342+ (void)value;
343+
344+ union arg* a = data;
345+ struct swc_rectangle geom;
346+
347+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
348+ return;
349+
350+ if (!wm.sel_client)
351+ return;
352+
353+ if (swc_window_get_geometry(wm.sel_client->win, &geom)) {
354+ geom.x += a->i;
355+ swc_window_set_geometry(wm.sel_client->win, &geom);
356+ }
357+
358+}
359+
360+void kb_move_y(void* data, uint32_t time, uint32_t value, uint32_t state) {
361+
362+ (void)time;
363+ (void)value;
364+
365+ union arg* a = data;
366+ struct swc_rectangle geom;
367+
368+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
369+ return;
370+
371+ if (!wm.sel_client)
372+ return;
373+
374+ if (swc_window_get_geometry(wm.sel_client->win, &geom)) {
375+ geom.y += a->i;
376+ swc_window_set_geometry(wm.sel_client->win, &geom);
377+ }
378+
379+}
380+
381+/* slgro - same thing here, ill figure out how to simplify this into one function another time, just focusing on making this work to begin with for now*/
382+void kb_resize_width(void* data, uint32_t time, uint32_t value, uint32_t state) {
383+
384+ (void)time;
385+ (void)value;
386+
387+ union arg* a = data;
388+ struct swc_rectangle geom;
389+
390+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
391+ return;
392+
393+ if (!wm.sel_client)
394+ return;
395+
396+ if (swc_window_get_geometry(wm.sel_client->win, &geom)) {
397+ geom.width += a->i;
398+ swc_window_set_geometry(wm.sel_client->win, &geom);
399+ }
400+
401+}
402+
403+void kb_resize_height(void* data, uint32_t time, uint32_t value, uint32_t state) {
404+
405+ (void)time;
406+ (void)value;
407+
408+ union arg* a = data;
409+ struct swc_rectangle geom;
410+
411+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
412+ return;
413+
414+ if (!wm.sel_client)
415+ return;
416+
417+ if (swc_window_get_geometry(wm.sel_client->win, &geom)) {
418+ geom.height += a->i;
419+ swc_window_set_geometry(wm.sel_client->win, &geom);
420+ }
421+
422+}
423+
424+/* slgro - idk if this is THAT useful but its kinda useful for me so that's what matters i suppose,,*/
425+void center_window(void* data, uint32_t time, uint32_t value, uint32_t state) {
426+
427+ (void)data;
428+ (void)value;
429+ (void)state;
430+ (void)time;
431+
432+ struct swc_rectangle geom;
433+
434+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
435+ return;
436+
437+ if (!wm.sel_client)
438+ return;
439+
440+ if (swc_window_get_geometry(wm.sel_client->win, &geom)) {
441+ geom.x = (wm.sel_client->scr->scr->usable_geometry.width / 2) - (geom.width / 2);
442+ geom.y = (wm.sel_client->scr->scr->usable_geometry.height / 2) - (geom.height / 2);
443+ swc_window_set_geometry(wm.sel_client->win, &geom);
444+ }
445+
446+}
447+
448+/* slgro - very experimental snapping, will prob refactor this at some point */
449+void snap_left_half(void* data, uint32_t time, uint32_t value, uint32_t state) {
450+
451+(void)data;
452+(void)value;
453+(void)state;
454+(void)time;
455+
456+struct swc_rectangle geom;
457+
458+if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
459+return;
460+
461+if (!wm.sel_client)
462+return;
463+
464+ geom.x = wm.sel_client->scr->scr->usable_geometry.x;
465+ geom.y = wm.sel_client->scr->scr->usable_geometry.y;
466+ geom.width = wm.sel_client->scr->scr->usable_geometry.width / 2;
467+ geom.height = wm.sel_client->scr->scr->usable_geometry.height;
468+ swc_window_set_geometry(wm.sel_client->win, &geom);
469+
470+}
471+
472+void snap_right_half(void* data, uint32_t time, uint32_t value, uint32_t state) {
473+
474+(void)data;
475+(void)value;
476+(void)state;
477+(void)time;
478+
479+struct swc_rectangle geom;
480+
481+if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
482+return;
483+
484+if (!wm.sel_client)
485+return;
486+
487+geom.x = wm.sel_client->scr->scr->usable_geometry.width / 2;
488+geom.y = wm.sel_client->scr->scr->usable_geometry.y;
489+geom.width = wm.sel_client->scr->scr->usable_geometry.width / 2;
490+geom.height = wm.sel_client->scr->scr->usable_geometry.height;
491+swc_window_set_geometry(wm.sel_client->win, &geom);
492+
493+}
494+
495+void new_screen(struct swc_screen* scr)
496+{
497+ struct screen* s;
498+
499+ s = malloc(sizeof(*s));
500+ if (!s)
501+ die(EXIT_FAILURE, "new screen calloc failed");
502+
503+ s->scr = scr;
504+
505+ s->x = 0;
506+ s->y = 0;
507+ s->w = 0;
508+ s->h = 0;
509+
510+ wl_list_insert(&wm.screens, &s->link);
511+
512+ if (!wm.sel_screen)
513+ wm.sel_screen = s;
514+
515+ swc_screen_set_handler(scr, &screen_handler, s);
516+
517+ _log(stderr, "new_screen=%p\n", (void*)scr);
518+}
519+
520+void new_window(struct swc_window* win)
521+{
522+ struct client* c;
523+
524+ c = malloc(sizeof(*c));
525+ if (!c)
526+ die(EXIT_FAILURE, "malloc client failed");
527+
528+ win->motion_throttle_ms = 1000 / cfg.motion_throttle_hz;
529+ win->min_width = 1;
530+ win->min_height = 1;
531+ win->max_width = 0;
532+ win->max_height = 0;
533+
534+ c->win = win;
535+ c->scr = wm.sel_screen;
536+ c->mapped = 0;
537+ c->floating = true;
538+ c->fullscreen = 0;
539+ c->ws = wm.ws;
540+ c->x = 0;
541+ c->y = 0;
542+ c->w = 0;
543+ c->h = 0;
544+
545+ wl_list_insert(&wm.clients, &c->link);
546+ swc_window_set_handler(win, &window_handler, c);
547+ swc_window_set_stacked(win);
548+ {
549+ /* swc reports cursor coordinates in wl_fixed_t (24.8) units */
550+ int32_t cx_fixed = 0;
551+ int32_t cy_fixed = 0;
552+
553+ if (swc_cursor_position(&cx_fixed, &cy_fixed))
554+ swc_window_set_position(win, cx_fixed / 256, cy_fixed / 256);
555+ }
556+ swc_window_show(win);
557+ focus(c);
558+
559+ _log(stderr, "new_window=%p\n", (void*)win);
560+}
561+
562+void new_device(struct libinput_device* dev)
563+{
564+ (void)dev;
565+}
566+
567+void quit(void* data, uint32_t time, uint32_t value, uint32_t state)
568+{
569+ (void)data;
570+ (void)time;
571+ (void)value;
572+ (void)state;
573+
574+ wl_display_terminate(wm.dpy);
575+}
576+
577+void spawn(void* data, uint32_t time, uint32_t value, uint32_t state)
578+{
579+ union arg* a = data;
580+ char* const* cmd = (char* const*)a->v;
581+
582+ (void)time;
583+ (void)value;
584+
585+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
586+ return;
587+
588+ if (fork() == 0) {
589+ execvp(cmd[0], cmd);
590+ _exit(127);
591+ }
592+}
593+
594+void workspace_goto(void* data, uint32_t time, uint32_t value, uint32_t state)
595+{
596+ union arg* a = data;
597+ struct client* c;
598+
599+ (void)time;
600+ (void)value;
601+
602+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
603+ return;
604+
605+ if (a->ui < 1 || a->ui > 9 || a->ui == wm.ws)
606+ return;
607+
608+ wm.ws = a->ui;
609+ sync_window_visibility();
610+
611+ c = first_client(wm.sel_screen);
612+ if (!c)
613+ c = first_client(NULL);
614+ focus(c);
615+}
616+
617+void workspace_moveto(void* data, uint32_t time, uint32_t value, uint32_t state)
618+{
619+ union arg* a = data;
620+ struct client* c;
621+ struct client* next;
622+
623+ (void)time;
624+ (void)value;
625+
626+ if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
627+ return;
628+
629+ if (!wm.sel_client)
630+ return;
631+
632+ if (a->ui < 1 || a->ui > 9)
633+ return;
634+
635+ c = wm.sel_client;
636+ if (c->ws == a->ui)
637+ return;
638+
639+ c->ws = a->ui;
640+ if (c->ws == wm.ws)
641+ swc_window_show(c->win);
642+ else
643+ swc_window_hide(c->win);
644+
645+ next = first_client(wm.sel_screen);
646+ if (!next)
647+ next = first_client(NULL);
648+ focus(next);
649+}
650+
651+int main(void)
652+{
653+ setup();
654+ wl_display_run(wm.dpy);
655+ swc_finalize();
656+ wl_display_destroy(wm.dpy);
657+ return EXIT_SUCCESS;
658+}
+44,
-0
1@@ -0,0 +1,44 @@
2+#include <stdlib.h>
3+
4+#include <swc.h>
5+
6+#include "include/util.h"
7+#include "include/slgro.h"
8+
9+void die(int ret, const char* fmt, ...)
10+{
11+ va_list ap;
12+
13+ fprintf(stderr, "slgro: ");
14+
15+ va_start(ap, fmt);
16+ vfprintf(stderr, fmt, ap);
17+ va_end(ap);
18+
19+ fputc('\n', stderr);
20+ fflush(stderr);
21+
22+ exit(ret);
23+}
24+
25+void _log(FILE* fd, const char* fmt, ...)
26+{
27+ va_list ap;
28+
29+ fprintf(fd, "slgro: ");
30+
31+ va_start(ap, fmt);
32+ vfprintf(fd, fmt, ap);
33+ va_end(ap);
34+
35+ fputc('\n', fd);
36+ fflush(fd);
37+}
38+
39+void sig_handler(int s)
40+{
41+ (void)s;
42+
43+ if (wm.dpy)
44+ wl_display_terminate(wm.dpy);
45+}