From 4a775ec99d11ac2b60f5e56dc0f13e38a8e1aebe Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Thu, 6 Oct 2022 20:50:39 -0400 Subject: [PATCH 1/5] Refactor pointer initialization code Additionally, make the pointer setup reentrant, destroying the previous setup if needed. Signed-off-by: Jim Ramsay --- src/main.c | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/src/main.c b/src/main.c index 530e4673..6c792181 100644 --- a/src/main.c +++ b/src/main.c @@ -847,6 +847,28 @@ void parse_keyboard_option(struct wayvnc* self, char* arg) self->kb_layout = arg; } +void setup_pointer(struct wayvnc* self) { + self->pointer_backend.vnc = self->nvnc; + self->pointer_backend.output = self->selected_output; + if (!self->pointer_manager) + return; + + if (self->pointer_backend.pointer) + pointer_destroy(&self->pointer_backend); + + int pointer_manager_version = + zwlr_virtual_pointer_manager_v1_get_version(self->pointer_manager); + + self->pointer_backend.pointer = pointer_manager_version >= 2 + ? zwlr_virtual_pointer_manager_v1_create_virtual_pointer_with_output( + self->pointer_manager, self->selected_seat->wl_seat, + self->selected_output->wl_output) + : zwlr_virtual_pointer_manager_v1_create_virtual_pointer( + self->pointer_manager, self->selected_seat->wl_seat); + + pointer_init(&self->pointer_backend); +} + void log_selected_output(struct wayvnc* self) { nvnc_log(NVNC_LOG_INFO, "Capturing output %s", @@ -1082,22 +1104,9 @@ int main(int argc, char* argv[]) } } - self.pointer_backend.vnc = self.nvnc; - self.pointer_backend.output = self.selected_output; - if (self.pointer_manager) { - int pointer_manager_version = - zwlr_virtual_pointer_manager_v1_get_version(self.pointer_manager); + setup_pointer(&self); - self.pointer_backend.pointer = 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->userdata = &self; From fe82ae02fb1a1e3b50ba022223f4584d16782c5f Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Thu, 6 Oct 2022 20:57:45 -0400 Subject: [PATCH 2/5] Refactor output selection code Signed-off-by: Jim Ramsay --- src/main.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main.c b/src/main.c index 6c792181..9f3780fe 100644 --- a/src/main.c +++ b/src/main.c @@ -884,6 +884,14 @@ void log_selected_output(struct wayvnc* self) } } +void set_selected_output(struct wayvnc* self, struct output* output) { + self->selected_output = output; + self->screencopy.wl_output = output->wl_output; + output->on_dimension_change = on_output_dimension_change; + output->userdata = self; + log_selected_output(self); +} + static int log_level_from_string(const char* str) { if (0 == strcmp(str, "quiet")) return NVNC_LOG_PANIC; @@ -1061,6 +1069,7 @@ int main(int argc, char* argv[]) goto failure; } } + set_selected_output(&self, out); struct seat* seat = NULL; if (seat_name) { @@ -1077,12 +1086,9 @@ int main(int argc, char* argv[]) } } - self.selected_output = out; self.selected_seat = seat; - self.screencopy.wl_output = out->wl_output; self.screencopy.rate_limit = max_rate; self.screencopy.enable_linux_dmabuf = enable_gpu_features; - log_selected_output(&self); if (self.keyboard_manager) { self.keyboard_backend.virtual_keyboard = @@ -1107,9 +1113,6 @@ int main(int argc, char* argv[]) setup_pointer(&self); - out->on_dimension_change = on_output_dimension_change; - out->userdata = &self; - #ifdef ENABLE_SCREENCOPY_DMABUF if (init_render_node(&drm_fd) < 0) { nvnc_log(NVNC_LOG_ERROR, "Failed to initialise DRM render node. No GPU acceleration will be available."); From 3238468bdf232a126d00c6f02b94be95c46c4c8d Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Sat, 8 Oct 2022 14:45:14 -0400 Subject: [PATCH 3/5] Add output_cycle to get next/prev outputs Signed-off-by: Jim Ramsay --- include/output.h | 8 ++++++++ src/output.c | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/output.h b/include/output.h index 20b8d1b9..17d3f4f1 100644 --- a/include/output.h +++ b/include/output.h @@ -60,6 +60,14 @@ struct output* output_find_by_id(struct wl_list* list, uint32_t id); struct output* output_find_by_name(struct wl_list* list, const char* name); struct output* output_first(struct wl_list* list); +enum output_cycle_direction { + OUTPUT_CYCLE_FORWARD, + OUTPUT_CYCLE_REVERSE, +}; +struct output* output_cycle(const struct wl_list* list, + const struct output* current, + enum output_cycle_direction); + uint32_t output_get_transformed_width(const struct output* self); uint32_t output_get_transformed_height(const struct output* self); diff --git a/src/output.c b/src/output.c index c756528e..cdd34456 100644 --- a/src/output.c +++ b/src/output.c @@ -285,3 +285,20 @@ struct output* output_first(struct wl_list* list) return output; } + +struct output* output_cycle(const struct wl_list* list, + const struct output* current, + enum output_cycle_direction direction) +{ + const struct wl_list* iter = current ? ¤t->link : list; + iter = (direction == OUTPUT_CYCLE_FORWARD) ? + iter->next : iter->prev; + if (iter == list) { + if (wl_list_empty(list)) + return NULL; + iter = (direction == OUTPUT_CYCLE_FORWARD) ? + iter->next : iter->prev; + } + struct output* output; + return wl_container_of(iter, output, link); +} From 0d84511a89a92538c330a0e8a8229d2530d78f24 Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Sat, 8 Oct 2022 14:48:04 -0400 Subject: [PATCH 4/5] Add functions to switch outputs on the fly One to switch to an arbitrary outout, and then two helpers to switch to the next/previous in the output list. Signed-off-by: Jim Ramsay --- src/main.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main.c b/src/main.c index 9f3780fe..1687230d 100644 --- a/src/main.c +++ b/src/main.c @@ -78,7 +78,7 @@ struct wayvnc { struct zwp_virtual_keyboard_manager_v1* keyboard_manager; struct zwlr_virtual_pointer_manager_v1* pointer_manager; - const struct output* selected_output; + struct output* selected_output; const struct seat* selected_seat; struct screencopy screencopy; @@ -107,6 +107,8 @@ struct wayvnc { void wayvnc_exit(struct wayvnc* self); void on_capture_done(struct screencopy* sc); static void on_client_new(struct nvnc_client* client); +void switch_to_next_output(struct wayvnc*); +void switch_to_prev_output(struct wayvnc*); #if defined(GIT_VERSION) static const char wayvnc_version[] = GIT_VERSION; @@ -885,6 +887,9 @@ void log_selected_output(struct wayvnc* self) } void set_selected_output(struct wayvnc* self, struct output* output) { + if (self->selected_output) { + self->selected_output->on_dimension_change = NULL; + } self->selected_output = output; self->screencopy.wl_output = output->wl_output; output->on_dimension_change = on_output_dimension_change; @@ -892,6 +897,35 @@ void set_selected_output(struct wayvnc* self, struct output* output) { log_selected_output(self); } +void switch_to_output(struct wayvnc* self, struct output* output) +{ + if (self->selected_output == output) { + nvnc_log(NVNC_LOG_DEBUG, "No-op: Already selected output %s", + output->name); + return; + } + screencopy_stop(&self->screencopy); + set_selected_output(self, output); + setup_pointer(self); + wayvnc_start_capture_immediate(self); +} + +void switch_to_next_output(struct wayvnc* self) +{ + nvnc_log(NVNC_LOG_INFO, "Rotating to next output"); + struct output* next = output_cycle(&self->outputs, + self->selected_output, OUTPUT_CYCLE_FORWARD); + switch_to_output(self, next); +} + +void switch_to_prev_output(struct wayvnc* self) +{ + nvnc_log(NVNC_LOG_INFO, "Rotating to previous output"); + struct output* prev = output_cycle(&self->outputs, + self->selected_output, OUTPUT_CYCLE_REVERSE); + switch_to_output(self, prev); +} + static int log_level_from_string(const char* str) { if (0 == strcmp(str, "quiet")) return NVNC_LOG_PANIC; From e414aa858fd9fc007f5236cb2e5b5ec0011f67ff Mon Sep 17 00:00:00 2001 From: Jim Ramsay Date: Sat, 8 Oct 2022 14:53:27 -0400 Subject: [PATCH 5/5] Switch to previous output if current output disappears Signed-off-by: Jim Ramsay --- src/main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main.c b/src/main.c index 1687230d..742cd6db 100644 --- a/src/main.c +++ b/src/main.c @@ -227,13 +227,18 @@ static void registry_remove(void* data, struct wl_registry* registry, struct output* out = output_find_by_id(&self->outputs, id); if (out) { - nvnc_log(NVNC_LOG_INFO, "Output %s went away", out->name); + if (out == self->selected_output) { + nvnc_log(NVNC_LOG_WARNING, "Selected output %s went away", + out->name); + switch_to_prev_output(self); + } else + nvnc_log(NVNC_LOG_INFO, "Output %s went away", out->name); wl_list_remove(&out->link); output_destroy(out); if (out == self->selected_output) { - nvnc_log(NVNC_LOG_ERROR, "Selected output went away. Exiting..."); + nvnc_log(NVNC_LOG_ERROR, "No fallback outputs left. Exiting..."); wayvnc_exit(self); }