summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoruint23 <[email protected]>2025-04-19 20:49:16 +0100
committeruint23 <[email protected]>2025-04-19 20:49:16 +0100
commit1ae8d76f4f49b6ae69844e9920b314d5c9f6b6b4 (patch)
tree5ac6b4a3bb3c99289a37fa98d1e54accc8957c44
parent2c65fd8577d87a7dc90c33f1e4d42839282278aa (diff)
statusbar support
-rw-r--r--src/defs.h2
-rw-r--r--src/sxwm.c207
-rw-r--r--src/usercfg.h5
3 files changed, 152 insertions, 62 deletions
diff --git a/src/defs.h b/src/defs.h
index 27a1a9e..ec4ab25 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -21,7 +21,7 @@
static const char *name[] = { __VA_ARGS__, NULL }
#define UDIST(a,b) abs((int)(a) - (int)(b))
-#define MAXCLIENTS 64
+#define MAXCLIENTS 99
#define MAXGAPS 100
enum { DRAG_NONE, DRAG_MOVE, DRAG_RESIZE } drag_mode = DRAG_NONE;
diff --git a/src/sxwm.c b/src/sxwm.c
index 99b959a..c2bf936 100644
--- a/src/sxwm.c
+++ b/src/sxwm.c
@@ -48,10 +48,11 @@ static void move_master_next(void);
static void move_master_prev(void);
static void other_wm(void);
static int other_wm_err(Display *dpy, XErrorEvent *ee);
-static uint64_t parse_col(const char *hex);
+static ulong parse_col(const char *hex);
static void quit(void);
static void run(void);
static void setup(void);
+static void setup_atoms(void);
static void spawn(const char **cmd);
static void tile(void);
static void toggle_floating(void);
@@ -61,6 +62,12 @@ static int xerr(Display *dpy, XErrorEvent *ee);
static void xev_case(XEvent *xev);
#include "usercfg.h"
+static Atom atom_net_supported;
+static Atom atom_wm_strut_partial;
+static Atom atom_wm_window_type;
+static Atom atom_net_wm_window_type_dock;
+static Atom atom_net_workarea;
+
static Cursor c_normal, c_move, c_resize;
static Client *clients = NULL;
static Client *drag_client = NULL;
@@ -70,9 +77,9 @@ static Display *dpy;
static Window root;
static Bool global_floating = False;
-static uint64_t last_motion_time = 0;
-static uint64_t border_foc_col;
-static uint64_t border_ufoc_col;
+static ulong last_motion_time = 0;
+static ulong border_foc_col;
+static ulong border_ufoc_col;
static uint gaps = GAPS;
static uint scr_width;
static uint scr_height;
@@ -80,6 +87,10 @@ static uint open_windows = 0;
static int drag_start_x, drag_start_y;
static int drag_orig_x, drag_orig_y, drag_orig_w, drag_orig_h;
+static uint reserve_left = 0;
+static uint reserve_right = 0;
+static uint reserve_top = 0;
+static uint reserve_bottom = 0;
static void
add_client(Window w)
@@ -326,13 +337,57 @@ hdl_keypress(XEvent *xev)
static void
hdl_map_req(XEvent *xev)
{
+ XConfigureRequestEvent *cr = &xev->xconfigurerequest;
+
+ Atom type;
+ int format;
+ ulong nitems, bytes_after;
+ Atom *types = NULL;
+
+ if (XGetWindowProperty(dpy, cr->window,
+ atom_wm_window_type, 0, 1, False,
+ XA_ATOM, &type, &format,
+ &nitems, &bytes_after,
+ (unsigned char**)&types) == Success && types)
+ {
+ if (nitems > 0 && types[0] == atom_net_wm_window_type_dock) {
+ XFree(types);
+
+ XMapWindow(dpy, cr->window);
+ ulong *strut = NULL;
+ if (XGetWindowProperty(dpy, cr->window,
+ atom_wm_strut_partial, 0, 12, False,
+ XA_CARDINAL, &type, &format,
+ &nitems, &bytes_after,
+ (unsigned char**)&strut) == Success && strut)
+ {
+ if (nitems >= 4) {
+ reserve_left = strut[0];
+ reserve_right = strut[1];
+ reserve_top = strut[2];
+ reserve_bottom = strut[3];
+ }
+ XFree(strut);
+ }
+
+ ulong workarea[4] = {
+ reserve_left,
+ reserve_top,
+ scr_width - reserve_left - reserve_right,
+ scr_height - reserve_top - reserve_bottom
+ };
+ XChangeProperty(dpy, root,
+ atom_net_workarea, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)workarea, 4);
+ return;
+ }
+ XFree(types);
+ }
+
if (open_windows == MAXCLIENTS)
return;
-
- XConfigureRequestEvent *cr = &xev->xconfigurerequest;
add_client(cr->window);
XMapWindow(dpy, cr->window);
-
if (!global_floating)
tile();
update_borders();
@@ -458,7 +513,7 @@ other_wm_err(Display *dpy, XErrorEvent *ee)
if (dpy && ee) return 0;
}
-static uint64_t
+static ulong
parse_col(const char *hex)
{
XColor col;
@@ -506,14 +561,15 @@ setup(void)
errx(0, "can't open display. quitting...");
root = XDefaultRootWindow(dpy);
+ setup_atoms();
+ other_wm();
+ grab_keys();
+
c_normal = XCreateFontCursor(dpy, XC_left_ptr);
c_move = XCreateFontCursor(dpy, XC_fleur);
c_resize = XCreateFontCursor(dpy, XC_bottom_right_corner);
XDefineCursor(dpy, root, c_normal);
- other_wm();
- grab_keys();
-
scr_width = XDisplayWidth(dpy, DefaultScreen(dpy));
scr_height = XDisplayHeight(dpy, DefaultScreen(dpy));
XSelectInput(dpy, root, SubstructureRedirectMask | SubstructureNotifyMask | KeyPressMask);
@@ -541,6 +597,32 @@ setup(void)
}
static void
+setup_atoms(void)
+{
+ /* intern the atoms we need */
+ atom_net_supported = XInternAtom(dpy, "_NET_SUPPORTED", False);
+ atom_wm_strut_partial = XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False);
+ atom_wm_window_type = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
+ atom_net_wm_window_type_dock = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK", False);
+ atom_net_workarea = XInternAtom(dpy, "_NET_WORKAREA", False);
+
+ /* advertise which EWMH hints we support on the root window */
+ Atom support_list[] = {
+ XInternAtom(dpy, "_NET_WM_STRUT_PARTIAL", False),
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False),
+ XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK",False),
+ XInternAtom(dpy, "_NET_WORKAREA", False),
+ /* you can add more here as you implement them: */
+ /* _NET_CLIENT_LIST, _NET_ACTIVE_WINDOW, etc. */
+ };
+ XChangeProperty(dpy, root,
+ atom_net_supported,
+ XA_ATOM, 32, PropModeReplace,
+ (unsigned char*)support_list,
+ sizeof(support_list)/sizeof(Atom));
+}
+
+static void
spawn(const char **cmd)
{
pid_t pid;
@@ -561,68 +643,75 @@ spawn(const char **cmd)
static void
tile(void)
{
- int n = 0;
+ uint total_windows = 0;
for (Client *c = clients; c; c = c->next)
if (!c->floating)
- ++n;
- if (n == 0) return;
-
- int stack_count = n - 1;
-
- int outer_x0 = gaps;
- int outer_y0 = gaps;
- int outer_w = scr_width - 2*gaps;
- int outer_h = scr_height - 2*gaps;
-
- int inter_x = (stack_count > 0 ? gaps : 0);
- int master_ow = (stack_count > 0)
- ? (int)(outer_w * MASTER_WIDTH)
- : outer_w;
- int stack_ow = (stack_count > 0)
- ? (outer_w - master_ow - inter_x)
- : 0;
+ ++total_windows;
+ if (total_windows == 0)
+ return;
- int master_x0 = outer_x0;
- int stack_x0 = outer_x0 + master_ow + inter_x;
+ uint stack_count = total_windows - 1;
- int inter_y_total = (stack_count > 1 ? gaps * (stack_count - 1) : 0);
- int each_oh = (stack_count > 0)
- ? (outer_h - inter_y_total) / stack_count
+ uint left = reserve_left + gaps;
+ uint top = reserve_top + gaps;
+ uint right = reserve_right + gaps;
+ uint bottom = reserve_bottom + gaps;
+
+ uint workarea_width = scr_width - left - right;
+ uint workarea_height = scr_height - top - bottom;
+
+ uint column_gap = (stack_count > 0 ? gaps : 0);
+ uint master_width = (stack_count > 0)
+ ? (int)(workarea_width * MASTER_WIDTH)
+ : workarea_width;
+ uint stack_width = (stack_count > 0)
+ ? (workarea_width - master_width - column_gap)
: 0;
- int used_h = each_oh * (stack_count > 0 ? stack_count - 1 : 0)
- + inter_y_total;
- int last_oh = (stack_count > 0)
- ? (outer_h - used_h)
- : outer_h;
+ uint master_x = left;
+ uint stack_x = left + master_width + column_gap;
+
+ uint total_row_gaps = (stack_count > 1 ? gaps * (stack_count - 1) : 0);
+ uint row_height = (stack_count > 0)
+ ? (workarea_height - total_row_gaps) / stack_count
+ : 0;
+ uint used_height = row_height * (stack_count > 0 ? stack_count - 1 : 0)
+ + total_row_gaps;
+ uint last_row_height = (stack_count > 0)
+ ? (workarea_height - used_height)
+ : workarea_height;
- int i = 0;
+ uint index = 0;
for (Client *c = clients; c; c = c->next) {
- if (c->floating) continue;
- XWindowChanges ch = { .border_width = BORDER_WIDTH };
-
- if (i == 0) {
- ch.x = master_x0;
- ch.y = outer_y0;
- ch.width = master_ow - 2*BORDER_WIDTH;
- ch.height = outer_h - 2*BORDER_WIDTH;
+ if (c->floating)
+ continue;
+
+ XWindowChanges changes = { .border_width = BORDER_WIDTH };
+
+ if (index == 0) {
+ changes.x = master_x;
+ changes.y = top;
+ changes.width = master_width - 2*BORDER_WIDTH;
+ changes.height = workarea_height - 2*BORDER_WIDTH;
} else {
- int row = i - 1;
- int outer_y = outer_y0 + row * (each_oh + gaps);
- int outer_hh = (row < stack_count - 1 ? each_oh : last_oh);
-
- ch.x = stack_x0;
- ch.y = outer_y;
- ch.width = stack_ow - 2*BORDER_WIDTH;
- ch.height = outer_hh - 2*BORDER_WIDTH;
+ uint row = index - 1;
+ uint y_pos = top + row * (row_height + gaps);
+ uint height = (row < stack_count - 1)
+ ? row_height
+ : last_row_height;
+
+ changes.x = stack_x;
+ changes.y = y_pos;
+ changes.width = stack_width - 2*BORDER_WIDTH;
+ changes.height = height - 2*BORDER_WIDTH;
}
XSetWindowBorder(dpy, c->win,
- (i == 0 ? border_foc_col : border_ufoc_col));
+ (index == 0 ? border_foc_col : border_ufoc_col));
XConfigureWindow(dpy, c->win,
CWX|CWY|CWWidth|CWHeight|CWBorderWidth,
- &ch);
- ++i;
+ &changes);
+ ++index;
}
}
diff --git a/src/usercfg.h b/src/usercfg.h
index 0d6e500..b364540 100644
--- a/src/usercfg.h
+++ b/src/usercfg.h
@@ -26,6 +26,7 @@
* MASTER_WIDTH (float):
* % of the screen the master window
* should take as a decimal value 0-1
+ * eg. 0.5 is 50%
*
* MOTION_THROTTLE (int):
* Usually you should set this to your
@@ -46,8 +47,8 @@
#define BORDER_FOC_COL "#005577"
#define BORDER_UFOC_COL "#444444"
-#define MASTER_WIDTH 0.6
-#define MOTION_THROTTLE 144
+#define MASTER_WIDTH 0.5
+#define MOTION_THROTTLE 60
#define SNAP_DISTANCE 5
/*