diff --git a/include/pointer.h b/include/pointer.h index b16134a..acba0be 100644 --- a/include/pointer.h +++ b/include/pointer.h @@ -34,7 +34,7 @@ struct pointer { uint32_t height; }; -int pointer_init(struct pointer* self); +int pointer_init(struct pointer* self, struct wl_seat* seat); void pointer_destroy(struct pointer* self); void pointer_set(struct pointer* self, uint32_t x, uint32_t y, diff --git a/include/seat.h b/include/seat.h new file mode 100644 index 0000000..356358d --- /dev/null +++ b/include/seat.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#pragma once + +#include +#include + +struct seat { + struct wl_seat* wl_seat; + struct wl_list link; + + uint32_t capabilities; + char name[256]; +}; + +struct seat* seat_new(struct wl_seat* wl_seat); +void seat_destroy(struct seat* self); +void seat_list_destroy(struct wl_list* list); + +struct seat* seat_find_by_name(struct wl_list* list, const char* name); +struct seat* seat_first(struct wl_list* list); diff --git a/meson.build b/meson.build index a79a429..59eb5a1 100644 --- a/meson.build +++ b/meson.build @@ -49,6 +49,7 @@ sources = [ 'src/output.c', 'src/pointer.c', 'src/keyboard.c', + 'src/seat.c', 'src/smooth.c', ] diff --git a/src/main.c b/src/main.c index 9f30a85..f36fc52 100644 --- a/src/main.c +++ b/src/main.c @@ -44,6 +44,7 @@ #include "output.h" #include "pointer.h" #include "keyboard.h" +#include "seat.h" #define DEFAULT_ADDRESS "127.0.0.1" #define DEFAULT_PORT 5900 @@ -58,12 +59,13 @@ struct wayvnc { struct wl_display* display; struct wl_registry* registry; struct wl_list outputs; - struct wl_seat* seat; + struct wl_list seats; struct zwp_virtual_keyboard_manager_v1* keyboard_manager; struct renderer renderer; const struct output* selected_output; + const struct seat* selected_seat; struct dmabuf_capture dmabuf_backend; struct screencopy screencopy_backend; @@ -163,8 +165,18 @@ static void registry_add(void* data, struct wl_registry* registry, } if (strcmp(interface, wl_seat_interface.name) == 0) { - self->seat = + struct wl_seat* wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, 7); + if (!wl_seat) + return; + + struct seat* seat = seat_new(wl_seat); + if (!seat) { + wl_seat_destroy(wl_seat); + return; + } + + wl_list_insert(&self->seats, &seat->link); return; } @@ -194,8 +206,8 @@ static void registry_remove(void* data, struct wl_registry* registry, void wayvnc_destroy(struct wayvnc* self) { output_list_destroy(&self->outputs); + seat_list_destroy(&self->seats); - wl_seat_destroy(self->seat); wl_shm_destroy(self->screencopy_backend.wl_shm); zwp_virtual_keyboard_v1_destroy(self->keyboard_backend.virtual_keyboard); @@ -225,6 +237,7 @@ static int init_wayland(struct wayvnc* self) return -1; wl_list_init(&self->outputs); + wl_list_init(&self->seats); self->registry = wl_display_get_registry(self->display); if (!self->registry) @@ -247,23 +260,6 @@ static int init_wayland(struct wayvnc* self) self->screencopy_backend.frame_capture.on_done = on_capture_done; self->screencopy_backend.frame_capture.userdata = self; - if (self->pointer_backend.manager) { - self->pointer_backend.vnc = self->nvnc; - pointer_init(&self->pointer_backend); - } else { - log_error("Compositor does not support %s.\n", - zwlr_virtual_pointer_manager_v1_interface.name); - } - - assert(self->seat); - assert(self->keyboard_manager); - - self->keyboard_backend.virtual_keyboard = - zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( - self->keyboard_manager, self->seat); - - keyboard_init(&self->keyboard_backend, self->kb_layout); - return 0; export_manager_failure: @@ -509,6 +505,7 @@ int wayvnc_usage(FILE* stream, int rc) " -c,--frame-capturing=screencopy|dmabuf Select frame capturing backend.\n" " -o,--output= Select output to capture.\n" " -k,--keyboard= Select keyboard layout.\n" +" -s,--seat= Select seat by name.\n" " -h,--help Get help (this text).\n" "\n"; @@ -527,13 +524,15 @@ int main(int argc, char* argv[]) int output_id = -1; enum frame_capture_backend_type fcbackend = FRAME_CAPTURE_BACKEND_SCREENCOPY; + const char* seat_name = NULL; - static const char* shortopts = "c:o:k:h"; + static const char* shortopts = "c:o:k:s:h"; static const struct option longopts[] = { { "frame-capturing", required_argument, NULL, 'c' }, { "output", required_argument, NULL, 'o' }, { "keyboard", required_argument, NULL, 'k' }, + { "seat", required_argument, NULL, 's' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; @@ -559,6 +558,9 @@ int main(int argc, char* argv[]) case 'k': self.kb_layout = optarg; break; + case 's': + seat_name = optarg; + break; case 'h': return wayvnc_usage(stdout, 0); default: @@ -600,7 +602,23 @@ int main(int argc, char* argv[]) } } + struct seat* seat; + if (seat_name) { + seat = seat_find_by_name(&self.seats, seat_name); + if (!seat) { + log_error("No such seat\n"); + goto failure; + } + } else { + seat = seat_first(&self.seats); + if (!seat) { + log_error("No seat found\n"); + goto failure; + } + } + self.selected_output = out; + self.selected_seat = seat; self.dmabuf_backend.fc.wl_output = out->wl_output; self.screencopy_backend.frame_capture.wl_output = out->wl_output; @@ -609,6 +627,22 @@ int main(int argc, char* argv[]) self.pointer_backend.height = out->height; } + assert(self.keyboard_manager); + + self.keyboard_backend.virtual_keyboard = + zwp_virtual_keyboard_manager_v1_create_virtual_keyboard( + self.keyboard_manager, self.selected_seat->wl_seat); + + keyboard_init(&self.keyboard_backend, self.kb_layout); + + if (self.pointer_backend.manager) { + self.pointer_backend.vnc = self.nvnc; + pointer_init(&self.pointer_backend, self.selected_seat->wl_seat); + } else { + log_error("Compositor does not support %s.\n", + zwlr_virtual_pointer_manager_v1_interface.name); + goto failure; + } if (renderer_init(&self.renderer, self.selected_output->width, self.selected_output->height) < 0) { diff --git a/src/pointer.c b/src/pointer.c index 890f28b..6a93e69 100644 --- a/src/pointer.c +++ b/src/pointer.c @@ -23,10 +23,10 @@ #include "wlr-virtual-pointer-unstable-v1.h" #include "time-util.h" -int pointer_init(struct pointer* self) +int pointer_init(struct pointer* self, struct wl_seat* seat) { self->pointer = - zwlr_virtual_pointer_manager_v1_create_virtual_pointer(self->manager, NULL); + zwlr_virtual_pointer_manager_v1_create_virtual_pointer(self->manager, seat); zwlr_virtual_pointer_v1_axis_source(self->pointer, WL_POINTER_AXIS_SOURCE_WHEEL); diff --git a/src/seat.c b/src/seat.c new file mode 100644 index 0000000..681334a --- /dev/null +++ b/src/seat.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019 Andri Yngvason + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +#include "seat.h" +#include "strlcpy.h" + +static void seat_capabilities(void* data, struct wl_seat* wl_seat, + uint32_t capabilities) +{ + struct seat* self = data; + + self->capabilities = capabilities; +} + +static void seat_name(void* data, struct wl_seat* wl_seat, const char* name) +{ + struct seat* self = data; + + strlcpy(self->name, name, sizeof(self->name)); +} + +static const struct wl_seat_listener seat_listener = { + .capabilities = seat_capabilities, + .name = seat_name, +}; + +struct seat* seat_new(struct wl_seat* wl_seat) +{ + struct seat* self = calloc(1, sizeof(*self)); + if (!self) + return NULL; + + self->wl_seat = wl_seat; + + wl_seat_add_listener(wl_seat, &seat_listener, self); + + return self; +} + +void seat_destroy(struct seat* self) +{ + wl_seat_destroy(self->wl_seat); + free(self); +} + +void seat_list_destroy(struct wl_list* list) +{ + struct seat* seat; + struct seat* tmp; + + wl_list_for_each_safe(seat, tmp, list, link) { + wl_list_remove(&seat->link); + seat_destroy(seat); + } +} + +struct seat* seat_find_by_name(struct wl_list* list, const char* name) +{ + struct seat* seat; + + wl_list_for_each(seat, list, link) + if (strcmp(seat->name, name) == 0) + return seat; + + return NULL; +} + +struct seat* seat_first(struct wl_list* list) +{ + struct seat* seat; + + wl_list_for_each(seat, list, link) + return seat; + + return NULL; +}