linux-qubasis

linux oasis port as a qubes template

git clone https://9o.is/git/linux-qubasis.git

commit 554fba3761107f1f90fedf2fd7cfe345c67f8e0a
parent 014eda514915d93a6e4df2d083e207a573e1667a
Author: Jul <jul@9o.is>
Date:   Sat, 19 Jul 2025 17:37:32 -0400

add dvtm

Diffstat:
M.gitmodules | 4++++
Apkg/dvtm/build | 23+++++++++++++++++++++++
Apkg/dvtm/config.h | 166+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apkg/dvtm/config.mk | 10++++++++++
Apkg/dvtm/patches/0001-customize-personal-UI.patch | 212+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apkg/dvtm/repo | 1+
6 files changed, 416 insertions(+), 0 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -7,3 +7,7 @@ path = pkg/yash/repo url = https://github.com/magicant/yash.git ignore = all +[submodule "dvtm"] + path = pkg/dvtm/repo + url = https://github.com/martanne/dvtm.git + ignore = all diff --git a/pkg/dvtm/build b/pkg/dvtm/build @@ -0,0 +1,23 @@ +#!/bin/sh +set -euo pipefail + +gitref="7bcf43f" +repodir="$srcdir/repo" + +if [ "$skip_clean" != "true" ]; then + git -C "$repodir" clean -dx + git -C "$repodir" reset --hard "$gitref" + + for patch in $srcdir/patches/*.patch; do + git -C "$repodir" am --no-gpg-sign "$patch" + done +fi + +rm -rf "$outdir" +cp "$srcdir/config.h" "$repodir" +cp "$srcdir/config.mk" "$repodir" + +export DESTDIR="$outdir" + +make -C "$repodir" +make -C "$repodir" install diff --git a/pkg/dvtm/config.h b/pkg/dvtm/config.h @@ -0,0 +1,166 @@ +/* valid curses attributes are listed below they can be ORed + * + * A_NORMAL Normal display (no highlight) + * A_STANDOUT Best highlighting mode of the terminal. + * A_UNDERLINE Underlining + * A_REVERSE Reverse video + * A_BLINK Blinking + * A_DIM Half bright + * A_BOLD Extra bright or bold + * A_PROTECT Protected mode + * A_INVIS Invisible or blank mode + */ + +enum { + DEFAULT, + BLUE, +}; + +static Color colors[] = { + [DEFAULT] = { .fg = -1, .bg = -1, .fg256 = -1, .bg256 = -1, }, + [BLUE] = { .fg = COLOR_BLUE, .bg = -1, .fg256 = 4, .bg256 = -1, }, +}; + +#define COLOR(c) COLOR_PAIR(colors[c].pair) +/* curses attributes for the currently focused window */ +#define SELECTED_ATTR (COLOR(BLUE) | A_NORMAL) +/* curses attributes for normal (not selected) windows */ +#define NORMAL_ATTR (COLOR(DEFAULT) | A_NORMAL) +/* curses attributes for a window with pending urgent flag */ +#define URGENT_ATTR NORMAL_ATTR +/* status bar (command line option -s) position */ +#define BAR_POS BAR_TOP /* BAR_BOTTOM, BAR_OFF */ +/* whether status bar should be hidden if only one client exists */ +#define BAR_AUTOHIDE true +/* master width factor [0.1 .. 0.9] */ +#define MFACT 0.6 +/* number of clients in master area */ +#define NMASTER 1 +/* scroll back buffer size in lines */ +#define SCROLL_HISTORY 10000 +/* curses attributes for the currently selected tags */ +#define TAG_SEL (COLOR(BLUE) | A_NORMAL) +/* curses attributes for not selected tags which contain windows */ +#define TAG_OCCUPIED (COLOR(DEFAULT) | A_NORMAL) +/* curses attributes for not selected tags which with urgent windows */ +#define TAG_URGENT (COLOR(DEFAULT) | A_NORMAL | A_BLINK) + +const char tags[][8] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; + +#include "tile.c" +#include "grid.c" +#include "bstack.c" +#include "fullscreen.c" + +/* by default the first layout entry is used */ +static Layout layouts[] = { + { "[ ]", fullscreen }, + { "[]=", tile }, + { "TTT", bstack }, + { "+++", grid }, +}; + +#define MOD CTRL('b') +#define TAGKEYS(KEY,TAG) \ + { { MOD, 'v', KEY, }, { view, { tags[TAG] } } }, \ + { { MOD, 't', KEY, }, { tag, { tags[TAG] } } }, \ + { { MOD, 'V', KEY, }, { toggleview, { tags[TAG] } } }, \ + { { MOD, 'T', KEY, }, { toggletag, { tags[TAG] } } }, + +/* you can specifiy at most 3 arguments */ +static KeyBinding bindings[] = { + { { MOD, 'c', }, { create, { NULL } } }, + { { MOD, 'C', }, { create, { NULL, NULL, "$CWD" } } }, + { { MOD, 'x', }, { killclient, { NULL } } }, + { { MOD, 'j', }, { focusnext, { NULL } } }, + { { MOD, 'J', }, { focusdown, { NULL } } }, + { { MOD, 'K', }, { focusup, { NULL } } }, + { { MOD, 'H', }, { focusleft, { NULL } } }, + { { MOD, 'L', }, { focusright, { NULL } } }, + { { MOD, 'k', }, { focusprev, { NULL } } }, + { { MOD, 'f', }, { setlayout, { "[]=" } } }, + { { MOD, 'g', }, { setlayout, { "+++" } } }, + { { MOD, 'b', }, { setlayout, { "TTT" } } }, + { { MOD, 'm', }, { setlayout, { "[ ]" } } }, + { { MOD, ' ', }, { setlayout, { NULL } } }, + { { MOD, 'i', }, { incnmaster, { "+1" } } }, + { { MOD, 'd', }, { incnmaster, { "-1" } } }, + { { MOD, 'h', }, { setmfact, { "-0.05" } } }, + { { MOD, 'l', }, { setmfact, { "+0.05" } } }, + { { MOD, '.', }, { toggleminimize, { NULL } } }, + { { MOD, 's', }, { togglebar, { NULL } } }, + { { MOD, 'S', }, { togglebarpos, { NULL } } }, + { { MOD, 'M', }, { togglemouse, { NULL } } }, + { { MOD, '\n', }, { zoom , { NULL } } }, + { { MOD, '\r', }, { zoom , { NULL } } }, + { { MOD, '1', }, { focusn, { "1" } } }, + { { MOD, '2', }, { focusn, { "2" } } }, + { { MOD, '3', }, { focusn, { "3" } } }, + { { MOD, '4', }, { focusn, { "4" } } }, + { { MOD, '5', }, { focusn, { "5" } } }, + { { MOD, '6', }, { focusn, { "6" } } }, + { { MOD, '7', }, { focusn, { "7" } } }, + { { MOD, '8', }, { focusn, { "8" } } }, + { { MOD, '9', }, { focusn, { "9" } } }, + { { MOD, '\t', }, { focuslast, { NULL } } }, + { { MOD, 'q', 'q', }, { quit, { NULL } } }, + { { MOD, 'a', }, { togglerunall, { NULL } } }, + { { MOD, CTRL('L'), }, { redraw, { NULL } } }, + { { MOD, 'r', }, { redraw, { NULL } } }, + { { MOD, 'e', }, { copymode, { "dvtm-editor" } } }, + { { MOD, 'E', }, { copymode, { "dvtm-pager" } } }, + { { MOD, '/', }, { copymode, { "dvtm-pager", "/" } } }, + { { MOD, 'p', }, { paste, { NULL } } }, + { { MOD, KEY_PPAGE, }, { scrollback, { "-1" } } }, + { { MOD, KEY_NPAGE, }, { scrollback, { "1" } } }, + { { MOD, '?', }, { create, { "man dvtm", "dvtm help" } } }, + { { MOD, MOD, }, { send, { (const char []){MOD, 0} } } }, + { { KEY_SPREVIOUS, }, { scrollback, { "-1" } } }, + { { KEY_SNEXT, }, { scrollback, { "1" } } }, + { { MOD, '0', }, { view, { NULL } } }, + { { MOD, KEY_F(1), }, { view, { tags[0] } } }, + { { MOD, KEY_F(2), }, { view, { tags[1] } } }, + { { MOD, KEY_F(3), }, { view, { tags[2] } } }, + { { MOD, KEY_F(4), }, { view, { tags[3] } } }, + { { MOD, KEY_F(5), }, { view, { tags[4] } } }, + { { MOD, KEY_F(6), }, { view, { tags[5] } } }, + { { MOD, KEY_F(7), }, { view, { tags[6] } } }, + { { MOD, KEY_F(8), }, { view, { tags[7] } } }, + { { MOD, KEY_F(9), }, { view, { tags[8] } } }, + { { MOD, 'v', '0' }, { view, { NULL } } }, + { { MOD, 'v', '\t', }, { viewprevtag, { NULL } } }, + { { MOD, 't', '0' }, { tag, { NULL } } }, + TAGKEYS( '1', 0) + TAGKEYS( '2', 1) + TAGKEYS( '3', 2) + TAGKEYS( '4', 3) + TAGKEYS( '5', 4) + TAGKEYS( '6', 5) + TAGKEYS( '7', 6) + TAGKEYS( '8', 7) + TAGKEYS( '9', 8) +}; + +static const ColorRule colorrules[] = { + { "", A_NORMAL, &colors[DEFAULT] }, /* default */ +}; + +#define ENABLE_MOUSE false + +static Cmd commands[] = { + /* create [cmd]: create a new window, run `cmd` in the shell if specified */ + { "create", { create, { NULL } } }, + /* focus <win_id>: focus the window whose `DVTM_WINDOW_ID` is `win_id` */ + { "focus", { focusid, { NULL } } }, + /* tag <win_id> <tag> [tag ...]: add +tag, remove -tag or set tag of the window with the given identifier */ + { "tag", { tagid, { NULL } } }, +}; + +/* gets executed when dvtm is started */ +static Action actions[] = { + { create, { NULL } }, +}; + +static char const * const keytable[] = { + /* add your custom key escape sequences */ +}; diff --git a/pkg/dvtm/config.mk b/pkg/dvtm/config.mk @@ -0,0 +1,10 @@ +PREFIX ?= /usr +MANPREFIX = ${PREFIX}/share/man +TERMINFO := ${DESTDIR}${PREFIX}/share/terminfo + +INCS = -I. +LIBS = -lc -lutil -lncursesw +CPPFLAGS = -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED +CFLAGS += -std=c99 ${INCS} -DNDEBUG ${CPPFLAGS} + +CC ?= cc diff --git a/pkg/dvtm/patches/0001-customize-personal-UI.patch b/pkg/dvtm/patches/0001-customize-personal-UI.patch @@ -0,0 +1,212 @@ +From e8337ba61c92afc5e45f54b6c5ddf95d68f179c3 Mon Sep 17 00:00:00 2001 +From: Jul <jul@qh.is> +Date: Sat, 19 Jul 2025 14:05:33 -0400 +Subject: [PATCH] customize personal UI + +--- + dvtm.c | 168 ++++++++++++++++++++++++++++----------------------------- + 1 file changed, 82 insertions(+), 86 deletions(-) + +diff --git a/dvtm.c b/dvtm.c +index 8382c83..79747d0 100644 +--- a/dvtm.c ++++ b/dvtm.c +@@ -324,74 +324,86 @@ showbar(void) { + + static void + drawbar(void) { +- int sx, sy, x, y, width; +- unsigned int occupied = 0, urgent = 0; +- if (bar.pos == BAR_OFF) +- return; +- +- for (Client *c = clients; c; c = c->next) { +- occupied |= c->tags; +- if (c->urgent) +- urgent |= c->tags; +- } +- +- getyx(stdscr, sy, sx); +- attrset(BAR_ATTR); +- move(bar.y, 0); +- +- for (unsigned int i = 0; i < LENGTH(tags); i++){ +- if (tagset[seltags] & (1 << i)) +- attrset(TAG_SEL); +- else if (urgent & (1 << i)) +- attrset(TAG_URGENT); +- else if (occupied & (1 << i)) +- attrset(TAG_OCCUPIED); +- else +- attrset(TAG_NORMAL); +- printw(TAG_SYMBOL, tags[i]); +- } +- +- attrset(runinall ? TAG_SEL : TAG_NORMAL); +- addstr(layout->symbol); +- attrset(TAG_NORMAL); +- +- for (unsigned int i = 0; i < MAX_KEYS && keys[i]; i++) { +- if (keys[i] < ' ') +- printw("^%c", 'A' - 1 + keys[i]); +- else +- printw("%c", keys[i]); +- } +- +- getyx(stdscr, y, x); +- (void)y; +- int maxwidth = screen.w - x - 2; +- +- addch(BAR_BEGIN); +- attrset(BAR_ATTR); +- +- wchar_t wbuf[sizeof bar.text]; +- size_t numchars = mbstowcs(wbuf, bar.text, sizeof bar.text); +- +- if (numchars != (size_t)-1 && (width = wcswidth(wbuf, maxwidth)) != -1) { +- int pos; +- for (pos = 0; pos + width < maxwidth; pos++) +- addch(' '); +- +- for (size_t i = 0; i < numchars; i++) { +- pos += wcwidth(wbuf[i]); +- if (pos > maxwidth) +- break; +- addnwstr(wbuf+i, 1); +- } +- +- clrtoeol(); +- } +- +- attrset(TAG_NORMAL); +- mvaddch(bar.y, screen.w - 1, BAR_END); +- attrset(NORMAL_ATTR); +- move(sy, sx); +- wnoutrefresh(stdscr); ++ int sx, sy, x, y, width; ++ unsigned int occupied = 0, urgent = 0, total_clients = 0; ++ if (bar.pos == BAR_OFF) ++ return; ++ ++ for (Client *c = clients; c; c = c->next) { ++ if (isvisible(c)) ++ total_clients++; ++ ++ occupied |= c->tags; ++ ++ if (c->urgent) ++ urgent |= c->tags; ++ } ++ ++ getyx(stdscr, sy, sx); ++ move(bar.y, 0); ++ ++ if (sel) { ++ char t = '\0'; ++ unsigned int maxlen = screen.w / 2; ++ ++ if ((size_t)maxlen < sizeof(sel->title)) { ++ t = sel->title[maxlen]; ++ sel->title[maxlen] = '\0'; ++ } ++ ++ printw("%s", *sel->title ? sel->title : ""); ++ if (t) ++ sel->title[maxlen] = t; ++ } ++ ++ move(bar.y, screen.w / 2 + 1); ++ getyx(stdscr, y, x); ++ (void)y; ++ ++ int maxwidth = screen.w - x - 16; ++ wchar_t wbuf[sizeof bar.text]; ++ size_t numchars = mbstowcs(wbuf, bar.text, sizeof bar.text); ++ ++ if (numchars != (size_t)-1 && (width = wcswidth(wbuf, maxwidth)) != -1) { ++ int pos; ++ for (pos = 0; pos + width < maxwidth; pos++) ++ addch(' '); ++ ++ for (size_t i = 0; i < numchars; i++) { ++ pos += wcwidth(wbuf[i]); ++ if (pos > maxwidth) ++ break; ++ addnwstr(wbuf+i, 1); ++ } ++ ++ clrtoeol(); ++ } ++ ++ if (sel && total_clients > 1) ++ printw(" [%d/%d]", sel->order, total_clients); ++ ++ unsigned int tag_position = 0; ++ for (unsigned int i = 0; i < LENGTH(tags); i++){ ++ move(bar.y, screen.w - tag_position - 1); ++ ++ if (tagset[seltags] & (1 << i)) { ++ attrset(TAG_SEL); ++ printw("%s", tags[i]); ++ tag_position++; ++ } else if (urgent & (1 << i)) { ++ attrset(TAG_URGENT); ++ printw("%s", tags[i]); ++ tag_position++; ++ } else if (occupied & (1 << i)) { ++ attrset(TAG_OCCUPIED); ++ printw("%s", tags[i]); ++ tag_position++; ++ } ++ } ++ ++ attrset(NORMAL_ATTR); ++ move(sy, sx); ++ wnoutrefresh(stdscr); + } + + static int +@@ -401,8 +413,7 @@ show_border(void) { + + static void + draw_border(Client *c) { +- char t = '\0'; +- int x, y, maxlen, attrs = NORMAL_ATTR; ++ int x, y, attrs = NORMAL_ATTR; + + if (!show_border()) + return; +@@ -414,20 +425,6 @@ draw_border(Client *c) { + wattrset(c->window, attrs); + getyx(c->window, y, x); + mvwhline(c->window, 0, 0, ACS_HLINE, c->w); +- maxlen = c->w - 10; +- if (maxlen < 0) +- maxlen = 0; +- if ((size_t)maxlen < sizeof(c->title)) { +- t = c->title[maxlen]; +- c->title[maxlen] = '\0'; +- } +- +- mvwprintw(c->window, 0, 2, "[%s%s#%d]", +- *c->title ? c->title : "", +- *c->title ? " | " : "", +- c->order); +- if (t) +- c->title[maxlen] = t; + wmove(c->window, y, x); + } + +@@ -634,8 +631,7 @@ term_title_handler(Vt *term, const char *title) { + strncpy(c->title, title, sizeof(c->title) - 1); + c->title[title ? sizeof(c->title) - 1 : 0] = '\0'; + settitle(c); +- if (!isarrange(fullscreen) || sel == c) +- draw_border(c); ++ drawbar(); + applycolorrules(c); + } + +-- +2.50.0 + diff --git a/pkg/dvtm/repo b/pkg/dvtm/repo @@ -0,0 +1 @@ +Subproject commit e8337ba61c92afc5e45f54b6c5ddf95d68f179c3