backend/wayland: Listen to pointers from all seats
This effectively gets swaywm/wlroots#1499 to the point where functionality somewhat preserved and no crash happens. We still can have only one cursor, but we can control it from multiple seats in time-sharing manner by entering/leaving output.
This commit is contained in:
parent
44c4773d58
commit
07e2e0f60c
|
@ -22,14 +22,16 @@
|
|||
#include "util/signal.h"
|
||||
#include "util/time.h"
|
||||
|
||||
static struct wlr_wl_pointer *output_get_pointer(struct wlr_wl_output *output) {
|
||||
static struct wlr_wl_pointer *output_get_pointer(
|
||||
struct wlr_wl_output *output,
|
||||
const struct wl_pointer *wl_pointer) {
|
||||
struct wlr_input_device *wlr_dev;
|
||||
wl_list_for_each(wlr_dev, &output->backend->devices, link) {
|
||||
if (wlr_dev->type != WLR_INPUT_DEVICE_POINTER) {
|
||||
continue;
|
||||
}
|
||||
struct wlr_wl_pointer *pointer = pointer_get_wl(wlr_dev->pointer);
|
||||
if (pointer->output == output) {
|
||||
if (pointer->output == output && pointer->wl_pointer == wl_pointer) {
|
||||
return pointer;
|
||||
}
|
||||
}
|
||||
|
@ -47,8 +49,15 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
|
|||
|
||||
struct wlr_wl_output *output = wl_surface_get_user_data(surface);
|
||||
assert(output);
|
||||
struct wlr_wl_pointer *pointer = output_get_pointer(output);
|
||||
assert(!backend->current_pointer || backend->current_pointer == pointer);
|
||||
struct wlr_wl_pointer *pointer = output_get_pointer(output, wl_pointer);
|
||||
|
||||
struct wlr_wl_pointer *current_pointer = backend->current_pointer;
|
||||
if (current_pointer && current_pointer != pointer) {
|
||||
wlr_log(WLR_INFO, "Ignoring seat %s pointer cursor in favor of seat %s",
|
||||
pointer->input_device->seat->name,
|
||||
current_pointer->input_device->seat->name);
|
||||
return;
|
||||
}
|
||||
|
||||
output->enter_serial = serial;
|
||||
backend->current_pointer = pointer;
|
||||
|
@ -422,6 +431,8 @@ static void input_device_destroy(struct wlr_input_device *wlr_dev) {
|
|||
wl_keyboard_release(seat->keyboard);
|
||||
seat->keyboard = NULL;
|
||||
}
|
||||
// We can't destroy pointer here because we might have multiple devices
|
||||
// exposing it to compositor.
|
||||
wl_list_remove(&dev->wlr_input_device.link);
|
||||
free(dev);
|
||||
}
|
||||
|
@ -625,16 +636,12 @@ void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) {
|
|||
struct wl_pointer *wl_pointer = seat->pointer;
|
||||
struct wlr_wl_backend *backend = output->backend;
|
||||
|
||||
struct wlr_input_device *wlr_dev;
|
||||
wl_list_for_each(wlr_dev, &output->backend->devices, link) {
|
||||
if (wlr_dev->type != WLR_INPUT_DEVICE_POINTER) {
|
||||
continue;
|
||||
}
|
||||
struct wlr_wl_pointer *pointer = pointer_get_wl(wlr_dev->pointer);
|
||||
if (pointer->output == output) {
|
||||
if (output_get_pointer(output, wl_pointer)) {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Pointer for seat %s and output %s already exists (ignoring)",
|
||||
seat->name, output->wlr_output.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_wl_pointer *pointer = calloc(1, sizeof(struct wlr_wl_pointer));
|
||||
if (pointer == NULL) {
|
||||
|
@ -642,7 +649,7 @@ void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) {
|
|||
return;
|
||||
}
|
||||
pointer->wl_pointer = wl_pointer;
|
||||
pointer->output = output;
|
||||
pointer->output = output; // we need output to map absolute coordinates onto
|
||||
|
||||
struct wlr_wl_input_device *dev =
|
||||
create_wl_input_device(seat, WLR_INPUT_DEVICE_POINTER);
|
||||
|
@ -656,7 +663,7 @@ void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) {
|
|||
wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy);
|
||||
pointer->output_destroy.notify = pointer_handle_output_destroy;
|
||||
|
||||
wlr_dev = &dev->wlr_input_device;
|
||||
struct wlr_input_device *wlr_dev = &dev->wlr_input_device;
|
||||
wlr_dev->pointer = &pointer->wlr_pointer;
|
||||
wlr_dev->output_name = strdup(output->wlr_output.name);
|
||||
wlr_pointer_init(wlr_dev->pointer, &pointer_impl);
|
||||
|
@ -748,11 +755,21 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
|||
if (!(caps & WL_SEAT_CAPABILITY_POINTER) && seat->pointer != NULL) {
|
||||
wlr_log(WLR_DEBUG, "seat %p dropped pointer", (void *)wl_seat);
|
||||
|
||||
struct wl_pointer *wl_pointer = seat->pointer;
|
||||
|
||||
struct wlr_input_device *device, *tmp;
|
||||
wl_list_for_each_safe(device, tmp, &backend->devices, link) {
|
||||
if (device->type == WLR_INPUT_DEVICE_POINTER) {
|
||||
wlr_input_device_destroy(device);
|
||||
if (device->type != WLR_INPUT_DEVICE_POINTER) {
|
||||
continue;
|
||||
}
|
||||
struct wlr_wl_pointer *pointer = pointer_get_wl(device->pointer);
|
||||
if (pointer->wl_pointer != wl_pointer) {
|
||||
continue;
|
||||
}
|
||||
wlr_log(WLR_DEBUG, "dropping pointer %s",
|
||||
pointer->input_device->wlr_input_device.name);
|
||||
wlr_input_device_destroy(device);
|
||||
assert(backend->current_pointer != pointer);
|
||||
}
|
||||
|
||||
wl_pointer_release(seat->pointer);
|
||||
|
@ -774,9 +791,16 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
|
|||
|
||||
struct wlr_input_device *device, *tmp;
|
||||
wl_list_for_each_safe(device, tmp, &backend->devices, link) {
|
||||
if (device->type == WLR_INPUT_DEVICE_KEYBOARD) {
|
||||
wlr_input_device_destroy(device);
|
||||
if (device->type != WLR_INPUT_DEVICE_KEYBOARD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_wl_input_device *input_device =
|
||||
get_wl_input_device_from_input_device(device);
|
||||
if (input_device->seat != seat) {
|
||||
continue;
|
||||
}
|
||||
wlr_input_device_destroy(device);
|
||||
}
|
||||
assert(seat->keyboard == NULL); // free'ed by input_device_destroy
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue