1 #include "proto/virtual-keyboard-unstable-v1-client-protocol.h"
2 #include <linux/input-event-codes.h>
3 #include <stdio.h>
4 #include <sys/mman.h>
5 #include "keyboard.h"
6 #include "drw.h"
7 #include "os-compatibility.h"
8 
9 #define MAX_LAYERS 25
10 
11 /* lazy die macro */
12 #define die(...)                                                               \
13 	fprintf(stderr, __VA_ARGS__);                                                \
14 	exit(1)
15 
16 #ifndef KEYMAP
17 #error "make sure to define KEYMAP"
18 #endif
19 #include KEYMAP
20 
21 void
kbd_switch_layout(struct kbd * kb,struct layout * l)22 kbd_switch_layout(struct kbd *kb, struct layout *l) {
23 	kb->prevlayout = kb->layout;
24 	kb->layout = l;
25 	if (kb->debug)
26 		fprintf(stderr, "Switching to layout %s)\n", kb->layout->name);
27 	if ((!kb->prevlayout) ||
28 	    (strcmp(kb->prevlayout->keymap_name, kb->layout->keymap_name) != 0)) {
29 		fprintf(stderr, "Switching to keymap %s\n", kb->layout->keymap_name);
30 		create_and_upload_keymap(kb, kb->layout->keymap_name, 0, 0);
31 	}
32 	kbd_draw_layout(kb);
33 }
34 
35 uint8_t
kbd_get_rows(struct layout * l)36 kbd_get_rows(struct layout *l) {
37 	uint8_t rows = 0;
38 	struct key *k = l->keys;
39 	while (k->type != Last) {
40 		if (k->type == EndRow) {
41 			rows++;
42 		}
43 		k++;
44 	}
45 	return rows + 1;
46 }
47 
48 void
kbd_init(struct kbd * kb,struct layout * layouts,char * layer_names_list)49 kbd_init(struct kbd *kb, struct layout *layouts, char *layer_names_list) {
50 	char *s;
51 	int i;
52 	bool found;
53 
54 	fprintf(stderr, "Initializing keyboard\n");
55 
56 	kb->layouts = layouts;
57 
58 	for (i = 0; i < NumLayouts - 1; i++)
59 		;
60 	fprintf(stderr, "Found %d layouts\n", i);
61 
62 	kb->layer_index = 0;
63 
64 	if (layer_names_list) {
65 		uint8_t numlayers = 0;
66 		kb->layers = malloc(MAX_LAYERS * sizeof(enum layout_id));
67 		s = strtok(layer_names_list, ",");
68 		while (s != NULL) {
69 			if (numlayers + 1 == MAX_LAYERS) {
70 				fprintf(stderr, "too many layers specified");
71 				exit(3);
72 			}
73 			found = false;
74 			for (i = 0; i < NumLayouts - 1; i++) {
75 				if (kb->layouts[i].name && strcmp(kb->layouts[i].name, s) == 0) {
76 					fprintf(stderr, "layer #%d = %s\n", numlayers + 1, s);
77 					kb->layers[numlayers++] = i;
78 					found = true;
79 					break;
80 				}
81 			}
82 			if (!found) {
83 				fprintf(stderr, "No such layer: %s\n", s);
84 				exit(3);
85 			}
86 			s = strtok(NULL, ",");
87 		}
88 		kb->layers[numlayers] = NumLayouts; // mark the end of the sequence
89 		if (numlayers == 0) {
90 			fprintf(stderr, "No layers defined\n");
91 			exit(3);
92 		}
93 	}
94 
95 	i = 0;
96 	enum layout_id lid = kb->layers[0];
97 	while (lid != NumLayouts) {
98 		lid = kb->layers[++i];
99 	}
100 	fprintf(stderr, "Found %d layers\n", i);
101 
102 	enum layout_id layer;
103 	if (kb->landscape) {
104 		layer = kb->landscape_layers[kb->layer_index];
105 	} else {
106 		layer = kb->layers[kb->layer_index];
107 	}
108 
109 	kb->layout = &kb->layouts[layer];
110 	kb->prevlayout = kb->layout;
111 
112 	/* upload keymap */
113 	create_and_upload_keymap(kb, kb->layout->keymap_name, 0, 0);
114 }
115 
116 void
kbd_init_layout(struct layout * l,uint32_t width,uint32_t height)117 kbd_init_layout(struct layout *l, uint32_t width, uint32_t height) {
118 	uint32_t x = 0, y = 0;
119 	uint8_t rows = kbd_get_rows(l);
120 
121 	l->keyheight = height / rows;
122 
123 	struct key *k = l->keys;
124 	double rowlength = kbd_get_row_length(k);
125 	while (k->type != Last) {
126 		if (k->type == EndRow) {
127 			y += l->keyheight;
128 			x = 0;
129 			rowlength = kbd_get_row_length(k + 1);
130 		} else if (k->width > 0) {
131 			k->x = x;
132 			k->y = y;
133 			k->w = ((double)width / rowlength) * k->width;
134 			x += k->w;
135 		}
136 		k->h = l->keyheight;
137 		k++;
138 	}
139 }
140 
141 double
kbd_get_row_length(struct key * k)142 kbd_get_row_length(struct key *k) {
143 	double l = 0.0;
144 	while ((k->type != Last) && (k->type != EndRow)) {
145 		l += k->width;
146 		k++;
147 	}
148 	return l;
149 }
150 
151 struct key *
kbd_get_key(struct kbd * kb,uint32_t x,uint32_t y)152 kbd_get_key(struct kbd *kb, uint32_t x, uint32_t y) {
153 	struct layout *l = kb->layout;
154 	struct key *k = l->keys;
155 	if (kb->debug)
156 		fprintf(stderr, "get key: +%d+%d\n", x, y);
157 	while (k->type != Last) {
158 		if ((k->type != EndRow) && (k->type != Pad) && (k->type != Pad) &&
159 		    (x >= k->x) && (y >= k->y) && (x < k->x + k->w) && (y < k->y + k->h)) {
160 			return k;
161 		}
162 		k++;
163 	}
164 	return NULL;
165 }
166 
167 void
kbd_unpress_key(struct kbd * kb,uint32_t time)168 kbd_unpress_key(struct kbd *kb, uint32_t time) {
169   bool unlatch_shift = false;
170 
171 	if (kb->last_press) {
172     unlatch_shift = (kb->mods & Shift) == Shift;
173 
174     if (unlatch_shift) {
175       kb->mods ^= Shift;
176       zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
177     }
178 
179     if (kb->last_press->type == Copy) {
180 			zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key
181 			                            WL_KEYBOARD_KEY_STATE_RELEASED);
182 		} else {
183 			zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
184 			                            WL_KEYBOARD_KEY_STATE_RELEASED);
185 		}
186 
187 		if (kb->compose >= 2) {
188 			kb->compose = 0;
189 			kbd_switch_layout(kb, kb->prevlayout);
190 		} else if (unlatch_shift) {
191 			kbd_draw_layout(kb);
192 		} else {
193       kbd_draw_key(kb, kb->last_press, Unpress);
194     }
195 
196 		kb->last_press = NULL;
197 	}
198 }
199 
kbd_release_key(struct kbd * kb,uint32_t time)200 void kbd_release_key(struct kbd *kb, uint32_t time) {
201 	kbd_unpress_key(kb, time);
202 	if (kb->print_intersect && kb->last_swipe) {
203 		printf("\n");
204 		// Important so autocompleted words get typed in time
205 		fflush(stdout);
206 		kbd_draw_layout(kb);
207 		kb->last_swipe = NULL;
208 	}
209 }
210 
kbd_motion_key(struct kbd * kb,uint32_t time,uint32_t x,uint32_t y)211 void kbd_motion_key(struct kbd *kb, uint32_t time, uint32_t x, uint32_t y) {
212 	// Output intersecting keys
213 	// (for external 'swiping'-based accelerators).
214 	if (kb->print_intersect) {
215 		if (kb->last_press) {
216 			kbd_unpress_key(kb, time);
217 			// Redraw last press as a swipe.
218 			kbd_draw_key(kb, kb->last_swipe, Swipe);
219 		}
220 		struct key *intersect_key;
221 		intersect_key = kbd_get_key(kb, x, y);
222 		if (intersect_key &&
223 		    (! kb->last_swipe || intersect_key->label != kb->last_swipe->label)) {
224 			kbd_print_key_stdout(kb, intersect_key);
225 			kb->last_swipe = intersect_key;
226 			kbd_draw_key(kb, kb->last_swipe, Swipe);
227 		}
228 	} else {
229 		kbd_unpress_key(kb, time);
230 	}
231 }
232 
233 void
kbd_press_key(struct kbd * kb,struct key * k,uint32_t time)234 kbd_press_key(struct kbd *kb, struct key *k, uint32_t time) {
235 	if ((kb->compose == 1) && (k->type != Compose) && (k->type != Mod) &&
236 	    (k->layout)) {
237 		kb->compose++;
238 		if (kb->debug)
239 			fprintf(stderr, "showing compose %d\n", kb->compose);
240 		kbd_switch_layout(kb, k->layout);
241 		return;
242 	}
243 
244 	switch (k->type) {
245 	case Code:
246 		if (k->code_mod) {
247 			if (k->reset_mod) {
248 				zwp_virtual_keyboard_v1_modifiers(kb->vkbd, k->code_mod, 0, 0, 0);
249 			} else {
250 				zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods ^ k->code_mod, 0,
251 				                                  0, 0);
252 			}
253 		} else {
254 			zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
255 		}
256 		kb->last_swipe = kb->last_press = k;
257 		kbd_draw_key(kb, k, Press);
258 		zwp_virtual_keyboard_v1_key(kb->vkbd, time, kb->last_press->code,
259 		                            WL_KEYBOARD_KEY_STATE_PRESSED);
260 		if (kb->print || kb->print_intersect)
261 			kbd_print_key_stdout(kb, k);
262 		if (kb->compose) {
263 			if (kb->debug)
264 				fprintf(stderr, "pressing composed key\n");
265 			kb->compose++;
266 		}
267 		break;
268 	case Mod:
269 		kb->mods ^= k->code;
270 		if (k->code == Shift) {
271 			kbd_draw_layout(kb);
272 		}
273 		if (kb->mods & k->code) {
274 			kbd_draw_key(kb, k, Press);
275 		} else {
276 			kbd_draw_key(kb, k, Unpress);
277 		}
278 		zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
279 		break;
280 	case Layout:
281 		// switch to the layout determined by the key
282 		kbd_switch_layout(kb, k->layout);
283 		break;
284 	case Compose:
285 		// switch to the associated layout determined by the *next* keypress
286 		if (kb->compose == 0) {
287 			kb->compose = 1;
288 		} else {
289 			kb->compose = 0;
290 		}
291 		if ((bool)kb->compose) {
292 			kbd_draw_key(kb, k, Press);
293 		} else {
294 			kbd_draw_key(kb, k, Unpress);
295 		}
296 		break;
297 	case NextLayer:
298 		// switch to the next layout in the layer sequence
299 		kb->layer_index++;
300 		enum layout_id layer;
301 		if (kb->landscape) {
302 			layer = kb->landscape_layers[kb->layer_index];
303 		} else {
304 			layer = kb->layers[kb->layer_index];
305 		}
306 		if (layer == NumLayouts) {
307 			kb->layer_index = 0;
308 			if (kb->landscape) {
309 				layer = kb->landscape_layers[kb->layer_index];
310 			} else {
311 				layer = kb->layers[kb->layer_index];
312 			}
313 		}
314 		kbd_switch_layout(kb, &kb->layouts[layer]);
315 		break;
316 	case BackLayer:
317 		// switch to the previously active layout
318 		if (kb->prevlayout)
319 			kbd_switch_layout(kb, kb->prevlayout);
320 		break;
321 	case Copy:
322 		// copy code as unicode chr by setting a temporary keymap
323 		kb->last_swipe = kb->last_press = k;
324 		kbd_draw_key(kb, k, Press);
325 		if (kb->debug)
326 			fprintf(stderr, "pressing copy key\n");
327 		create_and_upload_keymap(kb, kb->layout->keymap_name, k->code, k->code_mod);
328 		zwp_virtual_keyboard_v1_modifiers(kb->vkbd, kb->mods, 0, 0, 0);
329 		zwp_virtual_keyboard_v1_key(kb->vkbd, time, 127, // COMP key
330 		                            WL_KEYBOARD_KEY_STATE_PRESSED);
331 		if (kb->print || kb->print_intersect)
332 			kbd_print_key_stdout(kb, k);
333 		break;
334 	default:
335 		break;
336 	}
337 }
338 
339 void
kbd_print_key_stdout(struct kbd * kb,struct key * k)340 kbd_print_key_stdout(struct kbd *kb, struct key *k) {
341 	/* printed keys may slightly differ from the actual output
342 	 * we generally print what is on the key LABEL and only support the normal
343 	 * and shift layers. Other modifiers produce no output (Ctrl,Alt)
344 	 * */
345 
346 	bool handled = true;
347 	if (k->type == Code) {
348 		switch (k->code) {
349 		case KEY_SPACE:
350 			printf(" ");
351 			break;
352 		case KEY_ENTER:
353 			printf("\n");
354 			break;
355 		case KEY_BACKSPACE:
356 			printf("\b");
357 			break;
358 		case KEY_TAB:
359 			printf("\t");
360 			break;
361 		default:
362 			handled = false;
363 			break;
364 		}
365 	} else if (k->type != Copy) {
366 		return;
367 	}
368 
369 	if (!handled) {
370 		if ((kb->mods & Shift) || (kb->mods & CapsLock))
371 			printf("%s", k->shift_label);
372 		else if (!(kb->mods & Ctrl) && !(kb->mods & Alt) && !(kb->mods & Super))
373 			printf("%s", k->label);
374 	}
375 	fflush(stdout);
376 }
377 
378 void
kbd_draw_key(struct kbd * kb,struct key * k,enum key_draw_type type)379 kbd_draw_key(struct kbd *kb, struct key *k, enum key_draw_type type) {
380 	struct drwsurf *d = kb->surf;
381 	const char *label = (kb->mods & Shift) ? k->shift_label : k->label;
382 	if (kb->debug)
383 		fprintf(stderr, "Draw key +%d+%d %dx%d -> %s\n", k->x, k->y, k->w, k->h,
384 		        label);
385 	struct clr_scheme *scheme = (k->scheme == 0) ? &(kb->scheme) : &(kb->scheme1);
386 	switch (type) {
387 	case Unpress:
388 		draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->fg);
389 		break;
390 	case Press:
391 		draw_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->high);
392 		break;
393 	case Swipe:
394 		draw_over_inset(d, k->x, k->y, k->w, k->h, KBD_KEY_BORDER, scheme->swipe);
395 		break;
396 	}
397 	drw_draw_text(d, scheme->text, k->x, k->y, k->w, k->h, label);
398 }
399 
400 void
kbd_draw_layout(struct kbd * kb)401 kbd_draw_layout(struct kbd *kb) {
402 	struct drwsurf *d = kb->surf;
403 	struct key *next_key = kb->layout->keys;
404 	if (kb->debug)
405 		fprintf(stderr, "Draw layout");
406 
407 	drw_fill_rectangle(d, kb->scheme.bg, 0, 0, kb->w, kb->h);
408 
409 	while (next_key->type != Last) {
410 		if ((next_key->type == Pad) || (next_key->type == EndRow)) {
411 			next_key++;
412 			continue;
413 		}
414 		if (next_key->type == Mod && kb->mods & next_key->code) {
415 			kbd_draw_key(kb, next_key, Press);
416 		} else {
417 			kbd_draw_key(kb, next_key, Unpress);
418 		}
419 		next_key++;
420 	}
421 }
422 
423 void
kbd_resize(struct kbd * kb,struct layout * layouts,uint8_t layoutcount)424 kbd_resize(struct kbd *kb, struct layout *layouts, uint8_t layoutcount) {
425 	struct drwsurf *d = kb->surf;
426 
427 	fprintf(stderr, "Resize %dx%d %d, %d layouts\n", kb->w, kb->h, kb->s,
428 	        layoutcount);
429 
430 	drwsurf_resize(d, kb->w, kb->h, kb->s);
431 	for (int i = 0; i < layoutcount; i++) {
432 		kbd_init_layout(&layouts[i], kb->w, kb->h);
433 	}
434 	kbd_draw_layout(kb);
435 }
436 
437 void
draw_inset(struct drwsurf * ds,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t border,Color color)438 draw_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
439            uint32_t height, uint32_t border, Color color) {
440 	drw_fill_rectangle(ds, color, x + border, y + border, width - border,
441 	                   height - border);
442 }
443 void
draw_over_inset(struct drwsurf * ds,uint32_t x,uint32_t y,uint32_t width,uint32_t height,uint32_t border,Color color)444 draw_over_inset(struct drwsurf *ds, uint32_t x, uint32_t y, uint32_t width,
445                 uint32_t height, uint32_t border, Color color) {
446 	drw_over_rectangle(ds, color, x + border, y + border, width - border,
447 	                   height - border);
448 }
449 
450 void
create_and_upload_keymap(struct kbd * kb,const char * name,uint32_t comp_unichr,uint32_t comp_shift_unichr)451 create_and_upload_keymap(struct kbd *kb, const char *name, uint32_t comp_unichr,
452                          uint32_t comp_shift_unichr) {
453 	int keymap_index = -1;
454 	for (int i = 0; i < NUMKEYMAPS; i++) {
455 		if (!strcmp(keymap_names[i], name)) {
456 			keymap_index = i;
457 		}
458 	}
459 	if (keymap_index == -1) {
460 		fprintf(stderr, "No such keymap defined: %s\n", name);
461 		exit(9);
462 	}
463 	const char *keymap_template = keymaps[keymap_index];
464 	const size_t keymap_size = strlen(keymap_template) + 64;
465 	char *keymap_str = malloc(keymap_size);
466 	sprintf(keymap_str, keymap_template, comp_unichr, comp_shift_unichr);
467 	int keymap_fd = os_create_anonymous_file(keymap_size);
468 	if (keymap_fd < 0) {
469 		die("could not create keymap fd\n");
470 	}
471 	void *ptr =
472 	  mmap(NULL, keymap_size, PROT_READ | PROT_WRITE, MAP_SHARED, keymap_fd, 0);
473 	if (ptr == (void *)-1) {
474 		die("could not map keymap data\n");
475 	}
476 	if (kb->vkbd == NULL) {
477 		die("kb.vkbd = NULL\n");
478 	}
479 	strcpy(ptr, keymap_str);
480 	zwp_virtual_keyboard_v1_keymap(kb->vkbd, WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
481 	                               keymap_fd, keymap_size);
482 	free((void *)keymap_str);
483 }
484