foxygit / sxbar Log in
commit d8b85eedadf84be78c1baf335447c1902b37bd77
Author:     Jens Kristoffersson <144891562+MrJensK@users.noreply.github.com>
AuthorDate: Tue Aug 26 19:17:31 2025 +0200
Commit:     GitHub <noreply@github.com>
CommitDate: Tue Aug 26 19:17:31 2025 +0200

    Add files via upload

    If you only want the patch
---
 sxbar_boxes.patch | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 134 insertions(+)

diff --git a/sxbar_boxes.patch b/sxbar_boxes.patch
new file mode 100644
index 0000000..c685d65
--- /dev/null
+++ b/sxbar_boxes.patch
@@ -0,0 +1,134 @@
+--- sxbar.c	2025-08-26 19:00:29.330170683 +0200
++++ /home/mrfox/sxbar/src/sxbar.c	2025-08-26 18:50:52.119470570 +0200
+@@ -13,6 +13,7 @@
+
+ #include "defs.h"
+
++
+ void cleanup_modules(void);
+ void cleanup_resources(void);
+ void create_bars(void);
+@@ -44,6 +45,41 @@
+ int nmonitors = 0;
+ int scr;
+
++int window_on_monitor(Window win, int monitor_index) {
++    XWindowAttributes attr;
++    if (!XGetWindowAttributes(dpy, win, &attr))
++        return 0;
++    int mx = monitors[monitor_index].x_org;
++    int my = monitors[monitor_index].y_org;
++    int mw = monitors[monitor_index].width;
++    int mh = monitors[monitor_index].height;
++    // Kontrollera om fönstrets position är inom monitorns rektangel
++    return (attr.x >= mx && attr.x < mx + mw && attr.y >= my && attr.y < my + mh);
++}
++
++int workspace_has_window(int ws) {
++    Atom at = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
++    Atom ret_type;
++    int fmt;
++    unsigned long n, after;
++    unsigned char *data = NULL;
++    if (XGetWindowProperty(dpy, root, at, 0, (~0L), False, XA_WINDOW, &ret_type, &fmt, &n, &after, &data) == Success && data) {
++        Atom ws_atom = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
++        for (unsigned long i = 0; i < n; i++) {
++            Window win = ((Window *)data)[i];
++            unsigned char *ws_data = NULL;
++            if (XGetWindowProperty(dpy, win, ws_atom, 0, 1, False, XA_CARDINAL, &ret_type, &fmt, &n, &after, &ws_data) == Success && ws_data) {
++                int win_ws = *(unsigned long *)ws_data;
++                XFree(ws_data);
++                if (win_ws == ws)
++                    return 1;
++            }
++        }
++        XFree(data);
++    }
++    return 0;
++}
++
+ void cleanup_modules(void)
+ {
+ 	for (int i = 0; i < config.module_count; i++) {
+@@ -196,6 +232,46 @@
+ 				XSetForeground(dpy, gc, config.foreground_colour);
+ 			}
+ 			XDrawString(dpy, draw, gc, pos[i], text_y, tmp, strlen(tmp));
++
++ 			int max_boxes = 4;
++            int box_size = 5;
++            int box_spacing = 2;
++			int win_count = 0;
++			{
++    		Atom at = XInternAtom(dpy, "_NET_CLIENT_LIST", False);
++    		Atom ret_type;
++    		int fmt;
++    		unsigned long nclients, afterclients;
++    		unsigned char *clients_data = NULL;
++    		if (XGetWindowProperty(dpy, root, at, 0, (~0L), False, XA_WINDOW, &ret_type, &fmt, &nclients, &afterclients, &clients_data) == Success && clients_data) {
++        		Atom ws_atom = XInternAtom(dpy, "_NET_WM_DESKTOP", False);
++        		for (unsigned long j = 0; j < nclients; j++) {
++            		Window win = ((Window *)clients_data)[j];
++            		unsigned long ndesk, afterdesk;
++            		unsigned char *ws_data = NULL;
++            		if (XGetWindowProperty(dpy, win, ws_atom, 0, 1, False, XA_CARDINAL, &ret_type, &fmt, &ndesk, &afterdesk, &ws_data) == Success && ws_data) {
++                		unsigned long win_ws = *(unsigned long *)ws_data;
++                		XFree(ws_data);
++                			if ((int)win_ws == i && window_on_monitor(win, monitor_index))
++                    			win_count++;
++           }
++		        }
++        		XFree(clients_data);
++    		}
++		}
++            if (win_count > 0) {
++                if (win_count > max_boxes) win_count = max_boxes;
++                // Färg: svart om markerad, annars foreground
++                unsigned long box_col = (i == current_ws) ? parse_col("#000000") : config.foreground_colour;
++                XSetForeground(dpy, gc, box_col);
++                for (int b = 0; b < win_count; b++) {
++                    int box_x = pos[i] - pad + 1 + b * (box_size + box_spacing); // 1 pixel från vänster kant
++					int box_y = text_y - font->ascent - pad + 1; // 1 pixel från toppen
++                    XFillRectangle(dpy, draw, gc, box_x, box_y, box_size, box_size);
++                }
++                // Återställ foreground
++                XSetForeground(dpy, gc, (i == current_ws) ? config.background_colour : config.foreground_colour);
++            }
+ 			free(names[i]);
+ 		}
+ 		free(names);
+@@ -307,7 +383,7 @@
+
+ void init_defaults(void)
+ {
+-	config.bottom_bar = True;
++	config.bottom_bar = False;
+ 	config.height = 19;
+ 	config.vertical_padding = 0;
+ 	config.horizontal_padding = 0;
+@@ -363,7 +439,7 @@
+ 	/* volume */
+ 	config.modules[config.module_count++] =
+ 	    (Module){.name = strdup("volume"),
+-	             .command = "amixer get Master | grep -o '[0-9]*%' | head -1 || echo 'N/A'",
++	             .command = "LC_ALL=C wpctl get-volume @DEFAULT_AUDIO_SINK@ 2>/dev/null | awk '/Volume:/ {print $2}' | xargs -I{} bash -c 'echo \"{} * 100 / 1\" | bc | awk \"{print \\$1 \\\"%\\\"}\"'",
+ 	             .enabled = True,
+ 	             .refresh_interval = 5,
+ 	             .last_update = 0,
+@@ -373,7 +449,7 @@
+ 		(Module){.name = strdup("cpu"),
+ 	             .command = "top -bn1 | grep 'Cpu(s)' | sed 's/.*, *\\([0-9.]*\\)%* id.*/\\1/' "
+ 	                        "| awk '{print 100-$1\"%\"}'",
+-	             .enabled = True,
++	             .enabled = False,
+ 	             .refresh_interval = 3,
+ 	             .last_update = 0,
+ 	             .cached_output = NULL};
+@@ -478,6 +554,7 @@
+
+ 	init_defaults();
+ 	create_bars();
++	update_modules();
+ }
+
+ int main(int ac, char **av)