1 Commits

13 changed files with 190 additions and 437 deletions

1
.gitignore vendored
View File

@@ -6,6 +6,5 @@ include/config.h
.gdb_history
*.log
wvkbd
*.1
config.h
wvkbd-mobintl

View File

@@ -10,10 +10,9 @@ PKGS = wayland-client xkbcommon pangocairo
WVKBD_SOURCES += $(wildcard $(SRC)/*.c)
WVKBD_HEADERS += $(wildcard $(SRC)/*.h)
PKG_CONFIG ?= pkg-config
CFLAGS += -std=gnu99 -Wall -g -DWITH_WAYLAND_SHM -DLAYOUT=\"layout.${LAYOUT}.h\" -DKEYMAP=\"keymap.${LAYOUT}.h\"
CFLAGS += $(shell $(PKG_CONFIG) --cflags $(PKGS))
LDFLAGS += $(shell $(PKG_CONFIG) --libs $(PKGS)) -lm -lutil -lrt
CFLAGS += $(shell pkg-config --cflags $(PKGS))
LDFLAGS += $(shell pkg-config --libs $(PKGS)) -lm -lutil -lrt
WAYLAND_HEADERS = $(wildcard proto/*.xml)
@@ -21,12 +20,9 @@ HDRS = $(WAYLAND_HEADERS:.xml=-client-protocol.h)
WAYLAND_SRC = $(HDRS:.h=.c)
SOURCES = $(WVKBD_SOURCES) $(WAYLAND_SRC)
SCDOC=scdoc
DOCS = wvkbd.1
OBJECTS = $(SOURCES:.c=.o)
all: ${BIN} ${DOCS}
all: ${BIN}
config.h:
cp config.def.h config.h
@@ -43,14 +39,11 @@ wvkbd-${LAYOUT}: config.h $(OBJECTS) layout.${LAYOUT}.h
$(CC) -o wvkbd-${LAYOUT} $(OBJECTS) $(LDFLAGS)
clean:
rm -f $(OBJECTS) $(HDRS) $(WAYLAND_SRC) ${BIN} ${DOCS}
rm -f $(OBJECTS) $(HDRS) $(WAYLAND_SRC) ${BIN}
format:
clang-format -i $(WVKBD_SOURCES) $(WVKBD_HEADERS)
%: %.scd
$(SCDOC) < $< > $@
install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${NAME}-${LAYOUT} ${DESTDIR}${PREFIX}/bin

View File

@@ -1,6 +1,6 @@
# wvkbd - On-screen keyboard for wlroots that sucks less
<img src="https://raw.githubusercontent.com/jjsullivan5196/wvkbd/master/contrib/wvkbd-mobintl.jpg" width=300 /> <img src="https://raw.githubusercontent.com/jjsullivan5196/wvkbd/master/contrib/wvkbd-mobintl-cyrillic.jpg" width=300 />
<img src="https://raw.githubusercontent.com/proycon/wvkbd/master/contrib/wvkbd-mobintl.jpg" width=300 /> <img src="https://raw.githubusercontent.com/proycon/wvkbd/master/contrib/wvkbd-mobintl-cyrillic.jpg" width=300 />
This project aims to deliver a minimal but practically usable implementation of a wlroots on-screen
keyboard in legible C. This will **only** be a keyboard, not a feedback buzzer,
@@ -25,7 +25,7 @@ new features.
- Automatic portrait/landscape detection and subsequent layout switching
<img src="https://raw.githubusercontent.com/jjsullivan5196/wvkbd/master/contrib/wvkbd-mobintl-landscape.jpg" width=640 />
<img src="https://raw.githubusercontent.com/proycon/wvkbd/master/contrib/wvkbd-mobintl-landscape.jpg" width=640 />
There are some areas that still need work:
@@ -42,8 +42,6 @@ You'll need the following developer packages
- wayland-client
- xkbcommon
You also need [scdoc](https://git.sr.ht/~sircmpwn/scdoc/) to generate the documentation.
Make any customizations you would like in `config.def.h` and run `make`
The default set of layouts is called `mobintl` *(mobile international)*, which groups various layouts aimed at mobile devices

View File

@@ -2,7 +2,6 @@
#define config_def_h_INCLUDED
#define DEFAULT_FONT "Sans 14"
#define DEFAULT_ROUNDING 5
static const int transparency = 255;
struct clr_scheme schemes[] = {
@@ -14,7 +13,6 @@ struct clr_scheme schemes[] = {
.swipe = {.bgra = {100, 255, 100, 64}},
.text = {.color = UINT32_MAX},
.font = DEFAULT_FONT,
.rounding = DEFAULT_ROUNDING,
},
{
/* colors */
@@ -24,7 +22,6 @@ struct clr_scheme schemes[] = {
.swipe = {.bgra = {100, 255, 100, 64}},
.text = {.color = UINT32_MAX},
.font = DEFAULT_FONT,
.rounding = DEFAULT_ROUNDING,
}
};

View File

@@ -1,4 +1,4 @@
VERSION = 0.17
VERSION = 0.14.3
CFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=700
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man

218
drw.c
View File

@@ -6,132 +6,34 @@
#include "shm_open.h"
#include "math.h"
void drwbuf_handle_release(void *data, struct wl_buffer *wl_buffer) {
struct drwsurf *ds = data;
ds->released = true;
};
const struct wl_buffer_listener buffer_listener = {
.release = drwbuf_handle_release
};
void drwsurf_handle_frame_cb(void* data, struct wl_callback* callback,
uint32_t time)
{
struct drwsurf *ds = data;
wl_callback_destroy(ds->frame_cb);
ds->frame_cb = NULL;
cairo_rectangle_int_t r = {0};
for (int i = 0; i < cairo_region_num_rectangles(ds->damage); i++) {
cairo_region_get_rectangle(ds->damage, i, &r);
wl_surface_damage(ds->surf, r.x, r.y, r.width, r.height);
};
cairo_region_subtract(ds->damage, ds->damage);
drwsurf_attach(ds);
}
const struct wl_callback_listener frame_listener = {
.done = drwsurf_handle_frame_cb
};
void drwsurf_register_frame_cb(struct drwsurf *ds)
{
if (ds->frame_cb)
return;
if (!ds->attached)
return;
ds->frame_cb = wl_surface_frame(ds->surf);
wl_callback_add_listener(ds->frame_cb, &frame_listener, ds);
wl_surface_commit(ds->surf);
}
void drwsurf_damage(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
cairo_rectangle_int_t rect = { x, y, w, h };
cairo_region_union_rectangle(ds->damage, &rect);
cairo_region_union_rectangle(ds->backport_damage, &rect);
drwsurf_register_frame_cb(ds);
}
void
drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h, double s)
{
if (ds->buf) {
munmap(ds->pool_data, ds->size);
wl_buffer_destroy(ds->buf);
ds->buf = NULL;
}
ds->scale = s;
ds->width = ceil(w * s);
ds->height = ceil(h * s);
if (ds->damage)
cairo_region_destroy(ds->damage);
ds->damage = cairo_region_create();
if (ds->backport_damage)
cairo_region_destroy(ds->backport_damage);
ds->backport_damage = cairo_region_create();
ds->released = true;
setup_buffer(ds, ds->back_buffer);
setup_buffer(ds, ds->display_buffer);
}
void
drwsurf_backport(struct drwsurf *ds)
{
cairo_save(ds->back_buffer->cairo);
cairo_scale(ds->back_buffer->cairo, 1/ds->scale, 1/ds->scale);
cairo_set_operator(ds->back_buffer->cairo, CAIRO_OPERATOR_SOURCE);
cairo_rectangle_int_t r = {0};
for (int i = 0; i < cairo_region_num_rectangles(ds->backport_damage); i++) {
cairo_region_get_rectangle(ds->backport_damage, i, &r);
cairo_set_source_surface(ds->back_buffer->cairo, ds->display_buffer->cairo_surf, 0, 0);
cairo_rectangle(
ds->back_buffer->cairo,
r.x * ds->scale,
r.y * ds->scale,
r.width * ds->scale,
r.height * ds->scale
);
cairo_fill(ds->back_buffer->cairo);
};
cairo_restore(ds->back_buffer->cairo);
cairo_region_subtract(ds->backport_damage, ds->backport_damage);
}
void
drwsurf_attach(struct drwsurf *ds)
{
wl_surface_attach(ds->surf, ds->back_buffer->buf, 0, 0);
wl_surface_commit(ds->surf);
ds->released = false;
ds->attached = true;
setup_buffer(ds);
}
void
drwsurf_flip(struct drwsurf *ds)
{
if (ds->released)
return;
ds->released = true;
struct drwbuf *tmp = ds->back_buffer;
ds->back_buffer = ds->display_buffer;
ds->display_buffer = tmp;
drwsurf_backport(ds);
wl_surface_attach(ds->surf, ds->buf, 0, 0);
wl_surface_commit(ds->surf);
}
void
drw_draw_text(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
drw_draw_text(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, uint32_t b, const char *label,
PangoFontDescription *font_description)
{
drwsurf_flip(ds);
struct drwbuf *d = ds->back_buffer;
drwsurf_damage(ds, x, y, w, h);
cairo_save(d->cairo);
@@ -156,12 +58,8 @@ drw_draw_text(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
}
void
drw_do_clear(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
drw_do_clear(struct drwsurf *d, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
{
drwsurf_flip(ds);
struct drwbuf *d = ds->back_buffer;
drwsurf_damage(ds, x, y, w, h);
cairo_save(d->cairo);
cairo_set_operator(d->cairo, CAIRO_OPERATOR_CLEAR);
@@ -172,13 +70,9 @@ drw_do_clear(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t w, uint32_t h)
}
void
drw_do_rectangle(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, bool over, int rounding)
drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, bool over)
{
drwsurf_flip(ds);
struct drwbuf *d = ds->back_buffer;
drwsurf_damage(ds, x, y, w, h);
cairo_save(d->cairo);
if (over) {
@@ -187,99 +81,65 @@ drw_do_rectangle(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE);
}
if (rounding > 0) {
double radius = rounding / 1.0;
double degrees = M_PI / 180.0;
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_new_sub_path (d->cairo);
cairo_arc (d->cairo, x + w - radius, y + radius, radius, -90 * degrees, 0 * degrees);
cairo_arc (d->cairo, x + w - radius, y + h - radius, radius, 0 * degrees, 90 * degrees);
cairo_arc (d->cairo, x + radius, y + h - radius, radius, 90 * degrees, 180 * degrees);
cairo_arc (d->cairo, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
cairo_close_path (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_fill (d->cairo);
cairo_set_source_rgba(d->cairo, 0, 0, 0, 0.9);
cairo_set_line_width(d->cairo, 1.0);
cairo_stroke(d->cairo);
cairo_restore(d->cairo);
}
else {
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);
}
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, int rounding)
uint32_t w, uint32_t h)
{
drw_do_rectangle(d, color, x, y, w, h, false, rounding);
drw_do_rectangle(d, color, x, y, w, h, false);
}
void
drw_over_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, int rounding)
uint32_t w, uint32_t h)
{
drw_do_rectangle(d, color, x, y, w, h, true, rounding);
drw_do_rectangle(d, color, x, y, w, h, true);
}
uint32_t
setup_buffer(struct drwsurf *drwsurf, struct drwbuf *drwbuf)
setup_buffer(struct drwsurf *drwsurf)
{
int prev_size = drwbuf->size;
int stride = drwsurf->width * 4;
drwbuf->size = stride * drwsurf->height;
drwsurf->size = stride * drwsurf->height;
int fd = allocate_shm_file(drwbuf->size);
int fd = allocate_shm_file(drwsurf->size);
if (fd == -1) {
return 1;
}
if (drwbuf->pool_data)
munmap(drwbuf->pool_data, prev_size);
drwbuf->pool_data =
mmap(NULL, drwbuf->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (drwbuf->pool_data == MAP_FAILED) {
drwsurf->pool_data =
mmap(NULL, drwsurf->size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (drwsurf->pool_data == MAP_FAILED) {
close(fd);
return 1;
}
if (drwbuf->buf)
wl_buffer_destroy(drwbuf->buf);
struct wl_shm_pool *pool =
wl_shm_create_pool(drwsurf->ctx->shm, fd, drwbuf->size);
drwbuf->buf =
wl_shm_create_pool(drwsurf->ctx->shm, fd, drwsurf->size);
drwsurf->buf =
wl_shm_pool_create_buffer(pool, 0, drwsurf->width, drwsurf->height,
stride, WL_SHM_FORMAT_ARGB8888);
wl_shm_pool_destroy(pool);
close(fd);
wl_buffer_add_listener(drwbuf->buf, &buffer_listener, drwsurf);
if (drwbuf->cairo_surf)
cairo_surface_destroy(drwbuf->cairo_surf);
drwbuf->cairo_surf = cairo_image_surface_create_for_data(
drwbuf->pool_data, CAIRO_FORMAT_ARGB32, drwsurf->width,
cairo_surface_t *s = cairo_image_surface_create_for_data(
drwsurf->pool_data, CAIRO_FORMAT_ARGB32, drwsurf->width,
drwsurf->height, stride);
if (drwbuf->cairo)
cairo_destroy(drwbuf->cairo);
drwbuf->cairo = cairo_create(drwbuf->cairo_surf);
cairo_scale(drwbuf->cairo, drwsurf->scale, drwsurf->scale);
cairo_set_antialias(drwbuf->cairo, CAIRO_ANTIALIAS_NONE);
drwbuf->layout = pango_cairo_create_layout(drwbuf->cairo);
pango_layout_set_auto_dir(drwbuf->layout, false);
cairo_save(drwbuf->cairo);
drwsurf->cairo = cairo_create(s);
cairo_scale(drwsurf->cairo, drwsurf->scale, drwsurf->scale);
cairo_set_antialias(drwsurf->cairo, CAIRO_ANTIALIAS_NONE);
drwsurf->layout = pango_cairo_create_layout(drwsurf->cairo);
pango_layout_set_auto_dir(drwsurf->layout, false);
cairo_save(drwsurf->cairo);
return 0;
}

41
drw.h
View File

@@ -7,53 +7,42 @@
struct drw {
struct wl_shm *shm;
};
struct drwbuf {
uint32_t size;
struct wl_buffer *buf;
cairo_surface_t *cairo_surf;
cairo_t *cairo;
PangoLayout *layout;
unsigned char *pool_data;
};
struct drwsurf {
uint32_t width, height;
uint32_t width, height, size;
double scale;
struct drw *ctx;
struct wl_surface *surf;
struct wl_buffer *buf;
struct wl_shm *shm;
struct wl_callback *frame_cb;
unsigned char *pool_data;
cairo_region_t *damage, *backport_damage;
bool attached;
bool released;
struct drwbuf *back_buffer;
struct drwbuf *display_buffer;
cairo_t *cairo;
PangoLayout *layout;
};
struct kbd;
void drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h, double s);
void drwsurf_attach(struct drwsurf *ds);
void drwsurf_flip(struct drwsurf *ds);
typedef union {
uint8_t bgra[4];
uint32_t color;
} Color;
void drw_do_clear(struct drwsurf *ds, uint32_t x, uint32_t y,
void drw_do_clear(struct drwsurf *d, uint32_t x, uint32_t y,
uint32_t w, uint32_t h);
void drw_do_rectangle(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, bool fill, int rounding);
void drw_fill_rectangle(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, int rounding);
void drw_over_rectangle(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, int rounding);
void drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, bool fill);
void drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h);
void drw_over_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h);
void drw_draw_text(struct drwsurf *ds, Color color, uint32_t x, uint32_t y,
void drw_draw_text(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, uint32_t b, const char *label,
PangoFontDescription *font_description);
uint32_t setup_buffer(struct drwsurf *ds, struct drwbuf *db);
uint32_t setup_buffer(struct drwsurf *drwsurf);
#endif

View File

@@ -3,7 +3,6 @@
#include <stddef.h>
#include <stdio.h>
#include <sys/mman.h>
#include <ctype.h>
#include "keyboard.h"
#include "drw.h"
#include "os-compatibility.h"
@@ -277,23 +276,13 @@ kbd_get_layer_index(struct kbd *kb, struct layout *l)
void
kbd_unpress_key(struct kbd *kb, uint32_t time)
{
bool unlatch_shift, unlatch_ctrl, unlatch_alt, unlatch_super, unlatch_altgr;
unlatch_shift = unlatch_ctrl = unlatch_alt = unlatch_super = unlatch_altgr = false;
bool unlatch_shift = false;
if (kb->last_press) {
unlatch_shift = (kb->mods & Shift) == Shift;
unlatch_ctrl = (kb->mods & Ctrl) == Ctrl;
unlatch_alt = (kb->mods & Alt) == Alt;
unlatch_super = (kb->mods & Super) == Super;
unlatch_altgr = (kb->mods & AltGr) == AltGr;
if (unlatch_shift) kb->mods ^= Shift;
if (unlatch_ctrl) kb->mods ^= Ctrl;
if (unlatch_alt) kb->mods ^= Alt;
if (unlatch_super) kb->mods ^= Super;
if (unlatch_altgr) kb->mods ^= AltGr;
if (unlatch_shift||unlatch_ctrl||unlatch_alt||unlatch_super||unlatch_altgr) {
if (unlatch_shift) {
kb->mods ^= Shift;
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
}
@@ -315,7 +304,7 @@ kbd_unpress_key(struct kbd *kb, uint32_t time)
if (kb->compose >= 2) {
kb->compose = 0;
kbd_switch_layout(kb, kb->last_abc_layout, kb->last_abc_index);
} else if (unlatch_shift||unlatch_ctrl||unlatch_alt||unlatch_super||unlatch_altgr) {
} else if (unlatch_shift) {
kbd_draw_layout(kb);
} else {
kbd_draw_key(kb, kb->last_press, Unpress);
@@ -337,7 +326,10 @@ kbd_release_key(struct kbd *kb, uint32_t time)
kb->last_swipe = NULL;
}
drwsurf_flip(kb->surf);
kbd_clear_last_popup(kb);
drwsurf_flip(kb->popup_surf);
}
void
@@ -363,7 +355,10 @@ kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y)
kbd_unpress_key(kb, time);
}
drwsurf_flip(kb->surf);
kbd_clear_last_popup(kb);
drwsurf_flip(kb->popup_surf);
}
void
@@ -423,7 +418,7 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time)
break;
case Mod:
kb->mods ^= k->code;
if ((k->code == Shift) || (k->code == CapsLock)) {
if (k->code == Shift) {
kbd_draw_layout(kb);
} else {
if (kb->mods & k->code) {
@@ -495,6 +490,9 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time)
default:
break;
}
drwsurf_flip(kb->surf);
drwsurf_flip(kb->popup_surf);
}
void
@@ -529,8 +527,7 @@ kbd_print_key_stdout(struct kbd *kb, struct key *k)
}
if (!handled) {
if ((kb->mods & Shift) ||
((kb->mods & CapsLock) & (strlen(k->label) == 1 && isalpha(k->label[0]))))
if ((kb->mods & Shift) || (kb->mods & CapsLock))
printf("%s", k->shift_label);
else if (!(kb->mods & Ctrl) && !(kb->mods & Alt) && !(kb->mods & Super))
printf("%s", k->label);
@@ -544,6 +541,9 @@ kbd_clear_last_popup(struct kbd *kb)
if (kb->last_popup_w && kb->last_popup_h) {
drw_do_clear(kb->popup_surf, kb->last_popup_x, kb->last_popup_y,
kb->last_popup_w, kb->last_popup_h);
wl_surface_damage(kb->popup_surf->surf, kb->last_popup_x,
kb->last_popup_y, kb->last_popup_w, kb->last_popup_h);
kb->last_popup_w = kb->last_popup_h = 0;
}
}
@@ -551,8 +551,7 @@ kbd_clear_last_popup(struct kbd *kb)
void
kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type)
{
const char *label = ((kb->mods & Shift)||((kb->mods & CapsLock) &&
strlen(k->label) == 1 && isalpha(k->label[0]))) ? k->shift_label : k->label;
const char *label = (kb->mods & Shift) ? k->shift_label : k->label;
if (kb->debug)
fprintf(stderr, "Draw key +%d+%d %dx%d -> %s\n", k->x, k->y, k->w, k->h,
label);
@@ -562,20 +561,21 @@ kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type)
case None:
case Unpress:
draw_inset(kb->surf, k->x, k->y, k->w, k->h, KBD_KEY_BORDER,
scheme->fg, scheme->rounding);
scheme->fg);
break;
case Press:
draw_inset(kb->surf, k->x, k->y, k->w, k->h, KBD_KEY_BORDER,
scheme->high, scheme->rounding);
scheme->high);
break;
case Swipe:
draw_over_inset(kb->surf, k->x, k->y, k->w, k->h, KBD_KEY_BORDER,
scheme->swipe, scheme->rounding);
scheme->swipe);
break;
}
drw_draw_text(kb->surf, scheme->text, k->x, k->y, k->w, k->h,
KBD_KEY_BORDER, label, scheme->font_description);
wl_surface_damage(kb->surf->surf, k->x, k->y, k->w, k->h);
if (type == Press || type == Unpress) {
kbd_clear_last_popup(kb);
@@ -586,12 +586,14 @@ kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type)
kb->last_popup_h = k->h;
drw_fill_rectangle(kb->popup_surf, scheme->bg, k->x,
kb->last_popup_y, k->w, k->h, scheme->rounding);
kb->last_popup_y, k->w, k->h);
draw_inset(kb->popup_surf, k->x, kb->last_popup_y, k->w, k->h,
KBD_KEY_BORDER, scheme->high, scheme->rounding);
KBD_KEY_BORDER, scheme->high);
drw_draw_text(kb->popup_surf, scheme->text, k->x, kb->last_popup_y,
k->w, k->h, KBD_KEY_BORDER, label,
scheme->font_description);
wl_surface_damage(kb->popup_surf->surf, k->x, kb->last_popup_y, k->w,
k->h);
}
}
@@ -603,7 +605,7 @@ kbd_draw_layout(struct kbd *kb)
if (kb->debug)
fprintf(stderr, "Draw layout\n");
drw_fill_rectangle(d, kb->schemes[0].bg, 0, 0, kb->w, kb->h, 0);
drw_fill_rectangle(d, kb->schemes[0].bg, 0, 0, kb->w, kb->h);
while (next_key->type != Last) {
if ((next_key->type == Pad) || (next_key->type == EndRow)) {
@@ -618,6 +620,7 @@ kbd_draw_layout(struct kbd *kb)
}
next_key++;
}
wl_surface_damage(d->surf, 0, 0, kb->w, kb->h);
}
void
@@ -644,17 +647,17 @@ kbd_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount)
void
draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint32_t border, Color color, int rounding)
uint32_t height, uint32_t border, Color color)
{
drw_fill_rectangle(ds, color, x + border, y + border, width - (border * 2),
height - (border * 2), rounding);
height - (border * 2));
}
void
draw_over_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint32_t border, Color color, int rounding)
uint32_t height, uint32_t border, Color color)
{
drw_over_rectangle(ds, color, x + border, y + border, width - (border * 2),
height - (border * 2), rounding);
height - (border * 2));
}
void
@@ -675,7 +678,7 @@ create_and_upload_keymap(struct kbd *kb, const char *name, uint32_t comp_unichr,
size_t keymap_size = strlen(keymap_template) + 64;
char *keymap_str = malloc(keymap_size);
sprintf(keymap_str, keymap_template, comp_unichr, comp_shift_unichr);
keymap_size = strlen(keymap_str);
keymap_size = strlen(keymap_str) + 1;
int keymap_fd = os_create_anonymous_file(keymap_size);
if (keymap_fd < 0) {
die("could not create keymap fd\n");

View File

@@ -55,7 +55,6 @@ struct clr_scheme {
Color swipe;
Color text;
char *font;
int rounding;
PangoFontDescription *font_description;
};
@@ -122,9 +121,9 @@ struct kbd {
};
void draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint32_t border, Color color, int rounding);
uint32_t height, uint32_t border, Color color);
void draw_over_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint32_t border, Color color, int rounding);
uint32_t height, uint32_t border, Color color);
void kbd_init(struct kbd *kb, struct layout *layouts,
char *layer_names_list, char *landscape_layer_names_list);

View File

@@ -1626,8 +1626,7 @@ static struct key keys_compose_cyr_tse[] = {
static struct key keys_compose_cyr_g[] = {
{"ѓ", "Ѓ", 1.0, Copy, 0x0453, 0, 0x0403},
{"ґ", "Ґ", 1.0, Copy, 0x0491, 0, 0x0490},
{"", "", 8.0, Pad},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},

63
main.c
View File

@@ -28,7 +28,7 @@
#define countof(x) (sizeof(x) / sizeof(*x))
/* client state */
static const char *namespace = "wvkbd";
static const char *namespace = "wlroots";
static struct wl_display *display;
static struct wl_compositor *compositor;
static struct wl_seat *seat;
@@ -62,11 +62,10 @@ static int wl_outputs_size;
/* drawing */
static struct drw draw_ctx;
static struct drwbuf draw_surf_back_buffer, draw_surf_display_buffer, popup_draw_surf_back_buffer, popup_draw_surf_display_buffer;
static struct drwsurf draw_surf, popup_draw_surf;
/* layer surface parameters */
static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY;
static uint32_t layer = ZWLR_LAYER_SHELL_V1_LAYER_TOP;
static uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT;
@@ -77,7 +76,6 @@ static int cur_x = -1, cur_y = -1;
static bool cur_press = false;
static struct kbd keyboard;
static uint32_t height, normal_height, landscape_height;
static int rounding = DEFAULT_ROUNDING;
static bool hidden = false;
/* event handler prototypes */
@@ -133,7 +131,6 @@ static void layer_surface_configure(void *data,
static void layer_surface_closed(void *data,
struct zwlr_layer_surface_v1 *surface);
static void flip_landscape();
static void show();
/* event handlers */
static const struct wl_pointer_listener pointer_listener = {
@@ -333,6 +330,7 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time,
}
kbd_next_layer(&keyboard, NULL, (value >= 0));
drwsurf_flip(keyboard.surf);
}
void
@@ -517,7 +515,7 @@ xdg_popup_surface_configure(void *data, struct xdg_surface *xdg_surface,
{
xdg_surface_ack_configure(xdg_surface, serial);
popup_xdg_surface_configured = true;
drwsurf_attach(&popup_draw_surf);
drwsurf_flip(&popup_draw_surf);
}
static const struct xdg_surface_listener xdg_popup_surface_listener = {
@@ -561,7 +559,12 @@ flip_landscape()
if (current_output) {
keyboard.landscape = current_output->w > current_output->h;
} else if (wl_outputs_size) {
keyboard.landscape = wl_outputs[0].w > wl_outputs[0].h;
for (int i = 0; i < wl_outputs_size; i += 1) {
if (wl_outputs[i].w > wl_outputs[i].h) {
keyboard.landscape = true;
break;
}
}
}
enum layout_id layer;
@@ -579,25 +582,10 @@ flip_landscape()
keyboard.last_abc_layout = keyboard.layout;
keyboard.last_abc_index = 0;
if (layer_surface && previous_landscape != keyboard.landscape) {
if (popup_xdg_popup) {
xdg_popup_destroy(popup_xdg_popup);
popup_xdg_popup = NULL;
}
if (popup_xdg_surface) {
xdg_surface_destroy(popup_xdg_surface);
popup_xdg_surface = NULL;
}
if (popup_draw_surf.surf) {
wl_surface_destroy(popup_draw_surf.surf);
popup_draw_surf.surf = NULL;
}
zwlr_layer_surface_v1_destroy(layer_surface);
layer_surface = NULL;
wl_surface_destroy(draw_surf.surf);
show();
if (layer_surface) {
zwlr_layer_surface_v1_set_size(layer_surface, 0, height);
zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height);
wl_surface_commit(draw_surf.surf);
}
}
@@ -664,7 +652,7 @@ layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface,
zwlr_layer_surface_v1_ack_configure(surface, serial);
kbd_resize(&keyboard, layouts, NumLayouts);
drwsurf_attach(&draw_surf);
drwsurf_flip(&draw_surf);
} else {
zwlr_layer_surface_v1_ack_configure(surface, serial);
}
@@ -692,7 +680,6 @@ usage(char *argv0)
" -O - Print intersected keys to standard output\n");
fprintf(stderr, " -H [int] - Height in pixels\n");
fprintf(stderr, " -L [int] - Landscape height in pixels\n");
fprintf(stderr, " -R [int] - Rounding radius in pixels\n");
fprintf(stderr, " --fn [font] - Set font (e.g: DejaVu Sans 20)\n");
fprintf(stderr, " --hidden - Start hidden (send SIGUSR2 to show)\n");
fprintf(
@@ -810,7 +797,7 @@ set_kbd_colors(uint8_t *bgra, char *hex)
// bg, fg, text, high, swipe
int length = strlen(hex);
if (length == 6 || length == 8) {
char subhex[3] = { 0 };
char subhex[2];
memcpy(subhex, hex, 2);
bgra[2] = (int)strtol(subhex, NULL, 16);
memcpy(subhex, hex + 2, 2);
@@ -961,12 +948,6 @@ main(int argc, char **argv)
exit(1);
}
height = landscape_height = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-R")) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
rounding = atoi(argv[++i]);
} else if (!strcmp(argv[i], "-D")) {
keyboard.debug = true;
} else if ((!strcmp(argv[i], "-fn")) || (!strcmp(argv[i], "--fn"))) {
@@ -1007,22 +988,13 @@ main(int argc, char **argv)
schemes[i].font = fc_font_pattern;
}
if (rounding != DEFAULT_ROUNDING) {
for (i = 0; i < countof(schemes); i++)
schemes[i].rounding = rounding;
}
display = wl_display_connect(NULL);
if (display == NULL) {
die("Failed to create display\n");
}
draw_surf.ctx = &draw_ctx;
draw_surf.back_buffer = &draw_surf_back_buffer;
draw_surf.display_buffer = &draw_surf_display_buffer;
popup_draw_surf.ctx = &draw_ctx;
popup_draw_surf.back_buffer = &popup_draw_surf_back_buffer;
popup_draw_surf.display_buffer = &popup_draw_surf_display_buffer;
keyboard.surf = &draw_surf;
keyboard.popup_surf = &popup_draw_surf;
@@ -1046,9 +1018,6 @@ main(int argc, char **argv)
die("virtual_keyboard_manager not available\n");
}
// A second round-trip to receive wl_outputs events
wl_display_roundtrip(display);
empty_region = wl_compositor_create_region(compositor);
popup_xdg_positioner = xdg_wm_base_create_positioner(wm_base);

76
wvkbd.1 Normal file
View File

@@ -0,0 +1,76 @@
.TH "wvkbd" "1" "2022-03-12"
.P
.SH NAME
.P
wvkbd - on-screen keyboard for wlroots
.P
.SH SYNOPSIS
.P
wvkbd-mobintl [OPTION]...
.P
.SH DESCRIPTION
.P
wvkbd is an on-screen keyboard for wlroots that sucks less.
.P
.SH OPTIONS
.P
\fB-D\fR
.RS 4
enable debug
.P
.RE
\fB-o\fR
.RS 4
print pressed keys to standard output
.P
.RE
\fB-O\fR
.RS 4
print intersected keys to standard output
.P
.RE
\fB-l\fR
.RS 4
comma separated list of layers
.P
.RE
\fB--landscape-layers\fR
.RS 4
comma separated list of layers used in landscape mode
.P
.RE
\fB-H\fR \fIPX\fR
.RS 4
height in pixels
.P
.RE
\fB-L\fR \fIPX\fR
.RS 4
landscape height in pixels
.P
.RE
\fB--fn\fR \fIFONT\fR
.RS 4
set font (e.g: DejaVu Sans 20)
.P
.RE
\fB--hidden\fR
.RS 4
start hidden (send SIGUSR2 to show, SIGUSR1 to hide, SIGRTMIN to toggle)
.P
.RE
\fB-v\fR, \fB--version\fR
.RS 4
print version
.P
.RE
\fB-h\fR, \fB--help\fR
.RS 4
show help
.P
.RE
.SH AUTHORS
.P
Created by John Sullivan <jsullivan@csumb.edu>, maintained by the Sxmo project in
collaboration with other open source contributors. For more information about wvkbd development, see
<https://git.sr.ht/~proycon/wvkbd> or <https://github.com/jjsullivan5196/wvkbd>.

View File

@@ -1,129 +0,0 @@
wvkbd(1)
# NAME
wvkbd - on-screen virtual keyboard for wayland compositors using wlroots
# SYNOPSIS
wvkbd-mobintl [OPTIONS]...
*NOTE*: Your binary may have a different suffix depending on which layout you compiled.
# DESCRIPTION
This project aims to deliver a minimal but practically usable implementation of
a wlroots on-screen keyboard in legible C. This will _only_ be a keyboard, not
a feedback buzzer, led blinker, or anything that requires more than what's
needed to input text quickly. The end product should be a static codebase that
can be patched to add new features.
## OPTIONS
*-D*
enable debug mode.
*-o*
print pressed keys to standard output.
*-O*
print intersected keys to standard output.
*-l* _layers_
comma separated list of layers in vertical/portrait mode.
*--landscape-layers* _layers_
comma separated list of layers used in horizontal/landscape mode.
*--list-layers*
prints a list of all available layers.
*-H* _pixels_
Height of the keyboard in pixels, for vertical/portrait mode.
*-L* _pixels_
Height of the keyboard in pixels, for horizontal/landscape mode
*--fn* _font_
set font and size (e.g. DejaVu Sans 20)
*--hidden*
Start hidden (send SIGUSR2 to show).
*--alpha* _int_
Set alpha value (i.e. transparency) for all colors [0-255]
*--bg* _rrggbb|aa_
Set color of background
*--fg* _rrggbb|aa_
Set color of keys
*--fg-sp* _rrggbb|aa_
Set color of special keys
*--press* _rrggbb|aa_
Set color of pressed keys
*--press-sp* _rrggbb|aa_
Set color of pressed special keys
*--swipe* _rrggbb|aa_
Set color of swiped keys
*--swipe-sp* _rrggbb|aa_
Set color of swiped special keys
*--text* _rrggbb|aa_
Set color text on keys
*--text-sp* _rrggbb|aa_
Set color text on special keys
*--version*
Print version information
*-h*, *--help*
Print usage help
# SIGNALS
You can send signals to wvkbd to hide/show it (e.g. using _kill_(1) with _-s_):
*SIGUSR1*
Hide the keyboard.
*SIGUSR2*
Show the keyboard
*SIGRTMIN*
Toggle visibility
# COMPOSE BUTTON
The default mobile international layout features a Compose button (*Cmp*)
which, when combined with another key, opens up a layout that offers variants
for that key. This is similar to functionality that other keyboards implemented
using a *long press* (wvkbd has no such notion, holding a key will repeat
it like on a physical keyboard).
For example, press Cmp + a to access variants with diacritics like á,à,â,ä, etc..
Most layouts also feature the following that are less obvious:
- Press Cmp and . to access more punctuation
- Press Cmp and - or , to access 'mathematical' symbols (+,-,=,etc)
- Press Cmp and ' or 0 or 9 to access more brackets and quotes
- Press Cmp and q to access emojis
Last, but not least, pressing Cmp + space or Cmp + ⌨ or Cmp + Abc opens up an
index that allows you to immediately jump to any layout by name, even layouts
not explicitly added to your layers on startup.
# AUTHORS
Created by John Sullivan <jsullivan@csumb.edu>, maintained by the Sxmo project
<https://sxmo.org> in collaboration with other open source contributors. For
more information about wvkbd development, see <https://git.sr.ht/~proycon/wvkbd>
or <https://github.com/jjsullivan5196/wvkbd>.