From c9f28bb73890de5faa3ebcae7ca9df0fa62fc7d2 Mon Sep 17 00:00:00 2001 From: Nikita Langer Date: Mon, 13 Apr 2026 18:25:32 +0200 Subject: alpha --- Makefile | 7 +- config.def.h | 13 ++-- patches/tabbed-alpha-0.9.diff | 124 ++++++++++++++++++++++++++++++ patches/tabbed-drag-20230128-41e2b8f.diff | 83 ++++++++++++++++++++ tabbed.c | 102 +++++++++++++++++++++--- 5 files changed, 312 insertions(+), 17 deletions(-) create mode 100644 patches/tabbed-alpha-0.9.diff create mode 100644 patches/tabbed-drag-20230128-41e2b8f.diff diff --git a/Makefile b/Makefile index d7a2c35..9038198 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ DOCPREFIX = ${PREFIX}/share/doc/${NAME} # use system flags. TABBED_CFLAGS = -I/usr/X11R6/include -I/usr/include/freetype2 ${CFLAGS} -TABBED_LDFLAGS = -L/usr/X11R6/lib -lX11 -lfontconfig -lXft ${LDFLAGS} +TABBED_LDFLAGS = -L/usr/X11R6/lib -lX11 -lfontconfig -lXft -lXrender ${LDFLAGS} TABBED_CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700L # OpenBSD (uncomment) @@ -37,7 +37,10 @@ config.h: ${CC} -o $@ $< ${TABBED_LDFLAGS} clean: - rm -f ${BIN} ${OBJ} "${NAME}-${VERSION}.tar.gz" + rm -f ${BIN} ${OBJ} "${NAME}-${VERSION}.tar.gz" config.h + +patch: + rm -f *.rej *.orig dist: clean mkdir -p "${NAME}-${VERSION}" diff --git a/config.def.h b/config.def.h index 51bb13d..4707e5b 100644 --- a/config.def.h +++ b/config.def.h @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. */ /* appearance */ -static const char font[] = "monospace:size=9"; +static const char font[] = "JetBrains Mono Nerd Font Propo:size=10"; static const char* normbgcolor = "#222222"; static const char* normfgcolor = "#cccccc"; static const char* selbgcolor = "#555555"; @@ -27,17 +27,19 @@ static Bool npisrelative = False; .v = (char *[]){ "/bin/sh", "-c", \ "prop=\"`xwininfo -children -id $1 | grep '^ 0x' |" \ "sed -e's@^ *\\(0x[0-9a-f]*\\) \"\\([^\"]*\\)\".*@\\1 \\2@' |" \ - "xargs -0 printf %b | dmenu -l 10 -w $1`\" &&" \ + "xargs -0 printf %b | dmenu -vi -l 10 -w $1`\" &&" \ "xprop -id $1 -f $0 8s -set $0 \"$prop\"", \ p, winid, NULL \ } \ } -#define MODKEY ControlMask +// #define MODKEY ControlMask +#define MODKEY Mod1Mask static const Key keys[] = { /* modifier key function argument */ { MODKEY|ShiftMask, XK_Return, focusonce, { 0 } }, - { MODKEY|ShiftMask, XK_Return, spawn, { 0 } }, + // { MODKEY|ShiftMask, XK_Return, spawn, { 0 } }, + { MODKEY, XK_Return, spawn, { 0 } }, { MODKEY|ShiftMask, XK_l, rotate, { .i = +1 } }, { MODKEY|ShiftMask, XK_h, rotate, { .i = -1 } }, @@ -45,7 +47,8 @@ static const Key keys[] = { { MODKEY|ShiftMask, XK_k, movetab, { .i = +1 } }, { MODKEY, XK_Tab, rotate, { .i = 0 } }, - { MODKEY, XK_grave, spawn, SETPROP("_TABBED_SELECT_TAB") }, + // { MODKEY, XK_grave, spawn, SETPROP("_TABBED_SELECT_TAB") }, + { MODKEY, XK_g, spawn, SETPROP("_TABBED_SELECT_TAB") }, { MODKEY, XK_1, move, { .i = 0 } }, { MODKEY, XK_2, move, { .i = 1 } }, { MODKEY, XK_3, move, { .i = 2 } }, diff --git a/patches/tabbed-alpha-0.9.diff b/patches/tabbed-alpha-0.9.diff new file mode 100644 index 0000000..13e703b --- /dev/null +++ b/patches/tabbed-alpha-0.9.diff @@ -0,0 +1,124 @@ +diff --git a/Makefile b/Makefile +index d7a2c35..16ceff0 100644 +--- a/Makefile ++++ b/Makefile +@@ -10,7 +10,7 @@ DOCPREFIX = ${PREFIX}/share/doc/${NAME} + + # use system flags. + TABBED_CFLAGS = -I/usr/X11R6/include -I/usr/include/freetype2 ${CFLAGS} +-TABBED_LDFLAGS = -L/usr/X11R6/lib -lX11 -lfontconfig -lXft ${LDFLAGS} ++TABBED_LDFLAGS = -L/usr/X11R6/lib -lX11 -lfontconfig -lXft -lXrender ${LDFLAGS} + TABBED_CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -D_XOPEN_SOURCE=700L + + # OpenBSD (uncomment) +diff --git a/tabbed.c b/tabbed.c +index aa45716..d1911a3 100644 +--- a/tabbed.c ++++ b/tabbed.c +@@ -170,6 +170,9 @@ static char **cmd; + static char *wmname = "tabbed"; + static const char *geometry; + ++static Colormap cmap; ++static Visual *visual = NULL; ++ + char *argv0; + + /* configuration, allows nested code to access above variables */ +@@ -254,8 +257,8 @@ configurenotify(const XEvent *e) + ww = ev->width; + wh = ev->height; + XFreePixmap(dpy, dc.drawable); +- dc.drawable = XCreatePixmap(dpy, root, ww, wh, +- DefaultDepth(dpy, screen)); ++ dc.drawable = XCreatePixmap(dpy, win, ww, wh, ++ 32); + + if (!obh && (wh <= bh)) { + obh = bh; +@@ -407,7 +410,7 @@ drawtext(const char *text, XftColor col[ColLast]) + ; + } + +- d = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); ++ d = XftDrawCreate(dpy, dc.drawable, visual, cmap); + XftDrawStringUtf8(d, &col[ColFG], dc.font.xfont, x, y, (XftChar8 *) buf, len); + XftDrawDestroy(d); + } +@@ -587,7 +590,7 @@ getcolor(const char *colstr) + { + XftColor color; + +- if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), colstr, &color)) ++ if (!XftColorAllocName(dpy, visual, cmap, colstr, &color)) + die("%s: cannot allocate color '%s'\n", argv0, colstr); + + return color; +@@ -1049,18 +1052,60 @@ setup(void) + wy = dh + wy - wh - 1; + } + ++ XVisualInfo *vis; ++ XRenderPictFormat *fmt; ++ int nvi; ++ int i; ++ ++ XVisualInfo tpl = { ++ .screen = screen, ++ .depth = 32, ++ .class = TrueColor ++ }; ++ ++ vis = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask | VisualClassMask, &tpl, &nvi); ++ for(i = 0; i < nvi; i ++) { ++ fmt = XRenderFindVisualFormat(dpy, vis[i].visual); ++ if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { ++ visual = vis[i].visual; ++ break; ++ } ++ } ++ ++ XFree(vis); ++ ++ if (! visual) { ++ fprintf(stderr, "Couldn't find ARGB visual.\n"); ++ exit(1); ++ } ++ ++ cmap = XCreateColormap( dpy, root, visual, None); + dc.norm[ColBG] = getcolor(normbgcolor); + dc.norm[ColFG] = getcolor(normfgcolor); + dc.sel[ColBG] = getcolor(selbgcolor); + dc.sel[ColFG] = getcolor(selfgcolor); + dc.urg[ColBG] = getcolor(urgbgcolor); + dc.urg[ColFG] = getcolor(urgfgcolor); +- dc.drawable = XCreatePixmap(dpy, root, ww, wh, +- DefaultDepth(dpy, screen)); +- dc.gc = XCreateGC(dpy, root, 0, 0); + +- win = XCreateSimpleWindow(dpy, root, wx, wy, ww, wh, 0, +- dc.norm[ColFG].pixel, dc.norm[ColBG].pixel); ++ XSetWindowAttributes attrs; ++ attrs.background_pixel = dc.norm[ColBG].pixel; ++ attrs.border_pixel = dc.norm[ColFG].pixel; ++ attrs.bit_gravity = NorthWestGravity; ++ attrs.event_mask = FocusChangeMask | KeyPressMask ++ | ExposureMask | VisibilityChangeMask | StructureNotifyMask ++ | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; ++ attrs.background_pixmap = None ; ++ attrs.colormap = cmap; ++ ++ win = XCreateWindow(dpy, root, wx, wy, ++ ww, wh, 0, 32, InputOutput, ++ visual, CWBackPixmap | CWBorderPixel | CWBitGravity ++ | CWEventMask | CWColormap, &attrs); ++ ++ dc.drawable = XCreatePixmap(dpy, win, ww, wh, ++ 32); ++ dc.gc = XCreateGC(dpy, dc.drawable, 0, 0); ++ + XMapRaised(dpy, win); + XSelectInput(dpy, win, SubstructureNotifyMask | FocusChangeMask | + ButtonPressMask | ExposureMask | KeyPressMask | +-- +2.51.0 diff --git a/patches/tabbed-drag-20230128-41e2b8f.diff b/patches/tabbed-drag-20230128-41e2b8f.diff new file mode 100644 index 0000000..30af15c --- /dev/null +++ b/patches/tabbed-drag-20230128-41e2b8f.diff @@ -0,0 +1,83 @@ +From caf61ed5c47b32938bea4a0577f4f6953ddd1578 Mon Sep 17 00:00:00 2001 +From: Casey Fitzpatrick +Date: Fri, 27 Jan 2023 19:46:05 -0500 +Subject: [PATCH] Support draggable tabs + +--- + tabbed.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/tabbed.c b/tabbed.c +index eafe28a..2e3b61a 100644 +--- a/tabbed.c ++++ b/tabbed.c +@@ -88,6 +88,7 @@ typedef struct { + + /* function declarations */ + static void buttonpress(const XEvent *e); ++static void motionnotify(const XEvent *e); + static void cleanup(void); + static void clientmessage(const XEvent *e); + static void configurenotify(const XEvent *e); +@@ -151,6 +152,7 @@ static void (*handler[LASTEvent]) (const XEvent *) = { + [KeyPress] = keypress, + [MapRequest] = maprequest, + [PropertyNotify] = propertynotify, ++ [MotionNotify] = motionnotify, + }; + static int bh, obh, wx, wy, ww, wh; + static unsigned int numlockmask; +@@ -209,6 +211,41 @@ buttonpress(const XEvent *e) + } + } + ++void ++motionnotify(const XEvent *e) ++{ ++ const XMotionEvent *ev = &e->xmotion; ++ int i, fc; ++ Arg arg; ++ ++ if (ev->y < 0 || ev->y > bh) ++ return; ++ ++ if (! (ev->state & Button1Mask)) { ++ return; ++ } ++ ++ if (((fc = getfirsttab()) > 0 && ev->x < TEXTW(before)) || ev->x < 0) ++ return; ++ ++ if (sel < 0) ++ return; ++ ++ for (i = fc; i < nclients; i++) { ++ if (clients[i]->tabx > ev->x) { ++ if (i == sel+1) { ++ arg.i = 1; ++ movetab(&arg); ++ } ++ if (i == sel-1) { ++ arg.i = -1; ++ movetab(&arg); ++ } ++ break; ++ } ++ } ++} ++ + void + cleanup(void) + { +@@ -1046,7 +1083,7 @@ setup(void) + XSelectInput(dpy, win, SubstructureNotifyMask | FocusChangeMask | + ButtonPressMask | ExposureMask | KeyPressMask | + PropertyChangeMask | StructureNotifyMask | +- SubstructureRedirectMask); ++ SubstructureRedirectMask | ButtonMotionMask); + xerrorxlib = XSetErrorHandler(xerror); + + class_hint.res_name = wmname; +-- +2.25.1 + diff --git a/tabbed.c b/tabbed.c index 2fb5aa7..19307b1 100644 --- a/tabbed.c +++ b/tabbed.c @@ -89,6 +89,7 @@ typedef struct { /* function declarations */ static void buttonpress(const XEvent *e); +static void motionnotify(const XEvent *e); static void cleanup(void); static void clientmessage(const XEvent *e); static void configurenotify(const XEvent *e); @@ -151,6 +152,7 @@ static void (*handler[LASTEvent]) (const XEvent *) = { [KeyPress] = keypress, [MapRequest] = maprequest, [PropertyNotify] = propertynotify, + [MotionNotify] = motionnotify, }; static int bh, obh, wx, wy, ww, wh; static unsigned int numlockmask; @@ -170,6 +172,9 @@ static char **cmd; static char *wmname = "tabbed"; static const char *geometry; +static Colormap cmap; +static Visual *visual = NULL; + char *argv0; /* configuration, allows nested code to access above variables */ @@ -209,6 +214,41 @@ buttonpress(const XEvent *e) } } +void +motionnotify(const XEvent *e) +{ + const XMotionEvent *ev = &e->xmotion; + int i, fc; + Arg arg; + + if (ev->y < 0 || ev->y > bh) + return; + + if (! (ev->state & Button1Mask)) { + return; + } + + if (((fc = getfirsttab()) > 0 && ev->x < TEXTW(before)) || ev->x < 0) + return; + + if (sel < 0) + return; + + for (i = fc; i < nclients; i++) { + if (clients[i]->tabx > ev->x) { + if (i == sel+1) { + arg.i = 1; + movetab(&arg); + } + if (i == sel-1) { + arg.i = -1; + movetab(&arg); + } + break; + } + } +} + void cleanup(void) { @@ -254,8 +294,8 @@ configurenotify(const XEvent *e) ww = ev->width; wh = ev->height; XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, ww, wh, - DefaultDepth(dpy, screen)); + dc.drawable = XCreatePixmap(dpy, win, ww, wh, + 32); if (!obh && (wh <= bh)) { obh = bh; @@ -407,7 +447,7 @@ drawtext(const char *text, XftColor col[ColLast]) ; } - d = XftDrawCreate(dpy, dc.drawable, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); + d = XftDrawCreate(dpy, dc.drawable, visual, cmap); XftDrawStringUtf8(d, &col[ColFG], dc.font.xfont, x, y, (XftChar8 *) buf, len); XftDrawDestroy(d); } @@ -587,7 +627,7 @@ getcolor(const char *colstr) { XftColor color; - if (!XftColorAllocName(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), colstr, &color)) + if (!XftColorAllocName(dpy, visual, cmap, colstr, &color)) die("%s: cannot allocate color '%s'\n", argv0, colstr); return color; @@ -1049,23 +1089,65 @@ setup(void) wy = dh + wy - wh - 1; } + XVisualInfo *vis; + XRenderPictFormat *fmt; + int nvi; + int i; + + XVisualInfo tpl = { + .screen = screen, + .depth = 32, + .class = TrueColor + }; + + vis = XGetVisualInfo(dpy, VisualScreenMask | VisualDepthMask | VisualClassMask, &tpl, &nvi); + for(i = 0; i < nvi; i ++) { + fmt = XRenderFindVisualFormat(dpy, vis[i].visual); + if (fmt->type == PictTypeDirect && fmt->direct.alphaMask) { + visual = vis[i].visual; + break; + } + } + + XFree(vis); + + if (! visual) { + fprintf(stderr, "Couldn't find ARGB visual.\n"); + exit(1); + } + + cmap = XCreateColormap( dpy, root, visual, None); dc.norm[ColBG] = getcolor(normbgcolor); dc.norm[ColFG] = getcolor(normfgcolor); dc.sel[ColBG] = getcolor(selbgcolor); dc.sel[ColFG] = getcolor(selfgcolor); dc.urg[ColBG] = getcolor(urgbgcolor); dc.urg[ColFG] = getcolor(urgfgcolor); - dc.drawable = XCreatePixmap(dpy, root, ww, wh, - DefaultDepth(dpy, screen)); - dc.gc = XCreateGC(dpy, root, 0, 0); - win = XCreateSimpleWindow(dpy, root, wx, wy, ww, wh, 0, - dc.norm[ColFG].pixel, dc.norm[ColBG].pixel); + XSetWindowAttributes attrs; + attrs.background_pixel = dc.norm[ColBG].pixel; + attrs.border_pixel = dc.norm[ColFG].pixel; + attrs.bit_gravity = NorthWestGravity; + attrs.event_mask = FocusChangeMask | KeyPressMask + | ExposureMask | VisibilityChangeMask | StructureNotifyMask + | ButtonMotionMask | ButtonPressMask | ButtonReleaseMask; + attrs.background_pixmap = None ; + attrs.colormap = cmap; + + win = XCreateWindow(dpy, root, wx, wy, + ww, wh, 0, 32, InputOutput, + visual, CWBackPixmap | CWBorderPixel | CWBitGravity + | CWEventMask | CWColormap, &attrs); + + dc.drawable = XCreatePixmap(dpy, win, ww, wh, + 32); + dc.gc = XCreateGC(dpy, dc.drawable, 0, 0); + XMapRaised(dpy, win); XSelectInput(dpy, win, SubstructureNotifyMask | FocusChangeMask | ButtonPressMask | ExposureMask | KeyPressMask | PropertyChangeMask | StructureNotifyMask | - SubstructureRedirectMask); + SubstructureRedirectMask | ButtonMotionMask); xerrorxlib = XSetErrorHandler(xerror); class_hint.res_name = wmname; -- cgit