commit e208543c8be642d2ac3976564688f15b85c24ecd
Author: Abhinav <abhinav.prsai@gmail.com>
AuthorDate: Wed Jul 2 18:05:10 2025 +0100
Commit: Abhinav <abhinav.prsai@gmail.com>
CommitDate: Wed Jul 2 18:05:10 2025 +0100
add xinerama support
---
default_sxbarc | 0
src/config.h | 16 +++---
src/sxbar.c | 153 ++++++++++++++++++++++++++++++++++-----------------------
sxbar.1 | 0
4 files changed, 100 insertions(+), 69 deletions(-)
diff --git a/default_sxbarc b/default_sxbarc
new file mode 100644
index 0000000..e69de29
diff --git a/src/config.h b/src/config.h
index f17952f..b7feec1 100644
--- a/src/config.h
+++ b/src/config.h
@@ -1,17 +1,17 @@
-#define BOTTOM_BAR False
+#define BOTTOM_BAR True
#define BAR_HEIGHT 25
-#define BAR_VERT_PAD 15
-#define BAR_HORI_PAD 400
-#define BAR_BORDER True
+#define BAR_VERT_PAD 0
+#define BAR_HORI_PAD 0
+#define BAR_BORDER False
#define BAR_BORDER_W 2
-#define BAR_COLOR_BG "#56002e"
-#define BAR_COLOR_FG "#ffffff"
+#define BAR_COLOR_BG "#000000"
+#define BAR_COLOR_FG "#7abccd"
#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_HIGHLIGHT_LEFT "*"
+#define BAR_WS_HIGHLIGHT_RIGHT ""
#define BAR_WS_PADDING 10
#define BAR_WS_SPACING 10
diff --git a/src/sxbar.c b/src/sxbar.c
index 39df0ab..9a17efa 100644
--- a/src/sxbar.c
+++ b/src/sxbar.c
@@ -7,10 +7,11 @@
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <X11/extensions/Xinerama.h>
#include "defs.h"
-void create_win(void);
+void create_bars(void);
int get_current_workspace(void);
char **get_workspace_name(int *count);
void hdl_dummy(XEvent *xev);
@@ -19,12 +20,16 @@ void hdl_property(XEvent *xev);
unsigned long parse_col(const char *hex);
void run(void);
void setup(void);
-void xev_cases(XEvent *xev);
+int find_monitor_for_window(Window win);
+void draw_bar_content(Window win, int monitor_index);
EventHandler evtable[LASTEvent];
XFontStruct *font;
Display *dpy;
-Window root, win;
+Window root;
+Window *wins = NULL;
+int nmonitors = 0;
+XineramaScreenInfo *monitors = NULL;
GC gc;
int scr;
unsigned long fg_col;
@@ -33,50 +38,70 @@ unsigned long border_col;
#include "config.h"
-void create_win(void)
+void create_bars(void)
{
- 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;
+ int xin_active = 0;
+
+ if (XineramaIsActive(dpy)) {
+ monitors = XineramaQueryScreens(dpy, &nmonitors);
+ xin_active = 1;
}
- else {
- strut[2] = y + h + bw;
- strut[8] = x;
- strut[9] = x + w - 1;
+
+ /* fallback to single monitor if Xinerama is not available */
+ if (!xin_active || nmonitors <= 0) {
+ nmonitors = 1;
+ monitors = malloc(sizeof(XineramaScreenInfo));
+ monitors[0].screen_number = 0;
+ monitors[0].x_org = 0;
+ monitors[0].y_org = 0;
+ monitors[0].width = DisplayWidth(dpy, scr);
+ monitors[0].height = DisplayHeight(dpy, scr);
}
- XChangeProperty(dpy, win, A_STRUT, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)strut,
- 12);
+ wins = malloc(nmonitors * sizeof(Window));
+
+ for (int i = 0; i < nmonitors; i++) {
+ int bw = BAR_BORDER ? BAR_BORDER_W : 0;
+ int w = monitors[i].width - (2 * BAR_HORI_PAD);
+ int x = monitors[i].x_org + (monitors[i].width - w) / 2;
+ int h = BAR_HEIGHT;
+ int y = BOTTOM_BAR ? monitors[i].y_org + monitors[i].height - h - BAR_VERT_PAD - bw
+ : monitors[i].y_org + BAR_VERT_PAD;
+
+ XSetWindowAttributes wa = {.background_pixel = bg_col,
+ .border_pixel = border_col,
+ .event_mask = ExposureMask | ButtonPressMask};
+
+ wins[i] = 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, wins[i], 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, wins[i], A_STRUT, XA_CARDINAL, 32, PropModeReplace,
+ (unsigned char *)strut, 12);
- XMapRaised(dpy, win);
+ XMapRaised(dpy, wins[i]);
+ }
- gc = XCreateGC(dpy, win, 0, NULL);
+ gc = XCreateGC(dpy, wins[0], 0, NULL);
XSetForeground(dpy, gc, fg_col);
font = XLoadQueryFont(dpy, BAR_FONT);
if (!font) {
@@ -138,9 +163,18 @@ void hdl_dummy(XEvent *xev)
(void)xev;
}
-void hdl_expose(XEvent *xev)
+int find_monitor_for_window(Window win)
+{
+ for (int i = 0; i < nmonitors; i++) {
+ if (wins[i] == win) {
+ return i;
+ }
+ }
+ return 0; /* fallback to first monitor */
+}
+
+void draw_bar_content(Window win, int monitor_index)
{
- (void)xev;
XClearWindow(dpy, win);
int current_ws = get_current_workspace();
@@ -168,20 +202,27 @@ void hdl_expose(XEvent *xev)
free(names);
}
- int bar_width = DisplayWidth(dpy, scr) - (2 * BAR_HORI_PAD);
+ int bar_width = monitors[monitor_index].width - (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));
}
+void hdl_expose(XEvent *xev)
+{
+ Window win = xev->xexpose.window;
+ int monitor_index = find_monitor_for_window(win);
+ draw_bar_content(win, monitor_index);
+}
+
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);
+ /* redraw all bars */
+ for (int i = 0; i < nmonitors; i++) {
+ draw_bar_content(wins[i], i);
+ }
}
}
@@ -209,7 +250,7 @@ void run(void)
for (;;) {
XNextEvent(dpy, &xev);
- xev_cases(&xev);
+ evtable[xev.type](&xev);
}
}
@@ -232,17 +273,7 @@ void setup(void)
fg_col = parse_col(BAR_COLOR_FG);
bg_col = parse_col(BAR_COLOR_BG);
border_col = parse_col(BAR_COLOR_BORDER);
- create_win();
-}
-
-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);
- }
+ create_bars();
}
int main(int ac, char **av)
@@ -258,4 +289,4 @@ int main(int ac, char **av)
setup();
run();
return 0;
-}
+}
\ No newline at end of file
diff --git a/sxbar.1 b/sxbar.1
new file mode 100644
index 0000000..e69de29