blob: b5706e48cfe78a4a8ed449093d336992b823afc8 [file] [log] [blame] [edit]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sommelier.h" // NOLINT(build/include_directory)
#include "sommelier-inpututils.h" // NOLINT(build/include_directory)
#include "sommelier-transform.h" // NOLINT(build/include_directory)
#include <algorithm>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <wayland-util.h>
struct sl_touchrecorder {
struct wl_touch* proxy;
sl_touchrecorder_frame_cb* frame_cb;
sl_touchrecorder_cancel_cb* cancel_cb;
void* data;
unsigned events_size;
unsigned events_alloc;
struct sl_touchrecorder_event events[32];
};
static void sl_touchrecorder_reset(struct sl_touchrecorder* recorder) {
recorder->events_size = 0;
}
static void sl_touchrecorder_record_event(struct sl_touchrecorder* recorder,
enum sl_touchrecorder_event_type type,
uint32_t serial,
uint32_t time,
struct wl_surface* surface,
int32_t id,
wl_fixed_t x,
wl_fixed_t y) {
unsigned index = recorder->events_size;
if (index < recorder->events_alloc) {
struct sl_touchrecorder_event* event = &recorder->events[index];
if (index == recorder->events_alloc - 1) {
if (type == SL_TOUCHRECORDER_EVENT_FRAME ||
type == SL_TOUCHRECORDER_EVENT_CANCEL) {
event->type = type;
recorder->events_size++;
}
} else {
event->type = type;
event->serial = serial;
event->time = time;
event->surface = surface;
event->id = id;
event->x = x;
event->y = y;
recorder->events_size++;
}
}
if (type == SL_TOUCHRECORDER_EVENT_FRAME) {
if (recorder->frame_cb)
recorder->frame_cb(recorder->data, recorder);
sl_touchrecorder_reset(recorder);
} else if (type == SL_TOUCHRECORDER_EVENT_CANCEL) {
if (recorder->cancel_cb)
recorder->cancel_cb(recorder->data, recorder);
sl_touchrecorder_reset(recorder);
}
}
static void sl_touchrecorder_down(void* data,
struct wl_touch* wl_touch,
uint32_t serial,
uint32_t time,
struct wl_surface* surface,
int32_t id,
wl_fixed_t x,
wl_fixed_t y) {
struct sl_touchrecorder* recorder = static_cast<sl_touchrecorder*>(data);
sl_touchrecorder_record_event(recorder, SL_TOUCHRECORDER_EVENT_DOWN, serial,
time, surface, id, x, y);
}
static void sl_touchrecorder_up(void* data,
struct wl_touch* wl_touch,
uint32_t serial,
uint32_t time,
int32_t id) {
struct sl_touchrecorder* recorder = static_cast<sl_touchrecorder*>(data);
sl_touchrecorder_record_event(recorder, SL_TOUCHRECORDER_EVENT_UP, serial,
time, nullptr, id, 0, 0);
}
static void sl_touchrecorder_motion(void* data,
struct wl_touch* wl_touch,
uint32_t time,
int32_t id,
wl_fixed_t x,
wl_fixed_t y) {
struct sl_touchrecorder* recorder = static_cast<sl_touchrecorder*>(data);
sl_touchrecorder_record_event(recorder, SL_TOUCHRECORDER_EVENT_MOTION, 0,
time, nullptr, id, x, y);
}
static void sl_touchrecorder_frame(void* data, struct wl_touch* wl_touch) {
struct sl_touchrecorder* recorder = static_cast<sl_touchrecorder*>(data);
sl_touchrecorder_record_event(recorder, SL_TOUCHRECORDER_EVENT_FRAME, 0, 0,
nullptr, 0, 0, 0);
}
static void sl_touchrecorder_cancel(void* data, struct wl_touch* wl_touch) {
struct sl_touchrecorder* recorder = static_cast<sl_touchrecorder*>(data);
sl_touchrecorder_record_event(recorder, SL_TOUCHRECORDER_EVENT_CANCEL, 0, 0,
nullptr, 0, 0, 0);
}
static const struct wl_touch_listener sl_touchrecorder_listener = {
sl_touchrecorder_down, sl_touchrecorder_up, sl_touchrecorder_motion,
sl_touchrecorder_frame, sl_touchrecorder_cancel};
struct sl_touchrecorder* sl_touchrecorder_attach(
struct wl_touch* proxy,
sl_touchrecorder_frame_cb* frame_cb,
sl_touchrecorder_cancel_cb* cancel_cb,
void* data) {
struct sl_touchrecorder* recorder = new sl_touchrecorder();
recorder->proxy = proxy;
recorder->frame_cb = frame_cb;
recorder->cancel_cb = cancel_cb;
recorder->data = data;
recorder->events_size = 0;
recorder->events_alloc =
sizeof(recorder->events) / sizeof(recorder->events[0]);
wl_touch_add_listener(proxy, &sl_touchrecorder_listener, recorder);
return recorder;
}
void sl_touchrecorder_destroy(struct sl_touchrecorder* recorder) {
delete recorder;
}
void sl_touchrecorder_replay_to_listener(struct sl_touchrecorder* recorder,
const struct wl_touch_listener* listen,
void* data) {
for (unsigned i = 0; i < recorder->events_size; i++) {
struct sl_touchrecorder_event* event = &recorder->events[i];
switch (event->type) {
case SL_TOUCHRECORDER_EVENT_NONE:
break;
case SL_TOUCHRECORDER_EVENT_DOWN:
listen->down(data, recorder->proxy, event->serial, event->time,
event->surface, event->id, event->x, event->y);
break;
case SL_TOUCHRECORDER_EVENT_UP:
listen->up(data, recorder->proxy, event->serial, event->time,
event->id);
break;
case SL_TOUCHRECORDER_EVENT_MOTION:
listen->motion(data, recorder->proxy, event->time, event->id, event->x,
event->y);
break;
case SL_TOUCHRECORDER_EVENT_FRAME:
listen->frame(data, recorder->proxy);
break;
case SL_TOUCHRECORDER_EVENT_CANCEL:
listen->cancel(data, recorder->proxy);
break;
default:
abort();
}
}
}
void sl_touchrecorder_purge_id(struct sl_touchrecorder* recorder, int32_t id) {
for (unsigned i = 0; i < recorder->events_size; i++) {
struct sl_touchrecorder_event* event = &recorder->events[i];
if (event->type < SL_TOUCHRECORDER_EVENT_FRAME && event->id == id) {
event->type = SL_TOUCHRECORDER_EVENT_NONE;
}
}
}