commit 9831ea68f614d53127efea48602db3a3ed50d178
Author: uint23 <abhinav.prsai@gmail.com>
AuthorDate: Sun Apr 20 18:27:16 2025 +0100
Commit: uint23 <abhinav.prsai@gmail.com>
CommitDate: Sun Apr 20 18:27:16 2025 +0100
i forgot to commit again oops
---
Makefile | 38 ++++++----
src/config.h | 20 ++++-
src/defs.h | 4 +
src/sxbar.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 278 insertions(+), 22 deletions(-)
diff --git a/Makefile b/Makefile
index 15e6fec..65f5edc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,27 +1,35 @@
-# Flags
CC = gcc
-CFLAGS = -Wall -O2 -g `pkg-config --cflags x11 xft`
-LDFLAGS = `pkg-config --libs x11 xft`
+CFLAGS = -Wall -Wextra -O3 -g -Isrc -march=native -flto -s -Os
+LDFLAGS = -lX11
-# Dirs
SRC_DIR = src
-OBJ_DIR = obj
-BIN = sxbar
-
-# Source and object files
SRC = $(wildcard $(SRC_DIR)/*.c)
-OBJ = $(patsubst $(SRC_DIR)/%.c, $(OBJ_DIR)/%.o, $(SRC))
-
-.PHONY: all clean
+OBJ = $(SRC:.c=.o)
+BIN = sxbar
+PREFIX = /usr/local
all: $(BIN)
$(BIN): $(OBJ)
$(CC) -o $@ $^ $(LDFLAGS)
-$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
- @mkdir -p $(OBJ_DIR)
- $(CC) $(CFLAGS) -c $< -o $@
+$(SRC_DIR)/%.o: $(SRC_DIR)/%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
clean:
- rm -rf $(OBJ_DIR) $(BIN)
+ rm -f $(SRC_DIR)/*.o $(BIN)
+
+install: all
+ @echo "Installing $(BIN) to $(DESTDIR)$(PREFIX)/bin..."
+ @mkdir -p $(DESTDIR)$(PREFIX)/bin
+ @install -m 755 $(BIN) $(DESTDIR)$(PREFIX)/bin/$(BIN)
+ @echo "Installation complete."
+
+uninstall:
+ @echo "Uninstalling $(BIN) from $(DESTDIR)$(PREFIX)/bin..."
+ @rm -f $(DESTDIR)$(PREFIX)/bin/$(BIN)
+ @echo "Uninstallation complete."
+
+clean-install: clean install
+
+.PHONY: all clean install uninstall clean-install
diff --git a/src/config.h b/src/config.h
index 0147897..d605e37 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,5 +1,17 @@
-
-#define BAR_HEIGHT 10
-#define BAR_VERT_PAD 10
-#define BAR_HORI_PAD 100
+#define BOTTOM_BAR False
+#define BAR_HEIGHT 25
+#define BAR_VERT_PAD 15
+#define BAR_HORI_PAD 400
#define BAR_BORDER True
+#define BAR_BORDER_W 2
+
+#define BAR_COLOR_BG "#56002e"
+#define BAR_COLOR_FG "#ffffff"
+#define BAR_COLOR_BORDER "#005577"
+#define BAR_FONT "fixed"
+#define BAR_TEXT_PAD 10
+
+#define BAR_WS_HIGHLIGHT_LEFT "["
+#define BAR_WS_HIGHLIGHT_RIGHT "]"
+#define BAR_WS_PADDING 10
+#define BAR_WS_SPACING 10
diff --git a/src/defs.h b/src/defs.h
index 48a7b55..117c25a 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -1,6 +1,8 @@
#ifndef DEFS_H
#define DEFS_H
+#include <X11/Xlib.h>
+
#define uint unsigned int
#define ulong unsigned long
#define u_char unsigned char
@@ -9,4 +11,6 @@
#define SXBAR_AUTHOR "(C) Abhinav Prasai 2025"
#define SXBAR_LICINFO "See LICENSE for more info"
+typedef void (*EventHandler)(XEvent *);
+
#endif
diff --git a/src/sxbar.c b/src/sxbar.c
index 8c10d20..3f7ada6 100644
--- a/src/sxbar.c
+++ b/src/sxbar.c
@@ -1,22 +1,231 @@
#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <time.h>
+#include <X11/Xatom.h>
#include <X11/Xlib.h>
+#include <X11/Xutil.h>
#include "defs.h"
static void create_win(void);
+static int get_current_workspace(void);
+static char** get_workspace_name(int *count);
+static void hdl_dummy(XEvent *xev);
+static void hdl_expose(XEvent *xev);
+static void hdl_property(XEvent *xev);
+static ulong parse_col(const char *hex);
+static void run(void);
static void setup(void);
+static void xev_cases(XEvent *xev);
+static EventHandler evtable[LASTEvent];
+static XFontStruct *font;
static Display *dpy;
-static Window root;
+static Window root, win;
+static GC gc;
static uint scr;
+static ulong fg_col;
+static ulong bg_col;
+static ulong border_col;
+#include "config.h"
static void
create_win(void)
{
- ulong fg = WhitePixel(dpy, scr);
- ulong bg = BlackPixel(dpy, scr);
+ int sw = DisplayWidth(dpy, scr);
+ int sh = DisplayHeight(dpy, scr);
+
+ int bw = BAR_BORDER ? BAR_BORDER_W : 0;
+ int w = sw - (2 * BAR_HORI_PAD);
+ int x = (sw - w) / 2;
+ int h = BAR_HEIGHT;
+ int y = BOTTOM_BAR ? sh - h - BAR_VERT_PAD - bw : BAR_VERT_PAD;
+
+ XSetWindowAttributes wa = {
+ .background_pixel = bg_col,
+ .border_pixel = border_col,
+ .event_mask = ExposureMask | ButtonPressMask
+ };
+
+ win = XCreateWindow(dpy, root,
+ x, y,
+ w, h,
+ bw,
+ CopyFromParent,
+ InputOutput,
+ DefaultVisual(dpy, scr),
+ CWBackPixel | CWBorderPixel | CWEventMask,
+ &wa);
+
+ Atom A_WM_TYPE = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+ Atom A_WM_TYPE_DOCK = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
+ XChangeProperty(dpy, win, A_WM_TYPE, XA_ATOM, 32,
+ PropModeReplace,
+ (unsigned char *)&A_WM_TYPE_DOCK, 1);
+
+ Atom A_STRUT = XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False);
+ long strut[12] = {0};
+
+ if (BOTTOM_BAR) {
+ strut[3] = h + bw;
+ strut[10] = x;
+ strut[11] = x + w - 1;
+ } else {
+ strut[2] = y + h + bw;
+ strut[8] = x;
+ strut[9] = x + w - 1;
+ }
+
+ XChangeProperty(dpy, win, A_STRUT, XA_CARDINAL, 32,
+ PropModeReplace,
+ (unsigned char *)strut, 12);
+
+ XMapRaised(dpy, win);
+
+ gc = XCreateGC(dpy, win, 0, NULL);
+ XSetForeground(dpy, gc, fg_col);
+ font = XLoadQueryFont(dpy, BAR_FONT);
+ if (!font)
+ errx(1, "could not load font");
+ XSetFont(dpy, gc, font->fid);
+}
+
+static int
+get_current_workspace(void)
+{
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data = NULL;
+ Atom prop = XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False);
+
+ if (XGetWindowProperty(dpy, root, prop, 0, 1, False,
+ XA_CARDINAL, &actual_type, &actual_format,
+ &nitems, &bytes_after, &data) == Success && data) {
+ int ws = *(unsigned long *)data;
+ XFree(data);
+ return ws;
+ }
+ return -1;
+}
+
+static char**
+get_workspace_name(int *count)
+{
+ Atom actual_type;
+ int actual_format;
+ unsigned long nitems, bytes_after;
+ unsigned char *data = NULL;
+
+ Atom prop = XInternAtom(dpy, "_NET_DESKTOP_NAMES", False);
+ Atom utf8 = XInternAtom(dpy, "UTF8_STRING", False);
+
+ if (XGetWindowProperty(dpy, root, prop, 0, (~0L), False,
+ utf8, &actual_type, &actual_format,
+ &nitems, &bytes_after, &data) == Success && data) {
+
+ char **names = NULL;
+ int n = 0;
+ char *p = (char *)data;
+ while (n < 32 && p < (char *)data + nitems) {
+ names = realloc(names, (n + 1) * sizeof(char *));
+ names[n++] = strdup(p);
+ p += strlen(p) + 1;
+ }
+ XFree(data);
+ *count = n;
+ return names;
+ }
+ *count = 0;
+ return NULL;
+}
+
+static void
+hdl_dummy(XEvent *xev)
+{
+ (void) xev;
+}
+
+static void
+hdl_expose(XEvent *xev)
+{
+ (void) xev;
+ XClearWindow(dpy, win);
+
+ int current_ws = get_current_workspace();
+ int name_count = 0;
+ char **names = get_workspace_name(&name_count);
+
+ uint text_y = (BAR_HEIGHT + font->ascent - font->descent) / 2;
+
+ uint text_x = BAR_TEXT_PAD;
+ if (names) {
+ for (int i = 0; i < name_count; ++i) {
+ char label[64];
+ if (i == current_ws)
+ snprintf(label, sizeof(label), "%s%s%s ",
+ BAR_WS_HIGHLIGHT_LEFT, names[i], BAR_WS_HIGHLIGHT_RIGHT);
+ else
+ snprintf(label, sizeof(label), "%s ", names[i]);
+
+ XDrawString(dpy, win, gc, text_x, text_y,
+ label, strlen(label));
+ text_x += XTextWidth(font, label, strlen(label)) + BAR_WS_SPACING;
+ free(names[i]);
+ }
+ free(names);
+ }
+
+ int bar_width = DisplayWidth(dpy, scr) - (2 * BAR_HORI_PAD);
+ int version_width = XTextWidth(font, SXBAR_VERSION, strlen(SXBAR_VERSION));
+ int version_x = bar_width - version_width - BAR_TEXT_PAD;
+
+ XDrawString(dpy, win, gc, version_x, text_y,
+ SXBAR_VERSION, strlen(SXBAR_VERSION));
+}
+
+static void
+hdl_property(XEvent *xev)
+{
+ if (xev->xproperty.atom == XInternAtom(dpy, "_NET_CURRENT_DESKTOP", False)) {
+ XClearWindow(dpy, win);
+ XEvent expose;
+ expose.type = Expose;
+ evtable[Expose](&expose);
+ }
+}
+
+static ulong
+parse_col(const char *hex)
+{
+ XColor col;
+ Colormap cmap = DefaultColormap(dpy, DefaultScreen(dpy));
+
+ if (!XParseColor(dpy, cmap, hex, &col)) {
+ fprintf(stderr, "sxwm: cannot parse color %s\n", hex);
+ return WhitePixel(dpy, DefaultScreen(dpy));
+ }
+
+ if (!XAllocColor(dpy, cmap, &col)) {
+ fprintf(stderr, "sxwm: cannot allocate color %s\n", hex);
+ return WhitePixel(dpy, DefaultScreen(dpy));
+ }
+
+ return col.pixel;
+}
+
+static void
+run(void)
+{
+ XEvent xev;
+
+ for (;;) {
+ XNextEvent(dpy, &xev);
+ xev_cases(&xev);
+ }
}
static void
@@ -26,6 +235,27 @@ setup(void)
errx(0, "can't open display. quitting...");
root = XDefaultRootWindow(dpy);
scr = DefaultScreen(dpy);
+
+ for (int i = 0; i < LASTEvent; ++i)
+ evtable[i] = hdl_dummy;
+
+ evtable[Expose] = hdl_expose;
+ evtable[PropertyNotify] = hdl_property;
+
+ XSelectInput(dpy, root, PropertyChangeMask);
+ fg_col = parse_col(BAR_COLOR_FG);
+ bg_col = parse_col(BAR_COLOR_BG);
+ border_col = parse_col(BAR_COLOR_BORDER);
+ create_win();
+}
+
+static void
+xev_cases(XEvent *xev)
+{
+ if (xev->type >= 0 && xev->type < LASTEvent)
+ evtable[xev->type](xev);
+ else
+ printf("sxwm: invalid event type: %d\n", xev->type);
}
int
@@ -39,4 +269,6 @@ main(int ac, char **av)
}
setup();
+ run();
+ return 0;
}