Compare commits
6 Commits
master
...
transient-
Author | SHA1 | Date |
---|---|---|
Andri Yngvason | b927394490 | |
Andri Yngvason | c302c20939 | |
Andri Yngvason | 842da93de4 | |
Andri Yngvason | 0414e1fd87 | |
Andri Yngvason | 75173ea838 | |
Andri Yngvason | 1ef290d2d4 |
|
@ -21,10 +21,13 @@
|
|||
struct ctl;
|
||||
struct cmd_response;
|
||||
|
||||
struct ctl_server_vnc_client {
|
||||
char id[64];
|
||||
char hostname[256];
|
||||
char username[256];
|
||||
struct ctl_server_client;
|
||||
|
||||
struct ctl_server_client_info {
|
||||
int id;
|
||||
const char *hostname;
|
||||
const char *username;
|
||||
const char *seat;
|
||||
};
|
||||
|
||||
struct ctl_server_output {
|
||||
|
@ -46,11 +49,10 @@ struct ctl_server_actions {
|
|||
const char* id);
|
||||
struct cmd_response* (*on_wayvnc_exit)(struct ctl*);
|
||||
|
||||
// Return number of elements created
|
||||
// Allocate 'clients' array or set ton ULL if none
|
||||
// Receiver will free(clients) when done.
|
||||
int (*get_client_list)(struct ctl*,
|
||||
struct ctl_server_vnc_client** clients);
|
||||
struct ctl_server_client *(*client_next)(struct ctl*,
|
||||
struct ctl_server_client* prev);
|
||||
void (*client_info)(const struct ctl_server_client*,
|
||||
struct ctl_server_client_info* info);
|
||||
|
||||
// Return number of elements created
|
||||
// Allocate 'outputs' array or set to NULL if none
|
||||
|
@ -68,15 +70,11 @@ struct cmd_response* cmd_ok(void);
|
|||
struct cmd_response* cmd_failed(const char* fmt, ...);
|
||||
|
||||
void ctl_server_event_connected(struct ctl*,
|
||||
const char* client_id,
|
||||
const char* client_hostname,
|
||||
const char* client_username,
|
||||
const struct ctl_server_client_info *info,
|
||||
int new_connection_count);
|
||||
|
||||
void ctl_server_event_disconnected(struct ctl*,
|
||||
const char* client_id,
|
||||
const char* client_hostname,
|
||||
const char* client_username,
|
||||
const struct ctl_server_client_info *info,
|
||||
int new_connection_count);
|
||||
|
||||
void ctl_server_event_capture_changed(struct ctl*,
|
||||
|
|
|
@ -22,6 +22,7 @@ client_protocols = [
|
|||
'linux-dmabuf-unstable-v1.xml',
|
||||
'wlr-data-control-unstable-v1.xml',
|
||||
'wlr-output-power-management-unstable-v1.xml',
|
||||
'transient-seat-v1.xml',
|
||||
]
|
||||
|
||||
client_protos_src = []
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="transient_seat_v1">
|
||||
<copyright>
|
||||
Copyright © 2020 - 2023 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 privileved clients to create
|
||||
independent seats that will be removed from the compositor when the client
|
||||
destroys its seat.
|
||||
|
||||
This protocol is intended for use with virtual input protocols such as
|
||||
"virtual_keyboard_unstable_v1" or "wlr_virtual_pointer_unstable_v1", both
|
||||
of which allow the user to select a seat.
|
||||
|
||||
The "wl_seat" global created by this protocol does not generate input events
|
||||
on its own, or have any capabilities except those assigned to it by other
|
||||
protocol extensions, such as the ones mentioned above.
|
||||
|
||||
For example, a remote desktop server can create a seat with virtual inputs
|
||||
for each remote user by following these steps for each new connection:
|
||||
* Create a transient seat
|
||||
* Wait for the transient seat to be created
|
||||
* Locate a "wl_seat" global with a matching name
|
||||
* Create virtual inputs using the resulting "wl_seat" global
|
||||
</description>
|
||||
|
||||
<interface name="ext_transient_seat_manager_v1" version="1">
|
||||
<description summary="transient seat manager">
|
||||
The transient seat manager creates short-lived seats.
|
||||
</description>
|
||||
|
||||
<request name="create">
|
||||
<description summary="create a transient seat">
|
||||
Create a new seat that is removed when the client side object is
|
||||
destroyed.
|
||||
</description>
|
||||
<arg name="seat" type="new_id" interface="ext_transient_seat_v1"/>
|
||||
</request>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the manager">
|
||||
Destroy the manager.
|
||||
|
||||
All objects created by the manager will remain valid until they are
|
||||
destroyed themselves.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="ext_transient_seat_v1" version="1">
|
||||
<description summary="transient seat handle">
|
||||
The life time of the transient seat handle is equal to that of the seat
|
||||
itself.
|
||||
</description>
|
||||
|
||||
<event name="ready">
|
||||
<description summary="transient seat is ready">
|
||||
This event advertises the global name for the wl_seat to be used with
|
||||
wl_registry_bind.
|
||||
|
||||
It is sent exactly once, immediately after the transient seat is created
|
||||
and the new "wl_seat" global is advertised, if and only if the creation
|
||||
of the transient seat was allowed.
|
||||
</description>
|
||||
<arg name="global_name" type="uint"/>
|
||||
</event>
|
||||
|
||||
<event name="denied">
|
||||
<description summary="transient seat creation denied">
|
||||
The event informs the client that the compositor denied its request to
|
||||
create a transient seat.
|
||||
|
||||
It is sent exactly once, immediately after the transient seat object is
|
||||
created, if and only if the creation of the transient seat was denied.
|
||||
|
||||
After receiving this event, the client should destroy the object.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy transient seat">
|
||||
When the transient seat object is destroyed by the client, the
|
||||
associated seat created by the compositor is also destroyed.
|
||||
</description>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
|
@ -328,24 +328,51 @@ static struct cmd_response* generate_version_object()
|
|||
return response;
|
||||
}
|
||||
|
||||
static struct ctl_server_client* ctl_server_client_first(struct ctl* self)
|
||||
{
|
||||
return self->actions.client_next(self, NULL);
|
||||
}
|
||||
|
||||
static struct ctl_server_client* ctl_server_client_next(struct ctl* self,
|
||||
struct ctl_server_client* prev)
|
||||
{
|
||||
return self->actions.client_next(self, prev);
|
||||
}
|
||||
|
||||
static void ctl_server_client_get_info(struct ctl* self,
|
||||
const struct ctl_server_client* client,
|
||||
struct ctl_server_client_info* info)
|
||||
{
|
||||
return self->actions.client_info(client, info);
|
||||
}
|
||||
|
||||
static struct cmd_response* generate_vnc_client_list(struct ctl* self)
|
||||
{
|
||||
struct ctl_server_vnc_client* clients;
|
||||
size_t num_clients = self->actions.get_client_list(self, &clients);
|
||||
struct cmd_response* response = cmd_ok();
|
||||
|
||||
response->data = json_array();
|
||||
for (size_t i = 0; i < num_clients; ++i) {
|
||||
json_t* packed = json_pack("{s:s}", "id", clients[i].id);
|
||||
if (clients[i].hostname[0] != '\0')
|
||||
|
||||
struct ctl_server_client* client;
|
||||
for (client = ctl_server_client_first(self); client;
|
||||
client = ctl_server_client_next(self, client)) {
|
||||
struct ctl_server_client_info info = {};
|
||||
ctl_server_client_get_info(self, client, &info);
|
||||
|
||||
char id_str[64];
|
||||
snprintf(id_str, sizeof(id_str), "%d", info.id);
|
||||
json_t* packed = json_pack("{s:s}", "id", id_str);
|
||||
|
||||
if (info.hostname)
|
||||
json_object_set_new(packed, "hostname",
|
||||
json_string(clients[i].hostname));
|
||||
if (clients[i].username[0] != '\0')
|
||||
json_string(info.hostname));
|
||||
|
||||
if (info.username)
|
||||
json_object_set_new(packed, "username",
|
||||
json_string(clients[i].username));
|
||||
json_string(info.username));
|
||||
|
||||
json_object_set_new(packed, "seat", json_string(info.seat));
|
||||
json_array_append_new(response->data, packed);
|
||||
}
|
||||
free(clients);
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -829,15 +856,18 @@ struct cmd_response* cmd_failed(const char* fmt, ...)
|
|||
}
|
||||
|
||||
json_t* pack_connection_event_params(
|
||||
const char* client_id,
|
||||
const char* client_hostname,
|
||||
const char* client_username,
|
||||
const struct ctl_server_client_info *info,
|
||||
int new_connection_count)
|
||||
{
|
||||
return json_pack("{s:s, s:s?, s:s?, s:i}",
|
||||
"id", client_id,
|
||||
"hostname", client_hostname,
|
||||
"username", client_username,
|
||||
// TODO: Why is the id a string?
|
||||
char id_str[64];
|
||||
snprintf(id_str, sizeof(id_str), "%d", info->id);
|
||||
|
||||
return json_pack("{s:s, s:s?, s:s?, s:s?, s:i}",
|
||||
"id", id_str,
|
||||
"hostname", info->hostname,
|
||||
"username", info->username,
|
||||
"seat", info->seat,
|
||||
"connection_count", new_connection_count);
|
||||
}
|
||||
|
||||
|
@ -879,34 +909,28 @@ int ctl_server_enqueue_event(struct ctl* self, enum event_type evt_type,
|
|||
|
||||
static void ctl_server_event_connect(struct ctl* self,
|
||||
enum event_type evt_type,
|
||||
const char* client_id,
|
||||
const char* client_hostname,
|
||||
const char* client_username,
|
||||
const struct ctl_server_client_info *info,
|
||||
int new_connection_count)
|
||||
{
|
||||
json_t* params = pack_connection_event_params(client_id, client_hostname,
|
||||
client_username, new_connection_count);
|
||||
json_t* params =
|
||||
pack_connection_event_params(info, new_connection_count);
|
||||
ctl_server_enqueue_event(self, evt_type, params);
|
||||
}
|
||||
|
||||
void ctl_server_event_connected(struct ctl* self,
|
||||
const char* client_id,
|
||||
const char* client_hostname,
|
||||
const char* client_username,
|
||||
const struct ctl_server_client_info *info,
|
||||
int new_connection_count)
|
||||
{
|
||||
ctl_server_event_connect(self, EVT_CLIENT_CONNECTED, client_id,
|
||||
client_hostname, client_username, new_connection_count);
|
||||
ctl_server_event_connect(self, EVT_CLIENT_CONNECTED, info,
|
||||
new_connection_count);
|
||||
}
|
||||
|
||||
void ctl_server_event_disconnected(struct ctl* self,
|
||||
const char* client_id,
|
||||
const char* client_hostname,
|
||||
const char* client_username,
|
||||
const struct ctl_server_client_info *info,
|
||||
int new_connection_count)
|
||||
{
|
||||
ctl_server_event_connect(self, EVT_CLIENT_DISCONNECTED, client_id,
|
||||
client_hostname, client_username, new_connection_count);
|
||||
ctl_server_event_connect(self, EVT_CLIENT_DISCONNECTED, info,
|
||||
new_connection_count);
|
||||
}
|
||||
|
||||
void ctl_server_event_capture_changed(struct ctl* self,
|
||||
|
|
181
src/main.c
181
src/main.c
|
@ -40,6 +40,7 @@
|
|||
#include "xdg-output-unstable-v1.h"
|
||||
#include "wlr-output-power-management-unstable-v1.h"
|
||||
#include "linux-dmabuf-unstable-v1.h"
|
||||
#include "transient-seat-v1.h"
|
||||
#include "screencopy.h"
|
||||
#include "data-control.h"
|
||||
#include "strlcpy.h"
|
||||
|
@ -83,9 +84,10 @@ struct wayvnc {
|
|||
struct zwp_virtual_keyboard_manager_v1* keyboard_manager;
|
||||
struct zwlr_virtual_pointer_manager_v1* pointer_manager;
|
||||
struct zwlr_data_control_manager_v1* data_control_manager;
|
||||
struct ext_transient_seat_manager_v1* transient_seat_manager;
|
||||
|
||||
struct output* selected_output;
|
||||
const struct seat* selected_seat;
|
||||
struct seat* selected_seat;
|
||||
|
||||
struct screencopy screencopy;
|
||||
|
||||
|
@ -102,6 +104,7 @@ struct wayvnc {
|
|||
uint32_t n_frames_captured;
|
||||
|
||||
bool disable_input;
|
||||
bool use_transient_seat;
|
||||
|
||||
int nr_clients;
|
||||
struct aml_ticker* performance_ticker;
|
||||
|
@ -116,6 +119,9 @@ struct wayvnc_client {
|
|||
struct wayvnc* server;
|
||||
struct nvnc_client* nvnc_client;
|
||||
|
||||
struct seat* seat;
|
||||
struct ext_transient_seat_v1* transient_seat;
|
||||
|
||||
unsigned id;
|
||||
struct pointer pointer;
|
||||
struct keyboard keyboard;
|
||||
|
@ -128,6 +134,7 @@ static void on_nvnc_client_new(struct nvnc_client* client);
|
|||
void switch_to_output(struct wayvnc*, struct output*);
|
||||
void switch_to_next_output(struct wayvnc*);
|
||||
void switch_to_prev_output(struct wayvnc*);
|
||||
static void client_init_seat(struct wayvnc_client* self);
|
||||
static void client_init_pointer(struct wayvnc_client* self);
|
||||
static void client_init_keyboard(struct wayvnc_client* self);
|
||||
static void client_init_data_control(struct wayvnc_client* self);
|
||||
|
@ -155,7 +162,7 @@ static bool registry_add_input(void* data, struct wl_registry* registry,
|
|||
|
||||
struct seat* seat = seat_new(wl_seat, id);
|
||||
if (!seat) {
|
||||
wl_seat_destroy(wl_seat);
|
||||
wl_seat_release(wl_seat);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -183,6 +190,12 @@ static bool registry_add_input(void* data, struct wl_registry* registry,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (strcmp(interface, ext_transient_seat_manager_v1_interface.name) == 0) {
|
||||
self->transient_seat_manager = wl_registry_bind(registry, id,
|
||||
&ext_transient_seat_manager_v1_interface, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -416,6 +429,11 @@ static int init_wayland(struct wayvnc* self)
|
|||
goto failure;
|
||||
}
|
||||
|
||||
if (!self->transient_seat_manager && self->use_transient_seat) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "Transient seat protocol not supported by compositor.");
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (!self->screencopy.manager) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "Screencopy protocol not supported by compositor. Exiting. Refer to FAQ section in man page.");
|
||||
goto failure;
|
||||
|
@ -489,33 +507,27 @@ struct cmd_response* on_output_switch(struct ctl* ctl,
|
|||
return cmd_ok();
|
||||
}
|
||||
|
||||
static int get_client_list(struct ctl* ctl,
|
||||
struct ctl_server_vnc_client** clients)
|
||||
static struct ctl_server_client *client_next(struct ctl* ctl,
|
||||
struct ctl_server_client *prev)
|
||||
{
|
||||
struct wayvnc* self = ctl_server_userdata(ctl);
|
||||
if (self->nr_clients == 0) {
|
||||
*clients = NULL;
|
||||
return 0;
|
||||
}
|
||||
*clients = calloc(self->nr_clients, sizeof(**clients));
|
||||
struct nvnc_client* nvnc_client = nvnc_client_first(self->nvnc);
|
||||
for (int i = 0; i < self->nr_clients && nvnc_client; ++i) {
|
||||
struct wayvnc_client* client = nvnc_get_userdata(nvnc_client);
|
||||
struct ctl_server_vnc_client* ctl_client =&(*clients)[i];
|
||||
struct nvnc_client* vnc_prev = (struct nvnc_client*)prev;
|
||||
|
||||
snprintf(ctl_client->id, sizeof(ctl_client->id), "%u",
|
||||
client->id);
|
||||
const char* hostname = nvnc_client_get_hostname(nvnc_client);
|
||||
if (hostname)
|
||||
strlcpy(ctl_client->hostname, hostname,
|
||||
sizeof(ctl_client->hostname));
|
||||
const char* username = nvnc_client_get_auth_username(nvnc_client);
|
||||
if (username)
|
||||
strlcpy(ctl_client->username, username,
|
||||
sizeof(ctl_client->username));
|
||||
nvnc_client = nvnc_client_next(nvnc_client);
|
||||
return prev ? (struct ctl_server_client*)nvnc_client_next(vnc_prev) :
|
||||
(struct ctl_server_client*)nvnc_client_first(self->nvnc);
|
||||
}
|
||||
return self->nr_clients;
|
||||
|
||||
static void client_info(const struct ctl_server_client* client_handle,
|
||||
struct ctl_server_client_info* info)
|
||||
{
|
||||
const struct nvnc_client *vnc_client =
|
||||
(const struct nvnc_client*)client_handle;
|
||||
const struct wayvnc_client *client = nvnc_get_userdata(vnc_client);
|
||||
|
||||
info->id = client->id;
|
||||
info->hostname = nvnc_client_get_hostname(vnc_client);
|
||||
info->username = nvnc_client_get_auth_username(vnc_client);
|
||||
info->seat = client->seat->name;
|
||||
}
|
||||
|
||||
static int get_output_list(struct ctl* ctl,
|
||||
|
@ -1000,6 +1012,7 @@ static struct wayvnc_client* client_create(struct wayvnc* wayvnc,
|
|||
self->nvnc_client = nvnc_client;
|
||||
|
||||
self->id = next_client_id++;
|
||||
client_init_seat(self);
|
||||
client_init_keyboard(self);
|
||||
client_init_pointer(self);
|
||||
client_init_data_control(self);
|
||||
|
@ -1023,6 +1036,10 @@ static void client_destroy(void* obj)
|
|||
if (self->data_control.manager)
|
||||
data_control_destroy(&self->data_control);
|
||||
|
||||
if (self->server->use_transient_seat) {
|
||||
ext_transient_seat_v1_destroy(self->transient_seat);
|
||||
}
|
||||
|
||||
free(self);
|
||||
}
|
||||
|
||||
|
@ -1036,12 +1053,14 @@ static void on_nvnc_client_cleanup(struct nvnc_client* client)
|
|||
nvnc_log(NVNC_LOG_DEBUG, "Client disconnected, new client count: %d",
|
||||
self->nr_clients);
|
||||
|
||||
char id[64];
|
||||
snprintf(id, sizeof(id), "%u", wayvnc_client->id);
|
||||
ctl_server_event_disconnected(self->ctl, id,
|
||||
nvnc_client_get_hostname(client),
|
||||
nvnc_client_get_auth_username(client),
|
||||
self->nr_clients);
|
||||
struct ctl_server_client_info info = {
|
||||
.id = wayvnc_client->id,
|
||||
.hostname = nvnc_client_get_hostname(client),
|
||||
.username = nvnc_client_get_auth_username(client),
|
||||
.seat = wayvnc_client->seat->name,
|
||||
};
|
||||
|
||||
ctl_server_event_disconnected(self->ctl, &info, self->nr_clients);
|
||||
|
||||
if (self->nr_clients == 0) {
|
||||
nvnc_log(NVNC_LOG_INFO, "Stopping screen capture");
|
||||
|
@ -1069,12 +1088,14 @@ static void on_nvnc_client_new(struct nvnc_client* client)
|
|||
nvnc_log(NVNC_LOG_DEBUG, "Client connected, new client count: %d",
|
||||
self->nr_clients);
|
||||
|
||||
char id[64];
|
||||
snprintf(id, sizeof(id), "%u", wayvnc_client->id);
|
||||
ctl_server_event_connected(self->ctl, id,
|
||||
nvnc_client_get_hostname(client),
|
||||
nvnc_client_get_auth_username(client),
|
||||
self->nr_clients);
|
||||
struct ctl_server_client_info info = {
|
||||
.id = wayvnc_client->id,
|
||||
.hostname = nvnc_client_get_hostname(client),
|
||||
.username = nvnc_client_get_auth_username(client),
|
||||
.seat = wayvnc_client->seat->name,
|
||||
};
|
||||
|
||||
ctl_server_event_connected(self->ctl, &info, self->nr_clients);
|
||||
}
|
||||
|
||||
void parse_keyboard_option(struct wayvnc* self, const char* arg)
|
||||
|
@ -1107,16 +1128,73 @@ static void client_init_pointer(struct wayvnc_client* self)
|
|||
|
||||
self->pointer.pointer = pointer_manager_version >= 2
|
||||
? zwlr_virtual_pointer_manager_v1_create_virtual_pointer_with_output(
|
||||
wayvnc->pointer_manager, wayvnc->selected_seat->wl_seat,
|
||||
wayvnc->pointer_manager, self->seat->wl_seat,
|
||||
wayvnc->selected_output->wl_output)
|
||||
: zwlr_virtual_pointer_manager_v1_create_virtual_pointer(
|
||||
wayvnc->pointer_manager, wayvnc->selected_seat->wl_seat);
|
||||
wayvnc->pointer_manager, self->seat->wl_seat);
|
||||
|
||||
if (pointer_init(&self->pointer) < 0) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "Failed to initialise pointer");
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_transient_seat_ready(void* data,
|
||||
struct ext_transient_seat_v1* transient_seat,
|
||||
uint32_t global_name)
|
||||
{
|
||||
(void)transient_seat;
|
||||
|
||||
struct wayvnc_client* client = data;
|
||||
struct wayvnc* wayvnc = client->server;
|
||||
|
||||
struct seat* seat = seat_find_by_id(&wayvnc->seats, global_name);
|
||||
assert(seat);
|
||||
|
||||
client->seat = seat;
|
||||
}
|
||||
|
||||
static void handle_transient_seat_denied(void* data,
|
||||
struct ext_transient_seat_v1* transient_seat)
|
||||
{
|
||||
(void)transient_seat;
|
||||
|
||||
struct wayvnc_client* client = data;
|
||||
struct wayvnc* wayvnc = client->server;
|
||||
|
||||
// TODO: Should this perhaps be fatal?
|
||||
nvnc_log(NVNC_LOG_WARNING, "Transient seat denied");
|
||||
|
||||
client->seat = wayvnc->selected_seat;
|
||||
}
|
||||
|
||||
static void client_init_seat(struct wayvnc_client* self)
|
||||
{
|
||||
struct wayvnc* wayvnc = self->server;
|
||||
|
||||
if (wayvnc->disable_input)
|
||||
return;
|
||||
|
||||
if (wayvnc->use_transient_seat) {
|
||||
self->transient_seat = ext_transient_seat_manager_v1_create(
|
||||
wayvnc->transient_seat_manager);
|
||||
|
||||
static const struct ext_transient_seat_v1_listener listener = {
|
||||
.ready = handle_transient_seat_ready,
|
||||
.denied = handle_transient_seat_denied,
|
||||
};
|
||||
ext_transient_seat_v1_add_listener(self->transient_seat,
|
||||
&listener, self);
|
||||
|
||||
// TODO: Make this asynchronous
|
||||
wl_display_roundtrip(wayvnc->display);
|
||||
wl_display_dispatch(wayvnc->display);
|
||||
|
||||
assert(self->seat);
|
||||
} else {
|
||||
self->seat = wayvnc->selected_seat;
|
||||
}
|
||||
}
|
||||
|
||||
static void client_init_keyboard(struct wayvnc_client* self)
|
||||
{
|
||||
struct wayvnc* wayvnc = self->server;
|
||||
|
@ -1126,8 +1204,7 @@ static void client_init_keyboard(struct wayvnc_client* self)
|
|||
|
||||
self->keyboard.virtual_keyboard =
|
||||
zwp_virtual_keyboard_manager_v1_create_virtual_keyboard(
|
||||
wayvnc->keyboard_manager,
|
||||
wayvnc->selected_seat->wl_seat);
|
||||
wayvnc->keyboard_manager, self->seat->wl_seat);
|
||||
|
||||
struct xkb_rule_names rule_names = {
|
||||
.rules = wayvnc->cfg.xkb_rules,
|
||||
|
@ -1163,7 +1240,7 @@ static void client_init_data_control(struct wayvnc_client* self)
|
|||
|
||||
self->data_control.manager = wayvnc->data_control_manager;
|
||||
data_control_init(&self->data_control, wayvnc->display, wayvnc->nvnc,
|
||||
wayvnc->selected_seat->wl_seat);
|
||||
self->seat->wl_seat);
|
||||
}
|
||||
|
||||
void log_selected_output(struct wayvnc* self)
|
||||
|
@ -1266,6 +1343,7 @@ int main(int argc, char* argv[])
|
|||
bool show_performance = false;
|
||||
int max_rate = 30;
|
||||
bool disable_input = false;
|
||||
bool use_transient_seat = false;
|
||||
|
||||
int drm_fd MAYBE_UNUSED = -1;
|
||||
|
||||
|
@ -1290,6 +1368,8 @@ int main(int argc, char* argv[])
|
|||
"Select seat by name." },
|
||||
{ 'S', "socket", "<path>",
|
||||
"Control socket path." },
|
||||
{ 't', "transient-seat", NULL,
|
||||
"Use transient seat." },
|
||||
{ 'r', "render-cursor", NULL,
|
||||
"Enable overlay cursor rendering." },
|
||||
{ 'f', "max-fps", "<fps>",
|
||||
|
@ -1342,6 +1422,7 @@ int main(int argc, char* argv[])
|
|||
log_level = log_level_from_string(
|
||||
option_parser_get_value(&option_parser, "log-level"));
|
||||
max_rate = atoi(option_parser_get_value(&option_parser, "max-fps"));
|
||||
use_transient_seat = option_parser_get_value(&option_parser, "transient-seat");
|
||||
|
||||
keyboard_options = option_parser_get_value(&option_parser, "keyboard");
|
||||
if (keyboard_options)
|
||||
|
@ -1361,6 +1442,16 @@ int main(int argc, char* argv[])
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (use_transient_seat && disable_input) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "transient-seat and disable-input are conflicting options");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (seat_name && use_transient_seat) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "transient seat and seat are conflicting options");
|
||||
return 1;
|
||||
}
|
||||
|
||||
errno = 0;
|
||||
int cfg_rc = cfg_load(&self.cfg, cfg_file);
|
||||
if (cfg_rc != 0 && (cfg_file || errno != ENOENT)) {
|
||||
|
@ -1386,6 +1477,7 @@ int main(int argc, char* argv[])
|
|||
if (!port) port = DEFAULT_PORT;
|
||||
|
||||
self.disable_input = disable_input;
|
||||
self.use_transient_seat = use_transient_seat;
|
||||
|
||||
if (init_wayland(&self) < 0) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "Failed to initialise wayland");
|
||||
|
@ -1415,7 +1507,7 @@ int main(int argc, char* argv[])
|
|||
nvnc_log(NVNC_LOG_ERROR, "No such seat");
|
||||
goto failure;
|
||||
}
|
||||
} else if (!self.disable_input) {
|
||||
} else if (!self.disable_input && !self.use_transient_seat) {
|
||||
seat = seat_first(&self.seats);
|
||||
if (!seat) {
|
||||
nvnc_log(NVNC_LOG_ERROR, "No seat found");
|
||||
|
@ -1466,7 +1558,8 @@ int main(int argc, char* argv[])
|
|||
.userdata = &self,
|
||||
.on_output_cycle = on_output_cycle,
|
||||
.on_output_switch = on_output_switch,
|
||||
.get_client_list = get_client_list,
|
||||
.client_next = client_next,
|
||||
.client_info = client_info,
|
||||
.get_output_list = get_output_list,
|
||||
.on_disconnect_client = on_disconnect_client,
|
||||
.on_wayvnc_exit = on_wayvnc_exit,
|
||||
|
|
Loading…
Reference in New Issue