31 Commits
v0.5 ... v0.8.1

Author SHA1 Message Date
97fad52ee9 version bump 2022-06-17 19:54:31 +02:00
c3afabcdce Added manpage to Makefile and updated manpage 2022-06-17 19:52:23 +02:00
cc81e74997 version bump 2022-06-14 00:23:11 +02:00
11d6924a13 Draw compose key as pressed when compose is enabled
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-06-14 00:21:28 +02:00
7be30a6a56 Check for surface in display_handle_geometry
Fixes #23

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-06-14 00:10:31 +02:00
94ca075563 reran clang-format 2022-06-13 23:05:14 +02:00
88bbdb0c64 Add some math and punctiation symbols from simple grid 2022-06-13 22:47:25 +02:00
6ab0361d80 Replace , to - in simple layout 2022-06-13 22:47:13 +02:00
c8bd29ecd1 Use a simple transparency value 2022-06-13 22:42:13 +02:00
aa258a01dd Reverse nav backspace and whitespace 2022-06-13 22:41:52 +02:00
e6c7d0ff2a main.c: add a real-time signal for toggling visibility of the keyboard
Previously it was only possible to either show or hide the keyboard.
When you want to control the keyboard with a single button in, i.e.
a window manager, this requires a separate script to keep track of
state. This solves this by only needing one signal to toggle.

Since there are only 2 USR signals, I had to use real-time signals,
which are in the [POSIX
standard](https://standards.ieee.org/standard/1003_1b-1993.html) and
available in the [Linux kernel since
2.2](https://www.man7.org/linux/man-pages/man7/signal.7.html).
2022-06-13 22:18:03 +02:00
07b9f293c0 Add documentation for using the real-time signal 2022-06-13 22:17:15 +02:00
1b7f5c4968 Change in maintainership: support both sourcehut and the original github 2022-06-13 22:00:11 +02:00
0a680c0a7a More symbols and layout improvement 2022-06-13 21:58:26 +02:00
a8ba3c02a9 Modern Greek keyboard added 2022-06-13 21:58:19 +02:00
b77f0582fc Add Persian layout 2022-06-13 21:58:09 +02:00
35ac0d1d72 Include LDFLAGS from the environment
While working on packageing wvkbd for the aur, I got a warning from
namcap (an arch package verification tool) that RELRO wasn't enabled.
From what I can tell, this is because make was ignoring the LDFLAGS set
by makepkg.
2022-06-13 21:57:55 +02:00
718d2bdff3 update README.md 2022-06-13 21:57:43 +02:00
fc0da6aa18 add man page 2022-06-13 21:57:10 +02:00
c27f876634 main: prevent crash on sigpipe
This is commonly caused by a bad program in the output chain, e.g.

wvkbd -O | false
2022-06-13 21:56:49 +02:00
f74fe9a182 layout.mobintl.h: fix hungarian ő and Ő characters
Before this, the bigger one was typed for pressing the smaller,
and vica versa.
2022-06-13 21:56:35 +02:00
de4b4dcd2e layout.mobintl.h: fix same big/little issue for ų 2022-06-13 21:56:23 +02:00
849f4600e9 project: rerun clang-format
TODO make a commit or PR hook for this
2022-06-13 21:55:47 +02:00
78d2667818 config: update version number 2022-06-13 21:55:32 +02:00
905a0d100a version: Output newline 2022-06-13 21:55:15 +02:00
aa65896fbf keyboard.c: fix update/draw logic in kbd_unpress_key
thanks @0x4261756D @earboxer for pointing out this issue
2022-01-09 21:02:46 -08:00
bddf05e0fc key drawing: refactor kbd_draw_key 2022-01-10 03:08:06 +00:00
564eb4536a overlapped key output: highlight letters swiped through 2022-01-10 03:08:06 +00:00
2de12a90e4 output: add -O flag to output overlapped keys
the use-case for this is simple 'swipe'-typing:
another program can take the output, guess the word which is being typed, and type the rest of the word
2022-01-10 03:08:06 +00:00
c541c7dbd6 add Georgian layout 2022-01-08 07:53:34 +00:00
780a83dba5 Fixed erroneous glyphcodes for turkish dotless i and turkish capital I with dot 2022-01-08 07:48:49 +00:00
12 changed files with 4910 additions and 89 deletions

View File

@ -3,6 +3,7 @@ include config.mk
NAME=wvkbd NAME=wvkbd
BIN=${NAME}-${LAYOUT} BIN=${NAME}-${LAYOUT}
SRC=. SRC=.
MAN1 = ${NAME}.1
PKGS = wayland-client xkbcommon pangocairo PKGS = wayland-client xkbcommon pangocairo
@ -11,7 +12,7 @@ WVKBD_HEADERS += $(wildcard $(SRC)/*.h)
CFLAGS += -std=gnu99 -Wall -g -DWITH_WAYLAND_SHM -DLAYOUT=\"layout.${LAYOUT}.h\" -DKEYMAP=\"keymap.${LAYOUT}.h\" CFLAGS += -std=gnu99 -Wall -g -DWITH_WAYLAND_SHM -DLAYOUT=\"layout.${LAYOUT}.h\" -DKEYMAP=\"keymap.${LAYOUT}.h\"
CFLAGS += $(shell pkg-config --cflags $(PKGS)) CFLAGS += $(shell pkg-config --cflags $(PKGS))
LDFLAGS =$(shell pkg-config --libs $(PKGS)) -lm -lutil -lrt LDFLAGS += $(shell pkg-config --libs $(PKGS)) -lm -lutil -lrt
WAYLAND_HEADERS = $(wildcard proto/*.xml) WAYLAND_HEADERS = $(wildcard proto/*.xml)
@ -47,3 +48,5 @@ install: all
mkdir -p ${DESTDIR}${PREFIX}/bin mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${NAME}-${LAYOUT} ${DESTDIR}${PREFIX}/bin cp -f ${NAME}-${LAYOUT} ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}-${LAYOUT} chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}-${LAYOUT}
sed "s/VERSION/${VERSION}/g" < ${MAN1} > ${DESTDIR}${MANPREFIX}/man1/${MAN1}
chmod 644 ${DESTDIR}${MANPREFIX}/man1/${MAN1}

View File

@ -21,7 +21,7 @@ new features.
- Support for 'Copy' keys which are not on the keymap - Support for 'Copy' keys which are not on the keymap
- Emoji support - Emoji support
- Compose key for character variants (e.g. diacritics) - Compose key for character variants (e.g. diacritics)
- Show/hide keyboard on signals (SIGUSR1 = hide, SIGUSR2 = show) - Show/hide keyboard on signals (SIGUSR1 = hide, SIGUSR2 = show, SIGRTMIN = toggle)
- Automatic portrait/landscape detection and subsequent layout switching - Automatic portrait/landscape detection and subsequent layout switching
@ -37,7 +37,8 @@ There are some areas that still need work:
You'll need the following developer packages You'll need the following developer packages
- pangocairo - cairo
- pango
- wayland-client - wayland-client
- xkbcommon - xkbcommon
@ -46,7 +47,7 @@ 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 The default set of layouts is called `mobintl` *(mobile international)*, which groups various layouts aimed at mobile devices
and also attempts to accommodate various international users. The resulting binary is called `wvkbd-mobintl`. and also attempts to accommodate various international users. The resulting binary is called `wvkbd-mobintl`.
You can, however, define your own layouts by copying and and modifying `layout.mobintl.h` and `keymap.mobintl.h` You can, however, define your own layouts by copying and modifying `layout.mobintl.h` and `keymap.mobintl.h`
(replace `mobintl` for something like `yourlayout`). Then make your layout set using `make LAYOUT=yourlayout`, and (replace `mobintl` for something like `yourlayout`). Then make your layout set using `make LAYOUT=yourlayout`, and
the resulting binary will be `wvkbd-yourlayout` the resulting binary will be `wvkbd-yourlayout`
@ -59,27 +60,39 @@ want a subset of the available layers, you can define which wants you want and i
them using the `-l` parameter. This takes takes a ordered comma separated list of them using the `-l` parameter. This takes takes a ordered comma separated list of
layout names that are defined in your layout set. layout names that are defined in your layout set.
The keyboard can be hidden by sending it a `SIGUSR1` signal and shown again by sending it `SIGUSR2`. This saves some The keyboard can be hidden by sending it a `SIGUSR1` signal, shown again by sending it `SIGUSR2` or toggled by sending it `SIGRTMIN`.
start up time and may be appropriate in some low-resource environments. This saves some start up time and may be appropriate in some low-resource environments.
Wvkbd has an output mode `-o` that will echo its output to standard output. This facility can be used if users want Wvkbd has an output mode `-o` that will echo its output to standard output. This facility can be used if users want
audio/haptic feedback, a feature explicitly out of scope for wvkbd. To achieve this, simply pipe wvkbd's output through the external tool audio/haptic feedback, a feature explicitly out of scope for wvkbd. To achieve this, simply pipe wvkbd's output through the external tool
[clickclack](https://git.sr.ht/~proycon/clickclack): [clickclack](https://git.sr.ht/~proycon/clickclack):
`$ wvkbd-mobileintl -l simple,special,emoji -o | clickclack -V -f keypress.wav` `$ wvkbd-mobintl -l simple,special,emoji -o | clickclack -V -f keypress.wav`
Another output mode, `-O` will let the keyboard output keys which are swiped over. It can be used by an external program, such as [swipeGuess](https://git.sr.ht/~earboxer/swipeGuess) to get swipe-typing support.
`$ wvkbd-mobintl -O | swipeGuess.sh words.txt | completelyTypeWord.sh`
## Contribute ## Contribute
Any contributions are welcome, please tell me what I did wrong in issues or Any contributions are welcome, there are two ways to contribute, the first one is **preferred**:
PRs. I could also use some nice branding if that tickles your fancy.
For code contributions, all I ask for now is you run `make format` (requires 1. [Sourcehut](https://git.sr.ht/~proycon/wvkbd) - Submit your patches using `git mail` to [~mil/sxmo-devel@lists.sr.ht](mailto:~mil/sxmo-devel@lists.sr.ht), follow [these contribution guidelines](https://sxmo.org/contribute/). Questions can also be asked on Sxmo's [mailing lists](https://sxmo.org/support/).
`clang-format`) before opening a PR and include as much relevant detail as 2. [Github](https://github.com/jjsullivan5196/wvkbd/) - Submit a pull request or open an issue *(legacy method)*
This project was started by [John Sullivan](https://jsullivan.cc/) and is
currently being maintained by the [Sxmo](https://sxmo.org) project, whose
maintainers will ensure both git remotes are kept in sync at all times.
For code contributions, please run `make format` (requires `clang-format`)
before sending a patch (opening a PR) and include as much relevant detail as
possible. possible.
## Related projects ## Related projects
* [clickclack](https://git.sr.ht/~proycon/clickclack) - Audio/haptic feedback (standalone) * [clickclack](https://git.sr.ht/~proycon/clickclack) - Audio/haptic feedback (standalone)
* [swipeGuess](https://git.sr.ht/~earboxer/swipeGuess) - Word-completion for swipe-typing
* [Sxmo](https://sxmo.org) - A hackable mobile interface environment for Linux phones that adopted wvkbd as its keyboard * [Sxmo](https://sxmo.org) - A hackable mobile interface environment for Linux phones that adopted wvkbd as its keyboard
* [svkbd](https://tools.suckless.org/x/svkbd/) - A similar project as wvkbd but for X11 rather than Wayland * [svkbd](https://tools.suckless.org/x/svkbd/) - A similar project as wvkbd but for X11 rather than Wayland
* [squeekboard](https://gitlab.gnome.org/World/Phosh/squeekboard) - The virtual keyboard developed for the Librem5 (used * [squeekboard](https://gitlab.gnome.org/World/Phosh/squeekboard) - The virtual keyboard developed for the Librem5 (used

View File

@ -2,33 +2,37 @@
#define config_def_h_INCLUDED #define config_def_h_INCLUDED
static const char *default_font = "Monospace 14"; static const char *default_font = "Monospace 14";
static const int transparency = 225;
struct clr_scheme scheme = { struct clr_scheme scheme = {
/* colors */ /* colors */
.bg = {.bgra = {15, 15, 15, 225}}, .bg = {.bgra = {15, 15, 15, transparency}},
.fg = {.bgra = {45, 45, 45, 225}}, .fg = {.bgra = {45, 45, 45, transparency}},
.high = {.bgra = {100, 100, 100, 225}}, .high = {.bgra = {100, 100, 100, transparency}},
.swipe = {.bgra = {100, 255, 100, 64}},
.text = {.color = UINT32_MAX}, .text = {.color = UINT32_MAX},
}; };
struct clr_scheme scheme1 = { struct clr_scheme scheme1 = {
/* colors */ /* colors */
.bg = {.bgra = {15, 15, 15, 225}}, .bg = {.bgra = {15, 15, 15, transparency}},
.fg = {.bgra = {32, 32, 32, 225}}, .fg = {.bgra = {32, 32, 32, transparency}},
.high = {.bgra = {100, 100, 100, 225}}, .high = {.bgra = {100, 100, 100, transparency}},
.swipe = {.bgra = {100, 255, 100, 64}},
.text = {.color = UINT32_MAX}, .text = {.color = UINT32_MAX},
}; };
/* layers is an ordered list of layouts, used to cycle through */ /* layers is an ordered list of layouts, used to cycle through */
static enum layout_id layers[] = { static enum layout_id layers[] = {
Full, // First layout is the default layout on startup Full, // First layout is the default layout on startup
Special, Emoji, Simple, SimpleGrid, Nav, Dialer, Cyrillic, Arabic, Special, Emoji, Simple, SimpleGrid, Nav, Dialer,
Cyrillic, Arabic, Persian, Greek, Georgian,
NumLayouts // signals the last item, may not be omitted NumLayouts // signals the last item, may not be omitted
}; };
/* layers is an ordered list of layouts, used to cycle through */ /* layers is an ordered list of layouts, used to cycle through */
static enum layout_id landscape_layers[] = { static enum layout_id landscape_layers[] = {
Landscape, // First layout is the default layout on startup Landscape, // First layout is the default layout on startup
Special, Emoji, Nav, Special, Emoji, Nav, Greek,
NumLayouts // signals the last item, may not be omitted NumLayouts // signals the last item, may not be omitted
}; };

View File

@ -1,3 +1,5 @@
VERSION = 0.2 VERSION = 0.8.1
CFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=700 CFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=700
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
LAYOUT = mobintl LAYOUT = mobintl

20
drw.c
View File

@ -69,11 +69,15 @@ drw_draw_text(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
} }
void void
drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y, drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h) { uint32_t w, uint32_t h, bool over) {
cairo_save(d->cairo); cairo_save(d->cairo);
if (over) {
cairo_set_operator(d->cairo, CAIRO_OPERATOR_OVER);
} else {
cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE); cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE);
}
cairo_rectangle(d->cairo, x, y, w, h); cairo_rectangle(d->cairo, x, y, w, h);
cairo_set_source_rgba( cairo_set_source_rgba(
@ -86,6 +90,18 @@ drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
wl_surface_damage(d->surf, x, y, w, h); wl_surface_damage(d->surf, x, y, w, h);
} }
void
drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h) {
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) {
drw_do_rectangle(d, color, x, y, w, h, true);
}
uint32_t uint32_t
setup_buffer(struct drwsurf *drwsurf) { setup_buffer(struct drwsurf *drwsurf) {
int stride = drwsurf->width * 4; int stride = drwsurf->width * 4;

4
drw.h
View File

@ -31,8 +31,12 @@ typedef union {
uint32_t color; uint32_t color;
} Color; } Color;
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, void drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h); 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 *d, 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, const char *label); uint32_t w, uint32_t h, const char *label);

View File

@ -166,8 +166,16 @@ kbd_get_key(struct kbd *kb, uint32_t x, uint32_t y) {
void void
kbd_unpress_key(struct kbd *kb, uint32_t time) { kbd_unpress_key(struct kbd *kb, uint32_t time) {
bool unlatch_shift = false;
if (kb->last_press) { if (kb->last_press) {
kbd_draw_key(kb, kb->last_press, false); unlatch_shift = (kb->mods & Shift) == Shift;
if (unlatch_shift) {
kb->mods ^= Shift;
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
}
if (kb->last_press->type == Copy) { if (kb->last_press->type == Copy) {
zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key
WL_KEYBOARD_KEY_STATE_RELEASED); WL_KEYBOARD_KEY_STATE_RELEASED);
@ -175,17 +183,52 @@ kbd_unpress_key(struct kbd *kb, uint32_t time) {
zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code, zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
WL_KEYBOARD_KEY_STATE_RELEASED); WL_KEYBOARD_KEY_STATE_RELEASED);
} }
kb->last_press = NULL;
if (kb->compose >= 2) { if (kb->compose >= 2) {
kb->compose = 0; kb->compose = 0;
kbd_switch_layout(kb, kb->prevlayout); kbd_switch_layout(kb, kb->prevlayout);
if ((kb->mods & Shift) == Shift) } else if (unlatch_shift) {
kb->mods ^= Shift;
} else if ((kb->mods & Shift) == Shift) {
kb->mods ^= Shift;
kbd_draw_layout(kb); kbd_draw_layout(kb);
} else {
kbd_draw_key(kb, kb->last_press, Unpress);
} }
kb->last_press = NULL;
}
}
void
kbd_release_key(struct kbd *kb, uint32_t time) {
kbd_unpress_key(kb, time);
if (kb->print_intersect && kb->last_swipe) {
printf("\n");
// Important so autocompleted words get typed in time
fflush(stdout);
kbd_draw_layout(kb);
kb->last_swipe = NULL;
}
}
void
kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y) {
// Output intersecting keys
// (for external 'swiping'-based accelerators).
if (kb->print_intersect) {
if (kb->last_press) {
kbd_unpress_key(kb, time);
// Redraw last press as a swipe.
kbd_draw_key(kb, kb->last_swipe, Swipe);
}
struct key *intersect_key;
intersect_key = kbd_get_key(kb, x, y);
if (intersect_key &&
(!kb->last_swipe || intersect_key->label != kb->last_swipe->label)) {
kbd_print_key_stdout(kb, intersect_key);
kb->last_swipe = intersect_key;
kbd_draw_key(kb, kb->last_swipe, Swipe);
}
} else {
kbd_unpress_key(kb, time);
} }
} }
@ -212,11 +255,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
} else { } else {
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
} }
kb->last_press = k; kb->last_swipe = kb->last_press = k;
kbd_draw_key(kb, k, true); kbd_draw_key(kb, k, Press);
zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code, zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
WL_KEYBOARD_KEY_STATE_PRESSED); WL_KEYBOARD_KEY_STATE_PRESSED);
if (kb->print) if (kb->print || kb->print_intersect)
kbd_print_key_stdout(kb, k); kbd_print_key_stdout(kb, k);
if (kb->compose) { if (kb->compose) {
if (kb->debug) if (kb->debug)
@ -229,7 +272,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
if (k->code == Shift) { if (k->code == Shift) {
kbd_draw_layout(kb); kbd_draw_layout(kb);
} }
kbd_draw_key(kb, k, kb->mods & k->code); if (kb->mods & k->code) {
kbd_draw_key(kb, k, Press);
} else {
kbd_draw_key(kb, k, Unpress);
}
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
break; break;
case Layout: case Layout:
@ -243,7 +290,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
} else { } else {
kb->compose = 0; kb->compose = 0;
} }
kbd_draw_key(kb, k, (bool)kb->compose); if ((bool)kb->compose) {
kbd_draw_key(kb, k, Press);
} else {
kbd_draw_key(kb, k, Unpress);
}
break; break;
case NextLayer: case NextLayer:
// switch to the next layout in the layer sequence // switch to the next layout in the layer sequence
@ -271,15 +322,15 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
break; break;
case Copy: case Copy:
// copy code as unicode chr by setting a temporary keymap // copy code as unicode chr by setting a temporary keymap
kb->last_press = k; kb->last_swipe = kb->last_press = k;
kbd_draw_key(kb, k, true); kbd_draw_key(kb, k, Press);
if (kb->debug) if (kb->debug)
fprintf(stderr, "pressing copy key\n"); fprintf(stderr, "pressing copy key\n");
create_and_upload_keymap(kb, kb->layout->keymap_name, k->code, k->code_mod); create_and_upload_keymap(kb, kb->layout->keymap_name, k->code, k->code_mod);
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0); zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key
WL_KEYBOARD_KEY_STATE_PRESSED); WL_KEYBOARD_KEY_STATE_PRESSED);
if (kb->print) if (kb->print || kb->print_intersect)
kbd_print_key_stdout(kb, k); kbd_print_key_stdout(kb, k);
break; break;
default: default:
@ -327,15 +378,24 @@ kbd_print_key_stdout(struct kbd *kb, struct key *k) {
} }
void void
kbd_draw_key(struct kbd *kb, struct key *k, bool pressed) { kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type) {
struct drwsurf *d = kb->surf; struct drwsurf *d = kb->surf;
const char *label = (kb->mods & Shift) ? k->shift_label : k->label; const char *label = (kb->mods & Shift) ? k->shift_label : k->label;
if (kb->debug) if (kb->debug)
fprintf(stderr, "Draw key +%d+%d %dx%d -> %s\n", k->x, k->y, k->w, k->h, fprintf(stderr, "Draw key +%d+%d %dx%d -> %s\n", k->x, k->y, k->w, k->h,
label); label);
struct clr_scheme *scheme = (k->scheme == 0) ? &(kb->scheme) : &(kb->scheme1); struct clr_scheme *scheme = (k->scheme == 0) ? &(kb->scheme) : &(kb->scheme1);
Color *fill = pressed ? &scheme->high : &scheme->fg; switch (type) {
draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, *fill); case Unpress:
draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->fg);
break;
case Press:
draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->high);
break;
case Swipe:
draw_over_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->swipe);
break;
}
drw_draw_text(d, scheme->text, k->x, k->y, k->w, k->h, label); drw_draw_text(d, scheme->text, k->x, k->y, k->w, k->h, label);
} }
@ -343,7 +403,6 @@ void
kbd_draw_layout(struct kbd *kb) { kbd_draw_layout(struct kbd *kb) {
struct drwsurf *d = kb->surf; struct drwsurf *d = kb->surf;
struct key *next_key = kb->layout->keys; struct key *next_key = kb->layout->keys;
bool pressed = false;
if (kb->debug) if (kb->debug)
fprintf(stderr, "Draw layout"); fprintf(stderr, "Draw layout");
@ -354,8 +413,12 @@ kbd_draw_layout(struct kbd *kb) {
next_key++; next_key++;
continue; continue;
} }
pressed = next_key->type == Mod && kb->mods & next_key->code; if ((next_key->type == Mod && kb->mods & next_key->code) ||
kbd_draw_key(kb, next_key, pressed); (next_key->type == Compose && kb->compose)) {
kbd_draw_key(kb, next_key, Press);
} else {
kbd_draw_key(kb, next_key, Unpress);
}
next_key++; next_key++;
} }
} }
@ -380,6 +443,12 @@ draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
drw_fill_rectangle(ds, color, x + border, y + border, width - border, drw_fill_rectangle(ds, color, x + border, y + border, width - border,
height - border); height - border);
} }
void
draw_over_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint32_t border, Color color) {
drw_over_rectangle(ds, color, x + border, y + border, width - border,
height - border);
}
void void
create_and_upload_keymap(struct kbd *kb, const char *name, uint32_t comp_unichr, create_and_upload_keymap(struct kbd *kb, const char *name, uint32_t comp_unichr,

View File

@ -41,10 +41,17 @@ enum key_modifier_type {
AltGr = 128, AltGr = 128,
}; };
enum key_draw_type {
Unpress = 0,
Press,
Swipe,
};
struct clr_scheme { struct clr_scheme {
Color fg; Color fg;
Color bg; Color bg;
Color high; Color high;
Color swipe;
Color text; Color text;
}; };
@ -85,11 +92,13 @@ struct kbd {
struct clr_scheme scheme1; struct clr_scheme scheme1;
bool print; bool print;
bool print_intersect;
uint32_t w, h, s; uint32_t w, h, s;
bool landscape; bool landscape;
uint8_t mods; uint8_t mods;
uint8_t compose; uint8_t compose;
struct key *last_press; struct key *last_press;
struct key *last_swipe;
struct layout *prevlayout; struct layout *prevlayout;
size_t layer_index; size_t layer_index;
@ -103,14 +112,18 @@ struct kbd {
void draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width, void draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
uint32_t height, uint32_t border, Color color); 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);
void kbd_init(struct kbd *kb, struct layout *layouts, char *layer_names_list); void kbd_init(struct kbd *kb, struct layout *layouts, char *layer_names_list);
void kbd_init_layout(struct layout *l, uint32_t width, uint32_t height); void kbd_init_layout(struct layout *l, uint32_t width, uint32_t height);
struct key *kbd_get_key(struct kbd *kb, uint32_t x, uint32_t y); struct key *kbd_get_key(struct kbd *kb, uint32_t x, uint32_t y);
void kbd_unpress_key(struct kbd *kb, uint32_t time); void kbd_unpress_key(struct kbd *kb, uint32_t time);
void kbd_release_key(struct kbd *kb, uint32_t time);
void kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y);
void kbd_press_key(struct kbd *kb, struct key *k, uint32_t time); void kbd_press_key(struct kbd *kb, struct key *k, uint32_t time);
void kbd_print_key_stdout(struct kbd *kb, struct key *k); void kbd_print_key_stdout(struct kbd *kb, struct key *k);
void kbd_draw_key(struct kbd *kb, struct key *k, bool pressed); void kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type);
void kbd_draw_layout(struct kbd *kb); void kbd_draw_layout(struct kbd *kb);
void kbd_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount); void kbd_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount);
uint8_t kbd_get_rows(struct layout *l); uint8_t kbd_get_rows(struct layout *l);

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,4 @@
/* constants */ /* constants */
/* how tall the keyboard should be by default (can be overriden) */ /* how tall the keyboard should be by default (can be overriden) */
#define KBD_PIXEL_HEIGHT 240 #define KBD_PIXEL_HEIGHT 240
@ -21,6 +20,9 @@ enum layout_id {
Dialer, Dialer,
Cyrillic, Cyrillic,
Arabic, Arabic,
Persian,
Greek,
Georgian,
Emoji, Emoji,
Nav, Nav,
Landscape, Landscape,
@ -66,18 +68,19 @@ enum layout_id {
}; };
static struct key keys_full[], keys_special[], keys_simple[], keys_simplegrid[], static struct key keys_full[], keys_special[], keys_simple[], keys_simplegrid[],
keys_cyrillic[], keys_arabic[], keys_emoji[], keys_nav[], keys_landscape[], keys_cyrillic[], keys_arabic[], keys_persian[], keys_georgian[], keys_greek[],
keys_compose_a[], keys_compose_e[], keys_compose_y[], keys_compose_u[], keys_emoji[], keys_nav[], keys_landscape[], keys_compose_a[],
keys_compose_i[], keys_compose_o[], keys_compose_w[], keys_compose_r[], keys_compose_e[], keys_compose_y[], keys_compose_u[], keys_compose_i[],
keys_compose_t[], keys_compose_p[], keys_compose_s[], keys_compose_d[], keys_compose_o[], keys_compose_w[], keys_compose_r[], keys_compose_t[],
keys_compose_f[], keys_compose_g[], keys_compose_h[], keys_compose_j[], keys_compose_p[], keys_compose_s[], keys_compose_d[], keys_compose_f[],
keys_compose_k[], keys_compose_l[], keys_compose_z[], keys_compose_x[], keys_compose_g[], keys_compose_h[], keys_compose_j[], keys_compose_k[],
keys_compose_c[], keys_compose_v[], keys_compose_b[], keys_compose_n[], keys_compose_l[], keys_compose_z[], keys_compose_x[], keys_compose_c[],
keys_compose_m[], keys_compose_math[], keys_compose_punctuation[], keys_compose_v[], keys_compose_b[], keys_compose_n[], keys_compose_m[],
keys_compose_bracket[], keys_compose_cyr_i[], keys_compose_cyr_j[], keys_compose_math[], keys_compose_punctuation[], keys_compose_bracket[],
keys_compose_cyr_e[], keys_compose_cyr_u[], keys_compose_cyr_l[], keys_compose_cyr_i[], keys_compose_cyr_j[], keys_compose_cyr_e[],
keys_compose_cyr_n[], keys_compose_cyr_tse[], keys_compose_cyr_che[], keys_compose_cyr_u[], keys_compose_cyr_l[], keys_compose_cyr_n[],
keys_compose_cyr_g[], keys_compose_cyr_k[], keys_dialer[]; keys_compose_cyr_tse[], keys_compose_cyr_che[], keys_compose_cyr_g[],
keys_compose_cyr_k[], keys_dialer[];
static struct layout layouts[NumLayouts] = { static struct layout layouts[NumLayouts] = {
[Full] = {keys_full, "latin", "full"}, // second parameter is the keymap name [Full] = {keys_full, "latin", "full"}, // second parameter is the keymap name
@ -88,6 +91,9 @@ static struct layout layouts[NumLayouts] = {
[Cyrillic] = {keys_cyrillic, "cyrillic", "cyrillic"}, [Cyrillic] = {keys_cyrillic, "cyrillic", "cyrillic"},
[Dialer] = {keys_dialer, "latin", "dialer"}, [Dialer] = {keys_dialer, "latin", "dialer"},
[Arabic] = {keys_arabic, "arabic", "arabic"}, [Arabic] = {keys_arabic, "arabic", "arabic"},
[Georgian] = {keys_georgian, "georgian", "georgian"},
[Persian] = {keys_persian, "persian", "persian"},
[Greek] = {keys_greek, "greek", "greek"},
[Emoji] = {keys_emoji, "latin", "emoji"}, [Emoji] = {keys_emoji, "latin", "emoji"},
[Nav] = {keys_nav, "latin", "nav"}, [Nav] = {keys_nav, "latin", "nav"},
[Landscape] = {keys_landscape, "latin", "landscape"}, [Landscape] = {keys_landscape, "latin", "landscape"},
@ -334,7 +340,7 @@ static struct key keys_simple[] = {
{"Abc", "Abc", 1.0, NextLayer, .scheme = 1}, {"Abc", "Abc", 1.0, NextLayer, .scheme = 1},
{"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1},
{",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, {"-", "_", 1.0, Code, KEY_MINUS, &layouts[ComposeMath]},
{"", "", 4.0, Code, KEY_SPACE}, {"", "", 4.0, Code, KEY_SPACE},
{".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, {".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1}, {"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
@ -409,7 +415,7 @@ static struct key keys_simplegrid[] = {
{"Abc", "Abc", 1.0, NextLayer, .scheme = 1}, {"Abc", "Abc", 1.0, NextLayer, .scheme = 1},
{"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1},
{",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, {"-", "_", 1.0, Code, KEY_MINUS, &layouts[ComposeMath]},
{"Cmp", "Cmp", 1.0, Compose, .scheme = 1}, {"Cmp", "Cmp", 1.0, Compose, .scheme = 1},
{"", "", 3.0, Code, KEY_SPACE}, {"", "", 3.0, Code, KEY_SPACE},
{".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, {".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]},
@ -548,6 +554,194 @@ static struct key keys_arabic[] = {
{"", "", 0.0, Last}, {"", "", 0.0, Last},
}; };
static struct key keys_georgian[] = {
{"1", "!", 1.0, Code, KEY_1},
{"2", "@", 1.0, Code, KEY_2},
{"3", "#", 1.0, Code, KEY_3},
{"4", ";", 1.0, Code, KEY_4},
{"5", "%", 1.0, Code, KEY_5},
{"6", ":", 1.0, Code, KEY_6},
{"7", "&", 1.0, Code, KEY_7},
{"8", "*", 1.0, Code, KEY_8},
{"9", "(", 1.0, Code, KEY_9},
{"0", ")", 1.0, Code, KEY_0},
{"", "", 0.0, EndRow},
{"", "Q", 1.0, Code, KEY_Q},
{"", "", 1.0, Code, KEY_W},
{"", "E", 1.0, Code, KEY_E},
{"", "", 1.0, Code, KEY_R},
{"", "", 1.0, Code, KEY_T},
{"", "Y", 1.0, Code, KEY_Y},
{"", "U", 1.0, Code, KEY_U},
{"", "I", 1.0, Code, KEY_I},
{"", "O", 1.0, Code, KEY_O},
{"", "P", 1.0, Code, KEY_P},
{"", "", 0.0, EndRow},
{"", "A", 1.0, Code, KEY_A},
{"", "", 1.0, Code, KEY_S},
{"", "D", 1.0, Code, KEY_D},
{"", "F", 1.0, Code, KEY_F},
{"", "G", 1.0, Code, KEY_G},
{"", "H", 1.0, Code, KEY_H},
{"", "", 1.0, Code, KEY_J},
{"", "K", 1.0, Code, KEY_K},
{"", "L", 1.0, Code, KEY_L},
{";", ":", 1.0, Code, KEY_SEMICOLON},
{"", "", 0.0, EndRow},
{"", "", 1.0, Code, KEY_Z},
{"", "X", 1.0, Code, KEY_X},
{"", "", 1.0, Code, KEY_C},
{"", "V", 1.0, Code, KEY_V},
{"", "B", 1.0, Code, KEY_B},
{"", "N", 1.0, Code, KEY_N},
{"", "M", 1.0, Code, KEY_M},
{",", "<", 1.0, Code, KEY_COMMA},
{".", ">", 1.0, Code, KEY_DOT},
{"", "", 1.0, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, NextLayer, .scheme = 1},
{"", "", 1.0, Mod, Shift, .scheme = 1},
{"Cmp", "Cmp", 1.0, Compose, .scheme = 1},
{"", "", 5.0, Code, KEY_SPACE},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
/* end of layout */
{"", "", 0.0, Last},
};
static struct key keys_persian[] = {
{"۱", "|", 1.0, Code, KEY_1},
{"۲", "٬", 1.0, Code, KEY_2},
{"۳", "#", 1.0, Code, KEY_3},
{"۴", "", 1.0, Code, KEY_4},
{"۵", "٪", 1.0, Code, KEY_5},
{"۶", "×", 1.0, Code, KEY_6},
{"۷", "/", 1.0, Code, KEY_7},
{"۸", "*", 1.0, Code, KEY_8},
{"۹", ")", 1.0, Code, KEY_9},
{"۰", "(", 1.0, Code, KEY_0},
{"-", "_", 1.0, Code, KEY_MINUS},
{"=", "+", 1.0, Code, KEY_EQUAL},
{"", "", 0.0, EndRow},
{"ض", "ﹿ", 1.0, Code, KEY_Q},
{"ص", "ـٌ", 1.0, Code, KEY_W},
{"ث", "ـٍ", 1.0, Code, KEY_E},
{"ق", "ـً", 1.0, Code, KEY_R},
{"ف", "ـُ", 1.0, Code, KEY_T},
{"غ", "ـِ", 1.0, Code, KEY_Y},
{"ع", "ـَ", 1.0, Code, KEY_U},
{"ه", "", 1.0, Code, KEY_I},
{"خ", "]", 1.0, Code, KEY_O},
{"ح", "[", 1.0, Code, KEY_P},
{"ج", "}", 1.0, Code, KEY_LEFTBRACE},
{"چ", "{", 1.0, Code, KEY_RIGHTBRACE},
{"", "", 0.0, EndRow},
{"ش", "ؤ", 1.0, Code, KEY_A},
{"س", "ئ", 1.0, Code, KEY_S},
{"ی", "ي", 1.0, Code, KEY_D},
{"ب", "إ", 1.0, Code, KEY_F},
{"ل", "أ", 1.0, Code, KEY_G},
{"ا", "آ", 1.0, Code, KEY_H},
{"ت", "ة", 1.0, Code, KEY_J},
{"ن", "»", 1.0, Code, KEY_K},
{"م", "«", 1.0, Code, KEY_L},
{"ک", ":", 1.0, Code, KEY_SEMICOLON},
{"گ", "؛", 1.0, Code, KEY_APOSTROPHE},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"ظ", "ك", 1.0, Code, KEY_Z},
{"ط", "ـٓ", 1.0, Code, KEY_X},
{"ژ", ">", 1.0, Code, KEY_BACKSLASH},
{"ز", "<", 1.0, Code, KEY_C},
{"ر", "ـٰ", 1.0, Code, KEY_V},
{"ذ", "", 1.0, Code, KEY_B},
{"د", "ـٔ", 1.0, Code, KEY_N},
{"پ", "ء", 1.0, Code, KEY_M},
{"و", "\\", 1.0, Code, KEY_COMMA},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, NextLayer, .scheme = 1},
{"Cmp", "Cmp", 1.0, Compose, .scheme = 1},
{".", "،", 1.0, Code, KEY_DOT},
{"", "", 4.0, Code, KEY_SPACE},
{"", "", 1.0, Code, KEY_GRAVE},
{"؟", "!", 1.0, Code, KEY_SLASH},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
/* end of layout */
{"", "", 0.0, Last},
};
static struct key keys_greek[] = {
{"1", "!", 1.0, Code, KEY_1},
{"2", "@", 1.0, Code, KEY_2},
{"3", "#", 1.0, Code, KEY_3},
{"4", "$", 1.0, Code, KEY_4},
{"5", "%", 1.0, Code, KEY_5},
{"6", "^", 1.0, Code, KEY_6},
{"7", "&", 1.0, Code, KEY_7},
{"8", "*", 1.0, Code, KEY_8},
{"9", "(", 1.0, Code, KEY_9},
{"0", ")", 1.0, Code, KEY_0},
{"-", "_", 1.0, Code, KEY_MINUS},
{"=", "+", 1.0, Code, KEY_EQUAL},
{"", "", 0.0, EndRow},
{";", ":", 1.0, Code, KEY_Q},
{"ς", "Σ", 1.0, Code, KEY_W},
{"ε", "Ε", 1.0, Code, KEY_E},
{"ρ", "Ρ", 1.0, Code, KEY_R},
{"τ", "Τ", 1.0, Code, KEY_T},
{"υ", "Υ", 1.0, Code, KEY_Y},
{"θ", "Θ", 1.0, Code, KEY_U},
{"ι", "Ι", 1.0, Code, KEY_I},
{"ο", "Ο", 1.0, Code, KEY_O},
{"π", "Π", 1.0, Code, KEY_P},
{"", "", 0.0, EndRow},
{"α", "A", 1.0, Code, KEY_A},
{"σ", "Σ", 1.0, Code, KEY_S},
{"δ", "Δ", 1.0, Code, KEY_D},
{"φ", "Φ", 1.0, Code, KEY_F},
{"γ", "Γ", 1.0, Code, KEY_G},
{"η", "Η", 1.0, Code, KEY_H},
{"ξ", "Ξ", 1.0, Code, KEY_J},
{"κ", "Κ", 1.0, Code, KEY_K},
{"λ", "Λ", 1.0, Code, KEY_L},
{"΄", "¨", 1.0, Code, KEY_SEMICOLON},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"ζ", "Ζ", 1.0, Code, KEY_Z},
{"χ", "Χ", 1.0, Code, KEY_X},
{"ψ", "Ψ", 1.0, Code, KEY_C},
{"ω", "Ω", 1.0, Code, KEY_V},
{"β", "Β", 1.0, Code, KEY_B},
{"ν", "Ν", 1.0, Code, KEY_N},
{"μ", "Μ", 1.0, Code, KEY_M},
{"/", "\\", 1.0, Code, KEY_SLASH},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.5, NextLayer, .scheme = 1},
{",", "'", 1.0, Code, KEY_COMMA},
{"", "", 5, Code, KEY_SPACE},
{".", "\"", 1.0, Code, KEY_DOT},
{"Enter", "Enter", 2, Code, KEY_ENTER, .scheme = 1},
/* end of layout */
{"", "", 0.0, Last},
};
static struct key keys_compose_a[] = { static struct key keys_compose_a[] = {
{"à", "À", 1.0, Copy, 0x00E0, 0, 0x00C0}, {"à", "À", 1.0, Copy, 0x00E0, 0, 0x00C0},
{"á", "Á", 1.0, Copy, 0x00E1, 0, 0x00C1}, {"á", "Á", 1.0, Copy, 0x00E1, 0, 0x00C1},
@ -635,7 +829,7 @@ static struct key keys_compose_u[] = {
{"ŭ", "Ŭ", 1.0, Copy, 0x016D, 0, 0x016C}, {"ŭ", "Ŭ", 1.0, Copy, 0x016D, 0, 0x016C},
{"ů", "Ů", 1.0, Copy, 0x016F, 0, 0x016E}, {"ů", "Ů", 1.0, Copy, 0x016F, 0, 0x016E},
{"ű", "Ű", 1.0, Copy, 0x0171, 0, 0x0170}, {"ű", "Ű", 1.0, Copy, 0x0171, 0, 0x0170},
{"ų", "Ų", 1.0, Copy, 0x0172, 0, 0x0173}, {"ų", "Ų", 1.0, Copy, 0x0173, 0, 0x0172},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"υ", "Υ", 1.0, Copy, 0x03C5, 0, 0x03A5}, {"υ", "Υ", 1.0, Copy, 0x03C5, 0, 0x03A5},
{"", "", 9.0, Pad}, {"", "", 9.0, Pad},
@ -662,7 +856,7 @@ static struct key keys_compose_o[] = {
{"ø", "Ø", 1.0, Copy, 0x00F8, 0, 0x00D8}, {"ø", "Ø", 1.0, Copy, 0x00F8, 0, 0x00D8},
{"ō", "Ō", 1.0, Copy, 0x014D, 0, 0x014C}, {"ō", "Ō", 1.0, Copy, 0x014D, 0, 0x014C},
{"ŏ", "Ŏ", 1.0, Copy, 0x014F, 0, 0x014E}, {"ŏ", "Ŏ", 1.0, Copy, 0x014F, 0, 0x014E},
{"ő", "Ő", 1.0, Copy, 0x0150, 0, 0x0151}, {"ő", "Ő", 1.0, Copy, 0x0151, 0, 0x0150},
{"œ", "Œ", 1.0, Copy, 0x0153, 0, 0x0152}, {"œ", "Œ", 1.0, Copy, 0x0153, 0, 0x0152},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"ο", "Ο", 1.0, Copy, 0x03BF, 0, 0x039F}, {"ο", "Ο", 1.0, Copy, 0x03BF, 0, 0x039F},
@ -691,8 +885,8 @@ static struct key keys_compose_i[] = {
{"ī", "Ī", 1.0, Copy, 0x012B, 0, 0x012A}, {"ī", "Ī", 1.0, Copy, 0x012B, 0, 0x012A},
{"ĭ", "Ĭ", 1.0, Copy, 0x012D, 0, 0x012C}, {"ĭ", "Ĭ", 1.0, Copy, 0x012D, 0, 0x012C},
{"į", "Į", 1.0, Copy, 0x012F, 0, 0x012E}, {"į", "Į", 1.0, Copy, 0x012F, 0, 0x012E},
{"ı", "I", 1.0, Copy, 0x0150, 0, 0x0049}, {"ı", "I", 1.0, Copy, 0x0131, 0, 0x0049},
{"i", "İ", 1.0, Copy, 0x0069, 0, 0x0152}, {"i", "İ", 1.0, Copy, 0x0069, 0, 0x0130},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"ι", "Ι", 1.0, Copy, 0x03B9, 0, 0x0399}, {"ι", "Ι", 1.0, Copy, 0x03B9, 0, 0x0399},
{"η", "Η", 1.0, Copy, 0x03B7, 0, 0x0397}, {"η", "Η", 1.0, Copy, 0x03B7, 0, 0x0397},
@ -759,7 +953,7 @@ static struct key keys_emoji[] = {
static struct key keys_nav[] = { static struct key keys_nav[] = {
{"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1}, {"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1},
{"", "", 1.0, Code, KEY_SPACE, .scheme = 1}, {"", "", 1.0, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 1.0, Code, KEY_UP, .scheme = 1}, {"", "", 1.0, Code, KEY_UP, .scheme = 1},
{"", "", 1.0, Code, KEY_PAGEUP, .scheme = 1}, {"", "", 1.0, Code, KEY_PAGEUP, .scheme = 1},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
@ -771,7 +965,7 @@ static struct key keys_nav[] = {
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"Sym", "Sym", 1.0, NextLayer, .scheme = 1}, {"Sym", "Sym", 1.0, NextLayer, .scheme = 1},
{"", "", 1.0, Code, KEY_BACKSPACE, .scheme = 1}, {"", "", 1.0, Code, KEY_SPACE, .scheme = 1},
{"", "", 1.0, Code, KEY_DOWN, .scheme = 1}, {"", "", 1.0, Code, KEY_DOWN, .scheme = 1},
{"", "", 1.0, Code, KEY_PAGEDOWN, .scheme = 1}, {"", "", 1.0, Code, KEY_PAGEDOWN, .scheme = 1},
{"", "", 0.0, Last}, {"", "", 0.0, Last},
@ -1433,17 +1627,17 @@ static struct key keys_compose_math[] = {
{"", "", 10.0, Pad}, {"", "", 10.0, Pad},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"", "", 2, Mod, Shift, .scheme = 1}, {"", "", 2, Mod, Shift, .scheme = 1},
{"-", "-", 1, Code, KEY_MINUS},
{"+", "+", 1, Code, KEY_EQUAL, 0, Shift}, {"+", "+", 1, Code, KEY_EQUAL, 0, Shift},
{"/", "/", 1, Code, KEY_SLASH}, {"/", "/", 1, Code, KEY_SLASH},
{"*", "*", 1, Code, KEY_8, 0, Shift}, {"*", "*", 1, Code, KEY_8, 0, Shift},
{"=", "=", 1, Code, KEY_EQUAL}, {"=", "=", 1, Code, KEY_EQUAL},
{"_", "_", 1, Code, KEY_MINUS, 0, Shift}, {"_", "_", 1, Code, KEY_MINUS, 0, Shift},
{"", "", 1, Copy, 0x2014, 0, 0x2014},
{"", "", 2, Pad}, {"", "", 2, Pad},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, BackLayer}, {"Abc", "Abc", 1.0, BackLayer},
{"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1},
{",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]}, {"-", "-", 1, Code, KEY_MINUS},
{"", "", 4.0, Code, KEY_SPACE}, {"", "", 4.0, Code, KEY_SPACE},
{".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]}, {".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1}, {"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
@ -1465,13 +1659,14 @@ static struct key keys_compose_punctuation[] = {
{"", "", 10.0, Pad}, {"", "", 10.0, Pad},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"", "", 2, Mod, Shift, .scheme = 1}, {"", "", 2, Mod, Shift, .scheme = 1},
{"", "", 1, Pad}, {"", "", 1, Copy, 0x2026, 0, 0x2026},
{":", ":", 1, Code, KEY_SEMICOLON, 0, Shift}, {":", ":", 1, Code, KEY_SEMICOLON, 0, Shift},
{";", ";", 1, Code, KEY_SEMICOLON, 0}, {";", ";", 1, Code, KEY_SEMICOLON, 0},
{"!", "!", 1, Code, KEY_1, 0, Shift}, {"!", "!", 1, Code, KEY_1, 0, Shift},
{"?", "?", 1, Code, KEY_DOT, 0, Shift}, {"?", "?", 1, Code, KEY_DOT, 0, Shift},
{",", ",", 1, Code, KEY_COMMA}, {",", ",", 1, Code, KEY_COMMA},
{"", "", 2, Pad}, {"·", "·", 1, Copy, 0x2027, 0, 0x2027},
{"", "", 1, Pad},
{"", "", 0.0, EndRow}, {"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, BackLayer}, {"Abc", "Abc", 1.0, BackLayer},
{"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1}, {"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1},

64
main.c
View File

@ -42,8 +42,10 @@ static uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
/* application state */ /* application state */
static bool run_display = true; static bool run_display = true;
static int cur_x = -1, cur_y = -1; static int cur_x = -1, cur_y = -1;
static bool cur_press = false;
static struct kbd keyboard; static struct kbd keyboard;
static uint32_t height, normal_height, landscape_height; static uint32_t height, normal_height, landscape_height;
static bool hidden = false;
/* event handler prototypes */ /* event handler prototypes */
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
@ -159,13 +161,18 @@ wl_touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial,
void void
wl_touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial, wl_touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial,
uint32_t time, int32_t id) { uint32_t time, int32_t id) {
kbd_unpress_key(&keyboard, time); kbd_release_key(&keyboard, time);
} }
void void
wl_touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time, wl_touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time,
int32_t id, wl_fixed_t x, wl_fixed_t y) { int32_t id, wl_fixed_t x, wl_fixed_t y) {
kbd_unpress_key(&keyboard, time); uint32_t touch_x, touch_y;
touch_x = wl_fixed_to_int(x);
touch_y = wl_fixed_to_int(y);
kbd_motion_key(&keyboard, time, touch_x, touch_y);
} }
void void
@ -199,18 +206,24 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
cur_x = wl_fixed_to_int(surface_x); cur_x = wl_fixed_to_int(surface_x);
cur_y = wl_fixed_to_int(surface_y); cur_y = wl_fixed_to_int(surface_y);
kbd_unpress_key(&keyboard, time); if (cur_press) {
kbd_motion_key(&keyboard, time, cur_x, cur_y);
}
} }
void void
wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state) { uint32_t time, uint32_t button, uint32_t state) {
struct key *next_key; struct key *next_key;
bool press = state == WL_POINTER_BUTTON_STATE_PRESSED; cur_press = state == WL_POINTER_BUTTON_STATE_PRESSED;
if (cur_press) {
kbd_unpress_key(&keyboard, time); kbd_unpress_key(&keyboard, time);
} else {
kbd_release_key(&keyboard, time);
}
if (press && cur_x >= 0 && cur_y >= 0) { if (cur_press && cur_x >= 0 && cur_y >= 0) {
next_key = kbd_get_key(&keyboard, cur_x, cur_y); next_key = kbd_get_key(&keyboard, cur_x, cur_y);
if (next_key) { if (next_key) {
kbd_press_key(&keyboard, next_key, time); kbd_press_key(&keyboard, next_key, time);
@ -258,10 +271,12 @@ display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
keyboard.layout = &keyboard.layouts[layer]; keyboard.layout = &keyboard.layouts[layer];
keyboard.prevlayout = keyboard.layout; keyboard.prevlayout = keyboard.layout;
if (layer_surface) {
zwlr_layer_surface_v1_set_size(layer_surface, 0, height); zwlr_layer_surface_v1_set_size(layer_surface, 0, height);
zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height); zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height);
wl_surface_commit(draw_surf.surf); wl_surface_commit(draw_surf.surf);
} }
}
static void static void
display_handle_done(void *data, struct wl_output *wl_output) {} display_handle_done(void *data, struct wl_output *wl_output) {}
@ -335,7 +350,8 @@ usage(char *argv0) {
argv0); argv0);
fprintf(stderr, "Options:\n"); fprintf(stderr, "Options:\n");
fprintf(stderr, " -D - Enable debug\n"); fprintf(stderr, " -D - Enable debug\n");
fprintf(stderr, " -o - Print press keys to standard output\n"); fprintf(stderr, " -o - Print pressed keys to standard output\n");
fprintf(stderr, " -O - Print intersected keys to standard output\n");
fprintf(stderr, " -l - Comma separated list of layers\n"); fprintf(stderr, " -l - Comma separated list of layers\n");
fprintf(stderr, " -H [int] - Height in pixels\n"); fprintf(stderr, " -H [int] - Height in pixels\n");
fprintf(stderr, " -L [int] - Landscape height in pixels\n"); fprintf(stderr, " -L [int] - Landscape height in pixels\n");
@ -357,6 +373,8 @@ hide(int sigint) {
wl_callback_destroy(draw_surf.cb); wl_callback_destroy(draw_surf.cb);
draw_surf.cb = NULL; draw_surf.cb = NULL;
} }
hidden = true;
} }
void void
@ -383,6 +401,24 @@ show(int sigint) {
wl_display_roundtrip(display); wl_display_roundtrip(display);
drwsurf_flip(&draw_surf); drwsurf_flip(&draw_surf);
hidden = false;
}
void
toggle_visibility(int sigint) {
signal(SIGRTMIN, toggle_visibility);
if (hidden) {
show(sigint);
} else {
hide(sigint);
}
}
void
pipewarn(int sigint) {
fprintf(stderr, "wvkbd: cannot pipe data out.\n");
} }
int int
@ -409,12 +445,10 @@ main(int argc, char **argv) {
keyboard.scheme1 = scheme1; keyboard.scheme1 = scheme1;
keyboard.scheme1 = scheme1; keyboard.scheme1 = scheme1;
bool starthidden = false;
int i; int i;
for (i = 1; argv[i]; i++) { for (i = 1; argv[i]; i++) {
if ((!strcmp(argv[i], "-v")) || (!strcmp(argv[i], "--version"))) { if ((!strcmp(argv[i], "-v")) || (!strcmp(argv[i], "--version"))) {
printf("wvkbd-%s", VERSION); printf("wvkbd-%s\n", VERSION);
exit(0); exit(0);
} else if ((!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "--help"))) { } else if ((!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "--help"))) {
usage(argv[0]); usage(argv[0]);
@ -445,8 +479,11 @@ main(int argc, char **argv) {
fc_font_pattern = estrdup(argv[++i]); fc_font_pattern = estrdup(argv[++i]);
} else if (!strcmp(argv[i], "-o")) { } else if (!strcmp(argv[i], "-o")) {
keyboard.print = true; keyboard.print = true;
} else if ((!strcmp(argv[i], "-hidden")) || (!strcmp(argv[i], "--hidden"))) { } else if (!strcmp(argv[i], "-O")) {
starthidden = true; keyboard.print_intersect = true;
} else if ((!strcmp(argv[i], "-hidden")) ||
(!strcmp(argv[i], "--hidden"))) {
hidden = true;
} else { } else {
fprintf(stderr, "Invalid argument: %s\n", argv[i]); fprintf(stderr, "Invalid argument: %s\n", argv[i]);
usage(argv[0]); usage(argv[0]);
@ -494,8 +531,7 @@ main(int argc, char **argv) {
draw_ctx.font_description = draw_ctx.font_description =
pango_font_description_from_string(fc_font_pattern); pango_font_description_from_string(fc_font_pattern);
if (!hidden) {
if (!starthidden) {
draw_surf.surf = wl_compositor_create_surface(compositor); draw_surf.surf = wl_compositor_create_surface(compositor);
layer_surface = zwlr_layer_shell_v1_get_layer_surface( layer_surface = zwlr_layer_shell_v1_get_layer_surface(
@ -515,6 +551,8 @@ main(int argc, char **argv) {
signal(SIGUSR1, hide); signal(SIGUSR1, hide);
signal(SIGUSR2, show); signal(SIGUSR2, show);
signal(SIGPIPE, pipewarn);
signal(SIGRTMIN, toggle_visibility);
while (run_display) { while (run_display) {
while (wl_display_dispatch(display) != -1 && layer_surface) { while (wl_display_dispatch(display) != -1 && layer_surface) {

71
wvkbd.1 Normal file
View File

@ -0,0 +1,71 @@
.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-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>.