about summary refs log tree commit diff
diff options
context:
space:
mode:
-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;