Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-output: part 1 - internal functions to cycle between outputs #163

Merged
merged 5 commits into from
Nov 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions include/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
97 changes: 74 additions & 23 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -225,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);
}

Expand Down Expand Up @@ -847,6 +854,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",
Expand All @@ -862,6 +891,46 @@ 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;
output->userdata = self;
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;
Expand Down Expand Up @@ -1039,6 +1108,7 @@ int main(int argc, char* argv[])
goto failure;
}
}
set_selected_output(&self, out);

struct seat* seat = NULL;
if (seat_name) {
Expand All @@ -1055,12 +1125,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 =
Expand All @@ -1082,24 +1149,8 @@ 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);

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;
setup_pointer(&self);

#ifdef ENABLE_SCREENCOPY_DMABUF
if (init_render_node(&drm_fd) < 0) {
Expand Down
17 changes: 17 additions & 0 deletions src/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 ? &current->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);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can just as well say wl_container_of(iter, struct output, link) here.

}