parent
							
								
									1fe3cb8965
								
							
						
					
					
						commit
						066143adef
					
				| @ -0,0 +1,101 @@ | ||||
| #include <stdint.h> | ||||
| #include <stddef.h> | ||||
| #include "unicode.h" | ||||
| 
 | ||||
| size_t utf8_chsize(uint32_t ch) { | ||||
| 	if (ch < 0x80) { | ||||
| 		return 1; | ||||
| 	} else if (ch < 0x800) { | ||||
| 		return 2; | ||||
| 	} else if (ch < 0x10000) { | ||||
| 		return 3; | ||||
| 	} | ||||
| 	return 4; | ||||
| } | ||||
| 
 | ||||
| static const uint8_t masks[] = { | ||||
| 	0x7F, | ||||
| 	0x1F, | ||||
| 	0x0F, | ||||
| 	0x07, | ||||
| 	0x03, | ||||
| 	0x01 | ||||
| }; | ||||
| 
 | ||||
| uint32_t utf8_decode(const char **char_str) { | ||||
| 	uint8_t **s = (uint8_t **)char_str; | ||||
| 
 | ||||
| 	uint32_t cp = 0; | ||||
| 	if (**s < 128) { | ||||
| 		// shortcut
 | ||||
| 		cp = **s; | ||||
| 		++*s; | ||||
| 		return cp; | ||||
| 	} | ||||
| 	int size = utf8_size((char *)*s); | ||||
| 	if (size == -1) { | ||||
| 		++*s; | ||||
| 		return UTF8_INVALID; | ||||
| 	} | ||||
| 	uint8_t mask = masks[size - 1]; | ||||
| 	cp = **s & mask; | ||||
| 	++*s; | ||||
| 	while (--size) { | ||||
| 		cp <<= 6; | ||||
| 		cp |= **s & 0x3f; | ||||
| 		++*s; | ||||
| 	} | ||||
| 	return cp; | ||||
| } | ||||
| 
 | ||||
| size_t utf8_encode(char *str, uint32_t ch) { | ||||
| 	size_t len = 0; | ||||
| 	uint8_t first; | ||||
| 
 | ||||
| 	if (ch < 0x80) { | ||||
| 		first = 0; | ||||
| 		len = 1; | ||||
| 	} else if (ch < 0x800) { | ||||
| 		first = 0xc0; | ||||
| 		len = 2; | ||||
| 	} else if (ch < 0x10000) { | ||||
| 		first = 0xe0; | ||||
| 		len = 3; | ||||
| 	} else { | ||||
| 		first = 0xf0; | ||||
| 		len = 4; | ||||
| 	} | ||||
| 
 | ||||
| 	for (size_t i = len - 1; i > 0; --i) { | ||||
| 		str[i] = (ch & 0x3f) | 0x80; | ||||
| 		ch >>= 6; | ||||
| 	} | ||||
| 
 | ||||
| 	str[0] = ch | first; | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static const struct { | ||||
| 	uint8_t mask; | ||||
| 	uint8_t result; | ||||
| 	int octets; | ||||
| } sizes[] = { | ||||
| 	{ 0x80, 0x00, 1 }, | ||||
| 	{ 0xE0, 0xC0, 2 }, | ||||
| 	{ 0xF0, 0xE0, 3 }, | ||||
| 	{ 0xF8, 0xF0, 4 }, | ||||
| 	{ 0xFC, 0xF8, 5 }, | ||||
| 	{ 0xFE, 0xF8, 6 }, | ||||
| 	{ 0x80, 0x80, -1 }, | ||||
| }; | ||||
| 
 | ||||
| int utf8_size(const char *s) { | ||||
| 	uint8_t c = (uint8_t)*s; | ||||
| 	for (size_t i = 0; i < sizeof(sizes) / 2; ++i) { | ||||
| 		if ((c & sizes[i].mask) == sizes[i].result) { | ||||
| 			return sizes[i].octets; | ||||
| 		} | ||||
| 	} | ||||
| 	return -1; | ||||
| } | ||||
| @ -0,0 +1,33 @@ | ||||
| #ifndef _SWAY_UNICODE_H | ||||
| #define _SWAY_UNICODE_H | ||||
| #include <stddef.h> | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| // Technically UTF-8 supports up to 6 byte codepoints, but Unicode itself
 | ||||
| // doesn't really bother with more than 4.
 | ||||
| #define UTF8_MAX_SIZE 4 | ||||
| 
 | ||||
| #define UTF8_INVALID 0x80 | ||||
| 
 | ||||
| /**
 | ||||
|  * Grabs the next UTF-8 character and advances the string pointer | ||||
|  */ | ||||
| uint32_t utf8_decode(const char **str); | ||||
| 
 | ||||
| /**
 | ||||
|  * Encodes a character as UTF-8 and returns the length of that character. | ||||
|  */ | ||||
| size_t utf8_encode(char *str, uint32_t ch); | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns the size of the next UTF-8 character | ||||
|  */ | ||||
| int utf8_size(const char *str); | ||||
| 
 | ||||
| /**
 | ||||
|  * Returns the size of a UTF-8 character | ||||
|  */ | ||||
| size_t utf8_chsize(uint32_t ch); | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| @ -0,0 +1,57 @@ | ||||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include <xkbcommon/xkbcommon.h> | ||||
| #include "swaylock/swaylock.h" | ||||
| #include "swaylock/seat.h" | ||||
| #include "unicode.h" | ||||
| 
 | ||||
| static void backspace(struct swaylock_password *pw) { | ||||
| 	if (pw->len != 0) { | ||||
| 		pw->buffer[--pw->len] = 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { | ||||
| 	if (!pw->buffer) { | ||||
| 		pw->size = 8; | ||||
| 		if (!(pw->buffer = malloc(pw->size))) { | ||||
| 			// TODO: Display error
 | ||||
| 			return; | ||||
| 		} | ||||
| 		pw->buffer[0] = 0; | ||||
| 	} | ||||
| 	size_t utf8_size = utf8_chsize(codepoint); | ||||
| 	if (pw->len + utf8_size + 1 >= pw->size) { | ||||
| 		size_t size = pw->size * 2; | ||||
| 		char *buffer = realloc(pw->buffer, size); | ||||
| 		if (!buffer) { | ||||
| 			// TODO: Display error
 | ||||
| 			return; | ||||
| 		} | ||||
| 		pw->size = size; | ||||
| 		pw->buffer = buffer; | ||||
| 	} | ||||
| 	utf8_encode(&pw->buffer[pw->len], codepoint); | ||||
| 	pw->buffer[pw->len + utf8_size] = 0; | ||||
| 	pw->len += utf8_size; | ||||
| } | ||||
| 
 | ||||
| void swaylock_handle_key(struct swaylock_state *state, | ||||
| 		xkb_keysym_t keysym, uint32_t codepoint) { | ||||
| 	switch (keysym) { | ||||
| 		case XKB_KEY_KP_Enter: /* fallthrough */ | ||||
| 		case XKB_KEY_Return: | ||||
| 			// TODO: Attempt password
 | ||||
| 			break; | ||||
| 		case XKB_KEY_BackSpace: | ||||
| 			backspace(&state->password); | ||||
| 			break; | ||||
| 		default: | ||||
| 			if (codepoint) { | ||||
| 				append_ch(&state->password, codepoint); | ||||
| 			} | ||||
| 			break; | ||||
| 	} | ||||
| } | ||||
| @ -0,0 +1,21 @@ | ||||
| #include <wayland-client.h> | ||||
| #include "cairo.h" | ||||
| #include "background-image.h" | ||||
| #include "swaylock/swaylock.h" | ||||
| 
 | ||||
| void render_frame(struct swaylock_surface *surface) { | ||||
| 	struct swaylock_state *state = surface->state; | ||||
| 	surface->current_buffer = get_next_buffer(state->shm, | ||||
| 			surface->buffers, surface->width, surface->height); | ||||
| 	cairo_t *cairo = surface->current_buffer->cairo; | ||||
| 	if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR) { | ||||
| 		cairo_set_source_u32(cairo, state->args.color); | ||||
| 		cairo_paint(cairo); | ||||
| 	} else { | ||||
| 		render_background_image(cairo, surface->image, | ||||
| 				state->args.mode, surface->width, surface->height); | ||||
| 	} | ||||
| 	wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); | ||||
| 	wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); | ||||
| 	wl_surface_commit(surface->surface); | ||||
| } | ||||
					Loading…
					
					
				
		Reference in new issue