linux-qubasis

linux oasis port as a qubes template

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

0001-Port-to-wayland-using-wld-and-swc-panels.patch

(36663B)


      1 From d186aa8891ca777615b8138416c95565c05e0a09 Mon Sep 17 00:00:00 2001
      2 From: Michael Forney <mforney@mforney.org>
      3 Date: Thu, 27 Oct 2016 21:04:23 -0700
      4 Subject: [PATCH] Port to wayland using wld and swc panels
      5 
      6 ---
      7  Makefile  |  16 +-
      8  config.mk |  20 +-
      9  dmenu.c   | 566 ++++++++++++++++++++++++++++--------------------------
     10  drw.c     | 130 ++++++-------
     11  drw.h     |  26 ++-
     12  5 files changed, 381 insertions(+), 377 deletions(-)
     13 
     14 diff --git a/Makefile b/Makefile
     15 index a03a95c..4046899 100644
     16 --- a/Makefile
     17 +++ b/Makefile
     18 @@ -3,7 +3,7 @@
     19  
     20  include config.mk
     21  
     22 -SRC = drw.c dmenu.c stest.c util.c
     23 +SRC = drw.c dmenu.c stest.c panel-protocol.c util.c
     24  OBJ = $(SRC:.c=.o)
     25  
     26  all: options dmenu stest
     27 @@ -20,10 +20,18 @@ options:
     28  config.h:
     29  	cp config.def.h $@
     30  
     31 -$(OBJ): arg.h config.h config.mk drw.h
     32 +swc-protocol.c: $(SWCPROTO)
     33 +	@echo GEN $@
     34 +	@wayland-scanner code < $< > $@
     35  
     36 -dmenu: dmenu.o drw.o util.o
     37 -	$(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS)
     38 +swc-client-protocol.h: $(SWCPROTO)
     39 +	@echo GEN $@
     40 +	@wayland-scanner client-header < $< > $@
     41 +
     42 +$(OBJ): arg.h config.h config.mk drw.h swc-client-protocol.h
     43 +
     44 +dmenu: dmenu.o drw.o swc-protocol.o util.o
     45 +	$(CC) -o $@ dmenu.o drw.o swc-protocol.o util.o $(LDFLAGS)
     46  
     47  stest: stest.o
     48  	$(CC) -o $@ stest.o $(LDFLAGS)
     49 diff --git a/config.mk b/config.mk
     50 index 0929b4a..7e747ff 100644
     51 --- a/config.mk
     52 +++ b/config.mk
     53 @@ -5,25 +5,15 @@ VERSION = 4.9
     54  PREFIX = /usr/local
     55  MANPREFIX = $(PREFIX)/share/man
     56  
     57 -X11INC = /usr/X11R6/include
     58 -X11LIB = /usr/X11R6/lib
     59 -
     60 -# Xinerama, comment if you don't want it
     61 -XINERAMALIBS  = -lXinerama
     62 -XINERAMAFLAGS = -DXINERAMA
     63 -
     64 -# freetype
     65 -FREETYPELIBS = -lfontconfig -lXft
     66 -FREETYPEINC = /usr/include/freetype2
     67 -# OpenBSD (uncomment)
     68 -#FREETYPEINC = $(X11INC)/freetype2
     69 +PIXMANINC = /usr/include/pixman-1
     70 +SWCPROTO = /usr/share/swc/swc.xml
     71  
     72  # includes and libs
     73 -INCS = -I$(X11INC) -I$(FREETYPEINC)
     74 -LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
     75 +INCS = -I$(PIXMANINC)
     76 +LIBS = -lwayland-client -lxkbcommon -lwld
     77  
     78  # flags
     79 -CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
     80 +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\"
     81  CFLAGS   = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS)
     82  LDFLAGS  = $(LIBS)
     83  
     84 diff --git a/dmenu.c b/dmenu.c
     85 index 6b8f51b..877c459 100644
     86 --- a/dmenu.c
     87 +++ b/dmenu.c
     88 @@ -5,19 +5,18 @@
     89  #include <stdlib.h>
     90  #include <string.h>
     91  #include <strings.h>
     92 +#include <sys/mman.h>
     93  #include <time.h>
     94  #include <unistd.h>
     95  
     96 -#include <X11/Xlib.h>
     97 -#include <X11/Xatom.h>
     98 -#include <X11/Xutil.h>
     99 -#ifdef XINERAMA
    100 -#include <X11/extensions/Xinerama.h>
    101 -#endif
    102 -#include <X11/Xft/Xft.h>
    103 +#include <wayland-client.h>
    104 +#include <wld/wayland.h>
    105 +#include <wld/wld.h>
    106 +#include <xkbcommon/xkbcommon.h>
    107  
    108  #include "drw.h"
    109  #include "util.h"
    110 +#include "swc-client-protocol.h"
    111  
    112  /* macros */
    113  #define INTERSECT(x,y,w,h,r)  (MAX(0, MIN((x)+(w),(r).x_org+(r).width)  - MAX((x),(r).x_org)) \
    114 @@ -34,8 +33,16 @@ struct item {
    115  	int out;
    116  };
    117  
    118 +struct xkb {
    119 +	struct xkb_context *context;
    120 +	struct xkb_state *state;
    121 +	struct xkb_keymap *keymap;
    122 +	xkb_mod_index_t ctrl, alt, shift;
    123 +};
    124 +
    125 +static void paste(void);
    126 +
    127  static char text[BUFSIZ] = "";
    128 -static char *embed;
    129  static int bh, mw, mh;
    130  static int inputw = 0, promptw;
    131  static int lrpad; /* sum of left and right padding */
    132 @@ -43,12 +50,21 @@ static size_t cursor;
    133  static struct item *items = NULL;
    134  static struct item *matches, *matchend;
    135  static struct item *prev, *curr, *next, *sel;
    136 -static int mon = -1, screen;
    137 -
    138 -static Atom clip, utf8;
    139 -static Display *dpy;
    140 -static Window root, parentwin, win;
    141 -static XIC xic;
    142 +static int mon = -1;
    143 +
    144 +static struct wl_display *dpy;
    145 +static struct wl_compositor *compositor;
    146 +static struct wl_keyboard *kbd;
    147 +static struct wl_seat *seat;
    148 +static struct wl_shell *shell;
    149 +static struct wl_surface *surface;
    150 +static struct wl_data_device_manager *datadevman;
    151 +static struct wl_data_device *datadev;
    152 +static struct wl_data_offer *seloffer;
    153 +static struct swc_screen *screen;
    154 +static struct swc_panel_manager *panelman;
    155 +static struct swc_panel *panel;
    156 +static struct xkb xkb;
    157  
    158  static Drw *drw;
    159  static Clr *scheme[SchemeLast];
    160 @@ -94,12 +110,10 @@ cleanup(void)
    161  {
    162  	size_t i;
    163  
    164 -	XUngrabKey(dpy, AnyKey, AnyModifier, root);
    165  	for (i = 0; i < SchemeLast; i++)
    166  		free(scheme[i]);
    167  	drw_free(drw);
    168 -	XSync(dpy, False);
    169 -	XCloseDisplay(dpy);
    170 +	wl_display_disconnect(dpy);
    171  }
    172  
    173  static char *
    174 @@ -133,6 +147,7 @@ drawmenu(void)
    175  	struct item *item;
    176  	int x = 0, y = 0, w;
    177  
    178 +	wld_set_target_surface(drw->renderer, drw->surface);
    179  	drw_setscheme(drw, scheme[SchemeNorm]);
    180  	drw_rect(drw, 0, 0, mw, mh, 1, 1);
    181  
    182 @@ -172,42 +187,7 @@ drawmenu(void)
    183  			drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0);
    184  		}
    185  	}
    186 -	drw_map(drw, win, 0, 0, mw, mh);
    187 -}
    188 -
    189 -static void
    190 -grabfocus(void)
    191 -{
    192 -	struct timespec ts = { .tv_sec = 0, .tv_nsec = 10000000  };
    193 -	Window focuswin;
    194 -	int i, revertwin;
    195 -
    196 -	for (i = 0; i < 100; ++i) {
    197 -		XGetInputFocus(dpy, &focuswin, &revertwin);
    198 -		if (focuswin == win)
    199 -			return;
    200 -		XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
    201 -		nanosleep(&ts, NULL);
    202 -	}
    203 -	die("cannot grab focus");
    204 -}
    205 -
    206 -static void
    207 -grabkeyboard(void)
    208 -{
    209 -	struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000  };
    210 -	int i;
    211 -
    212 -	if (embed)
    213 -		return;
    214 -	/* try to grab keyboard, we may have to wait for another process to ungrab */
    215 -	for (i = 0; i < 1000; i++) {
    216 -		if (XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, GrabModeAsync,
    217 -		                  GrabModeAsync, CurrentTime) == GrabSuccess)
    218 -			return;
    219 -		nanosleep(&ts, NULL);
    220 -	}
    221 -	die("cannot grab keyboard");
    222 +	drw_map(drw, surface, 0, 0, mw, mh);
    223  }
    224  
    225  static void
    226 @@ -305,111 +285,105 @@ movewordedge(int dir)
    227  }
    228  
    229  static void
    230 -keypress(XKeyEvent *ev)
    231 +kbdkey(void *d, struct wl_keyboard *kbd, uint32_t serial, uint32_t time,
    232 +       uint32_t key, uint32_t state)
    233  {
    234  	char buf[32];
    235  	int len;
    236 -	KeySym ksym;
    237 -	Status status;
    238 +	xkb_keysym_t ksym = XKB_KEY_NoSymbol;
    239 +	int ctrl = xkb_state_mod_index_is_active(xkb.state, xkb.ctrl, XKB_STATE_MODS_EFFECTIVE);
    240 +	int shift = xkb_state_mod_index_is_active(xkb.state, xkb.shift, XKB_STATE_MODS_EFFECTIVE);
    241 +	int alt = xkb_state_mod_index_is_active(xkb.state, xkb.alt, XKB_STATE_MODS_EFFECTIVE);
    242  
    243 -	len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
    244 -	switch (status) {
    245 -	default: /* XLookupNone, XBufferOverflow */
    246 -		return;
    247 -	case XLookupChars:
    248 -		goto insert;
    249 -	case XLookupKeySym:
    250 -	case XLookupBoth:
    251 -		break;
    252 -	}
    253 +	if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
    254 +		goto update_state;
    255  
    256 -	if (ev->state & ControlMask) {
    257 +	ksym = xkb_state_key_get_one_sym(xkb.state, key + 8);
    258 +	if (ctrl) {
    259  		switch(ksym) {
    260 -		case XK_a: ksym = XK_Home;      break;
    261 -		case XK_b: ksym = XK_Left;      break;
    262 -		case XK_c: ksym = XK_Escape;    break;
    263 -		case XK_d: ksym = XK_Delete;    break;
    264 -		case XK_e: ksym = XK_End;       break;
    265 -		case XK_f: ksym = XK_Right;     break;
    266 -		case XK_g: ksym = XK_Escape;    break;
    267 -		case XK_h: ksym = XK_BackSpace; break;
    268 -		case XK_i: ksym = XK_Tab;       break;
    269 -		case XK_j: /* fallthrough */
    270 -		case XK_J: /* fallthrough */
    271 -		case XK_m: /* fallthrough */
    272 -		case XK_M: ksym = XK_Return; ev->state &= ~ControlMask; break;
    273 -		case XK_n: ksym = XK_Down;      break;
    274 -		case XK_p: ksym = XK_Up;        break;
    275 -
    276 -		case XK_k: /* delete right */
    277 +		case XKB_KEY_a: ksym = XKB_KEY_Home;      break;
    278 +		case XKB_KEY_b: ksym = XKB_KEY_Left;      break;
    279 +		case XKB_KEY_c: ksym = XKB_KEY_Escape;    break;
    280 +		case XKB_KEY_d: ksym = XKB_KEY_Delete;    break;
    281 +		case XKB_KEY_e: ksym = XKB_KEY_End;       break;
    282 +		case XKB_KEY_f: ksym = XKB_KEY_Right;     break;
    283 +		case XKB_KEY_g: ksym = XKB_KEY_Escape;    break;
    284 +		case XKB_KEY_h: ksym = XKB_KEY_BackSpace; break;
    285 +		case XKB_KEY_i: ksym = XKB_KEY_Tab;       break;
    286 +		case XKB_KEY_j: /* fallthrough */
    287 +		case XKB_KEY_J: /* fallthrough */
    288 +		case XKB_KEY_m: /* fallthrough */
    289 +		case XKB_KEY_M: ksym = XKB_KEY_Return; ctrl = 0; break;
    290 +		case XKB_KEY_n: ksym = XKB_KEY_Down;      break;
    291 +		case XKB_KEY_p: ksym = XKB_KEY_Up;        break;
    292 +
    293 +		case XKB_KEY_k: /* delete right */
    294  			text[cursor] = '\0';
    295  			match();
    296  			break;
    297 -		case XK_u: /* delete left */
    298 +		case XKB_KEY_u: /* delete left */
    299  			insert(NULL, 0 - cursor);
    300  			break;
    301 -		case XK_w: /* delete word */
    302 +		case XKB_KEY_w: /* delete word */
    303  			while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)]))
    304  				insert(NULL, nextrune(-1) - cursor);
    305  			while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)]))
    306  				insert(NULL, nextrune(-1) - cursor);
    307  			break;
    308 -		case XK_y: /* paste selection */
    309 -		case XK_Y:
    310 -			XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
    311 -			                  utf8, utf8, win, CurrentTime);
    312 +		case XKB_KEY_y: /* paste selection */
    313 +		case XKB_KEY_Y:
    314 +			paste();
    315  			return;
    316 -		case XK_Left:
    317 +		case XKB_KEY_Left:
    318  			movewordedge(-1);
    319  			goto draw;
    320 -		case XK_Right:
    321 +		case XKB_KEY_Right:
    322  			movewordedge(+1);
    323  			goto draw;
    324 -		case XK_Return:
    325 -		case XK_KP_Enter:
    326 +		case XKB_KEY_Return:
    327 +		case XKB_KEY_KP_Enter:
    328  			break;
    329 -		case XK_bracketleft:
    330 +		case XKB_KEY_bracketleft:
    331  			cleanup();
    332  			exit(1);
    333  		default:
    334  			return;
    335  		}
    336 -	} else if (ev->state & Mod1Mask) {
    337 +	} else if (alt) {
    338  		switch(ksym) {
    339 -		case XK_b:
    340 +		case XKB_KEY_b:
    341  			movewordedge(-1);
    342  			goto draw;
    343 -		case XK_f:
    344 +		case XKB_KEY_f:
    345  			movewordedge(+1);
    346  			goto draw;
    347 -		case XK_g: ksym = XK_Home;  break;
    348 -		case XK_G: ksym = XK_End;   break;
    349 -		case XK_h: ksym = XK_Up;    break;
    350 -		case XK_j: ksym = XK_Next;  break;
    351 -		case XK_k: ksym = XK_Prior; break;
    352 -		case XK_l: ksym = XK_Down;  break;
    353 +		case XKB_KEY_g: ksym = XKB_KEY_Home;  break;
    354 +		case XKB_KEY_G: ksym = XKB_KEY_End;   break;
    355 +		case XKB_KEY_h: ksym = XKB_KEY_Up;    break;
    356 +		case XKB_KEY_j: ksym = XKB_KEY_Next;  break;
    357 +		case XKB_KEY_k: ksym = XKB_KEY_Prior; break;
    358 +		case XKB_KEY_l: ksym = XKB_KEY_Down;  break;
    359  		default:
    360  			return;
    361  		}
    362  	}
    363 -
    364 -	switch(ksym) {
    365 +	switch (ksym) {
    366  	default:
    367 -insert:
    368 +		len = xkb_state_key_get_utf8(xkb.state, key + 8, buf, sizeof(buf));
    369  		if (!iscntrl(*buf))
    370  			insert(buf, len);
    371  		break;
    372 -	case XK_Delete:
    373 +	case XKB_KEY_Delete:
    374  		if (text[cursor] == '\0')
    375  			return;
    376  		cursor = nextrune(+1);
    377  		/* fallthrough */
    378 -	case XK_BackSpace:
    379 +	case XKB_KEY_BackSpace:
    380  		if (cursor == 0)
    381  			return;
    382  		insert(NULL, nextrune(-1) - cursor);
    383  		break;
    384 -	case XK_End:
    385 +	case XKB_KEY_End:
    386  		if (text[cursor] != '\0') {
    387  			cursor = strlen(text);
    388  			break;
    389 @@ -425,10 +399,10 @@ insert:
    390  		}
    391  		sel = matchend;
    392  		break;
    393 -	case XK_Escape:
    394 +	case XKB_KEY_Escape:
    395  		cleanup();
    396  		exit(1);
    397 -	case XK_Home:
    398 +	case XKB_KEY_Home:
    399  		if (sel == matches) {
    400  			cursor = 0;
    401  			break;
    402 @@ -436,7 +410,7 @@ insert:
    403  		sel = curr = matches;
    404  		calcoffsets();
    405  		break;
    406 -	case XK_Left:
    407 +	case XKB_KEY_Left:
    408  		if (cursor > 0 && (!sel || !sel->left || lines > 0)) {
    409  			cursor = nextrune(-1);
    410  			break;
    411 @@ -444,35 +418,35 @@ insert:
    412  		if (lines > 0)
    413  			return;
    414  		/* fallthrough */
    415 -	case XK_Up:
    416 +	case XKB_KEY_Up:
    417  		if (sel && sel->left && (sel = sel->left)->right == curr) {
    418  			curr = prev;
    419  			calcoffsets();
    420  		}
    421  		break;
    422 -	case XK_Next:
    423 +	case XKB_KEY_Next:
    424  		if (!next)
    425  			return;
    426  		sel = curr = next;
    427  		calcoffsets();
    428  		break;
    429 -	case XK_Prior:
    430 +	case XKB_KEY_Prior:
    431  		if (!prev)
    432  			return;
    433  		sel = curr = prev;
    434  		calcoffsets();
    435  		break;
    436 -	case XK_Return:
    437 -	case XK_KP_Enter:
    438 -		puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
    439 -		if (!(ev->state & ControlMask)) {
    440 +	case XKB_KEY_Return:
    441 +	case XKB_KEY_KP_Enter:
    442 +		puts((sel && !shift) ? sel->text : text);
    443 +		if (!ctrl) {
    444  			cleanup();
    445  			exit(0);
    446  		}
    447 -		if (sel)
    448 +		if(sel)
    449  			sel->out = 1;
    450  		break;
    451 -	case XK_Right:
    452 +	case XKB_KEY_Right:
    453  		if (text[cursor] != '\0') {
    454  			cursor = nextrune(+1);
    455  			break;
    456 @@ -480,13 +454,13 @@ insert:
    457  		if (lines > 0)
    458  			return;
    459  		/* fallthrough */
    460 -	case XK_Down:
    461 +	case XKB_KEY_Down:
    462  		if (sel && sel->right && (sel = sel->right) == next) {
    463  			curr = next;
    464  			calcoffsets();
    465  		}
    466  		break;
    467 -	case XK_Tab:
    468 +	case XKB_KEY_Tab:
    469  		if (!sel)
    470  			return;
    471  		strncpy(text, sel->text, sizeof text - 1);
    472 @@ -498,24 +472,28 @@ insert:
    473  
    474  draw:
    475  	drawmenu();
    476 +
    477 +update_state:
    478 +	xkb_state_update_key(xkb.state, key + 8,
    479 +			     state == WL_KEYBOARD_KEY_STATE_PRESSED ? XKB_KEY_DOWN : XKB_KEY_UP);
    480  }
    481  
    482  static void
    483  paste(void)
    484  {
    485 -	char *p, *q;
    486 -	int di;
    487 -	unsigned long dl;
    488 -	Atom da;
    489 -
    490 -	/* we have been given the current selection, now insert it into input */
    491 -	if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
    492 -	                   utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
    493 -	    == Success && p) {
    494 -		insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
    495 -		XFree(p);
    496 +	int fds[2], len;
    497 +	char buf[BUFSIZ], *nl;
    498 +
    499 +	if (seloffer) {
    500 +		pipe(fds);
    501 +		wl_data_offer_receive(seloffer, "text/plain", fds[1]);
    502 +		wl_display_flush(dpy);
    503 +		close(fds[1]);
    504 +		while((len = read(fds[0], buf, sizeof buf)) > 0)
    505 +			insert(buf, (nl = strchr(buf, '\n')) ? nl - buf : len);
    506 +		close(fds[0]);
    507 +		drawmenu();
    508  	}
    509 -	drawmenu();
    510  }
    511  
    512  static void
    513 @@ -550,148 +528,207 @@ readstdin(void)
    514  static void
    515  run(void)
    516  {
    517 -	XEvent ev;
    518 +	while (wl_display_dispatch(dpy) != -1)
    519 +		;
    520 +}
    521  
    522 -	while (!XNextEvent(dpy, &ev)) {
    523 -		if (XFilterEvent(&ev, None))
    524 -			continue;
    525 -		switch(ev.type) {
    526 -		case Expose:
    527 -			if (ev.xexpose.count == 0)
    528 -				drw_map(drw, win, 0, 0, mw, mh);
    529 -			break;
    530 -		case FocusIn:
    531 -			/* regrab focus from parent window */
    532 -			if (ev.xfocus.window != win)
    533 -				grabfocus();
    534 -			break;
    535 -		case KeyPress:
    536 -			keypress(&ev.xkey);
    537 -			break;
    538 -		case SelectionNotify:
    539 -			if (ev.xselection.property == utf8)
    540 -				paste();
    541 -			break;
    542 -		case VisibilityNotify:
    543 -			if (ev.xvisibility.state != VisibilityUnobscured)
    544 -				XRaiseWindow(dpy, win);
    545 -			break;
    546 -		}
    547 +/* wayland event handlers */
    548 +static void
    549 +regglobal(void *d, struct wl_registry *r, uint32_t name, const char *interface, uint32_t version)
    550 +{
    551 +	if(strcmp(interface, "wl_compositor") == 0)
    552 +		compositor = wl_registry_bind(r, name, &wl_compositor_interface, 1);
    553 +	else if(strcmp(interface, "wl_shell") == 0)
    554 +		shell = wl_registry_bind(r, name, &wl_shell_interface, 1);
    555 +	else if(strcmp(interface, "wl_seat") == 0)
    556 +		seat = wl_registry_bind(r, name, &wl_seat_interface, 1);
    557 +	else if(strcmp(interface, "wl_data_device_manager") == 0)
    558 +		datadevman = wl_registry_bind(r, name, &wl_data_device_manager_interface, 1);
    559 +	else if(strcmp(interface, "swc_panel_manager") == 0)
    560 +		panelman = wl_registry_bind(r, name, &swc_panel_manager_interface, 1);
    561 +	else if (strcmp(interface, "swc_screen") == 0) {
    562 +		if (mon != -1 && mon-- == 0)
    563 +			screen = wl_registry_bind(r, name, &swc_screen_interface, 1);
    564  	}
    565  }
    566  
    567 +static void
    568 +regglobalremove(void *d, struct wl_registry *reg, uint32_t name)
    569 +{
    570 +}
    571 +
    572 +static const struct wl_registry_listener reglistener = { regglobal, regglobalremove };
    573 +
    574 +static void
    575 +kbdenter(void *data, struct wl_keyboard *kbd, uint32_t serial,
    576 +         struct wl_surface *surface, struct wl_array *keys)
    577 +{
    578 +}
    579 +
    580 +static void
    581 +kbdleave(void *d, struct wl_keyboard *kbd, uint32_t serial,
    582 +         struct wl_surface *surface)
    583 +{
    584 +	/* XXX: swc doesn't handle refocusing panels, so just exit for now */
    585 +	cleanup();
    586 +	exit(1);
    587 +}
    588 +
    589 +/* kbdkey is defined above to reduce merge conflicts */
    590 +
    591 +static void
    592 +kbdkeymap(void *d, struct wl_keyboard *kbd, uint32_t format, int32_t fd, uint32_t size)
    593 +{
    594 +	char *string;
    595 +
    596 +	if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
    597 +		close(fd);
    598 +		return;
    599 +	}
    600 +
    601 +	string = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
    602 +
    603 +	if (string == MAP_FAILED) {
    604 +		close(fd);
    605 +		return;
    606 +	}
    607 +
    608 +	xkb.keymap = xkb_keymap_new_from_string(xkb.context, string,
    609 +						XKB_KEYMAP_FORMAT_TEXT_V1, 0);
    610 +	munmap(string, size);
    611 +	close(fd);
    612 +	xkb.state = xkb_state_new(xkb.keymap);
    613 +
    614 +	xkb.ctrl = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_CTRL);
    615 +	xkb.alt = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_ALT);
    616 +	xkb.shift = xkb_keymap_mod_get_index(xkb.keymap, XKB_MOD_NAME_SHIFT);
    617 +}
    618 +
    619 +static void
    620 +kbdmodifiers(void *d, struct wl_keyboard *kbd, uint32_t serial, uint32_t dep,
    621 +             uint32_t lat, uint32_t lck, uint32_t grp)
    622 +{
    623 +	xkb_state_update_mask(xkb.state, dep, lat, lck, grp, 0, 0);
    624 +}
    625 +
    626 +static const struct wl_keyboard_listener kbdlistener = {
    627 +	kbdkeymap, kbdenter, kbdleave, kbdkey, kbdmodifiers,
    628 +};
    629 +
    630 +static void
    631 +dataofferoffer(void *d, struct wl_data_offer *offer, const char *mimetype)
    632 +{
    633 +	if (strncmp(mimetype, "text/plain", 10) == 0)
    634 +		wl_data_offer_set_user_data(offer, (void *)(uintptr_t) 1);
    635 +}
    636 +
    637 +static const struct wl_data_offer_listener dataofferlistener = { dataofferoffer };
    638 +
    639 +static void
    640 +datadevoffer(void *d, struct wl_data_device *datadev, struct wl_data_offer *offer)
    641 +{
    642 +	wl_data_offer_add_listener(offer, &dataofferlistener, NULL);
    643 +}
    644 +
    645 +static void
    646 +datadeventer(void *d, struct wl_data_device *datadev, uint32_t serial,
    647 +             struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y,
    648 +             struct wl_data_offer *offer)
    649 +{
    650 +}
    651 +
    652 +static void
    653 +datadevleave(void *d, struct wl_data_device *datadev)
    654 +{
    655 +}
    656 +
    657 +static void
    658 +datadevmotion(void *d, struct wl_data_device *datadev, uint32_t time,
    659 +              wl_fixed_t x, wl_fixed_t y)
    660 +{
    661 +}
    662 +
    663 +static void
    664 +datadevdrop(void *d, struct wl_data_device *datadev)
    665 +{
    666 +}
    667 +
    668 +static void
    669 +datadevselection(void *d, struct wl_data_device *datadev, struct wl_data_offer *offer)
    670 +{
    671 +	if (offer && (uintptr_t) wl_data_offer_get_user_data(offer) == 1)
    672 +		seloffer = offer;
    673 +}
    674 +
    675 +static const struct wl_data_device_listener datadevlistener = {
    676 +	datadevoffer, datadeventer, datadevleave, datadevmotion, datadevdrop,
    677 +	datadevselection,
    678 +};
    679 +
    680 +static void
    681 +paneldocked(void *d, struct swc_panel *panel, uint32_t length)
    682 +{
    683 +	mw = length;
    684 +}
    685 +
    686 +static const struct swc_panel_listener panellistener = { paneldocked };
    687 +
    688  static void
    689  setup(void)
    690  {
    691 -	int x, y, i, j;
    692 -	unsigned int du;
    693 -	XSetWindowAttributes swa;
    694 -	XIM xim;
    695 -	Window w, dw, *dws;
    696 -	XWindowAttributes wa;
    697 -	XClassHint ch = {"dmenu", "dmenu"};
    698 -#ifdef XINERAMA
    699 -	XineramaScreenInfo *info;
    700 -	Window pw;
    701 -	int a, di, n, area = 0;
    702 -#endif
    703 +	int j;
    704 +
    705 +	if (!compositor || !seat || !panelman)
    706 +		exit(1);
    707 +
    708 +	kbd = wl_seat_get_keyboard(seat);
    709 +	wl_keyboard_add_listener(kbd, &kbdlistener, NULL);
    710 +	datadev = wl_data_device_manager_get_data_device(datadevman, seat);
    711 +	wl_data_device_add_listener(datadev, &datadevlistener, NULL);
    712 +
    713 +	xkb.context = xkb_context_new(0);
    714 +
    715  	/* init appearance */
    716  	for (j = 0; j < SchemeLast; j++)
    717  		scheme[j] = drw_scm_create(drw, colors[j], 2);
    718  
    719 -	clip = XInternAtom(dpy, "CLIPBOARD",   False);
    720 -	utf8 = XInternAtom(dpy, "UTF8_STRING", False);
    721 -
    722  	/* calculate menu geometry */
    723 -	bh = drw->fonts->h + 2;
    724 +	bh = drw->fonts->wld->height + 2;
    725  	lines = MAX(lines, 0);
    726  	mh = (lines + 1) * bh;
    727 -#ifdef XINERAMA
    728 -	i = 0;
    729 -	if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
    730 -		XGetInputFocus(dpy, &w, &di);
    731 -		if (mon >= 0 && mon < n)
    732 -			i = mon;
    733 -		else if (w != root && w != PointerRoot && w != None) {
    734 -			/* find top-level window containing current input focus */
    735 -			do {
    736 -				if (XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws)
    737 -					XFree(dws);
    738 -			} while (w != root && w != pw);
    739 -			/* find xinerama screen with which the window intersects most */
    740 -			if (XGetWindowAttributes(dpy, pw, &wa))
    741 -				for (j = 0; j < n; j++)
    742 -					if ((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) {
    743 -						area = a;
    744 -						i = j;
    745 -					}
    746 -		}
    747 -		/* no focused window is on screen, so use pointer location instead */
    748 -		if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du))
    749 -			for (i = 0; i < n; i++)
    750 -				if (INTERSECT(x, y, 1, 1, info[i]))
    751 -					break;
    752 -
    753 -		x = info[i].x_org;
    754 -		y = info[i].y_org + (topbar ? 0 : info[i].height - mh);
    755 -		mw = info[i].width;
    756 -		XFree(info);
    757 -	} else
    758 -#endif
    759 -	{
    760 -		if (!XGetWindowAttributes(dpy, parentwin, &wa))
    761 -			die("could not get embedding window attributes: 0x%lx",
    762 -			    parentwin);
    763 -		x = 0;
    764 -		y = topbar ? 0 : wa.height - mh;
    765 -		mw = wa.width;
    766 -	}
    767 +
    768 +	/* create menu surface */
    769 +	surface = wl_compositor_create_surface(compositor);
    770 +
    771 +	panel = swc_panel_manager_create_panel(panelman, surface);
    772 +	swc_panel_add_listener(panel, &panellistener, NULL);
    773 +	swc_panel_dock(panel, topbar ? SWC_PANEL_EDGE_TOP : SWC_PANEL_EDGE_BOTTOM, screen, 1);
    774 +
    775 +	wl_display_roundtrip(dpy);
    776 +	if (!mw)
    777 +		exit(1);
    778 +
    779  	promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
    780  	inputw = MIN(inputw, mw/3);
    781  	match();
    782  
    783 -	/* create menu window */
    784 -	swa.override_redirect = True;
    785 -	swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
    786 -	swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
    787 -	win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
    788 -	                    CopyFromParent, CopyFromParent, CopyFromParent,
    789 -	                    CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
    790 -	XSetClassHint(dpy, win, &ch);
    791 -
    792 -	/* open input methods */
    793 -	xim = XOpenIM(dpy, NULL, NULL, NULL);
    794 -	xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
    795 -	                XNClientWindow, win, XNFocusWindow, win, NULL);
    796 -
    797 -	XMapRaised(dpy, win);
    798 -	XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
    799 -	if (embed) {
    800 -		XSelectInput(dpy, parentwin, FocusChangeMask);
    801 -		if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
    802 -			for (i = 0; i < du && dws[i] != win; ++i)
    803 -				XSelectInput(dpy, dws[i], FocusChangeMask);
    804 -			XFree(dws);
    805 -		}
    806 -		grabfocus();
    807 -	}
    808 -	drw_resize(drw, mw, mh);
    809 +	drw_resize(drw, surface, mw, mh);
    810  	drawmenu();
    811  }
    812  
    813  static void
    814  usage(void)
    815  {
    816 -	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
    817 -	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
    818 +	fputs("usage: dmenu [-biv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
    819 +	      "             [-nb color] [-nf color] [-sb color] [-sf color]\n", stderr);
    820  	exit(1);
    821  }
    822  
    823  int
    824  main(int argc, char *argv[])
    825  {
    826 -	XWindowAttributes wa;
    827 -	int i, fast = 0;
    828 +	struct wl_registry *reg;
    829 +	int i;
    830  
    831  	for (i = 1; i < argc; i++)
    832  		/* these options take no arguments */
    833 @@ -700,8 +737,6 @@ main(int argc, char *argv[])
    834  			exit(0);
    835  		} else if (!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */
    836  			topbar = 0;
    837 -		else if (!strcmp(argv[i], "-f"))   /* grabs keyboard before reading stdin */
    838 -			fast = 1;
    839  		else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
    840  			fstrncmp = strncasecmp;
    841  			fstrstr = cistrstr;
    842 @@ -724,41 +759,28 @@ main(int argc, char *argv[])
    843  			colors[SchemeSel][ColBg] = argv[++i];
    844  		else if (!strcmp(argv[i], "-sf"))  /* selected foreground color */
    845  			colors[SchemeSel][ColFg] = argv[++i];
    846 -		else if (!strcmp(argv[i], "-w"))   /* embedding window id */
    847 -			embed = argv[++i];
    848  		else
    849  			usage();
    850  
    851 -	if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
    852 +	if (!setlocale(LC_CTYPE, ""))
    853  		fputs("warning: no locale support\n", stderr);
    854 -	if (!XSetLocaleModifiers(""))
    855 -		fputs("warning: no locale modifiers support\n", stderr);
    856 -	if (!(dpy = XOpenDisplay(NULL)))
    857 +	if (!(dpy = wl_display_connect(NULL)))
    858  		die("cannot open display");
    859 -	screen = DefaultScreen(dpy);
    860 -	root = RootWindow(dpy, screen);
    861 -	if (!embed || !(parentwin = strtol(embed, NULL, 0)))
    862 -		parentwin = root;
    863 -	if (!XGetWindowAttributes(dpy, parentwin, &wa))
    864 -		die("could not get embedding window attributes: 0x%lx",
    865 -		    parentwin);
    866 -	drw = drw_create(dpy, screen, root, wa.width, wa.height);
    867 +	if (!(reg = wl_display_get_registry(dpy)))
    868 +		die("cannot get registry");
    869 +	wl_registry_add_listener(reg, &reglistener, NULL);
    870 +	wl_display_roundtrip(dpy);
    871 +	drw = drw_create(dpy);
    872  	if (!drw_fontset_create(drw, fonts, LENGTH(fonts)))
    873  		die("no fonts could be loaded.");
    874 -	lrpad = drw->fonts->h;
    875 +	lrpad = drw->fonts->wld->height;
    876  
    877  #ifdef __OpenBSD__
    878  	if (pledge("stdio rpath", NULL) == -1)
    879  		die("pledge");
    880  #endif
    881  
    882 -	if (fast && !isatty(0)) {
    883 -		grabkeyboard();
    884 -		readstdin();
    885 -	} else {
    886 -		readstdin();
    887 -		grabkeyboard();
    888 -	}
    889 +	readstdin();
    890  	setup();
    891  	run();
    892  
    893 diff --git a/drw.c b/drw.c
    894 index 8fd1ca4..e4995a6 100644
    895 --- a/drw.c
    896 +++ b/drw.c
    897 @@ -2,8 +2,9 @@
    898  #include <stdio.h>
    899  #include <stdlib.h>
    900  #include <string.h>
    901 -#include <X11/Xlib.h>
    902 -#include <X11/Xft/Xft.h>
    903 +#include <wayland-client.h>
    904 +#include <wld/wld.h>
    905 +#include <wld/wayland.h>
    906  
    907  #include "drw.h"
    908  #include "util.h"
    909 @@ -61,40 +62,33 @@ utf8decode(const char *c, long *u, size_t clen)
    910  }
    911  
    912  Drw *
    913 -drw_create(Display *dpy, int screen, Window root, unsigned int w, unsigned int h)
    914 +drw_create(struct wl_display *dpy)
    915  {
    916  	Drw *drw = ecalloc(1, sizeof(Drw));
    917  
    918  	drw->dpy = dpy;
    919 -	drw->screen = screen;
    920 -	drw->root = root;
    921 -	drw->w = w;
    922 -	drw->h = h;
    923 -	drw->drawable = XCreatePixmap(dpy, root, w, h, DefaultDepth(dpy, screen));
    924 -	drw->gc = XCreateGC(dpy, root, 0, NULL);
    925 -	XSetLineAttributes(dpy, drw->gc, 1, LineSolid, CapButt, JoinMiter);
    926 +	drw->ctx = wld_wayland_create_context(dpy, WLD_ANY);
    927 +	drw->renderer = wld_create_renderer(drw->ctx);
    928 +	drw->fontctx = wld_font_create_context();
    929  
    930  	return drw;
    931  }
    932  
    933  void
    934 -drw_resize(Drw *drw, unsigned int w, unsigned int h)
    935 +drw_resize(Drw *drw, struct wl_surface *surface, unsigned int w, unsigned int h)
    936  {
    937 -	if (!drw)
    938 -		return;
    939 -
    940 -	drw->w = w;
    941 -	drw->h = h;
    942 -	if (drw->drawable)
    943 -		XFreePixmap(drw->dpy, drw->drawable);
    944 -	drw->drawable = XCreatePixmap(drw->dpy, drw->root, w, h, DefaultDepth(drw->dpy, drw->screen));
    945 +	if (drw->surface)
    946 +		wld_destroy_surface(drw->surface);
    947 +	drw->surface = wld_wayland_create_surface(drw->ctx, w, h, WLD_FORMAT_XRGB8888, 0, surface);
    948  }
    949  
    950  void
    951  drw_free(Drw *drw)
    952  {
    953 -	XFreePixmap(drw->dpy, drw->drawable);
    954 -	XFreeGC(drw->dpy, drw->gc);
    955 +	wld_destroy_surface(drw->surface);
    956 +	wld_destroy_renderer(drw->renderer);
    957 +	wld_destroy_context(drw->ctx);
    958 +	wld_font_destroy_context(drw->fontctx);
    959  	free(drw);
    960  }
    961  
    962 @@ -102,11 +96,10 @@ drw_free(Drw *drw)
    963   * drw_fontset_create instead.
    964   */
    965  static Fnt *
    966 -xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
    967 +wldfont_create(Drw *drw, const char *fontname, FcPattern *pattern)
    968  {
    969  	Fnt *font;
    970 -	XftFont *xfont = NULL;
    971 -	FcPattern *pattern = NULL;
    972 +	struct wld_font *wld = NULL;
    973  
    974  	if (fontname) {
    975  		/* Using the pattern found at font->xfont->pattern does not yield the
    976 @@ -114,17 +107,17 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
    977  		 * FcNameParse; using the latter results in the desired fallback
    978  		 * behaviour whereas the former just results in missing-character
    979  		 * rectangles being drawn, at least with some fonts. */
    980 -		if (!(xfont = XftFontOpenName(drw->dpy, drw->screen, fontname))) {
    981 +		if (!(wld = wld_font_open_name(drw->fontctx, fontname))) {
    982  			fprintf(stderr, "error, cannot load font from name: '%s'\n", fontname);
    983  			return NULL;
    984  		}
    985  		if (!(pattern = FcNameParse((FcChar8 *) fontname))) {
    986  			fprintf(stderr, "error, cannot parse font name to pattern: '%s'\n", fontname);
    987 -			XftFontClose(drw->dpy, xfont);
    988 +			wld_font_close(wld);
    989  			return NULL;
    990  		}
    991 -	} else if (fontpattern) {
    992 -		if (!(xfont = XftFontOpenPattern(drw->dpy, fontpattern))) {
    993 +	} else if (pattern) {
    994 +		if (!(wld = wld_font_open_pattern(drw->fontctx, pattern))) {
    995  			fprintf(stderr, "error, cannot load font from pattern.\n");
    996  			return NULL;
    997  		}
    998 @@ -140,28 +133,26 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
    999  	 * and lots more all over the internet.
   1000  	 */
   1001  	FcBool iscol;
   1002 -	if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
   1003 -		XftFontClose(drw->dpy, xfont);
   1004 +	if(FcPatternGetBool(pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
   1005 +		wld_font_close(wld);
   1006  		return NULL;
   1007  	}
   1008  
   1009  	font = ecalloc(1, sizeof(Fnt));
   1010 -	font->xfont = xfont;
   1011 +	font->wld = wld;
   1012  	font->pattern = pattern;
   1013 -	font->h = xfont->ascent + xfont->descent;
   1014 -	font->dpy = drw->dpy;
   1015  
   1016  	return font;
   1017  }
   1018  
   1019  static void
   1020 -xfont_free(Fnt *font)
   1021 +wldfont_free(Fnt *font)
   1022  {
   1023  	if (!font)
   1024  		return;
   1025  	if (font->pattern)
   1026  		FcPatternDestroy(font->pattern);
   1027 -	XftFontClose(font->dpy, font->xfont);
   1028 +	wld_font_close(font->wld);
   1029  	free(font);
   1030  }
   1031  
   1032 @@ -175,7 +166,7 @@ drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount)
   1033  		return NULL;
   1034  
   1035  	for (i = 1; i <= fontcount; i++) {
   1036 -		if ((cur = xfont_create(drw, fonts[fontcount - i], NULL))) {
   1037 +		if ((cur = wldfont_create(drw, fonts[fontcount - i], NULL))) {
   1038  			cur->next = ret;
   1039  			ret = cur;
   1040  		}
   1041 @@ -188,7 +179,7 @@ drw_fontset_free(Fnt *font)
   1042  {
   1043  	if (font) {
   1044  		drw_fontset_free(font->next);
   1045 -		xfont_free(font);
   1046 +		wldfont_free(font);
   1047  	}
   1048  }
   1049  
   1050 @@ -197,10 +188,7 @@ drw_clr_create(Drw *drw, Clr *dest, const char *clrname)
   1051  {
   1052  	if (!drw || !dest || !clrname)
   1053  		return;
   1054 -
   1055 -	if (!XftColorAllocName(drw->dpy, DefaultVisual(drw->dpy, drw->screen),
   1056 -	                       DefaultColormap(drw->dpy, drw->screen),
   1057 -	                       clrname, dest))
   1058 +	if (!(wld_lookup_named_color(clrname, dest)))
   1059  		die("error, cannot allocate color '%s'", clrname);
   1060  }
   1061  
   1062 @@ -213,7 +201,7 @@ drw_scm_create(Drw *drw, const char *clrnames[], size_t clrcount)
   1063  	Clr *ret;
   1064  
   1065  	/* need at least two colors for a scheme */
   1066 -	if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(XftColor))))
   1067 +	if (!drw || !clrnames || clrcount < 2 || !(ret = ecalloc(clrcount, sizeof(*ret))))
   1068  		return NULL;
   1069  
   1070  	for (i = 0; i < clrcount; i++)
   1071 @@ -240,11 +228,15 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
   1072  {
   1073  	if (!drw || !drw->scheme)
   1074  		return;
   1075 -	XSetForeground(drw->dpy, drw->gc, invert ? drw->scheme[ColBg].pixel : drw->scheme[ColFg].pixel);
   1076 +	Clr color = invert ? drw->scheme[ColBg] : drw->scheme[ColFg];
   1077  	if (filled)
   1078 -		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
   1079 -	else
   1080 -		XDrawRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w - 1, h - 1);
   1081 +		wld_fill_rectangle(drw->renderer, color, x, y, w, h);
   1082 +	else {
   1083 +		wld_fill_rectangle(drw->renderer, color, x, y, w, 1);
   1084 +		wld_fill_rectangle(drw->renderer, color, x + w - 1, y + 1, 1, h - 2);
   1085 +		wld_fill_rectangle(drw->renderer, color, x, y + 1, 1, h - 2);
   1086 +		wld_fill_rectangle(drw->renderer, color, x, y + h - 1, w, 1);
   1087 +	}
   1088  }
   1089  
   1090  int
   1091 @@ -253,7 +245,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1092  	char buf[1024];
   1093  	int ty;
   1094  	unsigned int ew;
   1095 -	XftDraw *d = NULL;
   1096  	Fnt *usedfont, *curfont, *nextfont;
   1097  	size_t i, len;
   1098  	int utf8strlen, utf8charlen, render = x || y || w || h;
   1099 @@ -262,7 +253,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1100  	FcCharSet *fccharset;
   1101  	FcPattern *fcpattern;
   1102  	FcPattern *match;
   1103 -	XftResult result;
   1104 +	FcResult result;
   1105  	int charexists = 0;
   1106  
   1107  	if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
   1108 @@ -271,11 +262,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1109  	if (!render) {
   1110  		w = ~w;
   1111  	} else {
   1112 -		XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
   1113 -		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
   1114 -		d = XftDrawCreate(drw->dpy, drw->drawable,
   1115 -		                  DefaultVisual(drw->dpy, drw->screen),
   1116 -		                  DefaultColormap(drw->dpy, drw->screen));
   1117 +		wld_fill_rectangle(drw->renderer, drw->scheme[invert ? ColFg : ColBg], x, y, w, h);
   1118  		x += lpad;
   1119  		w -= lpad;
   1120  	}
   1121 @@ -288,7 +275,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1122  		while (*text) {
   1123  			utf8charlen = utf8decode(text, &utf8codepoint, UTF_SIZ);
   1124  			for (curfont = drw->fonts; curfont; curfont = curfont->next) {
   1125 -				charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
   1126 +				charexists = charexists || wld_font_ensure_char(curfont->wld,  utf8codepoint);
   1127  				if (charexists) {
   1128  					if (curfont == usedfont) {
   1129  						utf8strlen += utf8charlen;
   1130 @@ -320,9 +307,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1131  						; /* NOP */
   1132  
   1133  				if (render) {
   1134 -					ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
   1135 -					XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
   1136 -					                  usedfont->xfont, x, ty, (XftChar8 *)buf, len);
   1137 +					ty = y + (h - usedfont->wld->height) / 2 + usedfont->wld->ascent;
   1138 +					wld_draw_text(drw->renderer, usedfont->wld, drw->scheme[invert ? ColBg : ColFg],
   1139 +					              x, ty, buf, len, NULL);
   1140  				}
   1141  				x += ew;
   1142  				w -= ew;
   1143 @@ -343,7 +330,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1144  			FcCharSetAddChar(fccharset, utf8codepoint);
   1145  
   1146  			if (!drw->fonts->pattern) {
   1147 -				/* Refer to the comment in xfont_create for more information. */
   1148 +				/* Refer to the comment in wldfont_create for more information. */
   1149  				die("the first font in the cache must be loaded from a font string.");
   1150  			}
   1151  
   1152 @@ -354,38 +341,37 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
   1153  
   1154  			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
   1155  			FcDefaultSubstitute(fcpattern);
   1156 -			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
   1157 +			match = FcFontMatch(NULL, fcpattern, &result);
   1158  
   1159  			FcCharSetDestroy(fccharset);
   1160  			FcPatternDestroy(fcpattern);
   1161  
   1162  			if (match) {
   1163 -				usedfont = xfont_create(drw, NULL, match);
   1164 -				if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
   1165 +				usedfont = wldfont_create(drw, NULL, match);
   1166 +				if (usedfont && wld_font_ensure_char(usedfont->wld, utf8codepoint)) {
   1167  					for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
   1168  						; /* NOP */
   1169  					curfont->next = usedfont;
   1170  				} else {
   1171 -					xfont_free(usedfont);
   1172 +					wldfont_free(usedfont);
   1173  					usedfont = drw->fonts;
   1174  				}
   1175  			}
   1176  		}
   1177  	}
   1178 -	if (d)
   1179 -		XftDrawDestroy(d);
   1180  
   1181  	return x + (render ? w : 0);
   1182  }
   1183  
   1184  void
   1185 -drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
   1186 +drw_map(Drw *drw, struct wl_surface *surface, int x, int y, unsigned int w, unsigned int h)
   1187  {
   1188  	if (!drw)
   1189  		return;
   1190  
   1191 -	XCopyArea(drw->dpy, drw->drawable, win, drw->gc, x, y, w, h, x, y);
   1192 -	XSync(drw->dpy, False);
   1193 +	wl_surface_damage(surface, x, y, w, h);
   1194 +	wld_flush(drw->renderer);
   1195 +	wld_swap(drw->surface);
   1196  }
   1197  
   1198  unsigned int
   1199 @@ -399,18 +385,19 @@ drw_fontset_getwidth(Drw *drw, const char *text)
   1200  void
   1201  drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
   1202  {
   1203 -	XGlyphInfo ext;
   1204 +	struct wld_extents ext;
   1205  
   1206  	if (!font || !text)
   1207  		return;
   1208  
   1209 -	XftTextExtentsUtf8(font->dpy, font->xfont, (XftChar8 *)text, len, &ext);
   1210 +	wld_font_text_extents_n(font->wld, text, len, &ext);
   1211  	if (w)
   1212 -		*w = ext.xOff;
   1213 +		*w = ext.advance;
   1214  	if (h)
   1215 -		*h = font->h;
   1216 +		*h = font->wld->height;
   1217  }
   1218  
   1219 +#if 0
   1220  Cur *
   1221  drw_cur_create(Drw *drw, int shape)
   1222  {
   1223 @@ -433,3 +420,4 @@ drw_cur_free(Drw *drw, Cur *cursor)
   1224  	XFreeCursor(drw->dpy, cursor->cursor);
   1225  	free(cursor);
   1226  }
   1227 +#endif
   1228 diff --git a/drw.h b/drw.h
   1229 index 4c67419..1f1967e 100644
   1230 --- a/drw.h
   1231 +++ b/drw.h
   1232 @@ -1,34 +1,30 @@
   1233  /* See LICENSE file for copyright and license details. */
   1234  
   1235 -typedef struct {
   1236 -	Cursor cursor;
   1237 -} Cur;
   1238 +typedef void Cur;
   1239  
   1240  typedef struct Fnt {
   1241 -	Display *dpy;
   1242 -	unsigned int h;
   1243 -	XftFont *xfont;
   1244 +	struct wld_font *wld;
   1245  	FcPattern *pattern;
   1246  	struct Fnt *next;
   1247  } Fnt;
   1248  
   1249  enum { ColFg, ColBg }; /* Clr scheme index */
   1250 -typedef XftColor Clr;
   1251 +typedef uint32_t Clr;
   1252  
   1253  typedef struct {
   1254  	unsigned int w, h;
   1255 -	Display *dpy;
   1256 -	int screen;
   1257 -	Window root;
   1258 -	Drawable drawable;
   1259 -	GC gc;
   1260 +	struct wl_display *dpy;
   1261 +	struct wld_context *ctx;
   1262 +	struct wld_renderer *renderer;
   1263 +	struct wld_surface *surface;
   1264 +	struct wld_font_context *fontctx;
   1265  	Clr *scheme;
   1266  	Fnt *fonts;
   1267  } Drw;
   1268  
   1269  /* Drawable abstraction */
   1270 -Drw *drw_create(Display *dpy, int screen, Window win, unsigned int w, unsigned int h);
   1271 -void drw_resize(Drw *drw, unsigned int w, unsigned int h);
   1272 +Drw *drw_create(struct wl_display *dpy);
   1273 +void drw_resize(Drw *drw, struct wl_surface *surface, unsigned int w, unsigned int h);
   1274  void drw_free(Drw *drw);
   1275  
   1276  /* Fnt abstraction */
   1277 @@ -54,4 +50,4 @@ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled
   1278  int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
   1279  
   1280  /* Map functions */
   1281 -void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
   1282 +void drw_map(Drw *drw, struct wl_surface *surface, int x, int y, unsigned int w, unsigned int h);
   1283 -- 
   1284 2.30.1
   1285