62 Commits
v0.2 ... v0.11

Author SHA1 Message Date
1577b2f742 version bump prior to release 2022-10-07 21:04:46 +02:00
9bbc8d4a99 main: Allow user to override layers in landscape mode
Add a new parameter `--landscape-layers` as well as an environment
variable `WVKBD_LANDSCAPE_LAYERS` that allows the user to override the
default set of layers in landscape mode. This complements the existing
`-l` parameter and `WVKBD_LAYERS` environment variable, which do the
equivalent for non-landscape mode.

Furthermore, add documentation for the new switch. Move the `-l`
parameter to the bottom so we don't have to realign all parameters and
so all layer-related parameters are grouped together.
2022-10-07 21:02:29 +02:00
dfae590264 keyboard: Allow overriding the layers in landscape mode
Add a new parameter to allow overriding the default list of layers used
in landscape mode. This functionality is not yet used.
2022-10-07 21:02:29 +02:00
7fe983af16 keyboard: Extract logic to parse keyboard layer list
The user can optionally override the list of keyboard layers compiled
into the executable. Right now this only works for non-landscape mode
though.

Pull out the logic to parse the list of keyboard layers so that we can
reuse it to also optionally override layers in landscape mode.
2022-10-07 21:02:29 +02:00
acf38cf46e Add a --list-layers option
To get a list of available layers for the -l option.

Signed-off-by: Emmanuel LE TRONG <emmanuel.le-trong@cnrs-orleans.fr>
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-08-16 17:29:50 +02:00
7af52d695d version bump 2022-07-27 18:41:48 +02:00
f446bf9147 fixup: code indentation fixes after last patch 2022-07-27 18:39:11 +02:00
e29b029308 add: args to customize keyboard colors (takes rrggbb or rrggbbaa values) add: function to set keyboard colors from rrggbb or rrggbbaa values fix: handle empty font arg
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-27 18:30:11 +02:00
12c0d67f41 version bump prior to release 2022-07-26 22:04:22 +02:00
5de2fcc39d fix: arabic key layout
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-25 10:54:20 +02:00
a10b504cda allow modifiers with next layer button to switch to first/previous layer
- shift (or capslock) switch to the previous layer in the defined order
- control, alt or compose resets the view to the first layer

related fix: compose key resets on layer switch (doesn't stick now)
2022-07-15 22:03:27 +02:00
14f0f0824b shift key: change icon when shifted
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-10 22:57:55 +02:00
f9bf42129a border: display around all sides
(not just top and left edges)

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-10 22:52:22 +02:00
0cd0d5e1a1 layout: Implement spacing better
to no longer need overscan

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-10 22:52:22 +02:00
1843e60a74 only commit surface when it changed
Previously wvkbd would commit an (usually) unchanged surface at the
framerate of the compositor, this only commits the buffer when we render
something new.

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-05 22:13:21 +02:00
a2cacb7e25 use signalfd instead of signal
Switch to using signalfds because using the signal syscall was causing
problems without the frame callbacks (the change in the next commit), I
think this is because it would end up with multiple tasks polling the
same wayland file descriptor.

Previously this would exit after the second SIGPIPE signal. I checked
with earboxer on irc, and confirmed that handling all occurrences is the
correct behavior.

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-05 22:12:54 +02:00
dbe1e01fe9 call show instead of duplicating in startshidden check
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-05 22:12:48 +02:00
c1b95f2700 reset layer index on rotation
If there are more layers in one orientation than the other this can
cause wvkbd to overshoot the end of the layer list when switching
layers. It also means that switching layers after rotating will jump to
the next layer in the list, which is somewhat unexpected.

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-05 18:08:14 +02:00
9d6696fb23 call kbd_resize when showing
Since layer_surface_configure was changed to only call kbd_resize when
an output dimension changed, kbd_resize doesn't get called if the
keyboard was hidden and is being shown again, meaning it doesn't tell
the compositor about the scale.

This causes it to only output the top-right quarter of the keybaord
stretched to the entire window size after a SIGUSR1 + SIGUSR2 cycle with
the display scale set to 2.

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-05 18:08:06 +02:00
f540cf36fa Use output dimensions to detect landscape mode
Most displays are in landscape mode by default, so checking to see if
it's rotated will produce the exact opposite of the expected results.

Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-07-05 18:08:02 +02:00
b974877be4 Add + sign in dialer. 2022-07-05 06:39:23 -05:00
6d34f5af59 version bump 2022-06-25 15:21:43 +02:00
22ff01fb8b Keyboard: Avoid unnecessary resizes
Signed-off-by: Maarten van Gompel <proycon@anaproy.nl>
2022-06-25 15:19:33 +02:00
28c24749ba version bump: previous version had Makefile issues 2022-06-17 20:48:08 +02:00
cc73ab2c7c Makefile: fix for installing man pages 2022-06-17 20:47:15 +02:00
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
6abc005124 added missing abc/sym key to dialer layer 2021-12-01 10:01:43 -08:00
35c5f44e3c change config.def.h to include dialer 2021-11-16 11:04:21 -08:00
4bf9d53a00 Add a dialer layout
Signed-off-by: Stacy Harper <contact@stacyharper.net>
2021-11-16 10:23:29 -08:00
1562c08a06 added missing sym key to nav layer 2021-11-01 12:47:25 -07:00
1bbeb8861e added simple navigation layer 2021-11-01 12:47:25 -07:00
31f209bcd5 fixed emoji layout 2021-11-01 12:42:46 -07:00
13 changed files with 5288 additions and 253 deletions

View File

@ -3,6 +3,7 @@ include config.mk
NAME=wvkbd
BIN=${NAME}-${LAYOUT}
SRC=.
MAN1 = ${NAME}.1
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 += $(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)
@ -47,3 +48,6 @@ install: all
mkdir -p ${DESTDIR}${PREFIX}/bin
cp -f ${NAME}-${LAYOUT} ${DESTDIR}${PREFIX}/bin
chmod 755 ${DESTDIR}${PREFIX}/bin/${NAME}-${LAYOUT}
mkdir -p "${DESTDIR}${MANPREFIX}/man1"
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
- Emoji support
- 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
@ -37,7 +37,8 @@ There are some areas that still need work:
You'll need the following developer packages
- pangocairo
- cairo
- pango
- wayland-client
- 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
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
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
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
start up time and may be appropriate in some low-resource environments.
The keyboard can be hidden by sending it a `SIGUSR1` signal, shown again by sending it `SIGUSR2` or toggled by sending it `SIGRTMIN`.
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
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):
`$ 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
Any contributions are welcome, please tell me what I did wrong in issues or
PRs. I could also use some nice branding if that tickles your fancy.
Any contributions are welcome, there are two ways to contribute, the first one is **preferred**:
For code contributions, all I ask for now is you run `make format` (requires
`clang-format`) before opening a PR and include as much relevant detail as
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/).
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.
## Related projects
* [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
* [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

View File

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

View File

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

40
drw.c
View File

@ -20,30 +20,12 @@ drwsurf_resize(struct drwsurf *ds, uint32_t w, uint32_t h, uint32_t s) {
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};
void
drwsurf_flip(struct drwsurf *ds) {
ds->cb = wl_surface_frame(ds->surf);
wl_callback_add_listener(ds->cb, &frame_listener, (void *)ds);
wl_surface_attach(ds->surf, ds->buf, 0, 0);
wl_surface_commit(ds->surf);
}
void
surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time) {
struct drwsurf *ds = (struct drwsurf *)data;
wl_callback_destroy(cb);
ds->cb = NULL;
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) {
@ -69,11 +51,15 @@ drw_draw_text(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) {
drw_do_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
uint32_t w, uint32_t h, bool over) {
cairo_save(d->cairo);
cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE);
if (over) {
cairo_set_operator(d->cairo, CAIRO_OPERATOR_OVER);
} else {
cairo_set_operator(d->cairo, CAIRO_OPERATOR_SOURCE);
}
cairo_rectangle(d->cairo, x, y, w, h);
cairo_set_source_rgba(
@ -86,6 +72,18 @@ drw_fill_rectangle(struct drwsurf *d, Color color, uint32_t x, uint32_t y,
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
setup_buffer(struct drwsurf *drwsurf) {
int stride = drwsurf->width * 4;

5
drw.h
View File

@ -15,7 +15,6 @@ struct drwsurf {
struct wl_surface *surf;
struct wl_buffer *buf;
struct wl_shm *shm;
struct wl_callback *cb;
unsigned char *pool_data;
cairo_t *cairo;
@ -31,8 +30,12 @@ typedef union {
uint32_t 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,
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,
uint32_t w, uint32_t h, const char *label);

View File

@ -45,11 +45,49 @@ kbd_get_rows(struct layout *l) {
return rows + 1;
}
void
kbd_init(struct kbd *kb, struct layout *layouts, char *layer_names_list) {
enum layout_id *
kbd_init_layers(char *layer_names_list) {
enum layout_id *layers;
uint8_t numlayers = 0;
bool found;
char *s;
int i;
bool found;
layers = malloc(MAX_LAYERS * sizeof(enum layout_id));
s = strtok(layer_names_list, ",");
while (s != NULL) {
if (numlayers + 1 == MAX_LAYERS) {
fprintf(stderr, "too many layers specified");
exit(3);
}
found = false;
for (i = 0; i < NumLayouts - 1; i++) {
if (layouts[i].name && strcmp(layouts[i].name, s) == 0) {
fprintf(stderr, "layer #%d = %s\n", numlayers + 1, s);
layers[numlayers++] = i;
found = true;
break;
}
}
if (!found) {
fprintf(stderr, "No such layer: %s\n", s);
exit(3);
}
s = strtok(NULL, ",");
}
layers[numlayers] = NumLayouts; // mark the end of the sequence
if (numlayers == 0) {
fprintf(stderr, "No layers defined\n");
exit(3);
}
return layers;
}
void
kbd_init(struct kbd *kb, struct layout *layouts,
char *layer_names_list, char *landscape_layer_names_list) {
int i;
fprintf(stderr, "Initializing keyboard\n");
@ -61,36 +99,10 @@ kbd_init(struct kbd *kb, struct layout *layouts, char *layer_names_list) {
kb->layer_index = 0;
if (layer_names_list) {
uint8_t numlayers = 0;
kb->layers = malloc(MAX_LAYERS * sizeof(enum layout_id));
s = strtok(layer_names_list, ",");
while (s != NULL) {
if (numlayers + 1 == MAX_LAYERS) {
fprintf(stderr, "too many layers specified");
exit(3);
}
found = false;
for (i = 0; i < NumLayouts - 1; i++) {
if (kb->layouts[i].name && strcmp(kb->layouts[i].name, s) == 0) {
fprintf(stderr, "layer #%d = %s\n", numlayers + 1, s);
kb->layers[numlayers++] = i;
found = true;
break;
}
}
if (!found) {
fprintf(stderr, "No such layer: %s\n", s);
exit(3);
}
s = strtok(NULL, ",");
}
kb->layers[numlayers] = NumLayouts; // mark the end of the sequence
if (numlayers == 0) {
fprintf(stderr, "No layers defined\n");
exit(3);
}
}
if (layer_names_list)
kb->layers = kbd_init_layers(layer_names_list);
if (landscape_layer_names_list)
kb->landscape_layers = kbd_init_layers(landscape_layer_names_list);
i = 0;
enum layout_id lid = kb->layers[0];
@ -122,16 +134,23 @@ kbd_init_layout(struct layout *l, uint32_t width, uint32_t height) {
struct key *k = l->keys;
double rowlength = kbd_get_row_length(k);
double rowwidth = 0.0;
while (k->type != Last) {
if (k->type == EndRow) {
y += l->keyheight;
x = 0;
rowwidth = 0.0;
rowlength = kbd_get_row_length(k + 1);
} else if (k->width > 0) {
k->x = x;
k->y = y;
k->w = ((double)width / rowlength) * k->width;
x += k->w;
rowwidth += k->width;
if (x < (rowwidth / rowlength) * (double)width) {
k->w++;
x++;
}
}
k->h = l->keyheight;
k++;
@ -166,8 +185,16 @@ kbd_get_key(struct kbd *kb, uint32_t x, uint32_t y) {
void
kbd_unpress_key(struct kbd *kb, uint32_t time) {
bool unlatch_shift = false;
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) {
zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key
WL_KEYBOARD_KEY_STATE_RELEASED);
@ -175,24 +202,63 @@ kbd_unpress_key(struct kbd *kb, uint32_t time) {
zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
WL_KEYBOARD_KEY_STATE_RELEASED);
}
kb->last_press = NULL;
if (kb->compose >= 2) {
kb->compose = 0;
kbd_switch_layout(kb, kb->prevlayout);
if ((kb->mods & Shift) == Shift)
kb->mods ^= Shift;
} else if ((kb->mods & Shift) == Shift) {
kb->mods ^= Shift;
} else if (unlatch_shift) {
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;
}
drwsurf_flip(kb->surf);
}
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);
}
drwsurf_flip(kb->surf);
}
void
kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
if ((kb->compose == 1) && (k->type != Compose) && (k->type != Mod) &&
(k->layout)) {
if ((kb->compose == 1) && (k->type != Compose) && (k->type != Mod) &&
(k->type != NextLayer) && (k->layout)) {
kb->compose++;
if (kb->debug)
fprintf(stderr, "showing compose %d\n", kb->compose);
@ -212,11 +278,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
} else {
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
}
kb->last_press = k;
kbd_draw_key(kb, k, true);
kb->last_swipe = kb->last_press = k;
kbd_draw_key(kb, k, Press);
zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
WL_KEYBOARD_KEY_STATE_PRESSED);
if (kb->print)
if (kb->print || kb->print_intersect)
kbd_print_key_stdout(kb, k);
if (kb->compose) {
if (kb->debug)
@ -229,7 +295,11 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
if (k->code == Shift) {
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);
break;
case Layout:
@ -243,11 +313,37 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
} else {
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;
case NextLayer:
// switch to the next layout in the layer sequence
kb->layer_index++;
if ((kb->mods & Ctrl) || (kb->mods & Alt) || (kb->mods & AltGr) || ((bool)kb->compose)) {
// with modifiers: switch to the first layer
kb->layer_index = 0;
kb->mods = 0;
} else if ((kb->mods & Shift) || (kb->mods & CapsLock)) {
// with modifiers: switch to the previous layout in the layer sequence
if (kb->layer_index > 0) {
kb->layer_index--;
} else {
size_t layercount = 0;
for (size_t i = 0; layercount == 0; i++) {
if (kb->landscape) {
if (kb->landscape_layers[i] == NumLayouts) layercount = i;
} else {
if (kb->layers[i] == NumLayouts) layercount = i;
}
}
kb->layer_index = layercount - 1;
}
kb->mods = 0;
} else {
// normal behaviour: switch to the next layout in the layer sequence
kb->layer_index++;
}
enum layout_id layer;
if (kb->landscape) {
layer = kb->landscape_layers[kb->layer_index];
@ -262,6 +358,10 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
layer = kb->layers[kb->layer_index];
}
}
if ((bool)kb->compose) {
kb->compose = 0;
kbd_draw_key(kb, k, Unpress);
}
kbd_switch_layout(kb, &kb->layouts[layer]);
break;
case BackLayer:
@ -271,20 +371,22 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
break;
case Copy:
// copy code as unicode chr by setting a temporary keymap
kb->last_press = k;
kbd_draw_key(kb, k, true);
kb->last_swipe = kb->last_press = k;
kbd_draw_key(kb, k, Press);
if (kb->debug)
fprintf(stderr, "pressing copy key\n");
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_key(kb->vkbd, time, 127, // COMP key
WL_KEYBOARD_KEY_STATE_PRESSED);
if (kb->print)
if (kb->print || kb->print_intersect)
kbd_print_key_stdout(kb, k);
break;
default:
break;
}
drwsurf_flip(kb->surf);
}
void
@ -327,15 +429,24 @@ kbd_print_key_stdout(struct kbd *kb, struct key *k) {
}
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;
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);
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);
switch (type) {
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);
}
@ -343,7 +454,6 @@ void
kbd_draw_layout(struct kbd *kb) {
struct drwsurf *d = kb->surf;
struct key *next_key = kb->layout->keys;
bool pressed = false;
if (kb->debug)
fprintf(stderr, "Draw layout");
@ -354,8 +464,12 @@ kbd_draw_layout(struct kbd *kb) {
next_key++;
continue;
}
pressed = next_key->type == Mod && kb->mods & next_key->code;
kbd_draw_key(kb, next_key, pressed);
if ((next_key->type == Mod && kb->mods & next_key->code) ||
(next_key->type == Compose && kb->compose)) {
kbd_draw_key(kb, next_key, Press);
} else {
kbd_draw_key(kb, next_key, Unpress);
}
next_key++;
}
}
@ -377,8 +491,14 @@ 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) {
drw_fill_rectangle(ds, color, x + border, y + border, width - border,
height - border);
drw_fill_rectangle(ds, color, x + border, y + border, width - (border * 2),
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) {
drw_over_rectangle(ds, color, x + border, y + border, width - (border * 2),
height - (border * 2));
}
void

View File

@ -41,10 +41,17 @@ enum key_modifier_type {
AltGr = 128,
};
enum key_draw_type {
Unpress = 0,
Press,
Swipe,
};
struct clr_scheme {
Color fg;
Color bg;
Color high;
Color swipe;
Color text;
};
@ -85,11 +92,13 @@ struct kbd {
struct clr_scheme scheme1;
bool print;
bool print_intersect;
uint32_t w, h, s;
bool landscape;
uint8_t mods;
uint8_t compose;
struct key *last_press;
struct key *last_swipe;
struct layout *prevlayout;
size_t layer_index;
@ -103,14 +112,19 @@ 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);
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, char *landscape_layer_names_list);
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);
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_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_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount);
uint8_t kbd_get_rows(struct layout *l);

File diff suppressed because it is too large Load Diff

View File

@ -1,16 +1,12 @@
/* constants */
/* how tall the keyboard should be by default (can be overriden) */
#define KBD_PIXEL_HEIGHT 240
/* how tall the keyboard should be by default (can be overriden) */
#define KBD_PIXEL_LANDSCAPE_HEIGHT 120
/* if your layout leaves an empty margin, increase this to fix it */
#define KBD_PIXEL_OVERSCAN_WIDTH 5
/* spacing between keys */
#define KBD_KEY_BORDER 2
/* spacing around each key */
#define KBD_KEY_BORDER 1
/* layout declarations */
enum layout_id {
@ -18,9 +14,14 @@ enum layout_id {
Special,
Simple,
SimpleGrid,
Dialer,
Cyrillic,
Arabic,
Persian,
Greek,
Georgian,
Emoji,
Nav,
Landscape,
ComposeA,
ComposeE,
@ -64,18 +65,19 @@ enum layout_id {
};
static struct key keys_full[], keys_special[], keys_simple[], keys_simplegrid[],
keys_cyrillic[], keys_arabic[], keys_emoji[], keys_landscape[],
keys_compose_a[], keys_compose_e[], keys_compose_y[], keys_compose_u[],
keys_compose_i[], keys_compose_o[], keys_compose_w[], keys_compose_r[],
keys_compose_t[], keys_compose_p[], keys_compose_s[], keys_compose_d[],
keys_compose_f[], keys_compose_g[], keys_compose_h[], keys_compose_j[],
keys_compose_k[], keys_compose_l[], keys_compose_z[], keys_compose_x[],
keys_compose_c[], keys_compose_v[], keys_compose_b[], keys_compose_n[],
keys_compose_m[], keys_compose_math[], keys_compose_punctuation[],
keys_compose_bracket[], keys_compose_cyr_i[], keys_compose_cyr_j[],
keys_compose_cyr_e[], keys_compose_cyr_u[], keys_compose_cyr_l[],
keys_compose_cyr_n[], keys_compose_cyr_tse[], keys_compose_cyr_che[],
keys_compose_cyr_g[], keys_compose_cyr_k[];
keys_cyrillic[], keys_arabic[], keys_persian[], keys_georgian[], keys_greek[],
keys_emoji[], keys_nav[], keys_landscape[], keys_compose_a[],
keys_compose_e[], keys_compose_y[], keys_compose_u[], keys_compose_i[],
keys_compose_o[], keys_compose_w[], keys_compose_r[], keys_compose_t[],
keys_compose_p[], keys_compose_s[], keys_compose_d[], keys_compose_f[],
keys_compose_g[], keys_compose_h[], keys_compose_j[], keys_compose_k[],
keys_compose_l[], keys_compose_z[], keys_compose_x[], keys_compose_c[],
keys_compose_v[], keys_compose_b[], keys_compose_n[], keys_compose_m[],
keys_compose_math[], keys_compose_punctuation[], keys_compose_bracket[],
keys_compose_cyr_i[], keys_compose_cyr_j[], keys_compose_cyr_e[],
keys_compose_cyr_u[], keys_compose_cyr_l[], keys_compose_cyr_n[],
keys_compose_cyr_tse[], keys_compose_cyr_che[], keys_compose_cyr_g[],
keys_compose_cyr_k[], keys_dialer[];
static struct layout layouts[NumLayouts] = {
[Full] = {keys_full, "latin", "full"}, // second parameter is the keymap name
@ -84,8 +86,13 @@ static struct layout layouts[NumLayouts] = {
[Simple] = {keys_simple, "latin", "simple"},
[SimpleGrid] = {keys_simplegrid, "latin", "simplegrid"},
[Cyrillic] = {keys_cyrillic, "cyrillic", "cyrillic"},
[Dialer] = {keys_dialer, "latin", "dialer"},
[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"},
[Nav] = {keys_nav, "latin", "nav"},
[Landscape] = {keys_landscape, "latin", "landscape"},
[ComposeA] = {keys_compose_a, "latin"},
[ComposeE] = {keys_compose_e, "latin"},
@ -208,7 +215,7 @@ static struct key keys_full[] = {
{"", "", 0.5, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]},
{"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]},
{"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]},
@ -268,7 +275,7 @@ static struct key keys_special[] = {
{"Del", "Del", 1.0, Code, KEY_DELETE, .scheme = 1},
{"", "", 0.0, EndRow},
{"", "", 2.0, Mod, Shift, .scheme = 1},
{"", "", 2.0, Mod, Shift, .scheme = 1},
{";", ":", 1.0, Code, KEY_SEMICOLON},
{"/", ">", 1.0, Code, KEY_SLASH},
{"<", "«", 1.0, Code, KEY_COMMA, 0, AltGr},
@ -317,7 +324,7 @@ static struct key keys_simple[] = {
{"'", "\"", 0.5, Code, KEY_APOSTROPHE, &layouts[ComposeBracket]},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]},
{"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]},
{"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]},
@ -330,7 +337,7 @@ static struct key keys_simple[] = {
{"Abc", "Abc", 1.0, NextLayer, .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},
{".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
@ -339,6 +346,34 @@ static struct key keys_simple[] = {
{"", "", 0.0, Last},
};
static struct key keys_dialer[] = {
{"Esc", "Esc", 1.0, Code, KEY_ESC},
{"+","+", 1.0, Code, KEY_KPPLUS},
{"", "", 1.0, Code, KEY_BACKSPACE},
{"", "", 0.0, EndRow},
{"1", "1", 1.0, Code, KEY_1},
{"2", "2", 1.0, Code, KEY_2},
{"3", "3", 1.0, Code, KEY_3},
{"", "", 0.0, EndRow},
{"4", "4", 1.0, Code, KEY_4},
{"5", "5", 1.0, Code, KEY_5},
{"6", "6", 1.0, Code, KEY_6},
{"", "", 0.0, EndRow},
{"7", "7", 1.0, Code, KEY_7},
{"8", "8", 1.0, Code, KEY_8},
{"9", "9", 1.0, Code, KEY_9},
{"", "", 0.0, EndRow},
{"*", "*", 1.0, Code, KEY_KPASTERISK},
{"0", "0", 1.0, Code, KEY_0},
{"#", "#", 1.0, Code, KEY_NUMERIC_POUND},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, NextLayer, .scheme = 1},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
/* end of layout */
{"", "", 0.0, Last},
};
static struct key keys_simplegrid[] = {
{"q", "Q", 1.0, Code, KEY_Q, &layouts[Emoji]},
{"w", "W", 1.0, Code, KEY_W, &layouts[ComposeW]},
@ -364,7 +399,7 @@ static struct key keys_simplegrid[] = {
{"'", "\"", 1.0, Code, KEY_APOSTROPHE, &layouts[ComposeBracket]},
{"", "", 0.0, EndRow},
{"", "", 1.0, Mod, Shift, .scheme = 1},
{"", "", 1.0, Mod, Shift, .scheme = 1},
{"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]},
{"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]},
{"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]},
@ -378,7 +413,7 @@ static struct key keys_simplegrid[] = {
{"Abc", "Abc", 1.0, NextLayer, .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},
{"", "", 3.0, Code, KEY_SPACE},
{".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]},
@ -430,7 +465,7 @@ static struct key keys_cyrillic[] = {
{"ж", "Ж", 1.0, Code, KEY_SEMICOLON},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"я", "Я", 1.0, Code, KEY_Z},
{"ч", "Ч", 1.0, Code, KEY_X, &layouts[ComposeCyrChe]},
{"c", "С", 1.0, Code, KEY_C},
@ -475,9 +510,9 @@ static struct key keys_arabic[] = {
{"غ", "إ", 1.0, Code, KEY_Y},
{"ع", "`", 1.0, Code, KEY_U},
{"ه", "", 1.0, Code, KEY_I},
{"ج", ";", 1.0, Code, KEY_O},
{"خ", ";", 1.0, Code, KEY_O},
{"ح", "", 1.0, Code, KEY_P},
{"خ", "<", 1.0, Code, KEY_LEFTBRACE},
{"ج", "<", 1.0, Code, KEY_LEFTBRACE},
{"", "", 0.0, EndRow},
{"ش", "ـِ", 1.0, Code, KEY_A},
@ -508,7 +543,7 @@ static struct key keys_arabic[] = {
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, NextLayer, .scheme = 1},
{"", "", 1.0, Mod, Shift, .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},
@ -517,6 +552,194 @@ static struct key keys_arabic[] = {
{"", "", 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[] = {
{"à", "À", 1.0, Copy, 0x00E0, 0, 0x00C0},
{"á", "Á", 1.0, Copy, 0x00E1, 0, 0x00C1},
@ -532,7 +755,7 @@ static struct key keys_compose_a[] = {
{"α", "Α", 1.0, Copy, 0x03B1, 0, 0x0391},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -560,7 +783,7 @@ static struct key keys_compose_e[] = {
{"ǝ", "Ə", 1.0, Copy, 0x0259, 0, 0x018F},
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift},
{"", "", 1.5, Mod, Shift},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE},
{"", "", 0.0, EndRow},
@ -581,7 +804,7 @@ static struct key keys_compose_y[] = {
{"", "", 0.0, EndRow},
{"υ", "Υ", 1.0, Copy, 0x03C5, 0, 0x03A5},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -604,12 +827,12 @@ static struct key keys_compose_u[] = {
{"ŭ", "Ŭ", 1.0, Copy, 0x016D, 0, 0x016C},
{"ů", "Ů", 1.0, Copy, 0x016F, 0, 0x016E},
{"ű", "Ű", 1.0, Copy, 0x0171, 0, 0x0170},
{"ų", "Ų", 1.0, Copy, 0x0172, 0, 0x0173},
{"ų", "Ų", 1.0, Copy, 0x0173, 0, 0x0172},
{"", "", 0.0, EndRow},
{"υ", "Υ", 1.0, Copy, 0x03C5, 0, 0x03A5},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -631,14 +854,14 @@ static struct key keys_compose_o[] = {
{"ø", "Ø", 1.0, Copy, 0x00F8, 0, 0x00D8},
{"ō", "Ō", 1.0, Copy, 0x014D, 0, 0x014C},
{"ŏ", "Ŏ", 1.0, Copy, 0x014F, 0, 0x014E},
{"ő", "Ő", 1.0, Copy, 0x0150, 0, 0x0151},
{"ő", "Ő", 1.0, Copy, 0x0151, 0, 0x0150},
{"œ", "Œ", 1.0, Copy, 0x0153, 0, 0x0152},
{"", "", 0.0, EndRow},
{"ο", "Ο", 1.0, Copy, 0x03BF, 0, 0x039F},
{"ω", "Ο", 1.0, Copy, 0x03C9, 0, 0x03A9},
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -660,14 +883,14 @@ static struct key keys_compose_i[] = {
{"ī", "Ī", 1.0, Copy, 0x012B, 0, 0x012A},
{"ĭ", "Ĭ", 1.0, Copy, 0x012D, 0, 0x012C},
{"į", "Į", 1.0, Copy, 0x012F, 0, 0x012E},
{"ı", "I", 1.0, Copy, 0x0150, 0, 0x0049},
{"i", "İ", 1.0, Copy, 0x0069, 0, 0x0152},
{"ı", "I", 1.0, Copy, 0x0131, 0, 0x0049},
{"i", "İ", 1.0, Copy, 0x0069, 0, 0x0130},
{"", "", 0.0, EndRow},
{"ι", "Ι", 1.0, Copy, 0x03B9, 0, 0x0399},
{"η", "Η", 1.0, Copy, 0x03B7, 0, 0x0397},
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -692,22 +915,22 @@ static struct key keys_emoji[] = {
{"😇", "", 1.0, Copy, 0x1f607, 0, 0x2728},
{"🤣", "💰", 1.0, Copy, 0x1f923, 0, 0x1f4b0},
{"", "", 0.0, EndRow},
{"😉", "🐕", 1.0, Copy, 0x1f609, 0, 0x1f407},
{"😉", "🐕", 1.0, Copy, 0x1f609, 0, 0x1f415},
{"😊", "🐈", 1.0, Copy, 0x1f60a, 0, 0x1f408},
{"😋", "🐧", 1.0, Copy, 0x1f60b, 0, 0x1f427},
{"😌", "💔", 1.0, Copy, 0x1f60c, 0, 0x1f494},
{"😍", "😘", 1.0, Copy, 0x1f60d, 0, 0x1f618},
{"😌", "🐇", 1.0, Copy, 0x1f60c, 0, 0x1f407},
{"😍", "💔", 1.0, Copy, 0x1f60d, 0, 0x1f494},
{"😘", "💕", 1.0, Copy, 0x1f618, 0, 0x1f495},
{"😎", "", 1.0, Copy, 0x1f60e, 0, 0x2764},
{"😐", "😏", 1.0, Copy, 0x1f610, 0, 0x1f60f},
{"😒", "👀", 1.0, Copy, 0x1f612, 0, 0x1f440},
{"😓", "💀", 1.0, Copy, 0x1f613, 0, 0x1f480},
{"", "", 0.0, EndRow},
{"", "", 1.0, Mod, Shift, .scheme = 1},
{"", "", 1.0, Mod, Shift, .scheme = 1},
{"😛", "😜", 1.0, Copy, 0x1f61b, 0, 0x1f61c},
{"😮", "😝", 1.0, Copy, 0x1f62e, 0, 0x1f61d},
{"😟", "😞", 1.0, Copy, 0x1f61f, 0, 0x1f61e},
{"😟", "🥺", 1.0, Copy, 0x1f620, 0, 0x1f97a},
{"😠", "🥺", 1.0, Copy, 0x1f620, 0, 0x1f97a},
{"😢", "👿", 1.0, Copy, 0x1f622, 0, 0x1f47f},
{"😭", "😯", 1.0, Copy, 0x1f62d, 0, 0x1f62f},
{"😳", "😕", 1.0, Copy, 0x1f633, 0, 0x1f615},
@ -719,13 +942,33 @@ static struct key keys_emoji[] = {
{"👇", "👌", 1.0, Copy, 0x1f447, 0, 0x1f44c},
{"👈", "👏", 1.0, Copy, 0x1f448, 0, 0x1f44f},
{"👉", "👐", 1.0, Copy, 0x1f449, 0, 0x1f450},
{"👋", "🙌", 1.0, Copy, 0x1f603, 0, 0x1f44c},
{"👍", "", 1.0, Copy, 0x1f604, 0, 0x2705},
{"👎", "💪", 1.0, Copy, 0x1f605, 0, 0x1f606},
{"👋", "🙌", 1.0, Copy, 0x1f44b, 0, 0x1f64c},
{"👍", "", 1.0, Copy, 0x1f44d, 0, 0x2705},
{"👎", "💪", 1.0, Copy, 0x1f44e, 0, 0x1f4aa},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
{"", "", 0.0, Last},
};
static struct key keys_nav[] = {
{"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1},
{"", "", 1.0, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 1.0, Code, KEY_UP, .scheme = 1},
{"", "", 1.0, Code, KEY_PAGEUP, .scheme = 1},
{"", "", 0.0, EndRow},
{"q", "q", 1.0, Code, KEY_Q, .scheme = 1},
{"", "", 1.0, Code, KEY_LEFT, .scheme = 1},
{"Enter", "Enter", 1.0, Code, KEY_ENTER, .scheme = 1},
{"", "", 1.0, Code, KEY_RIGHT, .scheme = 1},
{"", "", 0.0, EndRow},
{"Sym", "Sym", 1.0, NextLayer, .scheme = 1},
{"", "", 1.0, Code, KEY_SPACE, .scheme = 1},
{"", "", 1.0, Code, KEY_DOWN, .scheme = 1},
{"", "", 1.0, Code, KEY_PAGEDOWN, .scheme = 1},
{"", "", 0.0, Last},
};
static struct key keys_landscape[] = {
{"Esc", "Esc", 1.0, Code, KEY_ESC, .scheme = 1},
{"q", "Q", 1.0, Code, KEY_Q, &layouts[Emoji]},
@ -758,7 +1001,7 @@ static struct key keys_landscape[] = {
{"-", "_", 0.5, Code, KEY_MINUS, &layouts[ComposeBracket], .scheme = 1},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"z", "Z", 1.0, Code, KEY_Z, &layouts[ComposeZ]},
{"x", "X", 1.0, Code, KEY_X, &layouts[ComposeX]},
{"c", "C", 1.0, Code, KEY_C, &layouts[ComposeC]},
@ -790,7 +1033,7 @@ static struct key keys_compose_w[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -812,7 +1055,7 @@ static struct key keys_compose_r[] = {
{"ρ", "Ρ", 1.0, Copy, 0x03C1, 0, 0x03A1},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -836,7 +1079,7 @@ static struct key keys_compose_t[] = {
{"θ", "Θ", 1.0, Copy, 0x03B8, 0, 0x0398},
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -855,7 +1098,7 @@ static struct key keys_compose_p[] = {
{"π", "Π", 1.0, Copy, 0x03C0, 0, 0x03A0},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -880,7 +1123,7 @@ static struct key keys_compose_s[] = {
{"ς", "Σ", 1.0, Copy, 0x03C2, 0, 0x03A3},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -902,7 +1145,7 @@ static struct key keys_compose_d[] = {
{"δ", "Δ", 1.0, Copy, 0x03B4, 0, 0x0394},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -921,7 +1164,7 @@ static struct key keys_compose_f[] = {
{"φ", "Φ", 1.0, Copy, 0x03C6, 0, 0x03A6},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -942,7 +1185,7 @@ static struct key keys_compose_g[] = {
{"γ", "Γ", 1.0, Copy, 0x03B3, 0, 0x0393},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -963,7 +1206,7 @@ static struct key keys_compose_h[] = {
{"η", "Η", 1.0, Copy, 0x03B7, 0, 0x0397},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -982,7 +1225,7 @@ static struct key keys_compose_j[] = {
{"", "", 0.0, EndRow},
{"", "", 10.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1003,7 +1246,7 @@ static struct key keys_compose_k[] = {
{"κ", "Κ", 1.0, Copy, 0x03BA, 0, 0x039A},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1025,7 +1268,7 @@ static struct key keys_compose_l[] = {
{"λ", "Λ", 1.0, Copy, 0x03BB, 0, 0x039B},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1047,7 +1290,7 @@ static struct key keys_compose_z[] = {
{"ζ", "Ζ", 1.0, Copy, 0x03B6, 0, 0x0396},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1067,7 +1310,7 @@ static struct key keys_compose_x[] = {
{"ξ", "Ξ", 1.0, Copy, 0x03BE, 0, 0x039E},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1091,7 +1334,7 @@ static struct key keys_compose_c[] = {
{"χ", "Χ", 1.0, Copy, 0x03C7, 0, 0x03A7},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1109,7 +1352,7 @@ static struct key keys_compose_v[] = {
{"", "", 0.0, EndRow},
{"", "", 10.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1128,7 +1371,7 @@ static struct key keys_compose_b[] = {
{"β", "Β", 1.0, Copy, 0x03B2, 0, 0x0392},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1152,7 +1395,7 @@ static struct key keys_compose_n[] = {
{"ν", "Ν", 1.0, Copy, 0x03BD, 0, 0x039D},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1171,7 +1414,7 @@ static struct key keys_compose_m[] = {
{"μ", "Μ", 1.0, Copy, 0x03BC, 0, 0x039C},
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1190,7 +1433,7 @@ static struct key keys_compose_cyr_i[] = {
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1208,7 +1451,7 @@ static struct key keys_compose_cyr_j[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1226,7 +1469,7 @@ static struct key keys_compose_cyr_e[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1244,7 +1487,7 @@ static struct key keys_compose_cyr_u[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1262,7 +1505,7 @@ static struct key keys_compose_cyr_l[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1280,7 +1523,7 @@ static struct key keys_compose_cyr_n[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1299,7 +1542,7 @@ static struct key keys_compose_cyr_che[] = {
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1318,7 +1561,7 @@ static struct key keys_compose_cyr_tse[] = {
{"", "", 8.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1336,7 +1579,7 @@ static struct key keys_compose_cyr_g[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1354,7 +1597,7 @@ static struct key keys_compose_cyr_k[] = {
{"", "", 9.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 0.0, EndRow},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 1.5, Mod, Shift, .scheme = 1},
{"", "", 7, Pad},
{"", "", 1.5, Code, KEY_BACKSPACE, .scheme = 1},
{"", "", 0.0, EndRow},
@ -1381,18 +1624,18 @@ static struct key keys_compose_math[] = {
{"", "", 0.0, EndRow},
{"", "", 10.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 2, Mod, Shift, .scheme = 1},
{"-", "-", 1, Code, KEY_MINUS},
{"", "", 2, Mod, Shift, .scheme = 1},
{"+", "+", 1, Code, KEY_EQUAL, 0, Shift},
{"/", "/", 1, Code, KEY_SLASH},
{"*", "*", 1, Code, KEY_8, 0, Shift},
{"=", "=", 1, Code, KEY_EQUAL},
{"_", "_", 1, Code, KEY_MINUS, 0, Shift},
{"", "", 1, Copy, 0x2014, 0, 0x2014},
{"", "", 2, Pad},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, BackLayer},
{"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1},
{",", "'", 1.0, Code, KEY_COMMA, &layouts[ComposeMath]},
{"-", "-", 1, Code, KEY_MINUS},
{"", "", 4.0, Code, KEY_SPACE},
{".", "?", 1.0, Code, KEY_DOT, &layouts[ComposePunctuation]},
{"Enter", "Enter", 2.0, Code, KEY_ENTER, .scheme = 1},
@ -1413,14 +1656,15 @@ static struct key keys_compose_punctuation[] = {
{"", "", 0.0, EndRow},
{"", "", 10.0, Pad},
{"", "", 0.0, EndRow},
{"", "", 2, Mod, Shift, .scheme = 1},
{"", "", 1, Pad},
{"", "", 2, Mod, Shift, .scheme = 1},
{"", "", 1, Copy, 0x2026, 0, 0x2026},
{":", ":", 1, Code, KEY_SEMICOLON, 0, Shift},
{";", ";", 1, Code, KEY_SEMICOLON, 0},
{"!", "!", 1, Code, KEY_1, 0, Shift},
{"?", "?", 1, Code, KEY_DOT, 0, Shift},
{",", ",", 1, Code, KEY_COMMA},
{"", "", 2, Pad},
{"·", "·", 1, Copy, 0x2027, 0, 0x2027},
{"", "", 1, Pad},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, BackLayer},
{"Ctr", "Ctr", 1.0, Mod, Ctrl, .scheme = 1},
@ -1445,7 +1689,7 @@ static struct key keys_compose_bracket[] = {
{"\"", "\"", 1, Code, KEY_APOSTROPHE, 0, Shift},
{"'", "'", 1, Code, KEY_APOSTROPHE},
{"", "", 0.0, EndRow},
{"", "", 2, Mod, Shift, .scheme = 1},
{"", "", 2, Mod, Shift, .scheme = 1},
{"", "", 8, Pad},
{"", "", 0.0, EndRow},
{"Abc", "Abc", 1.0, BackLayer},

294
main.c
View File

@ -5,6 +5,8 @@
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/signalfd.h>
#include <poll.h>
#include <unistd.h>
#include <wayland-client.h>
#include <wchar.h>
@ -42,8 +44,10 @@ static uint32_t anchor = ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
/* application state */
static bool run_display = true;
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 bool hidden = false;
/* event handler prototypes */
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
@ -159,13 +163,18 @@ wl_touch_down(void *data, struct wl_touch *wl_touch, uint32_t serial,
void
wl_touch_up(void *data, struct wl_touch *wl_touch, uint32_t serial,
uint32_t time, int32_t id) {
kbd_unpress_key(&keyboard, time);
kbd_release_key(&keyboard, time);
}
void
wl_touch_motion(void *data, struct wl_touch *wl_touch, uint32_t time,
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
@ -199,18 +208,24 @@ wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
cur_x = wl_fixed_to_int(surface_x);
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
wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state) {
struct key *next_key;
bool press = state == WL_POINTER_BUTTON_STATE_PRESSED;
cur_press = state == WL_POINTER_BUTTON_STATE_PRESSED;
kbd_unpress_key(&keyboard, time);
if (cur_press) {
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);
if (next_key) {
kbd_press_key(&keyboard, next_key, time);
@ -238,29 +253,35 @@ static void
display_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
int physical_width, int physical_height, int subpixel,
const char *make, const char *model, int transform) {
if (transform % 2 == 0 && keyboard.landscape) {
keyboard.landscape = false;
height = normal_height;
} else if (transform % 2 != 0 && !keyboard.landscape) {
keyboard.landscape = true;
height = landscape_height;
} else {
return; // no changes
// Swap width and height on rotated displays
if (transform % 2 != 0) {
int tmp = physical_width;
physical_width = physical_height;
physical_height = tmp;
}
bool landscape = physical_width > physical_height;
if (landscape == keyboard.landscape) return;
keyboard.landscape = landscape;
enum layout_id layer;
if (keyboard.landscape) {
layer = keyboard.landscape_layers[0];
height = landscape_height;
} else {
layer = keyboard.layers[0];
height = normal_height;
}
keyboard.layout = &keyboard.layouts[layer];
keyboard.prevlayout = keyboard.layout;
keyboard.layer_index = 0;
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);
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);
}
}
static void
@ -313,11 +334,15 @@ handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {}
void
layer_surface_configure(void *data, struct zwlr_layer_surface_v1 *surface,
uint32_t serial, uint32_t w, uint32_t h) {
keyboard.w = w + KBD_PIXEL_OVERSCAN_WIDTH;
keyboard.h = h;
kbd_resize(&keyboard, layouts, NumLayouts);
if (keyboard.w != w || keyboard.h != h) {
keyboard.w = w;
keyboard.h = h;
kbd_resize(&keyboard, layouts, NumLayouts);
}
zwlr_layer_surface_v1_ack_configure(surface, serial);
drwsurf_flip(&draw_surf);
}
void
@ -334,18 +359,39 @@ usage(char *argv0) {
"layers]\n",
argv0);
fprintf(stderr, "Options:\n");
fprintf(stderr, " -D - Enable debug\n");
fprintf(stderr, " -o - Print press keys to standard output\n");
fprintf(stderr, " -l - Comma separated list of layers\n");
fprintf(stderr, " -H [int] - Height in pixels\n");
fprintf(stderr, " -L [int] - Landscape height in pixels\n");
fprintf(stderr, " -D - Enable debug\n");
fprintf(stderr, " -o - Print pressed keys to standard output\n");
fprintf(stderr, " -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, " --fn [font] - Set font (e.g: DejaVu Sans 20)\n");
fprintf(stderr, " --hidden - Start hidden (send SIGUSR2 to show)\n");
fprintf(stderr, " --hidden - Start hidden (send SIGUSR2 to show)\n");
fprintf(stderr, " --bg [rrggbb|aa] - Set color of background\n");
fprintf(stderr, " --fg [rrggbb|aa] - Set color of keys\n");
fprintf(stderr, " --fg-sp [rrggbb|aa] - Set color of special keys\n");
fprintf(stderr, " --press [rrggbb|aa] - Set color of pressed keys\n");
fprintf(stderr, " --press-sp [rrggbb|aa] - Set color of pressed special keys\n");
fprintf(stderr, " --swipe [rrggbb|aa] - Set color of swiped keys\n");
fprintf(stderr, " --swipe-sp [rrggbb|aa] - Set color of swiped special keys\n");
fprintf(stderr, " --text [rrggbb|aa] - Set color of text on keys\n");
fprintf(stderr, " --text-sp [rrggbb|aa] - Set color of text on special keys\n");
fprintf(stderr, " --list-layers - Print the list of available layers\n");
fprintf(stderr, " -l - Comma separated list of layers\n");
fprintf(stderr, " --landscape-layers - Comma separated list of landscape layers\n");
}
void
hide(int sigint) {
signal(SIGUSR1, hide);
list_layers() {
int i;
for (i = 0; i < NumLayouts - 1; i++) {
if (layouts[i].name) {
puts(layouts[i].name);
}
}
}
void
hide() {
if (!layer_surface) {
return;
}
@ -353,15 +399,11 @@ hide(int sigint) {
zwlr_layer_surface_v1_destroy(layer_surface);
wl_surface_destroy(draw_surf.surf);
layer_surface = NULL;
if (draw_surf.cb) {
wl_callback_destroy(draw_surf.cb);
draw_surf.cb = NULL;
}
hidden = true;
}
void
show(int sigint) {
signal(SIGUSR2, show);
show() {
if (layer_surface) {
return;
}
@ -369,7 +411,6 @@ show(int sigint) {
wl_display_sync(display);
draw_surf.surf = wl_compositor_create_surface(compositor);
;
layer_surface = zwlr_layer_shell_v1_get_layer_surface(
layer_shell, draw_surf.surf, wl_output, layer, namespace);
@ -382,13 +423,46 @@ show(int sigint) {
wl_surface_commit(draw_surf.surf);
wl_display_roundtrip(display);
kbd_resize(&keyboard, layouts, NumLayouts);
drwsurf_flip(&draw_surf);
hidden = false;
}
void
toggle_visibility() {
if (hidden) show();
else hide();
}
void
pipewarn() {
fprintf(stderr, "wvkbd: cannot pipe data out.\n");
}
void
set_kbd_colors(uint8_t * bgra, char * hex) {
// bg, fg, text, high, swipe
int length = strlen(hex);
if (length == 6 || length == 8) {
char subhex[2];
memcpy(subhex, hex, 2);
bgra[2] = (int)strtol(subhex, NULL, 16);
memcpy(subhex, hex+2, 2);
bgra[1] = (int)strtol(subhex, NULL, 16);
memcpy(subhex, hex+4, 2);
bgra[0] = (int)strtol(subhex, NULL, 16);
if (length == 8) {
memcpy(subhex, hex+6, 2);
bgra[3] = (int)strtol(subhex, NULL, 16);
}
}
}
int
main(int argc, char **argv) {
/* parse command line arguments */
char *layer_names_list = NULL;
char *layer_names_list = NULL, *landscape_layer_names_list = NULL;
const char *fc_font_pattern = NULL;
height = normal_height = KBD_PIXEL_HEIGHT;
landscape_height = KBD_PIXEL_LANDSCAPE_HEIGHT;
@ -396,6 +470,8 @@ main(int argc, char **argv) {
char *tmp;
if ((tmp = getenv("WVKBD_LAYERS")))
layer_names_list = estrdup(tmp);
if ((tmp = getenv("WVKBD_LANDSCAPE_LAYERS")))
landscape_layer_names_list = estrdup(tmp);
if ((tmp = getenv("WVKBD_HEIGHT")))
normal_height = atoi(tmp);
if ((tmp = getenv("WVKBD_LANDSCAPE_HEIGHT")))
@ -407,14 +483,11 @@ main(int argc, char **argv) {
keyboard.scheme = scheme;
keyboard.layer_index = 0;
keyboard.scheme1 = scheme1;
keyboard.scheme1 = scheme1;
bool starthidden = false;
int i;
for (i = 1; argv[i]; i++) {
if ((!strcmp(argv[i], "-v")) || (!strcmp(argv[i], "--version"))) {
printf("wvkbd-%s", VERSION);
printf("wvkbd-%s\n", VERSION);
exit(0);
} else if ((!strcmp(argv[i], "-h")) || (!strcmp(argv[i], "--help"))) {
usage(argv[0]);
@ -427,6 +500,69 @@ main(int argc, char **argv) {
if (layer_names_list)
free(layer_names_list);
layer_names_list = estrdup(argv[++i]);
} else if ((!strcmp(argv[i], "-landscape-layers")) ||
(!strcmp(argv[i], "--landscape-layers"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
if (landscape_layer_names_list)
free(landscape_layer_names_list);
landscape_layer_names_list = estrdup(argv[++i]);
} else if ((!strcmp(argv[i], "-bg")) || (!strcmp(argv[i], "--bg"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme.bg.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-fg")) || (!strcmp(argv[i], "--fg"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme.fg.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-fg-sp")) || (!strcmp(argv[i], "--fg-sp"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme1.fg.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-press")) || (!strcmp(argv[i], "--press"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme.high.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-press-sp")) || (!strcmp(argv[i], "--press-sp"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme1.high.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-swipe")) || (!strcmp(argv[i], "--swipe"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme.swipe.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-swipe-sp")) || (!strcmp(argv[i], "--swipe-sp"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme1.swipe.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-text")) || (!strcmp(argv[i], "--text"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme.text.bgra, argv[++i]);
} else if ((!strcmp(argv[i], "-text-sp")) || (!strcmp(argv[i], "--text-sp"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
set_kbd_colors(keyboard.scheme1.text.bgra, argv[++i]);
} else if (!strcmp(argv[i], "-H")) {
if (i >= argc - 1) {
usage(argv[0]);
@ -442,11 +578,22 @@ main(int argc, char **argv) {
} else if (!strcmp(argv[i], "-D")) {
keyboard.debug = true;
} else if ((!strcmp(argv[i], "-fn")) || (!strcmp(argv[i], "--fn"))) {
if (i >= argc - 1) {
usage(argv[0]);
exit(1);
}
fc_font_pattern = estrdup(argv[++i]);
} else if (!strcmp(argv[i], "-o")) {
keyboard.print = true;
} else if ((!strcmp(argv[i], "-hidden")) || (!strcmp(argv[i], "--hidden"))) {
starthidden = true;
} else if (!strcmp(argv[i], "-O")) {
keyboard.print_intersect = true;
} else if ((!strcmp(argv[i], "-hidden")) ||
(!strcmp(argv[i], "--hidden"))) {
hidden = true;
} else if ((!strcmp(argv[i], "-list-layers")) ||
(!strcmp(argv[i], "--list-layers"))) {
list_layers();
exit(0);
} else {
fprintf(stderr, "Invalid argument: %s\n", argv[i]);
usage(argv[0]);
@ -489,39 +636,56 @@ main(int argc, char **argv) {
die("failed to init virtual keyboard_manager\n");
}
kbd_init(&keyboard, (struct layout *)&layouts, layer_names_list);
kbd_init(&keyboard, (struct layout *)&layouts,
layer_names_list, landscape_layer_names_list);
draw_ctx.font_description =
pango_font_description_from_string(fc_font_pattern);
if (!hidden) show();
if (!starthidden) {
draw_surf.surf = wl_compositor_create_surface(compositor);
struct pollfd fds[2];
int WAYLAND_FD = 0;
int SIGNAL_FD = 1;
fds[WAYLAND_FD].events = POLLIN;
fds[SIGNAL_FD].events = POLLIN;
layer_surface = zwlr_layer_shell_v1_get_layer_surface(
layer_shell, draw_surf.surf, wl_output, layer, namespace);
zwlr_layer_surface_v1_set_size(layer_surface, 0, height);
zwlr_layer_surface_v1_set_anchor(layer_surface, anchor);
zwlr_layer_surface_v1_set_exclusive_zone(layer_surface, height);
zwlr_layer_surface_v1_set_keyboard_interactivity(layer_surface, false);
zwlr_layer_surface_v1_add_listener(layer_surface, &layer_surface_listener,
NULL);
wl_surface_commit(draw_surf.surf);
wl_display_roundtrip(display);
drwsurf_flip(&draw_surf);
fds[WAYLAND_FD].fd = wl_display_get_fd(display);
if (fds[WAYLAND_FD].fd == -1) {
die("Failed to get wayland_fd: %d\n", errno);
}
signal(SIGUSR1, hide);
signal(SIGUSR2, show);
sigset_t signal_mask;
sigemptyset(&signal_mask);
sigaddset(&signal_mask, SIGUSR1);
sigaddset(&signal_mask, SIGUSR2);
sigaddset(&signal_mask, SIGRTMIN);
sigaddset(&signal_mask, SIGPIPE);
if (sigprocmask(SIG_BLOCK, &signal_mask, NULL) == -1) {
die("Failed to disable handled signals: %d\n", errno);
}
fds[SIGNAL_FD].fd = signalfd(-1, &signal_mask, 0);
if (fds[SIGNAL_FD].fd == -1) {
die("Failed to get signalfd: %d\n", errno);
}
while (run_display) {
while (wl_display_dispatch(display) != -1 && layer_surface) {
}
wl_display_roundtrip(display);
while (run_display && !layer_surface) {
sleep(1);
wl_display_flush(display);
poll(fds, 2, -1);
if (fds[WAYLAND_FD].revents & POLLIN)
wl_display_dispatch(display);
if (fds[SIGNAL_FD].revents & POLLIN) {
struct signalfd_siginfo si;
if (read(fds[SIGNAL_FD].fd, &si, sizeof(si)) != sizeof(si))
fprintf(stderr, "Signal read error: %d", errno);
else if (si.ssi_signo == SIGUSR1) hide();
else if (si.ssi_signo == SIGUSR2) show();
else if (si.ssi_signo == SIGRTMIN) toggle_visibility();
else if (si.ssi_signo == SIGPIPE) pipewarn();
}
}

BIN
wvkbd-mobintl Executable file

Binary file not shown.

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>.