Compare commits
8 Commits
master
...
multi-seat
Author | SHA1 | Date |
---|---|---|
Andri Yngvason | 9e034fabbc | |
Andri Yngvason | 5476e431bd | |
Andri Yngvason | e037ca32ec | |
Andri Yngvason | b08a44e446 | |
Andri Yngvason | e4412e4d52 | |
Andri Yngvason | f818da7abe | |
Andri Yngvason | 3ff02f0681 | |
Andri Yngvason | 013dabf41e |
|
@ -17,6 +17,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
struct seat {
|
struct seat {
|
||||||
|
@ -26,6 +27,12 @@ struct seat {
|
||||||
uint32_t id;
|
uint32_t id;
|
||||||
uint32_t capabilities;
|
uint32_t capabilities;
|
||||||
char name[256];
|
char name[256];
|
||||||
|
|
||||||
|
bool has_capabilities;
|
||||||
|
bool has_name;
|
||||||
|
|
||||||
|
void (*on_ready)(struct seat*);
|
||||||
|
void* userdata;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct seat* seat_new(struct wl_seat* wl_seat, uint32_t id);
|
struct seat* seat_new(struct wl_seat* wl_seat, uint32_t id);
|
||||||
|
|
|
@ -21,6 +21,7 @@ client_protocols = [
|
||||||
'xdg-output-unstable-v1.xml',
|
'xdg-output-unstable-v1.xml',
|
||||||
'linux-dmabuf-unstable-v1.xml',
|
'linux-dmabuf-unstable-v1.xml',
|
||||||
'wlr-data-control-unstable-v1.xml',
|
'wlr-data-control-unstable-v1.xml',
|
||||||
|
'transient-seat-unstable-v1.xml',
|
||||||
]
|
]
|
||||||
|
|
||||||
client_protos_src = []
|
client_protos_src = []
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<protocol name="transient_seat_unstable_v1">
|
||||||
|
<copyright>
|
||||||
|
Copyright © 2020 Andri Yngvason
|
||||||
|
|
||||||
|
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.
|
||||||
|
</copyright>
|
||||||
|
|
||||||
|
<description summary="Protocol for creating temporary seats">
|
||||||
|
The transient seat protocol can be used by clients to create independent
|
||||||
|
seats that will be removed when the client disconnects. The client also gets
|
||||||
|
a handle to the seat which can be used to remove the seat.
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<interface name="zext_transient_seat_manager_v1" version="1">
|
||||||
|
<request name="create">
|
||||||
|
<description summary="Create a transient seat">
|
||||||
|
Create a new seat that is removed when the client closes the connection.
|
||||||
|
|
||||||
|
The client may suggest a name for the seat, but the server may choose
|
||||||
|
whichever name it sees fit, except the name must not collide with the
|
||||||
|
name of another seat.
|
||||||
|
|
||||||
|
It is suggested that the client choose a sufficiently unique name, e.g.
|
||||||
|
something containing the pid and an incremental numeric value.
|
||||||
|
</description>
|
||||||
|
<arg name="suggested_name" type="string"/>
|
||||||
|
<arg name="seat" type="new_id" interface="zext_transient_seat_v1"/>
|
||||||
|
</request>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="Destroy the manager">
|
||||||
|
Destroy the manager
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
|
||||||
|
<interface name="zext_transient_seat_v1" version="1">
|
||||||
|
<enum name="error">
|
||||||
|
<entry name="unspec" value="0"
|
||||||
|
summary="Operation failed for unspecified reason"/>
|
||||||
|
<entry name="name_taken" value="1"
|
||||||
|
summary="The suggested name was already taken"/>
|
||||||
|
<entry name="invalid_name" value="2"
|
||||||
|
summary="The suggested name contains invalid characters"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<event name="failed">
|
||||||
|
<description summary="seat creation failed">
|
||||||
|
This event indicates that the seat creation failed. No event is
|
||||||
|
generated after this and the client should destroy the transient seat
|
||||||
|
object.
|
||||||
|
</description>
|
||||||
|
<arg name="error" type="uint" enum="error"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<event name="ready">
|
||||||
|
<description summary="seat has been created">
|
||||||
|
This event indicates that the seat has been created and tells the client
|
||||||
|
which name was chosen for it. It is generated after the seat is created.
|
||||||
|
No event is generated after this.
|
||||||
|
</description>
|
||||||
|
<arg name="name" type="string"/>
|
||||||
|
</event>
|
||||||
|
|
||||||
|
<request name="destroy" type="destructor">
|
||||||
|
<description summary="Destroy the seat">
|
||||||
|
Destroy the seat
|
||||||
|
</description>
|
||||||
|
</request>
|
||||||
|
</interface>
|
||||||
|
</protocol>
|
213
src/main.c
213
src/main.c
|
@ -40,6 +40,7 @@
|
||||||
#include "virtual-keyboard-unstable-v1.h"
|
#include "virtual-keyboard-unstable-v1.h"
|
||||||
#include "xdg-output-unstable-v1.h"
|
#include "xdg-output-unstable-v1.h"
|
||||||
#include "linux-dmabuf-unstable-v1.h"
|
#include "linux-dmabuf-unstable-v1.h"
|
||||||
|
#include "transient-seat-unstable-v1.h"
|
||||||
#include "screencopy.h"
|
#include "screencopy.h"
|
||||||
#include "data-control.h"
|
#include "data-control.h"
|
||||||
#include "strlcpy.h"
|
#include "strlcpy.h"
|
||||||
|
@ -68,6 +69,17 @@
|
||||||
|
|
||||||
#define MAYBE_UNUSED __attribute__((unused))
|
#define MAYBE_UNUSED __attribute__((unused))
|
||||||
|
|
||||||
|
struct wv_client {
|
||||||
|
struct wl_list link;
|
||||||
|
|
||||||
|
struct keyboard kb;
|
||||||
|
struct pointer pointer;
|
||||||
|
|
||||||
|
struct wl_seat* wl_seat;
|
||||||
|
char seat_name[256];
|
||||||
|
struct zext_transient_seat_v1* chair;
|
||||||
|
};
|
||||||
|
|
||||||
struct wayvnc {
|
struct wayvnc {
|
||||||
bool do_exit;
|
bool do_exit;
|
||||||
|
|
||||||
|
@ -75,6 +87,7 @@ struct wayvnc {
|
||||||
struct wl_registry* registry;
|
struct wl_registry* registry;
|
||||||
struct wl_list outputs;
|
struct wl_list outputs;
|
||||||
struct wl_list seats;
|
struct wl_list seats;
|
||||||
|
struct wl_list clients;
|
||||||
struct cfg cfg;
|
struct cfg cfg;
|
||||||
|
|
||||||
struct zxdg_output_manager_v1* xdg_output_manager;
|
struct zxdg_output_manager_v1* xdg_output_manager;
|
||||||
|
@ -87,8 +100,6 @@ struct wayvnc {
|
||||||
const struct seat* selected_seat;
|
const struct seat* selected_seat;
|
||||||
|
|
||||||
struct screencopy screencopy;
|
struct screencopy screencopy;
|
||||||
struct pointer pointer_backend;
|
|
||||||
struct keyboard keyboard_backend;
|
|
||||||
struct data_control data_control;
|
struct data_control data_control;
|
||||||
|
|
||||||
struct aml_handler* wayland_handler;
|
struct aml_handler* wayland_handler;
|
||||||
|
@ -112,6 +123,7 @@ struct wayvnc {
|
||||||
void wayvnc_exit(struct wayvnc* self);
|
void wayvnc_exit(struct wayvnc* self);
|
||||||
void on_capture_done(struct screencopy* sc);
|
void on_capture_done(struct screencopy* sc);
|
||||||
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
static void on_render(struct nvnc_display* display, struct nvnc_fb* fb);
|
||||||
|
static void on_seat_ready(struct seat*);
|
||||||
|
|
||||||
#if defined(GIT_VERSION)
|
#if defined(GIT_VERSION)
|
||||||
static const char wayvnc_version[] = GIT_VERSION;
|
static const char wayvnc_version[] = GIT_VERSION;
|
||||||
|
@ -124,6 +136,9 @@ static const char wayvnc_version[] = "UNKNOWN";
|
||||||
struct wl_shm* wl_shm = NULL;
|
struct wl_shm* wl_shm = NULL;
|
||||||
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf = NULL;
|
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf = NULL;
|
||||||
struct gbm_device* gbm_device = NULL;
|
struct gbm_device* gbm_device = NULL;
|
||||||
|
struct zext_transient_seat_manager_v1* zext_transient_seat_manager = NULL;
|
||||||
|
|
||||||
|
static uint64_t seat_id = 0;
|
||||||
|
|
||||||
static void registry_add(void* data, struct wl_registry* registry,
|
static void registry_add(void* data, struct wl_registry* registry,
|
||||||
uint32_t id, const char* interface,
|
uint32_t id, const char* interface,
|
||||||
|
@ -188,6 +203,9 @@ static void registry_add(void* data, struct wl_registry* registry,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
seat->on_ready = on_seat_ready;
|
||||||
|
seat->userdata = self;
|
||||||
|
|
||||||
wl_list_insert(&self->seats, &seat->link);
|
wl_list_insert(&self->seats, &seat->link);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -211,6 +229,12 @@ static void registry_add(void* data, struct wl_registry* registry,
|
||||||
&zwlr_data_control_manager_v1_interface, 2);
|
&zwlr_data_control_manager_v1_interface, 2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (strcmp(interface, zext_transient_seat_manager_v1_interface.name) == 0) {
|
||||||
|
zext_transient_seat_manager = wl_registry_bind(registry, id,
|
||||||
|
&zext_transient_seat_manager_v1_interface, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registry_remove(void* data, struct wl_registry* registry,
|
static void registry_remove(void* data, struct wl_registry* registry,
|
||||||
|
@ -292,16 +316,15 @@ void wayvnc_destroy(struct wayvnc* self)
|
||||||
output_list_destroy(&self->outputs);
|
output_list_destroy(&self->outputs);
|
||||||
seat_list_destroy(&self->seats);
|
seat_list_destroy(&self->seats);
|
||||||
|
|
||||||
|
zext_transient_seat_manager_v1_destroy(zext_transient_seat_manager);
|
||||||
|
|
||||||
zxdg_output_manager_v1_destroy(self->xdg_output_manager);
|
zxdg_output_manager_v1_destroy(self->xdg_output_manager);
|
||||||
|
|
||||||
wl_shm_destroy(wl_shm);
|
wl_shm_destroy(wl_shm);
|
||||||
|
|
||||||
zwp_virtual_keyboard_v1_destroy(self->keyboard_backend.virtual_keyboard);
|
|
||||||
zwp_virtual_keyboard_manager_v1_destroy(self->keyboard_manager);
|
zwp_virtual_keyboard_manager_v1_destroy(self->keyboard_manager);
|
||||||
keyboard_destroy(&self->keyboard_backend);
|
|
||||||
|
|
||||||
zwlr_virtual_pointer_manager_v1_destroy(self->pointer_manager);
|
zwlr_virtual_pointer_manager_v1_destroy(self->pointer_manager);
|
||||||
pointer_destroy(&self->pointer_backend);
|
|
||||||
|
|
||||||
if (self->screencopy.manager)
|
if (self->screencopy.manager)
|
||||||
zwlr_screencopy_manager_v1_destroy(self->screencopy.manager);
|
zwlr_screencopy_manager_v1_destroy(self->screencopy.manager);
|
||||||
|
@ -337,6 +360,7 @@ static int init_wayland(struct wayvnc* self)
|
||||||
|
|
||||||
wl_list_init(&self->outputs);
|
wl_list_init(&self->outputs);
|
||||||
wl_list_init(&self->seats);
|
wl_list_init(&self->seats);
|
||||||
|
wl_list_init(&self->clients);
|
||||||
|
|
||||||
self->registry = wl_display_get_registry(self->display);
|
self->registry = wl_display_get_registry(self->display);
|
||||||
if (!self->registry)
|
if (!self->registry)
|
||||||
|
@ -385,7 +409,7 @@ void on_wayland_event(void* obj)
|
||||||
assert(rc == 0);
|
assert(rc == 0);
|
||||||
|
|
||||||
if (wl_display_read_events(self->display) < 0) {
|
if (wl_display_read_events(self->display) < 0) {
|
||||||
if (errno == EPIPE) {
|
if (errno == EPIPE || errno == ECONNRESET) {
|
||||||
log_error("Compositor has gone away. Exiting...\n");
|
log_error("Compositor has gone away. Exiting...\n");
|
||||||
wayvnc_exit(self);
|
wayvnc_exit(self);
|
||||||
} else {
|
} else {
|
||||||
|
@ -436,6 +460,128 @@ int init_main_loop(struct wayvnc* self)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void on_client_destroy(struct nvnc_client* nvnc_client)
|
||||||
|
{
|
||||||
|
struct wv_client* client = nvnc_get_userdata(nvnc_client);
|
||||||
|
assert(client);
|
||||||
|
|
||||||
|
if (client->pointer.pointer)
|
||||||
|
pointer_destroy(&client->pointer);
|
||||||
|
|
||||||
|
if (client->kb.virtual_keyboard) {
|
||||||
|
zwp_virtual_keyboard_v1_destroy(client->kb.virtual_keyboard);
|
||||||
|
keyboard_destroy(&client->kb);
|
||||||
|
}
|
||||||
|
|
||||||
|
zext_transient_seat_v1_destroy(client->chair);
|
||||||
|
|
||||||
|
wl_list_remove(&client->link);
|
||||||
|
free(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_client_inputs(struct wayvnc* wayvnc, struct wv_client* client)
|
||||||
|
{
|
||||||
|
// Keyboard
|
||||||
|
struct xkb_rule_names rule_names = {
|
||||||
|
.rules = wayvnc->cfg.xkb_rules,
|
||||||
|
.layout = wayvnc->kb_layout ? wayvnc->kb_layout :
|
||||||
|
wayvnc->cfg.xkb_layout,
|
||||||
|
.model = wayvnc->cfg.xkb_model ? wayvnc->cfg.xkb_model :
|
||||||
|
"pc105",
|
||||||
|
.variant = wayvnc->kb_variant ? wayvnc->kb_variant :
|
||||||
|
wayvnc->cfg.xkb_variant,
|
||||||
|
.options = wayvnc->cfg.xkb_options,
|
||||||
|
};
|
||||||
|
|
||||||
|
client->kb.virtual_keyboard =
|
||||||
|
zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
|
||||||
|
wayvnc->keyboard_manager, client->wl_seat);
|
||||||
|
assert(client->kb.virtual_keyboard);
|
||||||
|
|
||||||
|
int rc MAYBE_UNUSED = keyboard_init(&client->kb, &rule_names);
|
||||||
|
assert(rc == 0);
|
||||||
|
|
||||||
|
// Pointer
|
||||||
|
client->pointer.vnc = wayvnc->nvnc;
|
||||||
|
client->pointer.output = wayvnc->selected_output;
|
||||||
|
|
||||||
|
client->pointer.pointer = wayvnc->pointer_manager_version == 2
|
||||||
|
? zwlr_virtual_pointer_manager_v1_create_virtual_pointer_with_output(
|
||||||
|
wayvnc->pointer_manager, client->wl_seat,
|
||||||
|
wayvnc->selected_output->wl_output)
|
||||||
|
: zwlr_virtual_pointer_manager_v1_create_virtual_pointer(
|
||||||
|
wayvnc->pointer_manager, client->wl_seat);
|
||||||
|
|
||||||
|
pointer_init(&client->pointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_seat_ready(struct seat* seat)
|
||||||
|
{
|
||||||
|
struct wayvnc* wayvnc = seat->userdata;
|
||||||
|
|
||||||
|
struct wv_client* client;
|
||||||
|
wl_list_for_each(client, &wayvnc->clients, link)
|
||||||
|
if (!client->wl_seat &&
|
||||||
|
strcmp(client->seat_name, seat->name) == 0) {
|
||||||
|
client->wl_seat = seat->wl_seat;
|
||||||
|
init_client_inputs(wayvnc, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void transient_seat_failed(void* data, struct zext_transient_seat_v1* seat,
|
||||||
|
uint32_t reason)
|
||||||
|
{
|
||||||
|
// TODO: Handle properly
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void transient_seat_ready(void* data, struct zext_transient_seat_v1* chair,
|
||||||
|
const char* name)
|
||||||
|
{
|
||||||
|
struct nvnc_client* nvnc_client = data;
|
||||||
|
struct wv_client* client = nvnc_get_userdata(nvnc_client);
|
||||||
|
struct nvnc* nvnc = nvnc_client_get_server(nvnc_client);
|
||||||
|
struct wayvnc* wayvnc = nvnc_get_userdata(nvnc);
|
||||||
|
|
||||||
|
strlcpy(client->seat_name, name, sizeof(client->seat_name));
|
||||||
|
|
||||||
|
struct seat* seat = seat_find_by_name(&wayvnc->seats, name);
|
||||||
|
if (seat) {
|
||||||
|
client->wl_seat = seat->wl_seat;
|
||||||
|
init_client_inputs(wayvnc, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct zext_transient_seat_v1_listener transient_seat_listener = {
|
||||||
|
.failed = transient_seat_failed,
|
||||||
|
.ready = transient_seat_ready,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void on_new_client(struct nvnc_client* nvnc_client)
|
||||||
|
{
|
||||||
|
struct nvnc* nvnc = nvnc_client_get_server(nvnc_client);
|
||||||
|
struct wayvnc* wayvnc = nvnc_get_userdata(nvnc);
|
||||||
|
|
||||||
|
struct wv_client* client = calloc(1, sizeof(*client));
|
||||||
|
assert(client);
|
||||||
|
|
||||||
|
int pid = getpid();
|
||||||
|
|
||||||
|
char name[256];
|
||||||
|
snprintf(name, sizeof(name), "wayvnc-%d-%" PRIu64, pid, seat_id++);
|
||||||
|
|
||||||
|
client->chair = zext_transient_seat_manager_v1_create(
|
||||||
|
zext_transient_seat_manager, name);
|
||||||
|
|
||||||
|
zext_transient_seat_v1_add_listener(client->chair,
|
||||||
|
&transient_seat_listener, nvnc_client);
|
||||||
|
|
||||||
|
nvnc_set_userdata(nvnc_client, client);
|
||||||
|
nvnc_set_client_cleanup_fn(nvnc_client, on_client_destroy);
|
||||||
|
|
||||||
|
wl_list_insert(&wayvnc->clients, &client->link);
|
||||||
|
}
|
||||||
|
|
||||||
static void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t y,
|
static void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t y,
|
||||||
enum nvnc_button_mask button_mask)
|
enum nvnc_button_mask button_mask)
|
||||||
{
|
{
|
||||||
|
@ -443,29 +589,39 @@ static void on_pointer_event(struct nvnc_client* client, uint16_t x, uint16_t y,
|
||||||
|
|
||||||
struct nvnc* nvnc = nvnc_client_get_server(client);
|
struct nvnc* nvnc = nvnc_client_get_server(client);
|
||||||
struct wayvnc* wayvnc = nvnc_get_userdata(nvnc);
|
struct wayvnc* wayvnc = nvnc_get_userdata(nvnc);
|
||||||
|
struct wv_client* wv_client = nvnc_get_userdata(client);
|
||||||
|
|
||||||
|
if (!wv_client->pointer.pointer)
|
||||||
|
return; /* Client does not have a seat yet */
|
||||||
|
|
||||||
uint32_t xfx = 0, xfy = 0;
|
uint32_t xfx = 0, xfy = 0;
|
||||||
output_transform_coord(wayvnc->selected_output, x, y, &xfx, &xfy);
|
output_transform_coord(wayvnc->selected_output, x, y, &xfx, &xfy);
|
||||||
|
|
||||||
pointer_set(&wayvnc->pointer_backend, xfx, xfy, button_mask);
|
pointer_set(&wv_client->pointer, xfx, xfy, button_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_key_event(struct nvnc_client* client, uint32_t symbol,
|
static void on_key_event(struct nvnc_client* client, uint32_t symbol,
|
||||||
bool is_pressed)
|
bool is_pressed)
|
||||||
{
|
{
|
||||||
struct nvnc* nvnc = nvnc_client_get_server(client);
|
struct wv_client* wv_client = nvnc_get_userdata(client);
|
||||||
struct wayvnc* wayvnc = nvnc_get_userdata(nvnc);
|
assert(wv_client);
|
||||||
|
|
||||||
keyboard_feed(&wayvnc->keyboard_backend, symbol, is_pressed);
|
if (!wv_client->kb.virtual_keyboard)
|
||||||
|
return; /* Client does not have a seat yet */
|
||||||
|
|
||||||
|
keyboard_feed(&wv_client->kb, symbol, is_pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_key_code_event(struct nvnc_client* client, uint32_t code,
|
static void on_key_code_event(struct nvnc_client* client, uint32_t code,
|
||||||
bool is_pressed)
|
bool is_pressed)
|
||||||
{
|
{
|
||||||
struct nvnc* nvnc = nvnc_client_get_server(client);
|
struct wv_client* wv_client = nvnc_get_userdata(client);
|
||||||
struct wayvnc* wayvnc = nvnc_get_userdata(nvnc);
|
assert(wv_client);
|
||||||
|
|
||||||
keyboard_feed_code(&wayvnc->keyboard_backend, code + 8, is_pressed);
|
if (!wv_client->kb.virtual_keyboard)
|
||||||
|
return; /* Client does not have a seat yet */
|
||||||
|
|
||||||
|
keyboard_feed_code(&wv_client->kb, code + 8, is_pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on_client_cut_text(struct nvnc* server, const char* text, uint32_t len)
|
static void on_client_cut_text(struct nvnc* server, const char* text, uint32_t len)
|
||||||
|
@ -512,6 +668,8 @@ int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port)
|
||||||
|
|
||||||
nvnc_display_set_render_fn(self->nvnc_display, on_render);
|
nvnc_display_set_render_fn(self->nvnc_display, on_render);
|
||||||
|
|
||||||
|
nvnc_set_new_client_fn(self->nvnc, on_new_client);
|
||||||
|
|
||||||
if (self->cfg.enable_auth &&
|
if (self->cfg.enable_auth &&
|
||||||
nvnc_enable_auth(self->nvnc, self->cfg.private_key_file,
|
nvnc_enable_auth(self->nvnc, self->cfg.private_key_file,
|
||||||
self->cfg.certificate_file, on_auth, self) < 0) {
|
self->cfg.certificate_file, on_auth, self) < 0) {
|
||||||
|
@ -522,7 +680,7 @@ int init_nvnc(struct wayvnc* self, const char* addr, uint16_t port)
|
||||||
if (self->pointer_manager)
|
if (self->pointer_manager)
|
||||||
nvnc_set_pointer_fn(self->nvnc, on_pointer_event);
|
nvnc_set_pointer_fn(self->nvnc, on_pointer_event);
|
||||||
|
|
||||||
if (self->keyboard_backend.virtual_keyboard) {
|
if (self->keyboard_manager) {
|
||||||
nvnc_set_key_fn(self->nvnc, on_key_event);
|
nvnc_set_key_fn(self->nvnc, on_key_event);
|
||||||
nvnc_set_key_code_fn(self->nvnc, on_key_code_event);
|
nvnc_set_key_code_fn(self->nvnc, on_key_code_event);
|
||||||
}
|
}
|
||||||
|
@ -941,33 +1099,6 @@ int main(int argc, char* argv[])
|
||||||
self.screencopy.wl_output = out->wl_output;
|
self.screencopy.wl_output = out->wl_output;
|
||||||
self.screencopy.rate_limit = max_rate;
|
self.screencopy.rate_limit = max_rate;
|
||||||
|
|
||||||
self.keyboard_backend.virtual_keyboard =
|
|
||||||
zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
|
|
||||||
self.keyboard_manager, self.selected_seat->wl_seat);
|
|
||||||
|
|
||||||
struct xkb_rule_names rule_names = {
|
|
||||||
.rules = self.cfg.xkb_rules,
|
|
||||||
.layout = self.kb_layout ? self.kb_layout : self.cfg.xkb_layout,
|
|
||||||
.model = self.cfg.xkb_model ? self.cfg.xkb_model : "pc105",
|
|
||||||
.variant = self.kb_variant ? self.kb_variant :
|
|
||||||
self.cfg.xkb_variant,
|
|
||||||
.options = self.cfg.xkb_options,
|
|
||||||
};
|
|
||||||
|
|
||||||
keyboard_init(&self.keyboard_backend, &rule_names);
|
|
||||||
|
|
||||||
self.pointer_backend.vnc = self.nvnc;
|
|
||||||
self.pointer_backend.output = self.selected_output;
|
|
||||||
|
|
||||||
self.pointer_backend.pointer = self.pointer_manager_version == 2
|
|
||||||
? zwlr_virtual_pointer_manager_v1_create_virtual_pointer_with_output(
|
|
||||||
self.pointer_manager, self.selected_seat->wl_seat,
|
|
||||||
out->wl_output)
|
|
||||||
: zwlr_virtual_pointer_manager_v1_create_virtual_pointer(
|
|
||||||
self.pointer_manager, self.selected_seat->wl_seat);
|
|
||||||
|
|
||||||
pointer_init(&self.pointer_backend);
|
|
||||||
|
|
||||||
out->on_dimension_change = on_output_dimension_change;
|
out->on_dimension_change = on_output_dimension_change;
|
||||||
out->userdata = &self;
|
out->userdata = &self;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,10 @@ static void seat_capabilities(void* data, struct wl_seat* wl_seat,
|
||||||
struct seat* self = data;
|
struct seat* self = data;
|
||||||
|
|
||||||
self->capabilities = capabilities;
|
self->capabilities = capabilities;
|
||||||
|
self->has_capabilities = true;
|
||||||
|
|
||||||
|
if (self->has_capabilities && self->has_name && self->on_ready)
|
||||||
|
self->on_ready(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seat_name(void* data, struct wl_seat* wl_seat, const char* name)
|
static void seat_name(void* data, struct wl_seat* wl_seat, const char* name)
|
||||||
|
@ -37,6 +41,10 @@ static void seat_name(void* data, struct wl_seat* wl_seat, const char* name)
|
||||||
struct seat* self = data;
|
struct seat* self = data;
|
||||||
|
|
||||||
strlcpy(self->name, name, sizeof(self->name));
|
strlcpy(self->name, name, sizeof(self->name));
|
||||||
|
self->has_name = true;
|
||||||
|
|
||||||
|
if (self->has_capabilities && self->has_name && self->on_ready)
|
||||||
|
self->on_ready(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct wl_seat_listener seat_listener = {
|
static const struct wl_seat_listener seat_listener = {
|
||||||
|
|
Loading…
Reference in New Issue