linux-qubasis
linux oasis port as a qubes template
git clone https://9o.is/git/linux-qubasis.git
commit 1a05e79f00b7b0f45193d20e1fffff0e25a55f65 parent 59577322fe97d264c2692b39da9dc8b206f711f4 Author: Jul <jul@9o.is> Date: Sat, 29 Nov 2025 02:12:50 -0500 add dmenu Diffstat:
| M | .gitmodules | | | 4 | ++++ |
| A | pkg/dmenu/config.h | | | 23 | +++++++++++++++++++++++ |
| A | pkg/dmenu/gen.sh | | | 47 | +++++++++++++++++++++++++++++++++++++++++++++++ |
| A | pkg/dmenu/patch/0001-Port-to-wayland-using-wld-and-swc-panels.patch | | | 1285 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | pkg/gen.sh | | | 1 | + |
| M | qubes/example/gen.sh | | | 1 | + |
6 files changed, 1361 insertions(+), 0 deletions(-)
diff --git a/.gitmodules b/.gitmodules @@ -18,6 +18,10 @@ path = pkg/bzip2/src url = git://sourceware.org/git/bzip2.git ignore = all +[submodule "dmenu"] + path = pkg/dmenu/src + url = git://git.suckless.org/dmenu + ignore = all [submodule "e2fsprogs"] path = pkg/e2fsprogs/src url = https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git diff --git a/pkg/dmenu/config.h b/pkg/dmenu/config.h @@ -0,0 +1,23 @@ +/* See LICENSE file for copyright and license details. */ +/* Default settings; can be overriden by command line. */ + +static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ +/* -fn option overrides fonts[0]; default X11 font or font set */ +static const char *fonts[] = { + "Terminus:pixelsize=14" +}; +static const char *prompt = NULL; /* -p option; prompt to the left of input field */ +static const char *colors[SchemeLast][2] = { + /* fg bg */ + [SchemeNorm] = { "#999999", "#1a1a1a" }, + [SchemeSel] = { "#ffffff", "#338833" }, + [SchemeOut] = { "#000000", "#aaffaa" }, +}; +/* -l option; if nonzero, dmenu uses vertical list with given number of lines */ +static unsigned int lines = 0; + +/* + * Characters not considered part of a word while deleting words + * for example: " /?\"&[]" + */ +static const char worddelimiters[] = " "; diff --git a/pkg/dmenu/gen.sh b/pkg/dmenu/gen.sh @@ -0,0 +1,47 @@ +git 4.9 + +cflags " + -std=c99 + -DVERSION=\\\"4.9\\\" + -D_POSIX_C_SOURCE=200809L + -I$dir + -isystem $pkgdir/fontconfig/include + -isystem $pkgdir/libxkbcommon/include + -isystem $pkgdir/pixman/include + -isystem $pkgdir/swc/include + -isystem $pkgdir/wayland/include + -isystem $pkgdir/wld/include + -Wno-unused-parameter + -Wno-missing-field-initializers + -Wno-sign-compare +" + +dep " + fontconfig/headers + libxkbcommon/headers + pixman/headers + swc/headers + wayland/headers + wld/headers +" + +bin dmenu " + dmenu.c + drw.c + util.c + $pkgdir/swc/swc-protocol.c.o + $pkgdir/libxkbcommon/libxkbcommon.a + $pkgdir/wld/libwld.a.d + $pkgdir/fontconfig/libfontconfig.a.d + $pkgdir/wayland/libwayland-client.a.d +" + +bin stest stest.c + +binfiles " + dmenu_path + dmenu_run +" + +man dmenu.1 +man stest.1 diff --git a/pkg/dmenu/patch/0001-Port-to-wayland-using-wld-and-swc-panels.patch b/pkg/dmenu/patch/0001-Port-to-wayland-using-wld-and-swc-panels.patch @@ -0,0 +1,1285 @@ +From d186aa8891ca777615b8138416c95565c05e0a09 Mon Sep 17 00:00:00 2001 +From: Michael Forney <mforney@mforney.org> +Date: Thu, 27 Oct 2016 21:04:23 -0700 +Subject: [PATCH] Port to wayland using wld and swc panels + +--- + Makefile | 16 +- + config.mk | 20 +- + dmenu.c | 566 ++++++++++++++++++++++++++++-------------------------- + drw.c | 130 ++++++------- + drw.h | 26 ++- + 5 files changed, 381 insertions(+), 377 deletions(-) + +diff --git a/Makefile b/Makefile +index a03a95c..4046899 100644 +--- a/Makefile ++++ b/Makefile +@@ -3,7 +3,7 @@ + + include config.mk + +-SRC = drw.c dmenu.c stest.c util.c ++SRC = drw.c dmenu.c stest.c panel-protocol.c util.c + OBJ = $(SRC:.c=.o) + + all: options dmenu stest +@@ -20,10 +20,18 @@ options: + config.h: + cp config.def.h $@ + +-$(OBJ): arg.h config.h config.mk drw.h ++swc-protocol.c: $(SWCPROTO) ++ @echo GEN $@ ++ @wayland-scanner code < $< > $@ + +-dmenu: dmenu.o drw.o util.o +- $(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS) ++swc-client-protocol.h: $(SWCPROTO) ++ @echo GEN $@ ++ @wayland-scanner client-header < $< > $@ ++ ++$(OBJ): arg.h config.h config.mk drw.h swc-client-protocol.h ++ ++dmenu: dmenu.o drw.o swc-protocol.o util.o ++ $(CC) -o $@ dmenu.o drw.o swc-protocol.o util.o $(LDFLAGS) + + stest: stest.o + $(CC) -o $@ stest.o $(LDFLAGS) +diff --git a/config.mk b/config.mk +index 0929b4a..7e747ff 100644 +--- a/config.mk ++++ b/config.mk +@@ -5,25 +5,15 @@ VERSION = 4.9 + PREFIX = /usr/local + MANPREFIX = $(PREFIX)/share/man + +-X11INC = /usr/X11R6/include +-X11LIB = /usr/X11R6/lib +- +-# Xinerama, comment if you don't want it +-XINERAMALIBS = -lXinerama +-XINERAMAFLAGS = -DXINERAMA +- +-# freetype +-FREETYPELIBS = -lfontconfig -lXft +-FREETYPEINC = /usr/include/freetype2 +-# OpenBSD (uncomment) +-#FREETYPEINC = $(X11INC)/freetype2 ++PIXMANINC = /usr/include/pixman-1 ++SWCPROTO = /usr/share/swc/swc.xml + + # includes and libs +-INCS = -I$(X11INC) -I$(FREETYPEINC) +-LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) ++INCS = -I$(PIXMANINC) ++LIBS = -lwayland-client -lxkbcommon -lwld + + # flags +-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) ++CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" + CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) + LDFLAGS = $(LIBS) + +diff --git a/dmenu.c b/dmenu.c +index 6b8f51b..877c459 100644 +--- a/dmenu.c ++++ b/dmenu.c +@@ -5,19 +5,18 @@ + #include <stdlib.h> + #include <string.h> + #include <strings.h> ++#include <sys/mman.h> + #include <time.h> + #include <unistd.h> + +-#include <X11/Xlib.h> +-#include <X11/Xatom.h> +-#include <X11/Xutil.h> +-#ifdef XINERAMA +-#include <X11/extensions/Xinerama.h> +-#endif +-#include <X11/Xft/Xft.h> ++#include <wayland-client.h> ++#include <wld/wayland.h> ++#include <wld/wld.h> ++#include <xkbcommon/xkbcommon.h> + + #include "drw.h" + #include "util.h" ++#include "swc-client-protocol.h" + + /* macros */ + #define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ +@@ -34,8 +33,16 @@ struct item { + int out; + }; + ++struct xkb { ++ struct xkb_context *context; ++ struct xkb_state *state; ++ struct xkb_keymap *keymap; ++ xkb_mod_index_t ctrl, alt, shift; ++}; ++ ++static void paste(void); ++ + static char text[BUFSIZ] = ""; +-static char *embed; + static int bh, mw, mh; + static int inputw = 0, promptw; + static int lrpad; /* sum of left and right padding */ +@@ -43,12 +50,21 @@ static size_t cursor; + static struct item *items = NULL; + static struct item *matches, *matchend; + static struct item *prev, *curr, *next, *sel; +-static int mon = -1, screen; +- +-static Atom clip, utf8; +-static Display *dpy; +-static Window root, parentwin, win; +-static XIC xic; ++static int mon = -1; ++ ++static struct wl_display *dpy; ++static struct wl_compositor *compositor; ++static struct wl_keyboard *kbd; ++static struct wl_seat *seat; ++static struct wl_shell *shell; ++static struct wl_surface *surface; ++static struct wl_data_device_manager *datadevman; ++static struct wl_data_device *datadev; ++static struct wl_data_offer *seloffer; ++static struct swc_screen *screen; ++static struct swc_panel_manager *panelman; ++static struct swc_panel *panel; ++static struct xkb xkb; + + static Drw *drw; + static Clr *scheme[SchemeLast]; +@@ -94,12 +110,10 @@ cleanup(void) + { + size_t i; + +- XUngrabKey(dpy, AnyKey, AnyModifier, root); + for (i = 0; i < SchemeLast; i++) + free(scheme[i]); + drw_free(drw); +- XSync(dpy, False); +- XCloseDisplay(dpy); ++ wl_display_disconnect(dpy); + } + + static char * +@@ -133,6 +147,7 @@ drawmenu(void) + struct item *item; + int x = 0, y = 0, w; + ++ wld_set_target_surface(drw->renderer, drw->surface); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_rect(drw, 0, 0, mw, mh, 1, 1); + +@@ -172,42 +187,7 @@ drawmenu(void) + drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0); + } + } +- drw_map(drw, win, 0, 0, mw, mh); +-} +- +-static void +-grabfocus(void) +-{ +- struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000 }; +- Window focuswin; +- int i, revertwin; +- +- for (i = 0; i < 100; ++i) { +- XGetInputFocus(dpy, &focuswin, &revertwin); +- if (focuswin == win) +- return; +- XSetInputFocus(dpy, win, RevertToParent, CurrentTime); +- nanosleep(&ts, NULL); +- } +- die("cannot grab focus"); +-} +- +-static void +-grabkeyboard(void) +-{ +- struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; +- int i; +- +- if (embed) +- return; +- /* try to grab keyboard, we may have to wait for another process to ungrab */ +- for (i = 0; i < 1000; i++) { +- if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync, +- GrabModeAsync, CurrentTime) == GrabSuccess) +- return; +- nanosleep(&ts, NULL); +- } +- die("cannot grab keyboard"); ++ drw_map(drw, surface, 0, 0, mw, mh); + } + + static void +@@ -305,111 +285,105 @@ movewordedge(int dir) + } + + static void +-keypress(XKeyEvent *ev) ++kbdkey(void *d, struct wl_keyboard *kbd, uint32_t serial, uint32_t time, ++ uint32_t key, uint32_t state) + { + char buf[32]; + int len; +- KeySym ksym; +- Status status; ++ xkb_keysym_t ksym = XKB_KEY_NoSymbol; ++ int ctrl = xkb_state_mod_index_is_active(xkb.state, xkb.ctrl, XKB_STATE_MODS_EFFECTIVE); ++ int shift = xkb_state_mod_index_is_active(xkb.state, xkb.shift, XKB_STATE_MODS_EFFECTIVE); ++ int alt = xkb_state_mod_index_is_active(xkb.state, xkb.alt, XKB_STATE_MODS_EFFECTIVE); + +- len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); +- switch (status) { +- default: /* XLookupNone, XBufferOverflow */ +- return; +- case XLookupChars: +- goto insert; +- case XLookupKeySym: +- case XLookupBoth: +- break; +- } ++ if (state == WL_KEYBOARD_KEY_STATE_RELEASED) ++ goto update_state; + +- if (ev->state & ControlMask) { ++ ksym = xkb_state_key_get_one_sym(xkb.state, key + 8); ++ if (ctrl) { + switch(ksym) { +- case XK_a: ksym = XK_Home; break; +- case XK_b: ksym = XK_Left; break; +- case XK_c: ksym = XK_Escape; break; +- case XK_d: ksym = XK_Delete; break; +- case XK_e: ksym = XK_End; break; +- case XK_f: ksym = XK_Right; break; +- case XK_g: ksym = XK_Escape; break; +- case XK_h: ksym = XK_BackSpace; break; +- case XK_i: ksym = XK_Tab; break; +- case XK_j: /* fallthrough */ +- case XK_J: /* fallthrough */ +- case XK_m: /* fallthrough */ +- case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break; +- case XK_n: ksym = XK_Down; break; +- case XK_p: ksym = XK_Up; break; +- +- case XK_k: /* delete right */ ++ case XKB_KEY_a: ksym = XKB_KEY_Home; break; ++ case XKB_KEY_b: ksym = XKB_KEY_Left; break; ++ case XKB_KEY_c: ksym = XKB_KEY_Escape; break; ++ case XKB_KEY_d: ksym = XKB_KEY_Delete; break; ++ case XKB_KEY_e: ksym = XKB_KEY_End; break; ++ case XKB_KEY_f: ksym = XKB_KEY_Right; break; ++ case XKB_KEY_g: ksym = XKB_KEY_Escape; break; ++ case XKB_KEY_h: ksym = XKB_KEY_BackSpace; break; ++ case XKB_KEY_i: ksym = XKB_KEY_Tab; break; ++ case XKB_KEY_j: /* fallthrough */ ++ case XKB_KEY_J: /* fallthrough */ ++ case XKB_KEY_m: /* fallthrough */ ++ case XKB_KEY_M: ksym = XKB_KEY_Return; ctrl = 0; break; ++ case XKB_KEY_n: ksym = XKB_KEY_Down; break; ++ case XKB_KEY_p: ksym = XKB_KEY_Up; break; ++ ++ case XKB_KEY_k: /* delete right */ + text[cursor] = '\0'; + match(); + break; +- case XK_u: /* delete left */ ++ case XKB_KEY_u: /* delete left */ + insert(NULL, 0 - cursor); + break; +- case XK_w: /* delete word */ ++ case XKB_KEY_w: /* delete word */ + while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)])) + insert(NULL, nextrune(-1) - cursor); + break; +- case XK_y: /* paste selection */ +- case XK_Y: +- XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, +- utf8, utf8, win, CurrentTime); ++ case XKB_KEY_y: /* paste selection */ ++ case XKB_KEY_Y: ++ paste(); + return; +- case XK_Left: ++ case XKB_KEY_Left: + movewordedge(-1); + goto draw; +- case XK_Right: ++ case XKB_KEY_Right: + movewordedge(+1); + goto draw; +- case XK_Return: +- case XK_KP_Enter: ++ case XKB_KEY_Return: ++ case XKB_KEY_KP_Enter: + break; +- case XK_bracketleft: ++ case XKB_KEY_bracketleft: + cleanup(); + exit(1); + default: + return; + } +- } else if (ev->state & Mod1Mask) { ++ } else if (alt) { + switch(ksym) { +- case XK_b: ++ case XKB_KEY_b: + movewordedge(-1); + goto draw; +- case XK_f: ++ case XKB_KEY_f: + movewordedge(+1); + goto draw; +- case XK_g: ksym = XK_Home; break; +- case XK_G: ksym = XK_End; break; +- case XK_h: ksym = XK_Up; break; +- case XK_j: ksym = XK_Next; break; +- case XK_k: ksym = XK_Prior; break; +- case XK_l: ksym = XK_Down; break; ++ case XKB_KEY_g: ksym = XKB_KEY_Home; break; ++ case XKB_KEY_G: ksym = XKB_KEY_End; break; ++ case XKB_KEY_h: ksym = XKB_KEY_Up; break; ++ case XKB_KEY_j: ksym = XKB_KEY_Next; break; ++ case XKB_KEY_k: ksym = XKB_KEY_Prior; break; ++ case XKB_KEY_l: ksym = XKB_KEY_Down; break; + default: + return; + } + } +- +- switch(ksym) { ++ switch (ksym) { + default: +-insert: ++ len = xkb_state_key_get_utf8(xkb.state, key + 8, buf, sizeof(buf)); + if (!iscntrl(*buf)) + insert(buf, len); + break; +- case XK_Delete: ++ case XKB_KEY_Delete: + if (text[cursor] == '\0') + return; + cursor = nextrune(+1); + /* fallthrough */ +- case XK_BackSpace: ++ case XKB_KEY_BackSpace: + if (cursor == 0) + return; + insert(NULL, nextrune(-1) - cursor); + break; +- case XK_End: ++ case XKB_KEY_End: + if (text[cursor] != '\0') { + cursor = strlen(text); + break; +@@ -425,10 +399,10 @@ insert: + } + sel = matchend; + break; +- case XK_Escape: ++ case XKB_KEY_Escape: + cleanup(); + exit(1); +- case XK_Home: ++ case XKB_KEY_Home: + if (sel == matches) { + cursor = 0; + break; +@@ -436,7 +410,7 @@ insert: + sel = curr = matches; + calcoffsets(); + break; +- case XK_Left: ++ case XKB_KEY_Left: + if (cursor > 0 && (!sel || !sel->left || lines > 0)) { + cursor = nextrune(-1); + break; +@@ -444,35 +418,35 @@ insert: + if (lines > 0) + return; + /* fallthrough */ +- case XK_Up: ++ case XKB_KEY_Up: + if (sel && sel->left && (sel = sel->left)->right == curr) { + curr = prev; + calcoffsets(); + } + break; +- case XK_Next: ++ case XKB_KEY_Next: + if (!next) + return; + sel = curr = next; + calcoffsets(); + break; +- case XK_Prior: ++ case XKB_KEY_Prior: + if (!prev) + return; + sel = curr = prev; + calcoffsets(); + break; +- case XK_Return: +- case XK_KP_Enter: +- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); +- if (!(ev->state & ControlMask)) { ++ case XKB_KEY_Return: ++ case XKB_KEY_KP_Enter: ++ puts((sel && !shift) ? sel->text : text); ++ if (!ctrl) { + cleanup(); + exit(0); + } +- if (sel) ++ if(sel) + sel->out = 1; + break; +- case XK_Right: ++ case XKB_KEY_Right: + if (text[cursor] != '\0') { + cursor = nextrune(+1); + break; +@@ -480,13 +454,13 @@ insert: + if (lines > 0) + return; + /* fallthrough */ +- case XK_Down: ++ case XKB_KEY_Down: + if (sel && sel->right && (sel = sel->right) == next) { + curr = next; + calcoffsets(); + } + break; +- case XK_Tab: ++ case XKB_KEY_Tab: + if (!sel) + return; + strncpy(text, sel->text, sizeof text - 1); +@@ -498,24 +472,28 @@ insert: + + draw: + drawmenu(); ++ ++update_state: ++ xkb_state_update_key(xkb.state, key + 8, ++ state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP); + } + + static void + paste(void) + { +- char *p, *q; +- int di; +- unsigned long dl; +- Atom da; +- +- /* we have been given the current selection, now insert it into input */ +- if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, +- utf8, &da, &di, &dl, &dl, (unsigned char **)&p) +- == Success && p) { +- insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p)); +- XFree(p); ++ int fds[2], len; ++ char buf[BUFSIZ], *nl; ++ ++ if (seloffer) { ++ pipe(fds); ++ wl_data_offer_receive(seloffer, "text/plain", fds[1]); ++ wl_display_flush(dpy); ++ close(fds[1]); ++ while((len = read(fds[0], buf, sizeof buf)) > 0) ++ insert(buf, (nl = strchr(buf, '\n')) ? nl - buf : len); ++ close(fds[0]); ++ drawmenu(); + } +- drawmenu(); + } + + static void +@@ -550,148 +528,207 @@ readstdin(void) + static void + run(void) + { +- XEvent ev; ++ while (wl_display_dispatch(dpy) != -1) ++ ; ++} + +- while (!XNextEvent(dpy, &ev)) { +- if (XFilterEvent(&ev, None)) +- continue; +- switch(ev.type) { +- case Expose: +- if (ev.xexpose.count == 0) +- drw_map(drw, win, 0, 0, mw, mh); +- break; +- case FocusIn: +- /* regrab focus from parent window */ +- if (ev.xfocus.window != win) +- grabfocus(); +- break; +- case KeyPress: +- keypress(&ev.xkey); +- break; +- case SelectionNotify: +- if (ev.xselection.property == utf8) +- paste(); +- break; +- case VisibilityNotify: +- if (ev.xvisibility.state != VisibilityUnobscured) +- XRaiseWindow(dpy, win); +- break; +- } ++/* wayland event handlers */ ++static void ++regglobal(void *d, struct wl_registry *r, uint32_t name, const char *interface, uint32_t version) ++{ ++ if(strcmp(interface, "wl_compositor") == 0) ++ compositor = wl_registry_bind(r, name, &wl_compositor_interface, 1); ++ else if(strcmp(interface, "wl_shell") == 0) ++ shell = wl_registry_bind(r, name, &wl_shell_interface, 1); ++ else if(strcmp(interface, "wl_seat") == 0) ++ seat = wl_registry_bind(r, name, &wl_seat_interface, 1); ++ else if(strcmp(interface, "wl_data_device_manager") == 0) ++ datadevman = wl_registry_bind(r, name, &wl_data_device_manager_interface, 1); ++ else if(strcmp(interface, "swc_panel_manager") == 0) ++ panelman = wl_registry_bind(r, name, &swc_panel_manager_interface, 1); ++ else if (strcmp(interface, "swc_screen") == 0) { ++ if (mon != -1 && mon-- == 0) ++ screen = wl_registry_bind(r, name, &swc_screen_interface, 1); + } + } + ++static void ++regglobalremove(void *d, struct wl_registry *reg, uint32_t name) ++{ ++} ++ ++static const struct wl_registry_listener reglistener = { regglobal, regglobalremove }; ++ ++static void ++kbdenter(void *data, struct wl_keyboard *kbd, uint32_t serial, ++ struct wl_surface *surface, struct wl_array *keys) ++{ ++} ++ ++static void ++kbdleave(void *d, struct wl_keyboard *kbd, uint32_t serial, ++ struct wl_surface *surface) ++{ ++ /* XXX: swc doesn't handle refocusing panels, so just exit for now */ ++ cleanup(); ++ exit(1); ++} ++ ++/* kbdkey is defined above to reduce merge conflicts */ ++ ++static void ++kbdkeymap(void *d, struct wl_keyboard *kbd, uint32_t format, int32_t fd, uint32_t size) ++{ ++ char *string; ++ ++ if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { ++ close(fd); ++ return; ++ } ++ ++ string = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); ++ ++ if (string == MAP_FAILED) { ++ close(fd); ++ return; ++ } ++ ++ xkb.keymap = xkb_keymap_new_from_string(xkb.context, string, ++ XKB_KEYMAP_FORMAT_TEXT_V1, 0); ++ munmap(string, size); ++ close(fd); ++ xkb.state = xkb_state_new(xkb.keymap); ++ ++ xkb.ctrl = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_CTRL); ++ xkb.alt = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_ALT); ++ xkb.shift = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_SHIFT); ++} ++ ++static void ++kbdmodifiers(void *d, struct wl_keyboard *kbd, uint32_t serial, uint32_t dep, ++ uint32_t lat, uint32_t lck, uint32_t grp) ++{ ++ xkb_state_update_mask(xkb.state, dep, lat, lck, grp, 0, 0); ++} ++ ++static const struct wl_keyboard_listener kbdlistener = { ++ kbdkeymap, kbdenter, kbdleave, kbdkey, kbdmodifiers, ++}; ++ ++static void ++dataofferoffer(void *d, struct wl_data_offer *offer, const char *mimetype) ++{ ++ if (strncmp(mimetype, "text/plain", 10) == 0) ++ wl_data_offer_set_user_data(offer, (void *)(uintptr_t) 1); ++} ++ ++static const struct wl_data_offer_listener dataofferlistener = { dataofferoffer }; ++ ++static void ++datadevoffer(void *d, struct wl_data_device *datadev, struct wl_data_offer *offer) ++{ ++ wl_data_offer_add_listener(offer, &dataofferlistener, NULL); ++} ++ ++static void ++datadeventer(void *d, struct wl_data_device *datadev, uint32_t serial, ++ struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, ++ struct wl_data_offer *offer) ++{ ++} ++ ++static void ++datadevleave(void *d, struct wl_data_device *datadev) ++{ ++} ++ ++static void ++datadevmotion(void *d, struct wl_data_device *datadev, uint32_t time, ++ wl_fixed_t x, wl_fixed_t y) ++{ ++} ++ ++static void ++datadevdrop(void *d, struct wl_data_device *datadev) ++{ ++} ++ ++static void ++datadevselection(void *d, struct wl_data_device *datadev, struct wl_data_offer *offer) ++{ ++ if (offer && (uintptr_t) wl_data_offer_get_user_data(offer) == 1) ++ seloffer = offer; ++} ++ ++static const struct wl_data_device_listener datadevlistener = { ++ datadevoffer, datadeventer, datadevleave, datadevmotion, datadevdrop, ++ datadevselection, ++}; ++ ++static void ++paneldocked(void *d, struct swc_panel *panel, uint32_t length) ++{ ++ mw = length; ++} ++ ++static const struct swc_panel_listener panellistener = { paneldocked }; ++ + static void + setup(void) + { +- int x, y, i, j; +- unsigned int du; +- XSetWindowAttributes swa; +- XIM xim; +- Window w, dw, *dws; +- XWindowAttributes wa; +- XClassHint ch = {"dmenu", "dmenu"}; +-#ifdef XINERAMA +- XineramaScreenInfo *info; +- Window pw; +- int a, di, n, area = 0; +-#endif ++ int j; ++ ++ if (!compositor || !seat || !panelman) ++ exit(1); ++ ++ kbd = wl_seat_get_keyboard(seat); ++ wl_keyboard_add_listener(kbd, &kbdlistener, NULL); ++ datadev = wl_data_device_manager_get_data_device(datadevman, seat); ++ wl_data_device_add_listener(datadev, &datadevlistener, NULL); ++ ++ xkb.context = xkb_context_new(0); ++ + /* init appearance */ + for (j = 0; j < SchemeLast; j++) + scheme[j] = drw_scm_create(drw, colors[j], 2); + +- clip = XInternAtom(dpy, "CLIPBOARD", False); +- utf8 = XInternAtom(dpy, "UTF8_STRING", False); +- + /* calculate menu geometry */ +- bh = drw->fonts->h + 2; ++ bh = drw->fonts->wld->height + 2; + lines = MAX(lines, 0); + mh = (lines + 1) * bh; +-#ifdef XINERAMA +- i = 0; +- if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { +- XGetInputFocus(dpy, &w, &di); +- if (mon >= 0 && mon < n) +- i = mon; +- else if (w != root && w != PointerRoot && w != None) { +- /* find top-level window containing current input focus */ +- do { +- if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) +- XFree(dws); +- } while (w != root && w != pw); +- /* find xinerama screen with which the window intersects most */ +- if (XGetWindowAttributes(dpy, pw, &wa)) +- for (j = 0; j < n; j++) +- if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { +- area = a; +- i = j; +- } +- } +- /* no focused window is on screen, so use pointer location instead */ +- if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) +- for (i = 0; i < n; i++) +- if (INTERSECT(x, y, 1, 1, info[i])) +- break; +- +- x = info[i].x_org; +- y = info[i].y_org + (topbar ? 0 : info[i].height - mh); +- mw = info[i].width; +- XFree(info); +- } else +-#endif +- { +- if (!XGetWindowAttributes(dpy, parentwin, &wa)) +- die("could not get embedding window attributes: 0x%lx", +- parentwin); +- x = 0; +- y = topbar ? 0 : wa.height - mh; +- mw = wa.width; +- } ++ ++ /* create menu surface */ ++ surface = wl_compositor_create_surface(compositor); ++ ++ panel = swc_panel_manager_create_panel(panelman, surface); ++ swc_panel_add_listener(panel, &panellistener, NULL); ++ swc_panel_dock(panel, topbar ? SWC_PANEL_EDGE_TOP : SWC_PANEL_EDGE_BOTTOM, screen, 1); ++ ++ wl_display_roundtrip(dpy); ++ if (!mw) ++ exit(1); ++ + promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; + inputw = MIN(inputw, mw/3); + match(); + +- /* create menu window */ +- swa.override_redirect = True; +- swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; +- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; +- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, +- CopyFromParent, CopyFromParent, CopyFromParent, +- CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); +- XSetClassHint(dpy, win, &ch); +- +- /* open input methods */ +- xim = XOpenIM(dpy, NULL, NULL, NULL); +- xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, +- XNClientWindow, win, XNFocusWindow, win, NULL); +- +- XMapRaised(dpy, win); +- XSetInputFocus(dpy, win, RevertToParent, CurrentTime); +- if (embed) { +- XSelectInput(dpy, parentwin, FocusChangeMask); +- if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) { +- for (i = 0; i < du && dws[i] != win; ++i) +- XSelectInput(dpy, dws[i], FocusChangeMask); +- XFree(dws); +- } +- grabfocus(); +- } +- drw_resize(drw, mw, mh); ++ drw_resize(drw, surface, mw, mh); + drawmenu(); + } + + static void + usage(void) + { +- fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" +- " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); ++ fputs("usage: dmenu [-biv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" ++ " [-nb color] [-nf color] [-sb color] [-sf color]\n", stderr); + exit(1); + } + + int + main(int argc, char *argv[]) + { +- XWindowAttributes wa; +- int i, fast = 0; ++ struct wl_registry *reg; ++ int i; + + for (i = 1; i < argc; i++) + /* these options take no arguments */ +@@ -700,8 +737,6 @@ main(int argc, char *argv[]) + exit(0); + } else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ + topbar = 0; +- else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ +- fast = 1; + else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ + fstrncmp = strncasecmp; + fstrstr = cistrstr; +@@ -724,41 +759,28 @@ main(int argc, char *argv[]) + colors[SchemeSel][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colors[SchemeSel][ColFg] = argv[++i]; +- else if (!strcmp(argv[i], "-w")) /* embedding window id */ +- embed = argv[++i]; + else + usage(); + +- if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) ++ if (!setlocale(LC_CTYPE, "")) + fputs("warning: no locale support\n", stderr); +- if (!XSetLocaleModifiers("")) +- fputs("warning: no locale modifiers support\n", stderr); +- if (!(dpy = XOpenDisplay(NULL))) ++ if (!(dpy = wl_display_connect(NULL))) + die("cannot open display"); +- screen = DefaultScreen(dpy); +- root = RootWindow(dpy, screen); +- if (!embed || !(parentwin = strtol(embed, NULL, 0))) +- parentwin = root; +- if (!XGetWindowAttributes(dpy, parentwin, &wa)) +- die("could not get embedding window attributes: 0x%lx", +- parentwin); +- drw = drw_create(dpy, screen, root, wa.width, wa.height); ++ if (!(reg = wl_display_get_registry(dpy))) ++ die("cannot get registry"); ++ wl_registry_add_listener(reg, ®listener, NULL); ++ wl_display_roundtrip(dpy); ++ drw = drw_create(dpy); + if (!drw_fontset_create(drw, fonts, LENGTH(fonts))) + die("no fonts could be loaded."); +- lrpad = drw->fonts->h; ++ lrpad = drw->fonts->wld->height; + + #ifdef __OpenBSD__ + if (pledge("stdio rpath", NULL) == -1) + die("pledge"); + #endif + +- if (fast && !isatty(0)) { +- grabkeyboard(); +- readstdin(); +- } else { +- readstdin(); +- grabkeyboard(); +- } ++ readstdin(); + setup(); + run(); + +diff --git a/drw.c b/drw.c +index 8fd1ca4..e4995a6 100644 +--- a/drw.c ++++ b/drw.c +@@ -2,8 +2,9 @@ + #include <stdio.h> + #include <stdlib.h> + #include <string.h> +-#include <X11/Xlib.h> +-#include <X11/Xft/Xft.h> ++#include <wayland-client.h> ++#include <wld/wld.h> ++#include <wld/wayland.h> + + #include "drw.h" + #include "util.h" +@@ -61,40 +62,33 @@ utf8decode(const char *c, long *u, size_t clen) + } + + Drw * +-drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h) ++drw_create(struct wl_display *dpy) + { + Drw *drw = ecalloc(1, sizeof(Drw)); + + drw->dpy = dpy; +- drw->screen = screen; +- drw->root = root; +- drw->w = w; +- drw->h = h; +- drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen)); +- drw->gc = XCreateGC(dpy, root, 0, NULL); +- XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter); ++ drw->ctx = wld_wayland_create_context(dpy, WLD_ANY); ++ drw->renderer = wld_create_renderer(drw->ctx); ++ drw->fontctx = wld_font_create_context(); + + return drw; + } + + void +-drw_resize(Drw *drw, unsigned int w, unsigned int h) ++drw_resize(Drw *drw, struct wl_surface *surface, unsigned int w, unsigned int h) + { +- if (!drw) +- return; +- +- drw->w = w; +- drw->h = h; +- if (drw->drawable) +- XFreePixmap(drw->dpy, drw->drawable); +- drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen)); ++ if (drw->surface) ++ wld_destroy_surface(drw->surface); ++ drw->surface = wld_wayland_create_surface(drw->ctx, w, h, WLD_FORMAT_XRGB8888, 0, surface); + } + + void + drw_free(Drw *drw) + { +- XFreePixmap(drw->dpy, drw->drawable); +- XFreeGC(drw->dpy, drw->gc); ++ wld_destroy_surface(drw->surface); ++ wld_destroy_renderer(drw->renderer); ++ wld_destroy_context(drw->ctx); ++ wld_font_destroy_context(drw->fontctx); + free(drw); + } + +@@ -102,11 +96,10 @@ drw_free(Drw *drw) + * drw_fontset_create instead. + */ + static Fnt * +-xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) ++wldfont_create(Drw *drw, const char *fontname, FcPattern *pattern) + { + Fnt *font; +- XftFont *xfont = NULL; +- FcPattern *pattern = NULL; ++ struct wld_font *wld = NULL; + + if (fontname) { + /* Using the pattern found at font->xfont->pattern does not yield the +@@ -114,17 +107,17 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) + * FcNameParse; using the latter results in the desired fallback + * behaviour whereas the former just results in missing-character + * rectangles being drawn, at least with some fonts. */ +- if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) { ++ if (!(wld = wld_font_open_name(drw->fontctx, fontname))) { + fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname); + return NULL; + } + if (!(pattern = FcNameParse((FcChar8 *) fontname))) { + fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname); +- XftFontClose(drw->dpy, xfont); ++ wld_font_close(wld); + return NULL; + } +- } else if (fontpattern) { +- if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) { ++ } else if (pattern) { ++ if (!(wld = wld_font_open_pattern(drw->fontctx, pattern))) { + fprintf(stderr, "error, cannot load font from pattern.\n"); + return NULL; + } +@@ -140,28 +133,26 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) + * and lots more all over the internet. + */ + FcBool iscol; +- if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { +- XftFontClose(drw->dpy, xfont); ++ if(FcPatternGetBool(pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) { ++ wld_font_close(wld); + return NULL; + } + + font = ecalloc(1, sizeof(Fnt)); +- font->xfont = xfont; ++ font->wld = wld; + font->pattern = pattern; +- font->h = xfont->ascent + xfont->descent; +- font->dpy = drw->dpy; + + return font; + } + + static void +-xfont_free(Fnt *font) ++wldfont_free(Fnt *font) + { + if (!font) + return; + if (font->pattern) + FcPatternDestroy(font->pattern); +- XftFontClose(font->dpy, font->xfont); ++ wld_font_close(font->wld); + free(font); + } + +@@ -175,7 +166,7 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount) + return NULL; + + for (i = 1; i <= fontcount; i++) { +- if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) { ++ if ((cur = wldfont_create(drw, fonts[fontcount - i], NULL))) { + cur->next = ret; + ret = cur; + } +@@ -188,7 +179,7 @@ drw_fontset_free(Fnt *font) + { + if (font) { + drw_fontset_free(font->next); +- xfont_free(font); ++ wldfont_free(font); + } + } + +@@ -197,10 +188,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname) + { + if (!drw || !dest || !clrname) + return; +- +- if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen), +- clrname, dest)) ++ if (!(wld_lookup_named_color(clrname, dest))) + die("error, cannot allocate color '%s'", clrname); + } + +@@ -213,7 +201,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount) + Clr *ret; + + /* need at least two colors for a scheme */ +- if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor)))) ++ if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(*ret)))) + return NULL; + + for (i = 0; i < clrcount; i++) +@@ -240,11 +228,15 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int + { + if (!drw || !drw->scheme) + return; +- XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel); ++ Clr color = invert ? drw->scheme[ColBg] : drw->scheme[ColFg]; + if (filled) +- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); +- else +- XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1); ++ wld_fill_rectangle(drw->renderer, color, x, y, w, h); ++ else { ++ wld_fill_rectangle(drw->renderer, color, x, y, w, 1); ++ wld_fill_rectangle(drw->renderer, color, x + w - 1, y + 1, 1, h - 2); ++ wld_fill_rectangle(drw->renderer, color, x, y + 1, 1, h - 2); ++ wld_fill_rectangle(drw->renderer, color, x, y + h - 1, w, 1); ++ } + } + + int +@@ -253,7 +245,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + char buf[1024]; + int ty; + unsigned int ew; +- XftDraw *d = NULL; + Fnt *usedfont, *curfont, *nextfont; + size_t i, len; + int utf8strlen, utf8charlen, render = x || y || w || h; +@@ -262,7 +253,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + FcCharSet *fccharset; + FcPattern *fcpattern; + FcPattern *match; +- XftResult result; ++ FcResult result; + int charexists = 0; + + if (!drw || (render && !drw->scheme) || !text || !drw->fonts) +@@ -271,11 +262,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + if (!render) { + w = ~w; + } else { +- XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel); +- XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h); +- d = XftDrawCreate(drw->dpy, drw->drawable, +- DefaultVisual(drw->dpy, drw->screen), +- DefaultColormap(drw->dpy, drw->screen)); ++ wld_fill_rectangle(drw->renderer, drw->scheme[invert ? ColFg : ColBg], x, y, w, h); + x += lpad; + w -= lpad; + } +@@ -288,7 +275,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + while (*text) { + utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ); + for (curfont = drw->fonts; curfont; curfont = curfont->next) { +- charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint); ++ charexists = charexists || wld_font_ensure_char(curfont->wld, utf8codepoint); + if (charexists) { + if (curfont == usedfont) { + utf8strlen += utf8charlen; +@@ -320,9 +307,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + ; /* NOP */ + + if (render) { +- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent; +- XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg], +- usedfont->xfont, x, ty, (XftChar8 *)buf, len); ++ ty = y + (h - usedfont->wld->height) / 2 + usedfont->wld->ascent; ++ wld_draw_text(drw->renderer, usedfont->wld, drw->scheme[invert ? ColBg : ColFg], ++ x, ty, buf, len, NULL); + } + x += ew; + w -= ew; +@@ -343,7 +330,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + FcCharSetAddChar(fccharset, utf8codepoint); + + if (!drw->fonts->pattern) { +- /* Refer to the comment in xfont_create for more information. */ ++ /* Refer to the comment in wldfont_create for more information. */ + die("the first font in the cache must be loaded from a font string."); + } + +@@ -354,38 +341,37 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp + + FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); + FcDefaultSubstitute(fcpattern); +- match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result); ++ match = FcFontMatch(NULL, fcpattern, &result); + + FcCharSetDestroy(fccharset); + FcPatternDestroy(fcpattern); + + if (match) { +- usedfont = xfont_create(drw, NULL, match); +- if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) { ++ usedfont = wldfont_create(drw, NULL, match); ++ if (usedfont && wld_font_ensure_char(usedfont->wld, utf8codepoint)) { + for (curfont = drw->fonts; curfont->next; curfont = curfont->next) + ; /* NOP */ + curfont->next = usedfont; + } else { +- xfont_free(usedfont); ++ wldfont_free(usedfont); + usedfont = drw->fonts; + } + } + } + } +- if (d) +- XftDrawDestroy(d); + + return x + (render ? w : 0); + } + + void +-drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h) ++drw_map(Drw *drw, struct wl_surface *surface, int x, int y, unsigned int w, unsigned int h) + { + if (!drw) + return; + +- XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y); +- XSync(drw->dpy, False); ++ wl_surface_damage(surface, x, y, w, h); ++ wld_flush(drw->renderer); ++ wld_swap(drw->surface); + } + + unsigned int +@@ -399,18 +385,19 @@ drw_fontset_getwidth(Drw *drw, const char *text) + void + drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h) + { +- XGlyphInfo ext; ++ struct wld_extents ext; + + if (!font || !text) + return; + +- XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext); ++ wld_font_text_extents_n(font->wld, text, len, &ext); + if (w) +- *w = ext.xOff; ++ *w = ext.advance; + if (h) +- *h = font->h; ++ *h = font->wld->height; + } + ++#if 0 + Cur * + drw_cur_create(Drw *drw, int shape) + { +@@ -433,3 +420,4 @@ drw_cur_free(Drw *drw, Cur *cursor) + XFreeCursor(drw->dpy, cursor->cursor); + free(cursor); + } ++#endif +diff --git a/drw.h b/drw.h +index 4c67419..1f1967e 100644 +--- a/drw.h ++++ b/drw.h +@@ -1,34 +1,30 @@ + /* See LICENSE file for copyright and license details. */ + +-typedef struct { +- Cursor cursor; +-} Cur; ++typedef void Cur; + + typedef struct Fnt { +- Display *dpy; +- unsigned int h; +- XftFont *xfont; ++ struct wld_font *wld; + FcPattern *pattern; + struct Fnt *next; + } Fnt; + + enum { ColFg, ColBg }; /* Clr scheme index */ +-typedef XftColor Clr; ++typedef uint32_t Clr; + + typedef struct { + unsigned int w, h; +- Display *dpy; +- int screen; +- Window root; +- Drawable drawable; +- GC gc; ++ struct wl_display *dpy; ++ struct wld_context *ctx; ++ struct wld_renderer *renderer; ++ struct wld_surface *surface; ++ struct wld_font_context *fontctx; + Clr *scheme; + Fnt *fonts; + } Drw; + + /* Drawable abstraction */ +-Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h); +-void drw_resize(Drw *drw, unsigned int w, unsigned int h); ++Drw *drw_create(struct wl_display *dpy); ++void drw_resize(Drw *drw, struct wl_surface *surface, unsigned int w, unsigned int h); + void drw_free(Drw *drw); + + /* Fnt abstraction */ +@@ -54,4 +50,4 @@ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled + int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert); + + /* Map functions */ +-void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h); ++void drw_map(Drw *drw, struct wl_surface *surface, int x, int y, unsigned int w, unsigned int h); +-- +2.30.1 + diff --git a/pkg/gen.sh b/pkg/gen.sh @@ -19,6 +19,7 @@ pkg b3sum pkg bearssl pkg byacc pkg bzip2 +pkg dmenu pkg e2fsprogs pkg expat pkg fontconfig diff --git a/qubes/example/gen.sh b/qubes/example/gen.sh @@ -14,6 +14,7 @@ pkg b3sum pkg bearssl pkg byacc pkg bzip2 +pkg dmenu pkg e2fsprogs pkg fspec-sync pkg fzy