hikari/src/lock_indicator.c

183 lines
4.7 KiB
C

#include <hikari/lock_indicator.h>
#include <drm_fourcc.h>
#include <wlr/backend.h>
#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_matrix.h>
#include <hikari/configuration.h>
#include <hikari/geometry.h>
#include <hikari/output.h>
#include <hikari/server.h>
#define HIKARI_PI 3.14159265358979323846
static struct wlr_texture *
init_indicator_circle(float color[static 4])
{
const int size = 100;
struct wlr_texture *texture;
struct wlr_renderer *wlr_renderer = hikari_server.renderer;
cairo_surface_t *surface =
cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size, size);
cairo_t *cairo = cairo_create(surface);
PangoLayout *layout = pango_cairo_create_layout(cairo);
float *border_inactive = hikari_configuration->border_active;
cairo_set_source_rgba(cairo,
border_inactive[0],
border_inactive[1],
border_inactive[2],
border_inactive[3]);
cairo_set_line_width(cairo, 5);
cairo_translate(cairo, size / 2, size / 2);
cairo_arc(cairo, 0, 0, (size - 5) / 2, 0, 2 * HIKARI_PI);
cairo_stroke_preserve(cairo);
cairo_set_source_rgba(cairo, color[0], color[1], color[2], color[3]);
cairo_fill(cairo);
cairo_surface_flush(surface);
unsigned char *data = cairo_image_surface_get_data(surface);
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, size);
texture = wlr_texture_from_pixels(
wlr_renderer, DRM_FORMAT_ARGB8888, stride, size, size, data);
cairo_surface_destroy(surface);
g_object_unref(layout);
cairo_destroy(cairo);
return texture;
}
static int
reset_state_handler(void *data)
{
struct hikari_lock_indicator *lock_indicator = data;
if (lock_indicator->current == lock_indicator->deny) {
hikari_lock_indicator_clear(lock_indicator);
} else {
hikari_lock_indicator_set_wait(lock_indicator);
}
return 0;
}
void
hikari_lock_indicator_init(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
lock_indicator->wait = init_indicator_circle(hikari_configuration->clear);
lock_indicator->type =
init_indicator_circle(hikari_configuration->indicator_insert);
lock_indicator->verify =
init_indicator_circle(hikari_configuration->indicator_selected);
lock_indicator->deny =
init_indicator_circle(hikari_configuration->indicator_conflict);
lock_indicator->current = NULL;
lock_indicator->reset_state = wl_event_loop_add_timer(
hikari_server.event_loop, reset_state_handler, lock_indicator);
}
void
hikari_lock_indicator_fini(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
wlr_texture_destroy(lock_indicator->wait);
wlr_texture_destroy(lock_indicator->type);
wlr_texture_destroy(lock_indicator->verify);
wlr_texture_destroy(lock_indicator->deny);
wl_event_source_remove(lock_indicator->reset_state);
}
void
hikari_lock_indicator_set_type(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
lock_indicator->current = lock_indicator->type;
hikari_lock_indicator_damage(lock_indicator);
wl_event_source_timer_update(lock_indicator->reset_state, 100);
}
void
hikari_lock_indicator_set_verify(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
lock_indicator->current = lock_indicator->verify;
hikari_lock_indicator_damage(lock_indicator);
wl_event_source_timer_update(lock_indicator->reset_state, 0);
}
void
hikari_lock_indicator_set_deny(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
lock_indicator->current = lock_indicator->deny;
hikari_lock_indicator_damage(lock_indicator);
wl_event_source_timer_update(lock_indicator->reset_state, 1000);
}
void
hikari_lock_indicator_set_wait(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
lock_indicator->current = lock_indicator->wait;
hikari_lock_indicator_damage(lock_indicator);
}
void
hikari_lock_indicator_clear(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
lock_indicator->current = NULL;
hikari_lock_indicator_damage(lock_indicator);
wl_event_source_timer_update(lock_indicator->reset_state, 0);
}
static inline void
get_geometry(struct hikari_output *output, struct wlr_box *geometry)
{
const int size = 100;
geometry->width = size;
geometry->height = size;
struct wlr_box output_geometry = { .x = 0,
.y = 0,
.width = output->geometry.width,
.height = output->geometry.height };
hikari_geometry_position_center(
geometry, &output_geometry, &geometry->x, &geometry->y);
}
void
hikari_lock_indicator_damage(struct hikari_lock_indicator *lock_indicator)
{
assert(lock_indicator != NULL);
struct wlr_box geometry;
struct hikari_output *output;
wl_list_for_each (output, &hikari_server.outputs, server_outputs) {
get_geometry(output, &geometry);
hikari_output_add_damage(output, &geometry);
}
}