mirror of
https://github.com/swaywm/sway.git
synced 2024-11-25 17:31:28 +00:00
Add password buffer, refactor rendering/surfaces
This commit is contained in:
parent
1fe3cb8965
commit
066143adef
|
@ -9,6 +9,7 @@ lib_sway_common = static_library(
|
|||
'pango.c',
|
||||
'readline.c',
|
||||
'stringop.c',
|
||||
'unicode.c',
|
||||
'util.c'
|
||||
),
|
||||
dependencies: [
|
||||
|
|
101
common/unicode.c
Normal file
101
common/unicode.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -15,18 +15,25 @@ struct swaylock_args {
|
|||
bool show_indicator;
|
||||
};
|
||||
|
||||
struct swaylock_password {
|
||||
size_t size;
|
||||
size_t len;
|
||||
char *buffer;
|
||||
};
|
||||
|
||||
struct swaylock_state {
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
struct zwlr_layer_shell_v1 *layer_shell;
|
||||
struct wl_shm *shm;
|
||||
struct wl_list contexts;
|
||||
struct wl_list surfaces;
|
||||
struct swaylock_args args;
|
||||
struct swaylock_password password;
|
||||
struct swaylock_xkb xkb;
|
||||
bool run_display;
|
||||
};
|
||||
|
||||
struct swaylock_context {
|
||||
struct swaylock_surface {
|
||||
cairo_surface_t *image;
|
||||
struct swaylock_state *state;
|
||||
struct wl_output *output;
|
||||
|
@ -38,4 +45,8 @@ struct swaylock_context {
|
|||
struct wl_list link;
|
||||
};
|
||||
|
||||
void swaylock_handle_key(struct swaylock_state *state,
|
||||
xkb_keysym_t keysym, uint32_t codepoint);
|
||||
void render_frame(struct swaylock_surface *surface);
|
||||
|
||||
#endif
|
||||
|
|
33
include/unicode.h
Normal file
33
include/unicode.h
Normal file
|
@ -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
|
||||
|
|
@ -32,39 +32,22 @@ static void daemonize() {
|
|||
}
|
||||
}
|
||||
|
||||
static void render_frame(struct swaylock_context *context) {
|
||||
struct swaylock_state *state = context->state;
|
||||
context->current_buffer = get_next_buffer(state->shm,
|
||||
context->buffers, context->width, context->height);
|
||||
cairo_t *cairo = context->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, context->image,
|
||||
state->args.mode, context->width, context->height);
|
||||
}
|
||||
wl_surface_attach(context->surface, context->current_buffer->buffer, 0, 0);
|
||||
wl_surface_damage(context->surface, 0, 0, context->width, context->height);
|
||||
wl_surface_commit(context->surface);
|
||||
}
|
||||
|
||||
static void layer_surface_configure(void *data,
|
||||
struct zwlr_layer_surface_v1 *surface,
|
||||
struct zwlr_layer_surface_v1 *layer_surface,
|
||||
uint32_t serial, uint32_t width, uint32_t height) {
|
||||
struct swaylock_context *context = data;
|
||||
context->width = width;
|
||||
context->height = height;
|
||||
zwlr_layer_surface_v1_ack_configure(surface, serial);
|
||||
render_frame(context);
|
||||
struct swaylock_surface *surface = data;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
zwlr_layer_surface_v1_ack_configure(layer_surface, serial);
|
||||
render_frame(surface);
|
||||
}
|
||||
|
||||
static void layer_surface_closed(void *data,
|
||||
struct zwlr_layer_surface_v1 *surface) {
|
||||
struct swaylock_context *context = data;
|
||||
zwlr_layer_surface_v1_destroy(context->layer_surface);
|
||||
wl_surface_destroy(context->surface);
|
||||
context->state->run_display = false;
|
||||
struct zwlr_layer_surface_v1 *layer_surface) {
|
||||
struct swaylock_surface *surface = data;
|
||||
zwlr_layer_surface_v1_destroy(surface->layer_surface);
|
||||
wl_surface_destroy(surface->surface);
|
||||
surface->state->run_display = false;
|
||||
}
|
||||
|
||||
static const struct zwlr_layer_surface_v1_listener layer_surface_listener = {
|
||||
|
@ -89,12 +72,12 @@ static void handle_global(void *data, struct wl_registry *registry,
|
|||
state->layer_shell = wl_registry_bind(
|
||||
registry, name, &zwlr_layer_shell_v1_interface, 1);
|
||||
} else if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||
struct swaylock_context *context =
|
||||
calloc(1, sizeof(struct swaylock_context));
|
||||
context->state = state;
|
||||
context->output = wl_registry_bind(registry, name,
|
||||
struct swaylock_surface *surface =
|
||||
calloc(1, sizeof(struct swaylock_surface));
|
||||
surface->state = state;
|
||||
surface->output = wl_registry_bind(registry, name,
|
||||
&wl_output_interface, 1);
|
||||
wl_list_insert(&state->contexts, &context->link);
|
||||
wl_list_insert(&state->surfaces, &surface->link);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +181,7 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
wl_list_init(&state.contexts);
|
||||
wl_list_init(&state.surfaces);
|
||||
state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
assert(state.display = wl_display_connect(NULL));
|
||||
|
||||
|
@ -207,33 +190,33 @@ int main(int argc, char **argv) {
|
|||
wl_display_roundtrip(state.display);
|
||||
assert(state.compositor && state.layer_shell && state.shm);
|
||||
|
||||
if (wl_list_empty(&state.contexts)) {
|
||||
if (wl_list_empty(&state.surfaces)) {
|
||||
wlr_log(L_DEBUG, "Exiting - no outputs to show on.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct swaylock_context *context;
|
||||
wl_list_for_each(context, &state.contexts, link) {
|
||||
assert(context->surface =
|
||||
struct swaylock_surface *surface;
|
||||
wl_list_for_each(surface, &state.surfaces, link) {
|
||||
assert(surface->surface =
|
||||
wl_compositor_create_surface(state.compositor));
|
||||
|
||||
context->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
|
||||
state.layer_shell, context->surface, context->output,
|
||||
surface->layer_surface = zwlr_layer_shell_v1_get_layer_surface(
|
||||
state.layer_shell, surface->surface, surface->output,
|
||||
ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "lockscreen");
|
||||
assert(context->layer_surface);
|
||||
assert(surface->layer_surface);
|
||||
|
||||
zwlr_layer_surface_v1_set_size(context->layer_surface, 0, 0);
|
||||
zwlr_layer_surface_v1_set_anchor(context->layer_surface,
|
||||
zwlr_layer_surface_v1_set_size(surface->layer_surface, 0, 0);
|
||||
zwlr_layer_surface_v1_set_anchor(surface->layer_surface,
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT);
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(context->layer_surface, -1);
|
||||
zwlr_layer_surface_v1_set_exclusive_zone(surface->layer_surface, -1);
|
||||
zwlr_layer_surface_v1_set_keyboard_interactivity(
|
||||
context->layer_surface, true);
|
||||
zwlr_layer_surface_v1_add_listener(context->layer_surface,
|
||||
&layer_surface_listener, context);
|
||||
wl_surface_commit(context->surface);
|
||||
surface->layer_surface, true);
|
||||
zwlr_layer_surface_v1_add_listener(surface->layer_surface,
|
||||
&layer_surface_listener, surface);
|
||||
wl_surface_commit(surface->surface);
|
||||
wl_display_roundtrip(state.display);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
executable(
|
||||
'swaylock', [
|
||||
'main.c',
|
||||
'password.c',
|
||||
'render.c',
|
||||
'seat.c'
|
||||
],
|
||||
include_directories: [sway_inc],
|
||||
|
|
57
swaylock/password.c
Normal file
57
swaylock/password.c
Normal file
|
@ -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;
|
||||
}
|
||||
}
|
21
swaylock/render.c
Normal file
21
swaylock/render.c
Normal file
|
@ -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);
|
||||
}
|
|
@ -73,7 +73,9 @@ static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
|
|||
uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ?
|
||||
key + 8 : 0;
|
||||
uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode);
|
||||
wlr_log(L_DEBUG, "%c %d", codepoint, sym);
|
||||
if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
swaylock_handle_key(state, sym, codepoint);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
|
||||
|
|
Loading…
Reference in a new issue