diff options
Diffstat (limited to 'src/common/input.c')
| -rw-r--r-- | src/common/input.c | 80 |
1 files changed, 43 insertions, 37 deletions
diff --git a/src/common/input.c b/src/common/input.c index 471cd2b..0b55f1f 100644 --- a/src/common/input.c +++ b/src/common/input.c @@ -1,57 +1,64 @@ #include "input.h" +#include "yasl/loop.h" #include <stdlib.h> #include <string.h> -static const char *event_text(const struct yasl_input_event *ev, size_t *len) +static bool has_text(const struct yasl_event *ev) { - switch (ev->kind) { - case YASL_INPUT_TEXT: *len = ev->text.len; return ev->text.text; - case YASL_INPUT_PASTE: *len = ev->paste.len; return ev->paste.text; - case YASL_INPUT_DROP_FILES: *len = ev->drop_files.len; return ev->drop_files.files; - default: *len = 0; return NULL; - } -} - -static void set_text(struct yasl_input_event *ev, const char *text) -{ - switch (ev->kind) { - case YASL_INPUT_TEXT: ev->text.text = text; break; - case YASL_INPUT_PASTE: ev->paste.text = text; break; - case YASL_INPUT_DROP_FILES: ev->drop_files.files = text; break; - default: break; - } + return ev->type == YASL_EVENT_TEXT || ev->type == YASL_EVENT_PASTE || + ev->type == YASL_EVENT_DROP; } static void discard_pending(struct input_queue *q) { for (size_t i = 0; i < q->count; i++) { - size_t len; - free((void *)event_text(&q->events[(q->head + i) % q->capacity], &len)); + struct yasl_event *ev = &q->events[(q->head + i) & (q->capacity - 1)]; + if (has_text(ev)) free((void *)ev->text.data); } q->head = q->count = 0; } -bool input_queue_push(struct input_queue *q, const struct yasl_input_event *ev) +bool input_queue_push(struct input_queue *q, const struct yasl_event *ev) { - struct yasl_input_event copy = *ev; + struct yasl_event copy = *ev; char *owned = NULL; - if (ev->kind == YASL_INPUT_TEXT || ev->kind == YASL_INPUT_PASTE || - ev->kind == YASL_INPUT_DROP_FILES) { - size_t len; - const char *text = event_text(ev, &len); - if ((!text && len) || len == SIZE_MAX) goto failed; + if (!copy.time_ns) copy.time_ns = yasl_loop_now_ns(); + if (has_text(ev)) { + size_t len = ev->text.len; + if ((!ev->text.data && len) || len == SIZE_MAX) goto failed; owned = malloc(len + 1); if (!owned) goto failed; - if (len) memcpy(owned, text, len); + if (len) memcpy(owned, ev->text.data, len); owned[len] = '\0'; - set_text(©, owned); + copy.text.data = owned; + } + switch (ev->type) { + case YASL_EVENT_POINTER_MOTION: + if (!q->relative) { + copy.pointer.delta = q->has_last_pos + ? (struct yasl_vector2d){ev->pointer.pos.x - q->last_pos.x, + ev->pointer.pos.y - q->last_pos.y} + : (struct yasl_vector2d){0, 0}; + } + [[fallthrough]]; + case YASL_EVENT_POINTER_DOWN: + case YASL_EVENT_POINTER_UP: + q->last_pos = ev->pointer.pos; + q->has_last_pos = true; + break; + case YASL_EVENT_POINTER_LEAVE: + case YASL_EVENT_INPUT_RESET: + q->has_last_pos = false; + break; + default: + break; } if (q->count == q->capacity) { size_t capacity = q->capacity ? q->capacity * 2 : 32; if (capacity < q->capacity || capacity > SIZE_MAX / sizeof(*q->events)) goto failed; - struct yasl_input_event *events = malloc(capacity * sizeof(*events)); + struct yasl_event *events = malloc(capacity * sizeof(*events)); if (!events) goto failed; if (q->events && q->count > 0) { size_t first = q->capacity - q->head; @@ -76,10 +83,11 @@ failed: discard_pending(q); q->reset_surface = ev->surface; q->reset_pending = true; + q->has_last_pos = false; return false; } -bool input_queue_pop(struct input_queue *q, struct yasl_input_event *ev) +bool input_queue_pop(struct input_queue *q, struct yasl_event *ev) { if (!ev || (!q->count && !q->reset_pending)) return false; if (q->last_text) { @@ -87,18 +95,16 @@ bool input_queue_pop(struct input_queue *q, struct yasl_input_event *ev) q->last_text = NULL; } if (q->reset_pending) { - *ev = (struct yasl_input_event){ - .surface = q->reset_surface, .kind = YASL_INPUT_RESET, + *ev = (struct yasl_event){ + .type = YASL_EVENT_INPUT_RESET, .surface = q->reset_surface, + .time_ns = yasl_loop_now_ns(), }; q->reset_pending = false; return true; } *ev = q->events[q->head]; - if (ev->kind == YASL_INPUT_TEXT || ev->kind == YASL_INPUT_PASTE || - ev->kind == YASL_INPUT_DROP_FILES) { - size_t len; - q->last_text = (char *)event_text(ev, &len); - } + if (has_text(ev)) + q->last_text = (char *)ev->text.data; q->head = (q->head + 1) & (q->capacity - 1); q->count--; return true; |
