libinput: use head names for output matching

Associating input devices with weston_outputs by the output name fails
when one output has several heads. We need to match against head names
instead of output names to be able to find all names.

This fixes touchscreen output association in shared-CRTC clone mode when
outputs or input devices appear or disappear.

Even though notify_output_create() is called only when new outputs
appear, the implementation is prepared to also remove output
associations. This will be handy in the future when this function will
handle also head detaching from an output that remains enabled.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Pekka Paalanen 2018-03-19 14:55:41 +02:00
parent 98d50cc311
commit fd02efbc84
1 changed files with 41 additions and 10 deletions

View File

@ -58,6 +58,27 @@ get_udev_seat(struct udev_input *input, struct libinput_device *device)
return udev_seat_get_named(input, seat_name);
}
static struct weston_output *
output_find_by_head_name(struct weston_compositor *compositor,
const char *head_name)
{
struct weston_output *output;
struct weston_head *head;
if (!head_name)
return NULL;
/* only enabled outputs */
wl_list_for_each(output, &compositor->output_list, link) {
wl_list_for_each(head, &output->head_list, output_link) {
if (strcmp(head_name, head->name) == 0)
return output;
}
}
return NULL;
}
static void
device_added(struct udev_input *input, struct libinput_device *libinput_device)
{
@ -95,11 +116,10 @@ device_added(struct udev_input *input, struct libinput_device *libinput_device)
output_name = libinput_device_get_output_name(libinput_device);
if (output_name) {
device->output_name = strdup(output_name);
wl_list_for_each(output, &c->output_list, link)
if (output->name &&
strcmp(output->name, device->output_name) == 0)
evdev_device_set_output(device, output);
} else if (device->output == NULL && !wl_list_empty(&c->output_list)) {
output = output_find_by_head_name(c, output_name);
evdev_device_set_output(device, output);
} else if (!wl_list_empty(&c->output_list)) {
/* default assignment to an arbitrary output */
output = container_of(c->output_list.next,
struct weston_output, link);
evdev_device_set_output(device, output);
@ -363,15 +383,26 @@ notify_output_create(struct wl_listener *listener, void *data)
output_create_listener);
struct evdev_device *device;
struct weston_output *output = data;
struct weston_output *found;
wl_list_for_each(device, &seat->devices_list, link) {
if (device->output_name &&
strcmp(output->name, device->output_name) == 0) {
evdev_device_set_output(device, output);
/* If we find any input device without an associated output
* or an output name to associate with, just tie it with the
* output we got here - the default assingment.
*/
if (!device->output_name) {
if (!device->output)
evdev_device_set_output(device, output);
continue;
}
if (device->output_name == NULL && device->output == NULL)
evdev_device_set_output(device, output);
/* Update all devices' output associations, may they gain or
* lose it.
*/
found = output_find_by_head_name(output->compositor,
device->output_name);
evdev_device_set_output(device, found);
}
}