commit a3db7c5

soggy  ·  2026-11-05 18:32:11 +0000 UTC
parent a4adaa6
slgro - config can now autostart stuff + tweaked the window movement and snapping
6 files changed,  +286, -96
+18, -9
 1@@ -1,17 +1,24 @@
 2-border_active          = 0xff000000
 3-border_normal          = 0xff000000
 4-border_width           = 2
 5+border_active	= 0xff000000
 6+border_normal	= 0xff000000
 7+border_width	= 2
 8 
 9 -- for those who may want double borders, uncomment these !!
10---border_active_outer    = 0xffffffff
11---border_normal_outer    = 0xffffffff
12---border_width_outher    = 2
13+--border_active_outer	= 0xffffffff
14+--border_normal_outer	= 0xffffffff
15+--border_width_outher	= 2
16 
17-motion_throttle_hz     = 85
18+motion_throttle_hz	= 85
19 
20 terminal    = "foot"
21 menu        = "neumenu_run"
22 
23+autostart = {
24+	-- i forgor who suggested me to add autostart, but, thank you for the suggestion, and, here it is ^^
25+	
26+	-- to add smth to autostart the syntax is just
27+	-- "/home/dani/Prog/Scripts/verycoolscript.sh",
28+}
29+
30 binds = {
31     { mods="MOD4",       key="q",      action="spawn",          arg=terminal },
32     { mods="MOD4",       key="d",      action="spawn",          arg=menu },
33@@ -31,7 +38,9 @@ binds = {
34     { mods="MOD4|SHFT",  key="Left",   action="resize_width",   arg=-25 },
35     { mods="MOD4|SHFT",  key="Down",   action="resize_height",  arg=25 },
36     { mods="MOD4|SHFT",  key="Up",     action="resize_height",  arg=-25 },
37-    { mods="MOD4",       key="h",      action="snap_left" },
38+		{ mods="MOD4",			 key="k",			 action="snap_top" },
39+		{ mods="MOD4",			 key="j",			 action="snap_bottom" },
40+		{ mods="MOD4",       key="h",      action="snap_left" },
41     { mods="MOD4",       key="l",      action="snap_right" },
42     { mods="MOD4|SHFT",  key="Return", action="quit" },
43     { mods="MOD4",       key="1",      action="workspace_goto",   arg=1 },
44@@ -52,4 +61,4 @@ binds = {
45     { mods="MOD4|SHFT",  key="7",      action="workspace_moveto", arg=7 },
46     { mods="MOD4|SHFT",  key="8",      action="workspace_moveto", arg=8 },
47     { mods="MOD4|SHFT",  key="9",      action="workspace_moveto", arg=9 },
48-}
49+}
+2, -0
1@@ -12,6 +12,8 @@ extern void kb_move_x(void* data, uint32_t time, uint32_t value, uint32_t state)
2 extern void kb_move_y(void* data, uint32_t time, uint32_t value, uint32_t state);
3 extern void kb_resize_width(void* data, uint32_t time, uint32_t value, uint32_t state);
4 extern void kb_resize_height(void* data, uint32_t time, uint32_t value, uint32_t state);
5+void snap_top_half(void*, uint32_t, uint32_t, uint32_t);
6+void snap_bottom_half(void*, uint32_t, uint32_t, uint32_t);
7 extern void snap_left_half(void* data, uint32_t time, uint32_t value, uint32_t state);
8 extern void snap_right_half(void* data, uint32_t time, uint32_t value, uint32_t state);
9 extern void center_window(void* data, uint32_t time, uint32_t value, uint32_t state);
+1, -1
1@@ -76,4 +76,4 @@ struct wm {
2 	uint8_t        ws;
3 };
4 
5-#endif /* TYPES_H */
6+#endif /* TYPES_H */
+105, -18
  1@@ -2,9 +2,11 @@
  2 #include <luajit-2.1/lauxlib.h>
  3 #include <luajit-2.1/lualib.h>
  4 #include <xkbcommon/xkbcommon-keysyms.h>
  5+#include <sys/wait.h>
  6 #include <string.h>
  7 #include <stdlib.h>
  8 #include <stdio.h>
  9+#include <unistd.h>
 10 
 11 #include "include/types.h"
 12 #include "include/slgro.h"
 13@@ -14,31 +16,44 @@ struct bind *binds = NULL;
 14 size_t nbinds = 0;
 15 
 16 static char *spawn_args[128][2];
 17+static char *autostart[128];
 18+static size_t nautostart = 0;
 19 static size_t nspawn = 0;
 20 
 21-static uint32_t parse_mods(const char *s)
 22+static uint32_t parse_mods
 23+(const char *s)
 24 {
 25-    uint32_t mods = 0;
 26+	uint32_t mods = 0;
 27     char buf[64];
 28-    strncpy(buf, s, sizeof(buf) - 1);
 29-    char *tok = strtok(buf, "|");
 30-    while (tok) {
 31+
 32+    if (!s) return 0;
 33+    
 34+	strncpy(buf, s, sizeof(buf) - 1);
 35+    buf[sizeof(buf) - 1] = '\0';
 36+    
 37+	char *tok = strtok(buf, "|");
 38+	while (tok) {
 39+
 40         if      (!strcmp(tok, "MOD4")) mods |= SWC_MOD_LOGO;
 41         else if (!strcmp(tok, "MOD1")) mods |= SWC_MOD_ALT;
 42         else if (!strcmp(tok, "SHFT")) mods |= SWC_MOD_SHIFT;
 43         else if (!strcmp(tok, "CTRL")) mods |= SWC_MOD_CTRL;
 44         tok = strtok(NULL, "|");
 45     }
 46+
 47     return mods;
 48 }
 49 
 50-static uint32_t parse_key(const char *s)
 51+static uint32_t parse_key
 52+(const char *s)
 53 {
 54     if (s[1] == '\0') {
 55+
 56         if (s[0] >= 'a' && s[0] <= 'z') return XKB_KEY_a + (s[0] - 'a');
 57         if (s[0] >= '1' && s[0] <= '9') return XKB_KEY_1 + (s[0] - '1');
 58         if (s[0] == '0') return XKB_KEY_0;
 59     }
 60+
 61     if (!strcmp(s, "Return")) return XKB_KEY_Return;
 62     if (!strcmp(s, "Tab"))    return XKB_KEY_Tab;
 63     if (!strcmp(s, "space"))  return XKB_KEY_space;
 64@@ -47,24 +62,31 @@ static uint32_t parse_key(const char *s)
 65     if (!strcmp(s, "Up"))     return XKB_KEY_Up;
 66     if (!strcmp(s, "Down"))   return XKB_KEY_Down;
 67     fprintf(stderr, "slgro: sorry, unknown key >.< '%s'\n", s);
 68-    return XKB_KEY_VoidSymbol;
 69+    
 70+	return XKB_KEY_VoidSymbol;
 71 }
 72 
 73-static void resolve_action(const char *action, const char *arg_str, int arg_int, struct bind *b)
 74+static void resolve_action
 75+(const char *action, const char *arg_str, int arg_int, struct bind *b)
 76 {
 77     b->type = SWC_BINDING_KEY;
 78-    if (!strcmp(action, "spawn")) {
 79+
 80+	if (!strcmp(action, "spawn")) {
 81+
 82         spawn_args[nspawn][0] = strdup(arg_str);
 83         spawn_args[nspawn][1] = NULL;
 84         b->arg.v = spawn_args[nspawn++];
 85         b->fn = spawn;
 86     }
 87+
 88     else if (!strcmp(action, "kill"))             b->fn = kill_sel;
 89     else if (!strcmp(action, "focus_next"))       b->fn = focus_next;
 90     else if (!strcmp(action, "fullscreen"))       b->fn = fullscreen;
 91-    else if (!strcmp(action, "center"))           b->fn = center_window;
 92-    else if (!strcmp(action, "snap_left"))        b->fn = snap_left_half;
 93-    else if (!strcmp(action, "snap_right"))       b->fn = snap_right_half;
 94+	else if (!strcmp(action, "center"))           b->fn = center_window;
 95+	else if (!strcmp(action, "snap_top"))		  b->fn = snap_top_half;
 96+	else if	(!strcmp(action, "snap_bottom"))	  b->fn = snap_bottom_half;
 97+	else if (!strcmp(action, "snap_left"))        b->fn = snap_left_half;
 98+	else if (!strcmp(action, "snap_right"))       b->fn = snap_right_half;
 99     else if (!strcmp(action, "quit"))             b->fn = quit;
100     else if (!strcmp(action, "move_x"))         { b->fn = kb_move_x;        b->arg.i  = arg_int; }
101     else if (!strcmp(action, "move_y"))         { b->fn = kb_move_y;        b->arg.i  = arg_int; }
102@@ -75,7 +97,8 @@ static void resolve_action(const char *action, const char *arg_str, int arg_int,
103     else fprintf(stderr, "slgro: sorry, unknown action >.< '%s'\n", action);
104 }
105 
106-void load_config(void)
107+void load_config
108+(void)
109 {
110     const char *home = getenv("HOME");
111     char path[256];
112@@ -95,7 +118,9 @@ void load_config(void)
113     luaL_openlibs(L);
114 
115     if (luaL_dofile(L, path) != LUA_OK) {
116+
117         if (luaL_dofile(L, "/usr/share/slgro/config.lua") != LUA_OK) {
118+
119             fprintf(stderr, "slgro: %s\n", lua_tostring(L, -1));
120             fprintf(stderr, "slgro: using defaults :P\n");
121             lua_close(L);
122@@ -103,6 +128,31 @@ void load_config(void)
123         }
124     }
125 
126+    lua_getglobal(L, "autostart");
127+
128+	if (lua_istable(L, -1)) {
129+
130+        size_t n = lua_objlen(L, -1);
131+
132+        for (size_t i = 1; i <= n && nautostart < 128; i++) {
133+
134+            lua_rawgeti(L, -1, i);
135+
136+            if (lua_isstring(L, -1)) {
137+
138+                autostart[nautostart] = strdup(lua_tostring(L, -1));
139+                
140+				if (autostart[nautostart])
141+                    
142+					nautostart++;
143+            }
144+
145+            lua_pop(L, 1);
146+        }
147+    }
148+
149+    lua_pop(L, 1);
150+
151     lua_getglobal(L, "border_active");
152     if (lua_isnumber(L, -1)) cfg.border_col_active = (uint32_t)lua_tonumber(L, -1);
153     lua_pop(L, 1);
154@@ -128,21 +178,31 @@ void load_config(void)
155     lua_pop(L, 1);
156 
157     lua_getglobal(L, "motion_throttle_hz");
158-    if (lua_isnumber(L, -1)) cfg.motion_throttle_hz = (uint32_t)lua_tonumber(L, -1);
159+	if (lua_isnumber(L, -1)) cfg.motion_throttle_hz = (uint32_t)lua_tonumber(L, -1);
160     lua_pop(L, 1);
161 
162     lua_getglobal(L, "binds");
163+
164     if (!lua_istable(L, -1)) {
165+
166         fprintf(stderr, "slgro: couldn't find the binds table :<\n");
167         lua_close(L);
168         return;
169     }
170 
171     int binds_index = lua_gettop(L);
172-    size_t n = lua_objlen(L, binds_index);
173-    binds = calloc(n, sizeof(struct bind));
174+    size_t n = lua_objlen(L, binds_index);	
175+	binds = calloc(n, sizeof(struct bind));
176+
177+	if (n && !binds) {
178+
179+		fprintf(stderr, "slgro: couldn't allocate bindings :<\n");
180+		lua_close(L);
181+		return;
182+	}
183 
184     for (size_t i = 1; i <= n; i++) {
185+
186         lua_rawgeti(L, binds_index, i);
187         struct bind b = {0};
188 
189@@ -164,9 +224,36 @@ void load_config(void)
190         lua_pop(L, 1);
191 
192         if (action) resolve_action(action, arg_str, arg_int, &b);
193-        binds[nbinds++] = b;
194+        if (b.fn) binds[nbinds++] = b;
195         lua_pop(L, 1);
196     }
197 
198-    lua_close(L); /* man i love lua :3 */
199+    lua_close(L);
200+}
201+
202+void run_autostart
203+(void)
204+{
205+    for (size_t i = 0; i < nautostart; i++) {
206+
207+        pid_t pid = fork();
208+
209+        if (pid == 0) {
210+
211+            setsid();
212+
213+            if (fork() == 0) {
214+
215+                execl("/bin/sh", "sh", "-c", autostart[i], (char *)NULL);
216+                _exit(127);
217+            }
218+
219+            _exit(0);
220+        } 
221+
222+		else if (pid > 0) {
223+
224+            waitpid(pid, NULL, 0);
225+        }
226+    }
227 }
+154, -65
  1@@ -15,6 +15,7 @@ extern struct config cfg;
  2 extern struct bind *binds;
  3 extern size_t nbinds;
  4 extern void load_config(void);
  5+extern void run_autostart(void);
  6 
  7 #include "include/types.h"
  8 #include "include/util.h"
  9@@ -43,20 +44,23 @@ static void sync_window_visibility(void);
 10     union arg* a = (data)
 11 
 12 /* read geometry from client window; returns true if successful */
 13-static bool get_geometry(struct client *c, struct swc_rectangle *geom)
 14+static bool get_geometry
 15+(struct client *c, struct swc_rectangle *geom)
 16 {
 17     if (!c || !c->win)
 18-        return false;
 19+		return false;
 20 
 21     return swc_window_get_geometry(c->win, geom);
 22 }
 23 
 24 /* adjust geometry fields and write back */
 25-static void adjust_geom(struct client *c, int dx, int dy, int dw, int dh)
 26+static void adjust_geom
 27+(struct client *c, int dx, int dy, int dw, int dh)
 28 {
 29     struct swc_rectangle geom;
 30-    if (!get_geometry(c, &geom)) return;
 31-
 32+    if (!get_geometry(c, &geom)) 
 33+		return;
 34+	
 35     geom.x += dx;
 36     geom.y += dy;
 37 
 38@@ -79,54 +83,65 @@ struct swc_screen_handler screen_handler = {
 39     .destroy = on_screen_destroy,
 40 };
 41 
 42-static struct client* get_focus_candidate(struct screen* s)
 43+static struct client* get_focus_candidate
 44+(struct screen* s)
 45 {
 46     struct client* c = first_client(s);
 47     if (!c && s) c = first_client(NULL);
 48-    return c;
 49+		
 50+	return c;
 51 }
 52 
 53-static void focus(struct client* c)
 54+static void focus
 55+(struct client* c)
 56 {
 57     if (wm.sel_client && wm.sel_client != c) {
 58-        swc_window_set_border(wm.sel_client->win, cfg.border_col_normal, cfg.border_width, cfg.border_col_normal_outer, cfg.border_width_outer);
 59+
 60+		swc_window_set_border(wm.sel_client->win, cfg.border_col_normal, cfg.border_width, cfg.border_col_normal_outer, cfg.border_width_outer);
 61     }
 62+
 63     if (c) {
 64-        swc_window_set_border(c->win, cfg.border_col_active, cfg.border_width, cfg.border_col_active_outer, cfg.border_width_outer);
 65+        
 66+		swc_window_set_border(c->win, cfg.border_col_active, cfg.border_width, cfg.border_col_active_outer, cfg.border_width_outer);
 67     }
 68 
 69     swc_window_focus(c ? c->win : NULL);
 70     wm.sel_client = c;
 71 }
 72 
 73-static struct client* first_client(struct screen* s)
 74+static struct client* first_client
 75+(struct screen* s)
 76 {
 77     struct client* c;
 78 
 79     wl_list_for_each(c, &wm.clients, link) {
 80+
 81         if (is_ws_client(c, s))
 82-            return c;
 83+			return c;
 84     }
 85 
 86     return NULL;
 87 }
 88 
 89-static bool is_ws_client(const struct client* c, const struct screen* s)
 90+static bool is_ws_client
 91+(const struct client* c, const struct screen* s)
 92 {
 93     return c && c->ws == wm.ws && (!s || c->scr == s);
 94 }
 95 
 96-static void on_screen_destroy(void* data)
 97+static void on_screen_destroy
 98+(void* data)
 99 {
100     struct screen* s = data;
101 
102     if (!s)
103-        return;
104+		return;
105 
106     wl_list_remove(&s->link);
107 
108     if (wm.sel_screen == s) {
109-        wm.sel_screen = wl_list_empty(&wm.screens)
110+        
111+		wm.sel_screen = wl_list_empty(&wm.screens)
112             ? NULL
113             : wl_container_of(wm.screens.next, wm.sel_screen, link);
114     }
115@@ -134,10 +149,12 @@ static void on_screen_destroy(void* data)
116     free(s);
117 }
118 
119-static void on_win_destroy(void* data)
120+static void on_win_destroy
121+(void* data)
122 {
123     struct client* c = data;
124-    if (!c) return;
125+    if (!c) 
126+		return;
127 
128     if (wm.sel_client == c)
129         wm.sel_client = NULL;
130@@ -148,7 +165,8 @@ static void on_win_destroy(void* data)
131     focus(get_focus_candidate(wm.sel_screen));
132 }
133 
134-static void on_win_entered(void* data)
135+static void on_win_entered
136+(void* data)
137 {
138     struct client* c = data;
139     if (!is_ws_client(c, NULL))
140@@ -157,13 +175,14 @@ static void on_win_entered(void* data)
141     focus(c);
142 }
143 
144-static void setup(void)
145+static void setup
146+(void)
147 {
148     /* display */
149     load_config();
150     wm.dpy = wl_display_create();
151     if (!wm.dpy)
152-        die(EXIT_FAILURE, "wl_display_create failed");
153+		die(EXIT_FAILURE, "wl_display_create failed");
154 
155     /* variables */
156     wl_list_init(&wm.screens);
157@@ -176,7 +195,7 @@ static void setup(void)
158     /* event loop */
159     wm.ev_loop = wl_display_get_event_loop(wm.dpy);
160     if (!swc_initialize(wm.dpy, wm.ev_loop, &manager))
161-        die(EXIT_FAILURE, "swc_initialize failed\n");
162+		die(EXIT_FAILURE, "swc_initialize failed\n");
163 
164     setup_binds();
165 
166@@ -184,43 +203,51 @@ static void setup(void)
167     const char* sock;
168     sock = wl_display_add_socket_auto(wm.dpy);
169     if (!sock)
170-        die(EXIT_FAILURE, "wl_display_add_socket_auto failed\n");
171+		die(EXIT_FAILURE, "wl_display_add_socket_auto failed\n");
172 
173     setenv("WAYLAND_DISPLAY", sock, 1);
174     _log(stderr, "WAYLAND_DISPLAY=%s\n", sock);
175 
176+	run_autostart();
177+
178     /* signals */
179     signal(SIGINT,  sig_handler);
180     signal(SIGTERM, sig_handler);
181     signal(SIGQUIT, sig_handler);
182 }
183 
184-static void setup_binds(void)
185+static void setup_binds
186+(void)
187 {
188     for (size_t i = 0; i < nbinds; i++) {
189-        const struct bind* b = &binds[i];
190+        
191+		const struct bind* b = &binds[i];
192         swc_add_binding(b->type, b->mods, b->ksym, b->fn, (void*)&b->arg);
193     }
194 }
195 
196-static void sync_window_visibility(void)
197+static void sync_window_visibility
198+(void)
199 {
200     struct client* c;
201 
202     wl_list_for_each(c, &wm.clients, link) {
203         if (c->ws == wm.ws)
204-            swc_window_show(c->win);
205-        else
206+			swc_window_show(c->win);
207+        
208+		else
209             swc_window_hide(c->win);
210     }
211 }
212 
213 /* focus next/prev helpers */
214-static void focus_walk_direction(bool forward)
215+static void focus_walk_direction
216+(bool forward)
217 {
218     if (wl_list_empty(&wm.clients)) return;
219 
220     if (!is_ws_client(wm.sel_client, wm.sel_screen)) {
221+
222         focus(get_focus_candidate(wm.sel_screen));
223         return;
224     }
225@@ -239,24 +266,30 @@ static void focus_walk_direction(bool forward)
226         if (it == &wm.clients) break;
227 
228         c = wl_container_of(it, c, link);
229-        if (is_ws_client(c, wm.sel_screen)) {
230+
231+		if (is_ws_client(c, wm.sel_screen)) {
232+
233             focus(c);
234             return;
235         }
236 
237         it = forward ? it->next : it->prev;
238-    } while (it != start);
239+    } 
240+
241+	while (it != start);
242 
243     focus(get_focus_candidate(wm.sel_screen));
244 }
245 
246-void focus_next(void* data, uint32_t time, uint32_t value, uint32_t state)
247+void focus_next
248+(void* data, uint32_t time, uint32_t value, uint32_t state)
249 {
250     (void)data; BIND_EVENT(time, value, state);
251     focus_walk_direction(true);
252 }
253 
254-void kill_sel(void* data, uint32_t time, uint32_t value, uint32_t state)
255+void kill_sel
256+(void* data, uint32_t time, uint32_t value, uint32_t state)
257 {
258     (void)data; BIND_EVENT(time, value, state);
259 
260@@ -264,28 +297,35 @@ void kill_sel(void* data, uint32_t time, uint32_t value, uint32_t state)
261         swc_window_close(wm.sel_client->win);
262 }
263 
264-void fullscreen(void* data, uint32_t time, uint32_t value, uint32_t state)
265+void fullscreen
266+(void* data, uint32_t time, uint32_t value, uint32_t state)
267 {
268     (void)data; BIND_EVENT(time, value, state);
269-    if (!wm.sel_client) return;
270+    
271+	if (!wm.sel_client) 
272+		return;
273 
274     struct client *c = wm.sel_client;
275     struct swc_rectangle geom;
276 
277     if (c->fullscreen) {
278+
279         c->fullscreen = false;
280         swc_window_set_stacked(c->win);
281 
282         if (c->w > 0 && c->h > 0) {
283+
284             geom = (struct swc_rectangle){ c->x, c->y, c->w, c->h };
285             swc_window_set_geometry(c->win, &geom);
286         }
287+
288         return;
289     }
290 
291     if (!c->scr || !c->scr->scr) return;
292 
293     if (get_geometry(c, &geom)) {
294+
295         c->x = geom.x;
296         c->y = geom.y;
297         c->w = geom.width;
298@@ -296,52 +336,63 @@ void fullscreen(void* data, uint32_t time, uint32_t value, uint32_t state)
299     swc_window_set_fullscreen(c->win, c->scr->scr);
300 }
301 
302-void kb_move_x(void* data, uint32_t time, uint32_t value, uint32_t state)
303+void kb_move_x
304+(void* data, uint32_t time, uint32_t value, uint32_t state)
305 {
306     BIND_ACTION(data, time, value, state);
307     adjust_geom(wm.sel_client, a->i, 0, 0, 0);
308 }
309 
310-void kb_move_y(void* data, uint32_t time, uint32_t value, uint32_t state)
311+void kb_move_y
312+(void* data, uint32_t time, uint32_t value, uint32_t state)
313 {
314     BIND_ACTION(data, time, value, state);
315     adjust_geom(wm.sel_client, 0, a->i, 0, 0);
316 }
317 
318-void kb_resize_width(void* data, uint32_t time, uint32_t value, uint32_t state)
319+void kb_resize_width
320+(void* data, uint32_t time, uint32_t value, uint32_t state)
321 {
322     BIND_ACTION(data, time, value, state);
323     adjust_geom(wm.sel_client, 0, 0, a->i, 0);
324 }
325 
326-void kb_resize_height(void* data, uint32_t time, uint32_t value, uint32_t state)
327+void kb_resize_height
328+(void* data, uint32_t time, uint32_t value, uint32_t state)
329 {
330     BIND_ACTION(data, time, value, state);
331     adjust_geom(wm.sel_client, 0, 0, 0, a->i);
332 }
333 
334-static void apply_grid_geometry(struct client *c, float x_frac, float w_frac)
335+static void apply_grid_geometry
336+(struct client *c, float x_frac, float y_frac, float w_frac, float h_frac)
337 {
338-    if (!c || !c->scr || !c->scr->scr) return;
339+    if (!c || !c->scr || !c->scr->scr) 
340+		return;
341 
342     struct swc_rectangle geom;
343     struct swc_rectangle *ug = &c->scr->scr->usable_geometry;
344 
345     geom.x = ug->x + (ug->width * x_frac);
346-    geom.y = ug->y;
347+    geom.y = ug->y + (ug->height * y_frac);
348     geom.width = ug->width * w_frac;
349-    geom.height = ug->height;
350+    geom.height = ug->height * h_frac;
351 
352     swc_window_set_geometry(c->win, &geom);
353 }
354 
355-void center_window(void* data, uint32_t time, uint32_t value, uint32_t state)
356+void center_window
357+(void* data, uint32_t time, uint32_t value, uint32_t state)
358 {
359     (void)data; BIND_EVENT(time, value, state);
360-    if (!wm.sel_client->scr || !wm.sel_client->scr->scr) return;
361+	
362+	if (!wm.sel_client || !wm.sel_client->scr || !wm.sel_client->scr->scr) 
363+		return;
364 
365     struct swc_rectangle geom;
366-    if (!get_geometry(wm.sel_client, &geom)) return;
367+    
368+	if (!get_geometry(wm.sel_client, &geom)) 
369+		return;
370 
371     struct swc_rectangle *ug = &wm.sel_client->scr->scr->usable_geometry;
372     geom.x = ug->x + (ug->width - geom.width) / 2;
373@@ -350,22 +401,41 @@ void center_window(void* data, uint32_t time, uint32_t value, uint32_t state)
374     swc_window_set_geometry(wm.sel_client->win, &geom);
375 }
376 
377-void snap_left_half(void* data, uint32_t time, uint32_t value, uint32_t state)
378+void snap_top_half
379+(void* data, uint32_t time, uint32_t value, uint32_t state)
380+{
381+    (void)data; BIND_EVENT(time, value, state);
382+    apply_grid_geometry(wm.sel_client, 0.0f, 0.0f, 1.0f, 0.5f);
383+}
384+
385+void snap_bottom_half
386+(void* data, uint32_t time, uint32_t value, uint32_t state)
387+{
388+    (void)data; BIND_EVENT(time, value, state);
389+    apply_grid_geometry(wm.sel_client, 0.0f, 0.5f, 1.0f, 0.5f);
390+}
391+
392+void snap_left_half
393+(void* data, uint32_t time, uint32_t value, uint32_t state)
394 {
395     (void)data; BIND_EVENT(time, value, state);
396-    apply_grid_geometry(wm.sel_client, 0.0f, 0.5f);
397+    apply_grid_geometry(wm.sel_client, 0.0f, 0.0f, 0.5f, 1.0f);
398 }
399 
400-void snap_right_half(void* data, uint32_t time, uint32_t value, uint32_t state)
401+void snap_right_half
402+(void* data, uint32_t time, uint32_t value, uint32_t state)
403 {
404     (void)data; BIND_EVENT(time, value, state);
405-    apply_grid_geometry(wm.sel_client, 0.5f, 0.5f);
406+    apply_grid_geometry(wm.sel_client, 0.5f, 0.0f, 0.5f, 1.0f);
407 }
408 
409-void new_screen(struct swc_screen* scr)
410+void new_screen
411+(struct swc_screen* scr)
412 {
413     struct screen* s = calloc(1, sizeof(*s));
414-    if (!s) die(EXIT_FAILURE, "new screen calloc failed");
415+
416+	if (!s) 
417+		die(EXIT_FAILURE, "new screen calloc failed");
418 
419     s->scr = scr;
420     wl_list_insert(&wm.screens, &s->link);
421@@ -376,10 +446,13 @@ void new_screen(struct swc_screen* scr)
422     _log(stderr, "new_screen=%p\n", (void*)scr);
423 }
424 
425-void new_window(struct swc_window* win)
426+void new_window
427+(struct swc_window* win)
428 {
429     struct client* c = calloc(1, sizeof(*c));
430-    if (!c) die(EXIT_FAILURE, "calloc client failed");
431+    
432+	if (!c) 
433+		die(EXIT_FAILURE, "calloc client failed");
434 
435     win->motion_throttle_ms = 1000 / cfg.motion_throttle_hz;
436     win->min_width = 1;
437@@ -394,7 +467,8 @@ void new_window(struct swc_window* win)
438     swc_window_set_stacked(win);
439 
440     int32_t cx = 0, cy = 0;
441-    if (swc_cursor_position(&cx, &cy))
442+    
443+	if (swc_cursor_position(&cx, &cy))
444         swc_window_set_position(win, cx / 256, cy / 256);
445 
446     swc_window_show(win);
447@@ -403,43 +477,56 @@ void new_window(struct swc_window* win)
448     _log(stderr, "new_window=%p\n", (void*)win);
449 }
450 
451-void new_device(struct libinput_device* dev)
452+void new_device
453+(struct libinput_device* dev)
454 {
455     (void)dev;
456 }
457 
458-void quit(void* data, uint32_t time, uint32_t value, uint32_t state)
459+void quit
460+(void* data, uint32_t time, uint32_t value, uint32_t state)
461 {
462     (void)data; BIND_EVENT(time, value, state);
463     wl_display_terminate(wm.dpy);
464 }
465 
466-void spawn(void* data, uint32_t time, uint32_t value, uint32_t state)
467+void spawn
468+(void* data, uint32_t time, uint32_t value, uint32_t state)
469 {
470     BIND_EVENT(time, value, state);
471 
472     pid_t pid = fork();
473-    if (pid == 0) {
474+
475+	if (pid == 0) {
476+
477         setsid();
478-        if (fork() == 0) {
479+        
480+		if (fork() == 0) {
481+
482             union arg* a = data;
483             char* const* cmd = (char* const*)a->v;
484 
485             execvp(cmd[0], cmd);
486             _exit(127);
487         }
488+
489         _exit(0);
490-    } else if (pid > 0) {
491+    }
492+
493+	else if (pid > 0) {
494+
495         waitpid(pid, NULL, 0);
496     }
497 }
498 
499-void workspace_goto(void* data, uint32_t time, uint32_t value, uint32_t state)
500+void workspace_goto
501+(void* data, uint32_t time, uint32_t value, uint32_t state)
502 {
503     union arg* a = data;
504     BIND_EVENT(time, value, state);
505 
506-    if (a->ui < 1 || a->ui > 9 || a->ui == wm.ws) return;
507+    if (a->ui < 1 || a->ui > 9 || a->ui == wm.ws) 
508+		return;
509 
510     wm.ws = a->ui;
511     sync_window_visibility();
512@@ -447,7 +534,8 @@ void workspace_goto(void* data, uint32_t time, uint32_t value, uint32_t state)
513     focus(get_focus_candidate(wm.sel_screen));
514 }
515 
516-void workspace_moveto(void* data, uint32_t time, uint32_t value, uint32_t state)
517+void workspace_moveto
518+(void* data, uint32_t time, uint32_t value, uint32_t state)
519 {
520     BIND_ACTION(data, time, value, state);
521     if (a->ui < 1 || a->ui > 9 || wm.sel_client->ws == a->ui) return;
522@@ -457,7 +545,8 @@ void workspace_moveto(void* data, uint32_t time, uint32_t value, uint32_t state)
523 
524     if (c->ws == wm.ws)
525         swc_window_show(c->win);
526-    else
527+    
528+	else
529         swc_window_hide(c->win);
530 
531     focus(get_focus_candidate(wm.sel_screen));
+6, -3
 1@@ -5,7 +5,8 @@
 2 #include "include/util.h"
 3 #include "include/slgro.h"
 4 
 5-void die(int ret, const char* fmt, ...)
 6+void die
 7+(int ret, const char* fmt, ...)
 8 {
 9 	va_list ap;
10 
11@@ -21,7 +22,8 @@ void die(int ret, const char* fmt, ...)
12 	exit(ret);
13 }
14 
15-void _log(FILE* fd, const char* fmt, ...)
16+void _log
17+(FILE* fd, const char* fmt, ...)
18 {
19 	va_list ap;
20 
21@@ -35,7 +37,8 @@ void _log(FILE* fd, const char* fmt, ...)
22 	fflush(fd);
23 }
24 
25-void sig_handler(int s)
26+void sig_handler
27+(int s)
28 {
29 	(void)s;
30