2022-03-03 09:15:57 +10:00
|
|
|
/* SPDX-License-Identifier: MIT */
|
2020-07-28 14:19:28 +10:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2020 Red Hat, Inc.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include "util-bits.h"
|
|
|
|
|
#include "util-io.h"
|
|
|
|
|
#include "util-macros.h"
|
|
|
|
|
#include "util-mem.h"
|
|
|
|
|
#include "util-sources.h"
|
|
|
|
|
#include "util-strings.h"
|
2020-08-18 13:04:01 +10:00
|
|
|
#include "util-structs.h"
|
2022-07-26 10:39:02 +10:00
|
|
|
#include "util-tristate.h"
|
2023-02-01 10:32:15 +10:00
|
|
|
#include "util-time.h"
|
2023-02-02 19:10:39 +10:00
|
|
|
#include "util-version.h"
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
#include "libeis-private.h"
|
2020-08-18 19:21:13 +10:00
|
|
|
#include "libeis-proto.h"
|
2020-08-18 20:32:22 +10:00
|
|
|
#include "brei-shared.h"
|
2023-02-01 10:32:15 +10:00
|
|
|
#include "eis-proto.h"
|
2020-07-28 14:19:28 +10:00
|
|
|
|
2022-07-26 10:39:02 +10:00
|
|
|
DEFINE_TRISTATE(started, finished, connected);
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
static void
|
|
|
|
|
eis_client_destroy(struct eis_client *client)
|
|
|
|
|
{
|
2023-02-02 11:58:08 +10:00
|
|
|
eis_connection_setup_unref(client->setup);
|
2023-02-01 15:36:41 +10:00
|
|
|
eis_connection_unref(client->connection);
|
2020-07-28 14:19:28 +10:00
|
|
|
free(client->name);
|
2020-08-07 10:54:30 +10:00
|
|
|
source_remove(client->source);
|
2020-07-28 14:19:28 +10:00
|
|
|
source_unref(client->source);
|
|
|
|
|
list_remove(&client->link);
|
|
|
|
|
}
|
2020-08-03 07:32:32 +10:00
|
|
|
|
2020-09-16 08:28:18 +10:00
|
|
|
static
|
2020-08-03 07:33:32 +10:00
|
|
|
OBJECT_IMPLEMENT_CREATE(eis_client);
|
2020-07-28 14:19:28 +10:00
|
|
|
static
|
2020-08-03 07:33:32 +10:00
|
|
|
OBJECT_IMPLEMENT_PARENT(eis_client, eis);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
_public_
|
2020-08-03 07:33:32 +10:00
|
|
|
OBJECT_IMPLEMENT_REF(eis_client);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
_public_
|
2022-03-03 10:55:21 +10:00
|
|
|
OBJECT_IMPLEMENT_UNREF_CLEANUP(eis_client);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
_public_
|
2020-08-03 07:33:32 +10:00
|
|
|
OBJECT_IMPLEMENT_GETTER(eis_client, name, const char*);
|
2020-10-22 14:05:09 +10:00
|
|
|
_public_
|
|
|
|
|
OBJECT_IMPLEMENT_SETTER(eis_client, user_data, void*);
|
|
|
|
|
_public_
|
|
|
|
|
OBJECT_IMPLEMENT_GETTER(eis_client, user_data, void*);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
_public_ struct eis*
|
|
|
|
|
eis_client_get_context(struct eis_client *client)
|
|
|
|
|
{
|
|
|
|
|
return eis_client_parent(client);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 10:32:15 +10:00
|
|
|
const struct brei_object *
|
|
|
|
|
eis_client_get_proto_object(struct eis_client *client)
|
|
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
return &client->connection->proto_object;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
|
eis_client_get_new_id(struct eis_client *client)
|
|
|
|
|
{
|
|
|
|
|
static const int offset = 0xff000000;
|
|
|
|
|
return offset | (client->next_object_id++ & ~offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
eis_client_register_object(struct eis_client *client, struct brei_object *object)
|
|
|
|
|
{
|
|
|
|
|
struct eis *eis = eis_client_get_context(client);
|
|
|
|
|
log_debug(eis, "registering %s v%u object %#x", object->interface->name, object->version, object->id);
|
|
|
|
|
list_append(&client->proto_objects, &object->link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
eis_client_unregister_object(struct eis_client *client, struct brei_object *object)
|
|
|
|
|
{
|
|
|
|
|
struct eis *eis = eis_client_get_context(client);
|
|
|
|
|
log_debug(eis, "deregistering %s v%u object %#x", object->interface->name, object->version, object->id);
|
|
|
|
|
list_remove(&object->link);
|
2023-02-01 10:32:15 +10:00
|
|
|
}
|
|
|
|
|
|
2023-01-31 12:11:36 +10:00
|
|
|
struct eis_client *
|
|
|
|
|
eis_client_get_client(struct eis_client *client)
|
|
|
|
|
{
|
|
|
|
|
return client;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-25 14:41:28 +10:00
|
|
|
_public_ bool
|
2022-03-28 15:56:44 +10:00
|
|
|
eis_client_is_sender(struct eis_client *client)
|
2022-02-25 14:41:28 +10:00
|
|
|
{
|
2022-03-28 15:56:44 +10:00
|
|
|
return client->is_sender;
|
2022-02-25 14:41:28 +10:00
|
|
|
}
|
|
|
|
|
|
2022-07-29 15:25:16 +10:00
|
|
|
_public_ bool
|
|
|
|
|
eis_client_has_capability(struct eis_client *client,
|
|
|
|
|
enum eis_device_capability cap)
|
|
|
|
|
{
|
|
|
|
|
switch (cap) {
|
|
|
|
|
case EIS_DEVICE_CAP_POINTER:
|
|
|
|
|
case EIS_DEVICE_CAP_POINTER_ABSOLUTE:
|
|
|
|
|
case EIS_DEVICE_CAP_KEYBOARD:
|
|
|
|
|
case EIS_DEVICE_CAP_TOUCH:
|
|
|
|
|
return flag_is_set(client->restrictions.cap_allow_mask, cap);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Quietly ignore other capabilities, we don't want to future-proof this */
|
|
|
|
|
if (cap == 0)
|
|
|
|
|
log_bug_client(eis_client_get_context(client), "Check for invalid capability 0");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
static struct eis_device *
|
|
|
|
|
eis_client_find_device(struct eis_client *client, uint32_t deviceid)
|
|
|
|
|
{
|
|
|
|
|
struct eis_seat *seat;
|
|
|
|
|
|
|
|
|
|
list_for_each(seat, &client->seats, link) {
|
|
|
|
|
struct eis_device *device;
|
|
|
|
|
|
|
|
|
|
list_for_each(device, &seat->devices, link) {
|
|
|
|
|
if (device->id == deviceid)
|
|
|
|
|
return device;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 10:32:15 +10:00
|
|
|
int
|
|
|
|
|
eis_client_send_message(struct eis_client *client, uint32_t object_id,
|
|
|
|
|
uint32_t opcode, const char *signature, size_t nargs, ...)
|
|
|
|
|
{
|
|
|
|
|
struct eis *eis = eis_client_get_context(client);
|
|
|
|
|
int fd = source_get_fd(client->source);
|
|
|
|
|
|
|
|
|
|
log_debug(eis, "sending: %#x:%u signature '%s'", object_id, opcode, signature);
|
|
|
|
|
|
|
|
|
|
va_list args;
|
|
|
|
|
va_start(args, nargs);
|
|
|
|
|
int rc = brei_send_message(fd, object_id, opcode, signature, nargs, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
return rc < 0 ? rc : 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-26 10:39:02 +10:00
|
|
|
static int
|
2023-02-02 11:58:08 +10:00
|
|
|
client_send_connection_setup(struct eis_client *client, struct eis_connection_setup *setup)
|
2022-07-26 10:39:02 +10:00
|
|
|
{
|
2023-02-02 11:58:08 +10:00
|
|
|
return eis_connection_event_connection_setup(client->connection,
|
|
|
|
|
eis_connection_setup_get_id(setup),
|
|
|
|
|
eis_connection_setup_get_version(setup));
|
2022-07-26 10:39:02 +10:00
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
static int
|
2023-02-02 14:47:26 +10:00
|
|
|
client_send_disconnect(struct eis_client *client, const char *reason)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
2023-02-02 14:47:26 +10:00
|
|
|
return eis_connection_event_disconnected(client->connection,
|
|
|
|
|
reason ? EIS_CONNECTION_DISCONNECT_REASON_ERROR : EIS_CONNECTION_DISCONNECT_REASON_DISCONNECTED,
|
|
|
|
|
reason);
|
2020-07-28 14:19:28 +10:00
|
|
|
}
|
|
|
|
|
|
2020-09-14 17:16:50 +10:00
|
|
|
static int
|
|
|
|
|
client_send_seat_added(struct eis_client *client, struct eis_seat *seat)
|
|
|
|
|
{
|
2023-02-02 19:43:31 +10:00
|
|
|
return eis_connection_event_seat(client->connection, eis_seat_get_id(seat),
|
|
|
|
|
eis_seat_get_version(seat));
|
2020-09-14 17:16:50 +10:00
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
static int
|
2020-08-13 12:55:25 +10:00
|
|
|
client_send_device_added(struct eis_client *client, struct eis_device *device)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
2023-02-01 10:32:15 +10:00
|
|
|
struct eis_seat *seat = eis_device_get_seat(device);
|
2023-02-01 15:36:41 +10:00
|
|
|
int rc = eis_connection_event_device_added(client->connection, device->id, device->capabilities,
|
2023-02-02 19:43:31 +10:00
|
|
|
device->name, eis_seat_get_id(seat),
|
2023-02-01 10:32:15 +10:00
|
|
|
device->type, device->width, device->height);
|
2021-07-21 14:51:00 +10:00
|
|
|
|
2021-08-10 16:59:34 +10:00
|
|
|
if (rc >= 0 && device->keymap)
|
2023-02-01 15:36:41 +10:00
|
|
|
rc = eis_connection_event_device_keymap(client->connection, device->id, device->keymap->type, device->keymap->size, device->keymap->fd);
|
2021-08-10 16:59:34 +10:00
|
|
|
|
2022-03-11 10:33:54 +10:00
|
|
|
if (rc >= 0 && device->type == EIS_DEVICE_TYPE_VIRTUAL) {
|
2021-08-10 16:59:34 +10:00
|
|
|
struct eis_region *r;
|
|
|
|
|
list_for_each(r, &device->regions, link) {
|
2023-02-01 15:36:41 +10:00
|
|
|
rc = eis_connection_event_device_region(client->connection, device->id, r->x, r->y, r->width, r->height, r->physical_scale);
|
2021-08-10 16:59:34 +10:00
|
|
|
}
|
2021-07-21 14:52:04 +10:00
|
|
|
}
|
|
|
|
|
|
2021-07-21 14:51:00 +10:00
|
|
|
if (rc >= 0)
|
2023-02-01 15:36:41 +10:00
|
|
|
rc = eis_connection_event_device_done(client->connection, device->id);
|
2021-07-21 14:51:00 +10:00
|
|
|
return rc;
|
2020-07-28 14:19:28 +10:00
|
|
|
}
|
|
|
|
|
|
2020-07-29 09:41:07 +10:00
|
|
|
static int
|
2020-08-13 12:55:25 +10:00
|
|
|
client_send_device_removed(struct eis_client *client, struct eis_device *device)
|
2020-07-29 09:41:07 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
return eis_connection_event_device_removed(client->connection, device->id);
|
2020-07-29 09:41:07 +10:00
|
|
|
}
|
|
|
|
|
|
2020-08-19 13:39:32 +10:00
|
|
|
static int
|
2021-08-23 08:25:33 +10:00
|
|
|
client_send_device_paused(struct eis_client *client, struct eis_device *device)
|
2020-08-19 13:39:32 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
return eis_connection_event_device_paused(client->connection, device->id);
|
2020-08-19 13:39:32 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
client_send_device_resumed(struct eis_client *client, struct eis_device *device)
|
|
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
return eis_connection_event_device_resumed(client->connection, device->id);
|
2020-08-19 13:39:32 +10:00
|
|
|
}
|
|
|
|
|
|
2021-08-23 09:00:29 +10:00
|
|
|
static int
|
|
|
|
|
client_send_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
|
|
|
|
|
const struct eis_xkb_modifiers *mods)
|
|
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
return eis_connection_event_keyboard_modifiers(client->connection, device->id,
|
2023-02-01 10:32:15 +10:00
|
|
|
mods->depressed, mods->locked,
|
|
|
|
|
mods->latched, mods->group);
|
2021-08-23 09:00:29 +10:00
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
_public_ void
|
|
|
|
|
eis_client_connect(struct eis_client *client)
|
|
|
|
|
{
|
|
|
|
|
switch(client->state) {
|
2023-02-02 13:24:06 +10:00
|
|
|
case EIS_CLIENT_STATE_DISCONNECTED:
|
|
|
|
|
return;
|
2020-07-28 14:19:28 +10:00
|
|
|
case EIS_CLIENT_STATE_CONNECTING:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2020-09-29 15:15:54 +10:00
|
|
|
log_bug_client(eis_client_get_context(client),
|
2022-08-02 16:41:01 +10:00
|
|
|
"%s: client already connected", __func__);
|
2020-07-28 14:19:28 +10:00
|
|
|
return;
|
|
|
|
|
}
|
2023-02-02 11:58:08 +10:00
|
|
|
client->state = EIS_CLIENT_STATE_CONNECTED;
|
2020-07-28 14:19:28 +10:00
|
|
|
}
|
|
|
|
|
|
2023-02-02 14:47:26 +10:00
|
|
|
static void
|
|
|
|
|
client_disconnect(struct eis_client *client, const char *reason)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
|
|
|
|
switch(client->state) {
|
|
|
|
|
case EIS_CLIENT_STATE_DISCONNECTED:
|
|
|
|
|
/* Client already disconnected? don't bother sending an
|
|
|
|
|
* event */
|
|
|
|
|
return;
|
|
|
|
|
case EIS_CLIENT_STATE_CONNECTING:
|
|
|
|
|
case EIS_CLIENT_STATE_CONNECTED:
|
2020-07-29 09:41:07 +10:00
|
|
|
{
|
2021-07-22 13:13:03 +10:00
|
|
|
struct eis_seat *s;
|
|
|
|
|
list_for_each_safe(s, &client->seats, link) {
|
2022-02-25 15:45:07 +10:00
|
|
|
eis_seat_drop(s);
|
2020-10-26 09:24:43 +10:00
|
|
|
}
|
2020-07-29 09:41:07 +10:00
|
|
|
}
|
2020-07-28 14:19:28 +10:00
|
|
|
eis_queue_disconnect_event(client);
|
2020-08-26 11:00:50 +10:00
|
|
|
_fallthrough_;
|
2020-08-07 13:57:15 +10:00
|
|
|
case EIS_CLIENT_STATE_NEW:
|
2023-02-02 14:47:26 +10:00
|
|
|
client_send_disconnect(client, reason);
|
2020-07-28 14:19:28 +10:00
|
|
|
client->state = EIS_CLIENT_STATE_DISCONNECTED;
|
2020-07-30 21:17:54 +10:00
|
|
|
source_remove(client->source);
|
2020-07-28 14:19:28 +10:00
|
|
|
break;
|
|
|
|
|
}
|
2020-08-07 10:56:54 +10:00
|
|
|
|
|
|
|
|
eis_client_unref(client);
|
2020-07-28 14:19:28 +10:00
|
|
|
}
|
|
|
|
|
|
2023-02-02 14:47:26 +10:00
|
|
|
_public_ void
|
|
|
|
|
eis_client_disconnect(struct eis_client *client)
|
|
|
|
|
{
|
|
|
|
|
client_disconnect(client, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-02 11:58:08 +10:00
|
|
|
void
|
2023-02-02 19:10:39 +10:00
|
|
|
eis_client_setup_done(struct eis_client *client, const char *name, bool is_sender,
|
|
|
|
|
const struct eis_client_interface_versions *versions)
|
2023-02-02 11:58:08 +10:00
|
|
|
{
|
|
|
|
|
client->setup = NULL; /* connection object cleans itself up */
|
|
|
|
|
client->name = xstrdup(name);
|
|
|
|
|
client->is_sender = is_sender;
|
2023-02-02 19:10:39 +10:00
|
|
|
client->interface_versions = *versions;
|
2023-02-02 11:58:08 +10:00
|
|
|
|
|
|
|
|
eis_queue_connect_event(client);
|
|
|
|
|
client->state = EIS_CLIENT_STATE_CONNECTING;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_close_device(struct eis_connection *connection, uint32_t deviceid)
|
2021-07-16 18:17:15 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
|
|
|
|
eis_device_closed_by_client(device);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2021-07-16 18:17:15 +10:00
|
|
|
return 0;
|
|
|
|
|
}
|
2020-07-28 14:19:28 +10:00
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
#define DISCONNECT_IF_RECEIVER_CONTEXT(client_) do { \
|
|
|
|
|
if (!(client_)->is_sender) { \
|
2022-03-28 16:09:52 +10:00
|
|
|
struct eis *_ctx = eis_client_get_context(client_); \
|
2022-08-02 16:41:01 +10:00
|
|
|
log_bug_client(_ctx, "Invalid event from receiver ei context. Disconnecting client"); \
|
2022-02-25 14:41:28 +10:00
|
|
|
return -EINVAL; \
|
|
|
|
|
} \
|
|
|
|
|
} while(0)
|
|
|
|
|
|
2021-08-24 09:53:10 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_start_emulating(struct eis_connection *connection, uint32_t deviceid, uint32_t sequence)
|
2021-08-24 09:53:10 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-08-24 09:53:10 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2023-01-30 10:31:07 +10:00
|
|
|
eis_device_event_start_emulating(device, sequence);
|
2021-08-24 09:53:10 +10:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_stop_emulating(struct eis_connection *connection, uint32_t deviceid)
|
2021-08-24 09:53:10 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-08-24 09:53:10 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
eis_device_event_stop_emulating(device);
|
2021-08-24 09:53:10 +10:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-23 10:50:23 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_frame(struct eis_connection *connection, uint32_t deviceid, uint32_t time, uint32_t micros)
|
2021-08-23 10:50:23 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-08-23 10:50:23 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2023-02-01 10:32:15 +10:00
|
|
|
return eis_device_event_frame(device, ms2us(time) + micros);
|
2021-08-23 10:50:23 +10:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_pointer_rel(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
float x, float y)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_pointer_rel(device, x, y);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-22 13:17:54 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_pointer_abs(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
float x, float y)
|
2020-09-22 13:17:54 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2020-09-22 13:17:54 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_pointer_abs(device, x, y);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2020-09-22 13:17:54 +10:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 12:00:31 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_pointer_button(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
uint32_t button, uint32_t state)
|
2020-08-03 12:00:31 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2023-02-01 10:32:15 +10:00
|
|
|
return eis_device_event_pointer_button(device, button, !!state);
|
2020-08-03 12:00:31 +10:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-14 10:00:59 +02:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_pointer_scroll(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
float x, float y)
|
2021-07-14 10:00:59 +02:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-07-14 10:00:59 +02:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_pointer_scroll(device, x, y);
|
2021-07-14 10:00:59 +02:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_pointer_scroll_discrete(struct eis_connection *connection, uint32_t deviceid,
|
2021-08-12 10:20:42 +10:00
|
|
|
int32_t x, int32_t y)
|
2021-07-14 10:00:59 +02:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-07-14 10:00:59 +02:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_pointer_scroll_discrete(device, x, y);
|
2021-07-14 10:00:59 +02:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2021-08-23 11:28:56 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_pointer_scroll_stop(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
uint32_t x, uint32_t y, uint32_t is_cancel)
|
2021-08-23 11:28:56 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-08-23 11:28:56 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device) {
|
|
|
|
|
if (is_cancel)
|
2023-02-01 10:32:15 +10:00
|
|
|
return eis_device_event_pointer_scroll_cancel(device, !!x, !!y);
|
2022-02-22 13:13:37 +10:00
|
|
|
else
|
2023-02-01 10:32:15 +10:00
|
|
|
return eis_device_event_pointer_scroll_stop(device, !!x, !!y);
|
2021-08-23 11:28:56 +10:00
|
|
|
}
|
2022-02-22 13:13:37 +10:00
|
|
|
|
2021-08-23 11:28:56 +10:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-03 12:00:31 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_keyboard_key(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
uint32_t key, uint32_t state)
|
2020-08-03 12:00:31 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2020-08-03 12:00:31 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2023-02-01 10:32:15 +10:00
|
|
|
return eis_device_event_keyboard_key(device, key, !!state);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2020-08-03 12:00:31 +10:00
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-22 14:40:43 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_touch_down(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
uint32_t touchid, float x, float y)
|
2020-09-22 14:40:43 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2020-09-14 17:16:50 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_touch_down(device, touchid, x, y);
|
2020-09-22 14:40:43 +10:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-07 14:39:00 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_touch_motion(struct eis_connection *connection, uint32_t deviceid,
|
2023-02-01 10:32:15 +10:00
|
|
|
uint32_t touchid, float x, float y)
|
2021-08-12 10:20:42 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-08-12 10:20:42 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_touch_motion(device, touchid, x, y);
|
2021-08-12 10:20:42 +10:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_touch_up(struct eis_connection *connection, uint32_t deviceid, uint32_t touchid)
|
2021-08-12 10:20:42 +10:00
|
|
|
{
|
2023-02-01 15:36:41 +10:00
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
DISCONNECT_IF_RECEIVER_CONTEXT(client);
|
2022-02-25 14:41:28 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
struct eis_device *device = eis_client_find_device(client, deviceid);
|
2021-08-12 10:20:42 +10:00
|
|
|
|
2022-02-22 13:13:37 +10:00
|
|
|
if (device)
|
2022-02-22 13:28:53 +10:00
|
|
|
return eis_device_event_touch_up(device, touchid);
|
2021-08-12 10:20:42 +10:00
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
static int
|
2023-02-01 15:36:41 +10:00
|
|
|
client_msg_disconnect(struct eis_connection *connection)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
2023-02-02 14:47:26 +10:00
|
|
|
struct eis_client * client = eis_connection_get_client(connection);
|
|
|
|
|
client_disconnect(client, NULL);
|
|
|
|
|
return 0;
|
2020-07-28 14:19:28 +10:00
|
|
|
}
|
|
|
|
|
|
2023-02-02 10:07:31 +10:00
|
|
|
static int
|
|
|
|
|
client_msg_sync(struct eis_connection *connection, uint32_t new_id)
|
|
|
|
|
{
|
|
|
|
|
if (new_id == 0)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
struct eis_client *client = eis_connection_get_client(connection);
|
2023-02-03 09:06:53 +10:00
|
|
|
struct eis_callback *callback = eis_callback_new(client, new_id, client->interface_versions.ei_callback);
|
2023-02-02 10:07:31 +10:00
|
|
|
log_debug(eis_client_get_context(client) , "object %u: connection sync done", new_id);
|
|
|
|
|
int rc = eis_callback_event_done(callback, 0);
|
|
|
|
|
eis_callback_unref(callback);
|
|
|
|
|
return rc;
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
static const struct eis_connection_interface intf_state_new = {
|
2023-02-02 10:07:31 +10:00
|
|
|
.sync = client_msg_sync,
|
2021-08-12 10:20:42 +10:00
|
|
|
.disconnect = client_msg_disconnect,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Client is waiting for us, shouldn't send anything except disconnect */
|
2023-02-01 15:36:41 +10:00
|
|
|
static const struct eis_connection_interface intf_state_connecting = {
|
2023-02-02 10:07:31 +10:00
|
|
|
.sync = client_msg_sync,
|
2021-08-12 10:20:42 +10:00
|
|
|
.disconnect = client_msg_disconnect,
|
|
|
|
|
};
|
|
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
static const struct eis_connection_interface intf_state_connected = {
|
2023-02-02 10:07:31 +10:00
|
|
|
.sync = client_msg_sync,
|
2021-08-12 10:20:42 +10:00
|
|
|
.disconnect = client_msg_disconnect,
|
|
|
|
|
.close_device = client_msg_close_device,
|
2022-07-27 10:05:25 +10:00
|
|
|
|
2022-02-22 11:01:39 +10:00
|
|
|
/* events */
|
2021-08-24 09:53:10 +10:00
|
|
|
.start_emulating = client_msg_start_emulating,
|
|
|
|
|
.stop_emulating = client_msg_stop_emulating,
|
2023-02-01 10:32:15 +10:00
|
|
|
.pointer_relative = client_msg_pointer_rel,
|
|
|
|
|
.pointer_absolute = client_msg_pointer_abs,
|
|
|
|
|
.pointer_button = client_msg_pointer_button,
|
|
|
|
|
.pointer_scroll = client_msg_pointer_scroll,
|
|
|
|
|
.pointer_scroll_stop = client_msg_pointer_scroll_stop,
|
|
|
|
|
.pointer_scroll_discrete = client_msg_pointer_scroll_discrete,
|
|
|
|
|
.keyboard_key = client_msg_keyboard_key,
|
2021-08-12 10:20:42 +10:00
|
|
|
.touch_down = client_msg_touch_down,
|
|
|
|
|
.touch_motion = client_msg_touch_motion,
|
|
|
|
|
.touch_up = client_msg_touch_up,
|
2021-08-23 10:50:23 +10:00
|
|
|
.frame = client_msg_frame,
|
2021-08-12 10:20:42 +10:00
|
|
|
};
|
|
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
static const struct eis_connection_interface *interfaces[] = {
|
2021-08-12 10:20:42 +10:00
|
|
|
[EIS_CLIENT_STATE_NEW] = &intf_state_new,
|
|
|
|
|
[EIS_CLIENT_STATE_CONNECTING] = &intf_state_connecting,
|
|
|
|
|
[EIS_CLIENT_STATE_CONNECTED] = &intf_state_connected,
|
|
|
|
|
[EIS_CLIENT_STATE_DISCONNECTED] = NULL,
|
|
|
|
|
};
|
2020-07-28 14:19:28 +10:00
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
const struct eis_connection_interface *
|
2023-02-01 10:32:15 +10:00
|
|
|
eis_client_get_interface(struct eis_client *client)
|
|
|
|
|
{
|
|
|
|
|
assert(client->state < ARRAY_LENGTH(interfaces));
|
|
|
|
|
return interfaces[client->state];
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-18 20:32:22 +10:00
|
|
|
static int
|
2023-02-01 10:32:15 +10:00
|
|
|
lookup_object(uint32_t object_id, struct brei_object **object, void *userdata)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
2020-08-18 20:32:22 +10:00
|
|
|
struct eis_client *client = userdata;
|
2021-08-12 10:20:42 +10:00
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
struct brei_object *obj;
|
|
|
|
|
list_for_each(obj, &client->proto_objects, link) {
|
|
|
|
|
if (obj->id == object_id) {
|
|
|
|
|
*object = obj;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-08-12 10:20:42 +10:00
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
return -ENOENT;
|
2021-08-12 10:20:42 +10:00
|
|
|
}
|
2020-07-31 14:14:21 +10:00
|
|
|
|
2020-08-18 20:32:22 +10:00
|
|
|
static void
|
|
|
|
|
client_dispatch(struct source *source, void *userdata)
|
|
|
|
|
{
|
2020-10-21 10:45:52 +10:00
|
|
|
_unref_(eis_client) *client = eis_client_ref(userdata);
|
2020-08-18 20:32:22 +10:00
|
|
|
enum eis_client_state old_state = client->state;
|
2020-07-28 14:19:28 +10:00
|
|
|
|
2023-02-01 10:32:15 +10:00
|
|
|
int rc = brei_dispatch(source_get_fd(source), lookup_object, client);
|
2022-02-21 14:37:04 +10:00
|
|
|
if (rc < 0) {
|
|
|
|
|
brei_drain_fd(source_get_fd(source));
|
2023-02-02 14:47:26 +10:00
|
|
|
client_disconnect(client, strerror(-rc));
|
2022-02-21 14:37:04 +10:00
|
|
|
}
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
static const char *client_states[] = {
|
2020-08-07 13:57:15 +10:00
|
|
|
"NEW",
|
2020-07-28 14:19:28 +10:00
|
|
|
"CONNECTING",
|
|
|
|
|
"CONNECTED",
|
|
|
|
|
"DISCONNECTED",
|
|
|
|
|
};
|
2020-08-11 11:06:07 +10:00
|
|
|
if (rc == -ECANCELED)
|
2023-03-01 15:24:37 +10:00
|
|
|
log_info(eis_client_get_context(client), "Disconnected");
|
2020-08-11 11:06:07 +10:00
|
|
|
else if (rc)
|
2023-03-01 15:24:37 +10:00
|
|
|
log_warn(eis_client_get_context(client), "Client error: %s",
|
2020-07-28 14:19:28 +10:00
|
|
|
strerror(-rc));
|
2020-07-29 11:52:23 +10:00
|
|
|
if (old_state != client->state) {
|
2022-07-27 11:22:42 +10:00
|
|
|
assert(old_state < ARRAY_LENGTH(client_states));
|
|
|
|
|
assert(client->state < ARRAY_LENGTH(client_states));
|
2023-03-01 15:24:37 +10:00
|
|
|
log_debug(eis_client_get_context(client), "Client dispatch: %s -> %s",
|
2020-07-29 11:52:23 +10:00
|
|
|
client_states[old_state],
|
|
|
|
|
client_states[client->state]);
|
|
|
|
|
}
|
2020-07-28 14:19:28 +10:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct eis_client *
|
|
|
|
|
eis_client_new(struct eis *eis, int fd)
|
|
|
|
|
{
|
|
|
|
|
static uint32_t client_id;
|
|
|
|
|
struct eis_client *client = eis_client_create(&eis->object);
|
|
|
|
|
|
2022-03-28 15:56:44 +10:00
|
|
|
client->is_sender = true;
|
2020-07-28 14:19:28 +10:00
|
|
|
client->id = ++client_id;
|
2020-09-14 17:16:50 +10:00
|
|
|
list_init(&client->seats);
|
|
|
|
|
list_init(&client->seats_pending);
|
2023-02-01 15:36:41 +10:00
|
|
|
list_init(&client->proto_objects);
|
|
|
|
|
|
2023-02-02 19:10:39 +10:00
|
|
|
client->interface_versions = (struct eis_client_interface_versions){
|
|
|
|
|
.ei_connection = VERSION_V(1),
|
2023-02-03 15:48:50 +10:00
|
|
|
.ei_connection_setup = VERSION_V(1),
|
2023-02-03 09:06:53 +10:00
|
|
|
.ei_callback = VERSION_V(1),
|
2023-02-02 19:43:31 +10:00
|
|
|
.ei_seat = VERSION_V(1),
|
2023-02-02 19:10:39 +10:00
|
|
|
};
|
|
|
|
|
|
2023-02-01 15:36:41 +10:00
|
|
|
client->connection = eis_connection_new(client);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
2020-08-07 13:07:10 +10:00
|
|
|
struct source *s = source_new(fd, client_dispatch, client);
|
|
|
|
|
int rc = sink_add_source(eis->sink, s);
|
|
|
|
|
|
|
|
|
|
if (rc != 0) {
|
|
|
|
|
source_unref(s);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-07 10:54:30 +10:00
|
|
|
client->source = source_ref(s);
|
2020-08-07 13:57:15 +10:00
|
|
|
client->state = EIS_CLIENT_STATE_NEW;
|
2022-08-01 11:52:07 +10:00
|
|
|
client->restrictions.cap_allow_mask =
|
|
|
|
|
bit(EIS_DEVICE_CAP_KEYBOARD) |
|
|
|
|
|
bit(EIS_DEVICE_CAP_POINTER) |
|
|
|
|
|
bit(EIS_DEVICE_CAP_POINTER_ABSOLUTE) |
|
|
|
|
|
bit(EIS_DEVICE_CAP_TOUCH);
|
2020-07-28 14:19:28 +10:00
|
|
|
|
2020-08-07 10:56:54 +10:00
|
|
|
eis_add_client(eis, eis_client_ref(client));
|
|
|
|
|
|
2020-08-07 13:07:10 +10:00
|
|
|
source_unref(s);
|
|
|
|
|
|
2023-02-02 11:58:08 +10:00
|
|
|
/* Send the event for the connection setup interface */
|
2023-02-02 19:10:39 +10:00
|
|
|
struct eis_connection_setup *setup = eis_connection_setup_new(client, eis_client_get_new_id(client),
|
|
|
|
|
&client->interface_versions);
|
2023-02-02 11:58:08 +10:00
|
|
|
client_send_connection_setup(client, setup);
|
|
|
|
|
client->setup = setup;
|
2022-07-26 10:39:02 +10:00
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
return client;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-14 17:16:50 +10:00
|
|
|
void
|
|
|
|
|
eis_client_add_seat(struct eis_client *client, struct eis_seat *seat)
|
|
|
|
|
{
|
|
|
|
|
/* remove from the pending list first */
|
|
|
|
|
list_remove(&seat->link);
|
|
|
|
|
/* We own this seat now */
|
|
|
|
|
eis_seat_ref(seat);
|
|
|
|
|
list_append(&client->seats, &seat->link);
|
|
|
|
|
client_send_seat_added(client, seat);
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-28 14:19:28 +10:00
|
|
|
void
|
2021-07-16 18:17:15 +10:00
|
|
|
eis_client_add_device(struct eis_client *client, struct eis_device *device)
|
2020-07-28 14:19:28 +10:00
|
|
|
{
|
2020-08-13 12:55:25 +10:00
|
|
|
client_send_device_added(client, device);
|
2020-07-28 14:19:28 +10:00
|
|
|
}
|
2020-07-29 09:41:07 +10:00
|
|
|
|
|
|
|
|
void
|
2021-07-16 18:17:15 +10:00
|
|
|
eis_client_remove_device(struct eis_client *client, struct eis_device *device)
|
2020-07-29 09:41:07 +10:00
|
|
|
{
|
2020-08-13 12:55:25 +10:00
|
|
|
client_send_device_removed(client, device);
|
2020-07-29 09:41:07 +10:00
|
|
|
}
|
2020-08-19 13:39:32 +10:00
|
|
|
|
|
|
|
|
void
|
2021-08-23 08:25:33 +10:00
|
|
|
eis_client_pause_device(struct eis_client *client, struct eis_device *device)
|
2020-08-19 13:39:32 +10:00
|
|
|
{
|
2021-08-23 08:25:33 +10:00
|
|
|
client_send_device_paused(client, device);
|
2020-08-19 13:39:32 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
eis_client_resume_device(struct eis_client *client, struct eis_device *device)
|
|
|
|
|
{
|
|
|
|
|
client_send_device_resumed(client, device);
|
|
|
|
|
}
|
2021-08-23 09:00:29 +10:00
|
|
|
|
|
|
|
|
void
|
|
|
|
|
eis_client_keyboard_modifiers(struct eis_client *client, struct eis_device *device,
|
|
|
|
|
uint32_t depressed, uint32_t latched, uint32_t locked,
|
|
|
|
|
uint32_t group)
|
|
|
|
|
{
|
|
|
|
|
struct eis_xkb_modifiers mods = {
|
|
|
|
|
.depressed = depressed,
|
|
|
|
|
.locked = locked,
|
|
|
|
|
.latched = latched,
|
|
|
|
|
.group = group,
|
|
|
|
|
};
|
|
|
|
|
client_send_keyboard_modifiers(client, device, &mods);
|
|
|
|
|
}
|
|
|
|
|
|