suggestion picker: a persistent layer to complement virtual keyboards like wvkbd
-rw-r--r--keyboard.h83
-rw-r--r--main.c34
2 files changed, 90 insertions, 27 deletions
diff --git a/keyboard.h b/keyboard.h
index ea3bddc..bdd2f58 100644
--- a/keyboard.h
+++ b/keyboard.h
@@ -12,7 +12,9 @@ enum key_type {
Layout,
EndRow,
Last,
+ Compose,
CodeMod,
+ Copy,
};
/* Modifiers passed to the virtual_keyboard protocol. They are based on
@@ -23,6 +25,7 @@ enum key_modifier_type {
Shift = 1,
CapsLock = 2,
Ctrl = 4,
+ Alt = 8,
Super = 64,
AltGr = 128,
};
@@ -35,26 +38,30 @@ struct clr_scheme {
};
struct key {
- const char *label;
- const char *shift_label;
- const double width;
+ const char *label; //primary label
+ const char *shift_label; //secondary label
+ const double width; //relative width (1.0)
const enum key_type type;
- const uint32_t code;
- struct layout *layout;
- const uint32_t code_mod;
+ const uint32_t code; /* code: key scancode or modifier name (see
+ * `/usr/include/linux/input-event-codes.h` for scancode names, and
+ * `keyboard.h` for modifiers)
+ * XKB keycodes are +8 */
+ struct layout *layout; //pointer back to the parent layout that holds this key
+ const uint32_t code_mod; /* modifier to force when this key is pressed */
- //actual coordinates on the surface
+ //actual coordinates on the surface (pixels), will be computed automatically for all keys
uint32_t x, y, w, h;
};
struct layout {
struct key *keys;
- uint32_t keyheight;
+ uint32_t keyheight; //absolute height (pixels)
};
struct kbd {
struct layout *layout;
+ struct layout *prevlayout;
struct clr_scheme scheme;
uint32_t w, h;
@@ -148,8 +155,13 @@ kbd_unpress_key(struct kbd *kb, uint32_t time) {
kbd_draw_key(kb, kb->last_press, false);
kb->surf->dirty = true;
- zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
- WL_KEYBOARD_KEY_STATE_RELEASED);
+ if (kb->last_press->type == Copy) {
+ zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, //COMP key
+ WL_KEYBOARD_KEY_STATE_RELEASED);
+ } else {
+ zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
+ WL_KEYBOARD_KEY_STATE_RELEASED);
+ }
kb->last_press = NULL;
}
}
@@ -161,7 +173,7 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
case CodeMod:
mods_before = kb->mods;
- kb->mods = k->code_mod;
+ kb->mods ^= k->code_mod;
kb->last_press = k;
kbd_draw_key(kb, k, true);
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
@@ -172,10 +184,26 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
break;
case Code:
- kb->last_press = k;
- kbd_draw_key(kb, k, true);
- zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
- WL_KEYBOARD_KEY_STATE_PRESSED);
+ if (compose == 1) {
+ if (k->layout) {
+ compose++;
+ if (compose) {
+ fprintf(stderr,"showing compose %d\n", compose);
+ }
+ kb->prevlayout = kb->layout;
+ kb->layout = k->layout;
+ kbd_draw_layout(kb);
+ }
+ } else {
+ kb->last_press = k;
+ kbd_draw_key(kb, k, true);
+ zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
+ WL_KEYBOARD_KEY_STATE_PRESSED);
+ if (compose) {
+ fprintf(stderr,"pressing composed key\n");
+ compose++;
+ }
+ }
break;
case Mod:
kb->mods ^= k->code;
@@ -185,13 +213,36 @@ kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
kbd_draw_key(kb, k, kb->mods & k->code);
zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
break;
+ case Compose:
+ if (compose == 0) {
+ compose = 1;
+ } else {
+ compose = 0;
+ }
+ kbd_draw_key(kb, k, (bool) compose);
+ break;
case Layout:
kb->layout = k->layout;
kbd_draw_layout(kb);
+ case Copy:
+ kb->last_press = k;
+ kbd_draw_key(kb, k, true);
+ fprintf(stderr,"pressing copy key\n");
+ create_and_upload_keymap(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);
+ break;
default:
break;
}
+ if (compose == 3) {
+ compose = 0;
+ kb->layout = kb->prevlayout;
+ kbd_draw_layout(kb);
+ }
+
kb->surf->dirty = true;
}
@@ -252,3 +303,5 @@ draw_inset(struct drwsurf *d, uint32_t x, uint32_t y, uint32_t width,
wld_fill_rectangle(d->render, color, x + border, y + border, width - border,
height - border);
}
+
+
diff --git a/main.c b/main.c
index f37ea5c..ef3b217 100644
--- a/main.c
+++ b/main.c
@@ -6,6 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <wchar.h>
#include <sys/mman.h>
#include <wayland-client.h>
@@ -46,6 +47,7 @@ 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 int compose = 0;
/* event handler prototypes */
static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer,
@@ -92,6 +94,7 @@ static void layer_surface_configure(void *data,
uint32_t serial, uint32_t w, uint32_t h);
static void layer_surface_closed(void *data,
struct zwlr_layer_surface_v1 *surface);
+static void create_and_upload_keymap(uint32_t comp_unichr, uint32_t comp_shift_unichr);
/* event handlers */
static const struct wl_pointer_listener pointer_listener = {
@@ -273,10 +276,27 @@ layer_surface_closed(void *data, struct zwlr_layer_surface_v1 *surface) {
run_display = false;
}
+void
+create_and_upload_keymap(uint32_t comp_unichr, uint32_t comp_shift_unichr) {
+ const char * keymap_str = get_keymap(comp_unichr, comp_shift_unichr);
+ size_t keymap_size = strlen(keymap_str) + 1;
+ int keymap_fd = os_create_anonymous_file(keymap_size);
+ if (keymap_fd < 0) {
+ die("could not create keymap fd\n");
+ }
+ void *ptr =
+ mmap(NULL, keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymap_fd, 0);
+ if (ptr == (void *)-1) {
+ die("could not map keymap data\n");
+ }
+ strcpy(ptr, keymap_str);
+ zwp_virtual_keyboard_v1_keymap(
+ keyboard.vkbd, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymap_fd, keymap_size);
+}
+
int
main(int argc, char **argv) {
uint8_t i;
- int keymap_fd = os_create_anonymous_file(keymap_size);
/* connect to compositor */
display = wl_display_connect(NULL);
@@ -307,17 +327,7 @@ main(int argc, char **argv) {
zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(vkbd_mgr, seat);
/* upload keymap */
- if (keymap_fd < 0) {
- die("could not create keymap fd\n");
- }
- void *ptr =
- mmap(NULL, keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymap_fd, 0);
- if (ptr == (void *)-1) {
- die("could not map keymap data\n");
- }
- strcpy(ptr, keymap_str);
- zwp_virtual_keyboard_v1_keymap(
- keyboard.vkbd, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, keymap_fd, keymap_size);
+ create_and_upload_keymap(0,0);
/* assign kbd state */
keyboard.surf = &draw_surf;