Fix segfault after hot-plugging outputs
When new outputs appear, either because they were just created or because they have been disabled/reenabled, ensure we always set up the right xdg_output and wlr_output_power listeners. Signed-off-by: Jim Ramsay <i.am@jimramsay.com>pull/204/head
parent
2a9e3dac58
commit
3e5d6ea8eb
|
@ -20,7 +20,9 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
struct zxdg_output_manager_v1;
|
||||||
struct zxdg_output_v1;
|
struct zxdg_output_v1;
|
||||||
|
struct zwlr_output_power_manager_v1;
|
||||||
struct zwlr_output_power_v1;
|
struct zwlr_output_power_v1;
|
||||||
|
|
||||||
enum output_power_state {
|
enum output_power_state {
|
||||||
|
@ -65,10 +67,7 @@ struct output {
|
||||||
|
|
||||||
struct output* output_new(struct wl_output* wl_output, uint32_t id);
|
struct output* output_new(struct wl_output* wl_output, uint32_t id);
|
||||||
void output_destroy(struct output* output);
|
void output_destroy(struct output* output);
|
||||||
void output_set_xdg_output(struct output* output,
|
void output_setup_wl_managers(struct wl_list* list);
|
||||||
struct zxdg_output_v1* xdg_output);
|
|
||||||
void output_set_wlr_output_power(struct output* output,
|
|
||||||
struct zwlr_output_power_v1* wlr_output_power);
|
|
||||||
int output_set_power_state(struct output* output, enum output_power_state state);
|
int output_set_power_state(struct output* output, enum output_power_state state);
|
||||||
void output_list_destroy(struct wl_list* list);
|
void output_list_destroy(struct wl_list* list);
|
||||||
struct output* output_find_by_id(struct wl_list* list, uint32_t id);
|
struct output* output_find_by_id(struct wl_list* list, uint32_t id);
|
||||||
|
|
47
src/main.c
47
src/main.c
|
@ -78,8 +78,6 @@ struct wayvnc {
|
||||||
struct wl_list seats;
|
struct wl_list seats;
|
||||||
struct cfg cfg;
|
struct cfg cfg;
|
||||||
|
|
||||||
struct zxdg_output_manager_v1* xdg_output_manager;
|
|
||||||
struct zwlr_output_power_manager_v1* wlr_output_power_manager;
|
|
||||||
struct zwp_virtual_keyboard_manager_v1* keyboard_manager;
|
struct zwp_virtual_keyboard_manager_v1* keyboard_manager;
|
||||||
struct zwlr_virtual_pointer_manager_v1* pointer_manager;
|
struct zwlr_virtual_pointer_manager_v1* pointer_manager;
|
||||||
struct zwlr_data_control_manager_v1* data_control_manager;
|
struct zwlr_data_control_manager_v1* data_control_manager;
|
||||||
|
@ -134,6 +132,8 @@ static void client_init_data_control(struct wayvnc_client* self);
|
||||||
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 zxdg_output_manager_v1* xdg_output_manager = NULL;
|
||||||
|
struct zwlr_output_power_manager_v1* wlr_output_power_manager = NULL;
|
||||||
|
|
||||||
static bool registry_add_input(void* data, struct wl_registry* registry,
|
static bool registry_add_input(void* data, struct wl_registry* registry,
|
||||||
uint32_t id, const char* interface,
|
uint32_t id, const char* interface,
|
||||||
|
@ -190,6 +190,7 @@ static void registry_add(void* data, struct wl_registry* registry,
|
||||||
struct wayvnc* self = data;
|
struct wayvnc* self = data;
|
||||||
|
|
||||||
if (strcmp(interface, wl_output_interface.name) == 0) {
|
if (strcmp(interface, wl_output_interface.name) == 0) {
|
||||||
|
nvnc_trace("Registering new output %u", id);
|
||||||
struct wl_output* wl_output =
|
struct wl_output* wl_output =
|
||||||
wl_registry_bind(registry, id, &wl_output_interface, 3);
|
wl_registry_bind(registry, id, &wl_output_interface, 3);
|
||||||
if (!wl_output)
|
if (!wl_output)
|
||||||
|
@ -204,16 +205,20 @@ static void registry_add(void* data, struct wl_registry* registry,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
||||||
self->xdg_output_manager =
|
nvnc_trace("Registering new xdg_output_manager");
|
||||||
|
xdg_output_manager =
|
||||||
wl_registry_bind(registry, id,
|
wl_registry_bind(registry, id,
|
||||||
&zxdg_output_manager_v1_interface, 3);
|
&zxdg_output_manager_v1_interface, 3);
|
||||||
|
|
||||||
|
output_setup_wl_managers(&self->outputs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(interface, zwlr_output_power_manager_v1_interface.name) == 0) {
|
if (strcmp(interface, zwlr_output_power_manager_v1_interface.name) == 0) {
|
||||||
self->wlr_output_power_manager =
|
nvnc_trace("Registering new wlr_output_power_manager");
|
||||||
wl_registry_bind(registry, id,
|
wlr_output_power_manager = wl_registry_bind(registry, id,
|
||||||
&zwlr_output_power_manager_v1_interface, 1);
|
&zwlr_output_power_manager_v1_interface, 1);
|
||||||
|
output_setup_wl_managers(&self->outputs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,11 +332,11 @@ 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);
|
||||||
|
|
||||||
zxdg_output_manager_v1_destroy(self->xdg_output_manager);
|
if (xdg_output_manager)
|
||||||
|
zxdg_output_manager_v1_destroy(xdg_output_manager);
|
||||||
|
|
||||||
if (self->wlr_output_power_manager)
|
if (wlr_output_power_manager)
|
||||||
zwlr_output_power_manager_v1_destroy(
|
zwlr_output_power_manager_v1_destroy(wlr_output_power_manager);
|
||||||
self->wlr_output_power_manager);
|
|
||||||
|
|
||||||
wl_shm_destroy(wl_shm);
|
wl_shm_destroy(wl_shm);
|
||||||
|
|
||||||
|
@ -357,25 +362,6 @@ void wayvnc_destroy(struct wayvnc* self)
|
||||||
wl_display_disconnect(self->display);
|
wl_display_disconnect(self->display);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void init_outputs(struct wayvnc* self)
|
|
||||||
{
|
|
||||||
struct output* output;
|
|
||||||
wl_list_for_each(output, &self->outputs, link) {
|
|
||||||
struct zxdg_output_v1* xdg_output =
|
|
||||||
zxdg_output_manager_v1_get_xdg_output(
|
|
||||||
self->xdg_output_manager, output->wl_output);
|
|
||||||
output_set_xdg_output(output, xdg_output);
|
|
||||||
|
|
||||||
if (self->wlr_output_power_manager) {
|
|
||||||
struct zwlr_output_power_v1* wlr_output_power =
|
|
||||||
zwlr_output_power_manager_v1_get_output_power(
|
|
||||||
self->wlr_output_power_manager,
|
|
||||||
output->wl_output);
|
|
||||||
output_set_wlr_output_power(output, wlr_output_power);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int init_wayland(struct wayvnc* self)
|
static int init_wayland(struct wayvnc* self)
|
||||||
{
|
{
|
||||||
static const struct wl_registry_listener registry_listener = {
|
static const struct wl_registry_listener registry_listener = {
|
||||||
|
@ -399,8 +385,6 @@ static int init_wayland(struct wayvnc* self)
|
||||||
wl_display_dispatch(self->display);
|
wl_display_dispatch(self->display);
|
||||||
wl_display_roundtrip(self->display);
|
wl_display_roundtrip(self->display);
|
||||||
|
|
||||||
init_outputs(self);
|
|
||||||
|
|
||||||
if (!self->pointer_manager && !self->disable_input) {
|
if (!self->pointer_manager && !self->disable_input) {
|
||||||
nvnc_log(NVNC_LOG_ERROR, "Virtual Pointer protocol not supported by compositor.");
|
nvnc_log(NVNC_LOG_ERROR, "Virtual Pointer protocol not supported by compositor.");
|
||||||
nvnc_log(NVNC_LOG_ERROR, "wayvnc may still work if started with --disable-input.");
|
nvnc_log(NVNC_LOG_ERROR, "wayvnc may still work if started with --disable-input.");
|
||||||
|
@ -413,9 +397,6 @@ static int init_wayland(struct wayvnc* self)
|
||||||
goto failure;
|
goto failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_display_dispatch(self->display);
|
|
||||||
wl_display_roundtrip(self->display);
|
|
||||||
|
|
||||||
if (!self->screencopy.manager) {
|
if (!self->screencopy.manager) {
|
||||||
nvnc_log(NVNC_LOG_ERROR, "Screencopy protocol not supported by compositor. Exiting. Refer to FAQ section in man page.");
|
nvnc_log(NVNC_LOG_ERROR, "Screencopy protocol not supported by compositor. Exiting. Refer to FAQ section in man page.");
|
||||||
goto failure;
|
goto failure;
|
||||||
|
|
78
src/output.c
78
src/output.c
|
@ -31,6 +31,9 @@
|
||||||
#include "xdg-output-unstable-v1.h"
|
#include "xdg-output-unstable-v1.h"
|
||||||
#include "wlr-output-power-management-unstable-v1.h"
|
#include "wlr-output-power-management-unstable-v1.h"
|
||||||
|
|
||||||
|
extern struct zxdg_output_manager_v1* xdg_output_manager;
|
||||||
|
extern struct zwlr_output_power_manager_v1* wlr_output_power_manager;
|
||||||
|
|
||||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
|
||||||
|
@ -181,7 +184,8 @@ static const struct wl_output_listener output_listener = {
|
||||||
|
|
||||||
void output_destroy(struct output* output)
|
void output_destroy(struct output* output)
|
||||||
{
|
{
|
||||||
zxdg_output_v1_destroy(output->xdg_output);
|
if (output->xdg_output)
|
||||||
|
zxdg_output_v1_destroy(output->xdg_output);
|
||||||
if (output->wlr_output_power)
|
if (output->wlr_output_power)
|
||||||
zwlr_output_power_v1_destroy(output->wlr_output_power);
|
zwlr_output_power_v1_destroy(output->wlr_output_power);
|
||||||
wl_output_destroy(output->wl_output);
|
wl_output_destroy(output->wl_output);
|
||||||
|
@ -199,24 +203,6 @@ void output_list_destroy(struct wl_list* list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct output* output_new(struct wl_output* wl_output, uint32_t id)
|
|
||||||
{
|
|
||||||
struct output* output = calloc(1, sizeof(*output));
|
|
||||||
if (!output) {
|
|
||||||
nvnc_log(NVNC_LOG_ERROR, "OOM");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
output->wl_output = wl_output;
|
|
||||||
output->id = id;
|
|
||||||
output->power = OUTPUT_POWER_UNKNOWN;
|
|
||||||
|
|
||||||
wl_output_add_listener(output->wl_output, &output_listener,
|
|
||||||
output);
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void output_logical_position(void* data, struct zxdg_output_v1* xdg_output,
|
void output_logical_position(void* data, struct zxdg_output_v1* xdg_output,
|
||||||
int32_t x, int32_t y)
|
int32_t x, int32_t y)
|
||||||
{
|
{
|
||||||
|
@ -233,6 +219,7 @@ void output_name(void* data, struct zxdg_output_v1* xdg_output,
|
||||||
struct output* self = data;
|
struct output* self = data;
|
||||||
|
|
||||||
strlcpy(self->name, name, sizeof(self->name));
|
strlcpy(self->name, name, sizeof(self->name));
|
||||||
|
nvnc_trace("Output %u name: %s", self->id, self->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void output_description(void* data, struct zxdg_output_v1* xdg_output,
|
void output_description(void* data, struct zxdg_output_v1* xdg_output,
|
||||||
|
@ -241,6 +228,7 @@ void output_description(void* data, struct zxdg_output_v1* xdg_output,
|
||||||
struct output* self = data;
|
struct output* self = data;
|
||||||
|
|
||||||
strlcpy(self->description, description, sizeof(self->description));
|
strlcpy(self->description, description, sizeof(self->description));
|
||||||
|
nvnc_trace("Output %u description: %s", self->id, self->description);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct zxdg_output_v1_listener xdg_output_listener = {
|
static const struct zxdg_output_v1_listener xdg_output_listener = {
|
||||||
|
@ -251,13 +239,17 @@ static const struct zxdg_output_v1_listener xdg_output_listener = {
|
||||||
.description = output_description,
|
.description = output_description,
|
||||||
};
|
};
|
||||||
|
|
||||||
void output_set_xdg_output(struct output* self,
|
static void output_setup_xdg_output_manager(struct output* self)
|
||||||
struct zxdg_output_v1* xdg_output)
|
|
||||||
{
|
{
|
||||||
self->xdg_output = xdg_output;
|
if (!xdg_output_manager || self->xdg_output)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct zxdg_output_v1* xdg_output =
|
||||||
|
zxdg_output_manager_v1_get_xdg_output(
|
||||||
|
xdg_output_manager, self->wl_output);
|
||||||
|
self->xdg_output = xdg_output;
|
||||||
zxdg_output_v1_add_listener(self->xdg_output, &xdg_output_listener,
|
zxdg_output_v1_add_listener(self->xdg_output, &xdg_output_listener,
|
||||||
self);
|
self);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* output_power_state_name(enum output_power_state state)
|
const char* output_power_state_name(enum output_power_state state)
|
||||||
|
@ -310,9 +302,15 @@ static const struct zwlr_output_power_v1_listener wlr_output_power_listener = {
|
||||||
.failed = output_power_failed,
|
.failed = output_power_failed,
|
||||||
};
|
};
|
||||||
|
|
||||||
void output_set_wlr_output_power(struct output* self,
|
static void output_setup_wlr_output_power_manager(struct output* self)
|
||||||
struct zwlr_output_power_v1* wlr_output_power)
|
|
||||||
{
|
{
|
||||||
|
if (!wlr_output_power_manager || self->wlr_output_power)
|
||||||
|
return;
|
||||||
|
|
||||||
|
struct zwlr_output_power_v1* wlr_output_power =
|
||||||
|
zwlr_output_power_manager_v1_get_output_power(
|
||||||
|
wlr_output_power_manager,
|
||||||
|
self->wl_output);
|
||||||
self->wlr_output_power = wlr_output_power;
|
self->wlr_output_power = wlr_output_power;
|
||||||
|
|
||||||
zwlr_output_power_v1_add_listener(self->wlr_output_power,
|
zwlr_output_power_v1_add_listener(self->wlr_output_power,
|
||||||
|
@ -382,3 +380,33 @@ struct output* output_cycle(const struct wl_list* list,
|
||||||
struct output* output;
|
struct output* output;
|
||||||
return wl_container_of(iter, output, link);
|
return wl_container_of(iter, output, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void output_setup_wl_managers(struct wl_list* list)
|
||||||
|
{
|
||||||
|
struct output* output;
|
||||||
|
wl_list_for_each(output, list, link) {
|
||||||
|
output_setup_xdg_output_manager(output);
|
||||||
|
output_setup_wlr_output_power_manager(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct output* output_new(struct wl_output* wl_output, uint32_t id)
|
||||||
|
{
|
||||||
|
struct output* output = calloc(1, sizeof(*output));
|
||||||
|
if (!output) {
|
||||||
|
nvnc_log(NVNC_LOG_ERROR, "OOM");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
output->wl_output = wl_output;
|
||||||
|
output->id = id;
|
||||||
|
output->power = OUTPUT_POWER_UNKNOWN;
|
||||||
|
|
||||||
|
wl_output_add_listener(output->wl_output, &output_listener,
|
||||||
|
output);
|
||||||
|
|
||||||
|
output_setup_xdg_output_manager(output);
|
||||||
|
output_setup_wlr_output_power_manager(output);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue