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, ®listener, 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