wvkbd

git clone https://git.tarina.org/wvkbd
Log | Files | Refs | README | LICENSE

commit c806023fd55a153ab7ccb1a0ab04408cf9315493
parent 9b53b2c836b4fe0180d0558b68e9f576fc342ab4
Author: Stacy Harper <contact@stacyharper.net>
Date:   Tue, 24 Aug 2021 18:52:05 +0200

Drop wld and implement our own pangocairo renderer

Diffstat:
D.gitmodules | 3---
MMakefile | 13+++----------
Mdrw.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mdrw.h | 45++++++++++++++++++++++++++++++++-------------
Mkeyboard.h | 14++++++--------
Mlayout.mobintl.h | 5+----
Mmain.c | 2--
Ashm_open.c | 55+++++++++++++++++++++++++++++++++++++++++++++++++++++++
Ashm_open.h | 9+++++++++
Dwld | 1-
10 files changed, 203 insertions(+), 62 deletions(-)

diff --git a/.gitmodules b/.gitmodules @@ -1,3 +0,0 @@ -[submodule "wld"] - path = wld - url = https://github.com/michaelforney/wld.git diff --git a/Makefile b/Makefile @@ -3,16 +3,15 @@ include config.mk NAME=wvkbd BIN=${NAME}-${LAYOUT} SRC=. -WLDSRC=wld -PKGS = fontconfig wayland-client xkbcommon pixman-1 +PKGS = wayland-client xkbcommon pangocairo WVKBD_SOURCES += $(wildcard $(SRC)/*.c) WVKBD_HEADERS += $(wildcard $(SRC)/*.h) CFLAGS += -std=gnu99 -Wall -g -DWITH_WAYLAND_SHM -DLAYOUT=\"layout.${LAYOUT}.h\" CFLAGS += $(shell pkg-config --cflags $(PKGS)) -LDFLAGS =wld/libwld.a $(shell pkg-config --libs $(PKGS)) -lm -lutil +LDFLAGS =$(shell pkg-config --libs $(PKGS)) -lm -lutil -lrt WAYLAND_HEADERS = $(wildcard proto/*.xml) @@ -22,7 +21,7 @@ SOURCES = $(WVKBD_SOURCES) $(WAYLAND_SRC) OBJECTS = $(SOURCES:.c=.o) -all: wld ${BIN} +all: ${BIN} proto/%-client-protocol.c: proto/%.xml wayland-scanner code < $? > $@ @@ -35,14 +34,8 @@ $(OBJECTS): $(HDRS) $(WVKBD_HEADERS) wvkbd-${LAYOUT}: $(OBJECTS) layout.${LAYOUT}.h $(CC) -o wvkbd-${LAYOUT} $(OBJECTS) $(LDFLAGS) -wld: wld/libwld.a - -wld/libwld.a: - $(MAKE) -C wld ENABLE_DRM=0 - clean: rm -f $(OBJECTS) $(HDRS) $(WAYLAND_SRC) ${BIN} - $(MAKE) -C wld clean format: clang-format -i $(WVKBD_SOURCES) $(WVKBD_HEADERS) diff --git a/drw.c b/drw.c @@ -1,49 +1,43 @@ -#include "wld/wayland.h" -#include "wld/wld.h" #include <wayland-client.h> +#include <sys/mman.h> +#include <unistd.h> #include "drw.h" +#include "shm_open.h" void drw_init(struct drw *d, const char *fc_pattern, struct wl_display *dpy, - void *iface) { - d->wld = wld_wayland_create_context(dpy, WLD_ANY, iface); - d->fctx = wld_font_create_context(); - d->font = wld_font_open_name(d->fctx, fc_pattern); + void *shm) { + d->shm = shm; + d->font_description = pango_font_description_from_string(fc_pattern); } void drwsurf_init(struct drw *d, struct drwsurf *ds, struct wl_surface *surf) { ds->ctx = d; ds->surf = surf; - ds->render = wld_create_renderer(d->wld); } void drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h) { - union wld_object obj; - if (ds->buf) { - wld_buffer_unreference(ds->buf); + munmap(ds->pool_data, ds->s); + wl_buffer_destroy(ds->buf); ds->buf = NULL; - ds->ref = NULL; } ds->w = w; ds->h = h; - ds->buf = wld_create_buffer(ds->ctx->wld, w, h, WLD_FORMAT_ARGB8888, 0); - wld_set_target_buffer(ds->render, ds->buf); - - wld_export(ds->buf, WLD_WAYLAND_OBJECT_BUFFER, &obj); - ds->ref = obj.ptr; + setup_buffer(ds); } static void surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time); -static struct wl_callback_listener frame_listener = {.done = - surface_frame_callback}; +static struct wl_callback_listener frame_listener = { + .done = surface_frame_callback +}; void drwsurf_flip(struct drwsurf *ds) { @@ -52,12 +46,10 @@ drwsurf_flip(struct drwsurf *ds) { if (ds->dirty) { wl_surface_damage(ds->surf, 0, 0, ds->w, ds->h); - wld_flush(ds->render); - wld_set_target_buffer(ds->render, ds->buf); ds->dirty = false; } - wl_surface_attach(ds->surf, ds->ref, 0, 0); + wl_surface_attach(ds->surf, ds->buf, 0, 0); wl_surface_commit(ds->surf); } @@ -69,3 +61,87 @@ surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time) { drwsurf_flip(ds); } + +void +drw_draw_text(struct drwsurf *d, Color color, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h, + const char *label) { + + cairo_save(d->cairo); + + cairo_set_source_rgba ( + d->cairo, + color.bgra[2] / (double)255, + color.bgra[1] / (double)255, + color.bgra[0] / (double)255, + color.bgra[3] / (double)255 + ); + cairo_move_to(d->cairo, x + (double)w / 2.0, y + (double)h / 2.0); + + pango_layout_set_text(d->layout, label, -1); + + int width, height; + pango_layout_get_size(d->layout, &width, &height); + + cairo_rel_move_to(d->cairo, - ((double)width / PANGO_SCALE) / 2, - ((double)height / PANGO_SCALE) / 2); + pango_cairo_show_layout(d->cairo, d->layout); + cairo_restore(d->cairo); +} + +void +drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y, + uint32_t w, uint32_t h) { + cairo_save(d->cairo); + + cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE); + + cairo_rectangle(d->cairo, x, y, w, h); + cairo_set_source_rgba( + d->cairo, + color.bgra[2] / (double)255, + color.bgra[1] / (double)255, + color.bgra[0] / (double)255, + color.bgra[3] / (double)255 + ); + cairo_fill(d->cairo); + + cairo_restore(d->cairo); +} + +uint32_t +setup_buffer(struct drwsurf *drwsurf) +{ + int stride = drwsurf->w * 4; + drwsurf->s = stride * drwsurf->h; + + int fd = allocate_shm_file(drwsurf->s); + if (fd == -1) { + return 1; + } + + drwsurf->pool_data = mmap(NULL, drwsurf->s, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (drwsurf->pool_data == MAP_FAILED) { + close(fd); + return 1; + } + + struct wl_shm_pool *pool = wl_shm_create_pool(drwsurf->ctx->shm, fd, drwsurf->s); + drwsurf->buf = wl_shm_pool_create_buffer(pool, 0, + drwsurf->w, drwsurf->h, stride, WL_SHM_FORMAT_ARGB8888); + wl_shm_pool_destroy(pool); + close(fd); + + cairo_surface_t *s = cairo_image_surface_create_for_data(drwsurf->pool_data, + CAIRO_FORMAT_ARGB32, + drwsurf->w, drwsurf->h, stride); + + drwsurf->cairo = cairo_create(s); + drwsurf->layout = pango_cairo_create_layout(drwsurf->cairo); + pango_layout_set_font_description(drwsurf->layout, drwsurf->ctx->font_description); + cairo_save(drwsurf->cairo); + + return 0; +} + diff --git a/drw.h b/drw.h @@ -1,37 +1,56 @@ #ifndef __DRW_H #define __DRW_H +#include <pango/pangocairo.h> +#include <stdbool.h> + struct drw; struct drwsurf; +struct kbd; void drw_init(struct drw *d, const char *fc_pattern, struct wl_display *dpy, - void *iface); + void *iface); void drwsurf_init(struct drw *d, struct drwsurf *ds, struct wl_surface *surf); void drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h); void drwsurf_flip(struct drwsurf *ds); +typedef union { + uint8_t bgra[4]; + uint32_t color; +} Color; + +void +drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y, + uint32_t w, uint32_t h); + +void +drw_draw_text(struct drwsurf *d, Color color, + uint32_t x, uint32_t y, + uint32_t w, uint32_t h, + const char *label); + +uint32_t +setup_buffer(struct drwsurf *drwsurf); + struct drw { - struct wld_context *wld; - struct wld_font_context *fctx; - struct wld_font *font; + struct wl_shm *shm; + PangoFontDescription *font_description; }; struct drwsurf { - uint32_t w, h; + uint32_t w, h, s; bool dirty; struct drw *ctx; struct wl_surface *surf; - struct wld_renderer *render; - struct wld_buffer *buf; - struct wl_buffer *ref; + struct wl_buffer *buf; + struct wl_shm *shm; + unsigned char *pool_data; + + cairo_t *cairo; + PangoLayout *layout; struct wl_callback *cb; }; -typedef union { - uint8_t bgra[4]; - uint32_t color; -} Color; - #endif diff --git a/keyboard.h b/keyboard.h @@ -91,7 +91,7 @@ struct kbd { static inline void draw_inset(struct drwsurf *d, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t border, - uint32_t color); + Color color); static void kbd_init(struct kbd *kb, struct layout * layouts, char * layer_names_list); static void kbd_init_layout(struct layout *l, uint32_t width, uint32_t height); @@ -406,10 +406,8 @@ kbd_draw_key(struct kbd *kb, struct key *k, bool pressed) { label); struct clr_scheme *scheme = (k->scheme == 0) ? &(kb->scheme) : &(kb->scheme1); Color *fill = pressed ? &scheme->high : &scheme->fg; - draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, fill->color); - uint32_t xoffset = k->w / (strlen(label) + 2); - wld_draw_text(d->render, d->ctx->font, scheme->text.color, k->x + xoffset, - k->y + (k->h / 2), label, -1, NULL); + draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, *fill); + drw_draw_text(d, scheme->text, k->x, k->y, k->w, k->h, label); } void @@ -419,7 +417,7 @@ kbd_draw_layout(struct kbd *kb) { bool pressed = false; if (debug) fprintf(stderr, "Draw layout"); - wld_fill_rectangle(d->render, kb->scheme.bg.color, 0, 0, kb->w, kb->h); + drw_fill_rectangle(d, kb->scheme.bg, 0, 0, kb->w, kb->h); while (next_key->type != Last) { if ((next_key->type == Pad) || (next_key->type == EndRow)) { @@ -452,7 +450,7 @@ kbd_resize(struct kbd *kb, uint32_t w, uint32_t h, struct layout *layouts, void draw_inset(struct drwsurf *d, uint32_t x, uint32_t y, uint32_t width, - uint32_t height, uint32_t border, uint32_t color) { - wld_fill_rectangle(d->render, color, x + border, y + border, width - border, + uint32_t height, uint32_t border, Color color) { + drw_fill_rectangle(d, color, x + border, y + border, width - border, height - border); } diff --git a/layout.mobintl.h b/layout.mobintl.h @@ -71,10 +71,7 @@ static enum layout_id layers[] = { #include "keymap.mobintl.h" #include "keyboard.h" -/* font (see `man fonts-conf` for instructions) */ -static const char *fc_font_pattern = - "Monospace:size=16:antialias=true:hinting=true"; - +static const char *fc_font_pattern = "Monospace 16"; static struct key keys_full[], keys_special[], keys_simple[], keys_cyrillic[], keys_arabic[], diff --git a/main.c b/main.c @@ -1,7 +1,5 @@ #include "proto/virtual-keyboard-unstable-v1-client-protocol.h" #include "proto/wlr-layer-shell-unstable-v1-client-protocol.h" -#include "wld/wayland.h" -#include "wld/wld.h" #include <linux/input-event-codes.h> #include <stdio.h> #include <stdlib.h> diff --git a/shm_open.c b/shm_open.c @@ -0,0 +1,55 @@ +#define _POSIX_C_SOURCE 200112L +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <time.h> +#include <unistd.h> + +static void +randname(char *buf) +{ + struct timespec ts; + long r; + clock_gettime(CLOCK_REALTIME, &ts); + r = ts.tv_nsec; + for (int i = 0; i < 6; ++i) { + buf[i] = 'A'+(r&15)+(r&16)*2; + r >>= 5; + } +} + +static int +create_shm_file(void) +{ + int retries = 100; + int fd; + do { + char name[] = "/wl_shm-XXXXXX"; + randname(name + sizeof(name) - 7); + --retries; + fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd >= 0) { + shm_unlink(name); + return fd; + } + } while (retries > 0 && errno == EEXIST); + return -1; +} + +int +allocate_shm_file(size_t size) +{ + int fd = create_shm_file(); + int ret; + if (fd < 0) + return -1; + do { + ret = ftruncate(fd, size); + } while (ret < 0 && errno == EINTR); + if (ret < 0) { + close(fd); + return -1; + } + return fd; +} + diff --git a/shm_open.h b/shm_open.h @@ -0,0 +1,9 @@ +#ifndef shm_open_h_INCLUDED +#define shm_open_h_INCLUDED + +void randname(char *buf); +int create_shm_file(void); +int allocate_shm_file(size_t size); + +#endif // shm_open_h_INCLUDED + diff --git a/wld b/wld @@ -1 +0,0 @@ -Subproject commit ea4eccb64cfcfc508b029a530fc434d6e6695af5