#pragma once
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
#include <time.h>
#define SXBAR_VERSION "sxbar ver. 1.1"
#define SXBAR_AUTHOR "(C) Abhinav Prasai 2025"
#define SXBAR_LICINFO "See LICENSE for more info"
#define MAX_MONITORS 32
/* module horizontal alignment groups -- RIGHT is 0 so existing configs
* (which never set align) keep today's right-anchored-cluster behaviour */
#define ALIGN_RIGHT 0
#define ALIGN_LEFT 1
#define ALIGN_CENTER 2
/* whether a module has a popup at all: NONE is 0 so existing configs
* (which never set popup) keep today's plain click/scroll behaviour with
* no floating window. A popup is a list of rows (PopupItem), each with
* its own POPUP_ROW_* type -- text, button and slider rows can all be
* mixed freely in the same popup. */
#define POPUP_NONE 0
#define POPUP_BUTTONS 1
#define POPUP_TRIGGER_CLICK 0
#define POPUP_TRIGGER_HOVER 1
#define POPUP_ROW_TEXT 0 /* purely informational -- not clickable at all */
#define POPUP_ROW_BUTTON 1 /* spawns command; popup stays open on click */
#define POPUP_ROW_SLIDER 2 /* draggable 0-100% track; doesn't close on click/drag */
#define POPUP_ROW_IMAGE 3 /* renders an image file (e.g. album art); not clickable */
#define POPUP_ROW_BUTTONS 4 /* one row split into N equal-width button segments,
* e.g. media transport controls (prev/play/next) */
/* one segment of a POPUP_ROW_BUTTONS row -- same label/command shape as a
* plain POPUP_ROW_BUTTON, just laid out side by side instead of stacked */
typedef struct PopupButton {
char *label;
char *command;
} PopupButton;
/* one row of a popup. label_command, if set, is re-run fresh (via
* run_command()) every time the popup opens instead of using a fixed
* label -- used by TEXT and BUTTON rows for live status text (label
* itself is then overwritten in place and freed/reused across opens). A
* SLIDER row instead seeds its value from the module's own command
* output, and set_command receives the new value as $1 when dragged. An
* IMAGE row's image_command is re-run the same way as label_command, but
* its output is a path to a local image file (or empty for "no image
* this time"); `image` is the XImage decoded (via vendored stb_image.h)
* and scaled from that path by the most recent popup_open() (opaque here
* -- only sxbar.c touches it directly), sized image_w x image_h. A
* BUTTONS row's `buttons`/`button_count` hold its segments; labels are
* static (no per-segment label_command). A TEXT/BUTTON row whose label
* doesn't fit the popup's width (e.g. the popup's width came from an
* IMAGE/SLIDER/BUTTONS row instead of growing to fit this text) scrolls
* within it instead, using its own scroll_offset -- same marquee scheme
* as a bar module's max_width, just scoped to one popup row. */
typedef struct PopupItem {
int type;
char *label;
char *command;
char *label_command;
char *set_command;
char *image_command;
void *image;
int image_w, image_h;
PopupButton *buttons;
int button_count;
int scroll_offset; /* TEXT/BUTTON: marquee position, in pixels */
int value; /* SLIDER: current 0-100 */
int last_spawned; /* SLIDER: last value set_command was actually run for */
} PopupItem;
/* one window entry in the built-in `taskbar` module -- see
* update_taskbar() (src/sxbar.c) for how these get populated from
* scripts/taskbar.sh's internal listing format, and id's role in
* highlighting whichever entry is the current _NET_ACTIVE_WINDOW */
typedef struct TaskbarEntry {
char *label; /* window title */
char *command; /* spawned on click, e.g. "taskbar.sh focus 0x0140..." */
Window id;
int monitor; /* which monitor (index into monitors[]) the script placed
* this window on, or -1 if the script didn't say -- see
* update_taskbar()'s geometry args and taskbar.sh's
* `list` case, which does the actual window-to-monitor
* matching in awk */
} TaskbarEntry;
typedef struct Module {
char *name;
char *command;
char *click_command;
char *scroll_up_command;
char *scroll_down_command;
char *colour;
char *prefix;
char *prefix_command;
char *prefix_cached;
int min_width;
int max_width; /* 0 = no cap; text wider than this scrolls (marquee)
* instead of stretching the bar -- see max_width in
* sxbarc */
int scroll_offset; /* marquee: current scroll position, in pixels */
int on_secondary;
int align;
int icon_only; /* show only the prefix/icon, never the module's own text */
XftColor xft_colour;
int has_colour;
int enabled;
int refresh_interval;
time_t last_update;
char *cached_output;
/* floating popup window opened on hover or click */
int popup_type;
int popup_trigger;
PopupItem *popup_items;
int popup_item_count;
int popup_item_max;
int popup_image_size; /* IMAGE rows scale to fit within this square box,
* in pixels; 0 = built-in default (see
* POPUP_IMAGE_SIZE in sxbar.c) */
int popup_items_from_config; /* config popup_item/popup_info lines replace the built-in defaults, once */
int slider_item_idx; /* which popup_items[] entry popup_set manages, or -1 */
/* the built-in `taskbar` module only: renders one clickable segment
* per current-workspace window directly in the bar itself, instead
* of a single cached_output string -- see update_taskbar() and the
* dedicated block in draw_bar_into() (src/sxbar.c) */
TaskbarEntry *taskbar_entries;
int taskbar_entry_count;
} Module;
/* maps a workspace's displayed label -- its _NET_DESKTOP_NAMES string,
* e.g. "1" -- to replacement text, e.g. a Nerd Font glyph, via the
* `workspace_icon` config directive */
typedef struct WorkspaceIcon {
char *name;
char *icon;
} WorkspaceIcon;
typedef struct Config {
int bottom_bar;
int height;
int vertical_padding;
int horizontal_padding;
int text_padding;
int border;
int border_width;
unsigned long background_colour;
unsigned long foreground_colour;
unsigned long border_colour;
char *font;
int show_version;
char *version_text;
Module *modules;
int module_count;
int max_modules;
int secondary_bar;
WorkspaceIcon *workspace_icons;
int workspace_icon_count;
int workspace_icon_max;
} Config;
/* one on-screen bar window: either the primary bar (workspaces + all
* primary-tagged modules + version) or the secondary bar (modules tagged
* `bar : module_name : secondary` only, on the opposite edge) */
typedef struct Bar {
int monitor;
int is_secondary;
Window win;
Pixmap buffer;
XftDraw *xft_draw;
} Bar;
/* the single floating popup window (at most one open at a time) */
typedef struct Popup {
int open;
Window win;
Pixmap buffer;
XftDraw *xft_draw;
Module *module;
int bar_idx;
int trigger;
int x, y, w, h;
int hover_row; /* row index highlighted (BUTTON/BUTTONS rows only), or -1 */
int hover_col; /* BUTTONS row: which segment is highlighted, or -1 */
int dragging_row; /* row index of the SLIDER row being dragged, or -1 */
} Popup;
typedef void (*EventHandler)(XEvent *);