libinput-seat.c 12.2 KB
Newer Older
1 2 3 4
/*
 * Copyright © 2013 Intel Corporation
 * Copyright © 2013 Jonas Ådahl
 *
5 6 7 8 9 10 11
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
12
 *
13 14 15 16 17 18 19 20 21 22 23 24
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
25 26 27 28
 */

#include "config.h"

29
#include <stdint.h>
30 31 32 33 34 35 36 37 38 39 40
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <libinput.h>
#include <libudev.h>

#include "compositor.h"
#include "launcher-util.h"
#include "libinput-seat.h"
#include "libinput-device.h"
41
#include "shared/helpers.h"
42 43 44 45 46 47 48 49

static void
process_events(struct udev_input *input);
static struct udev_seat *
udev_seat_create(struct udev_input *input, const char *seat_name);
static void
udev_seat_destroy(struct udev_seat *seat);

50 51 52 53 54 55 56 57 58 59 60
static struct udev_seat *
get_udev_seat(struct udev_input *input, struct libinput_device *device)
{
	struct libinput_seat *libinput_seat;
	const char *seat_name;

	libinput_seat = libinput_device_get_seat(device);
	seat_name = libinput_seat_get_logical_name(libinput_seat);
	return udev_seat_get_named(input, seat_name);
}

61 62 63 64 65 66 67 68 69 70
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;

71 72 73 74 75
	/* Only enabled outputs with connected heads.
	 * This means force-enabled outputs but with disconnected heads
	 * will be ignored; if the touchscreen doesn't have a video signal,
	 * touching it is meaningless.
	 */
76 77
	wl_list_for_each(output, &compositor->output_list, link) {
		wl_list_for_each(head, &output->head_list, output_link) {
78 79 80
			if (!weston_head_is_connected(head))
				continue;

81 82 83 84 85 86 87 88
			if (strcmp(head_name, head->name) == 0)
				return output;
		}
	}

	return NULL;
}

89 90 91 92 93 94 95 96 97
static void
device_added(struct udev_input *input, struct libinput_device *libinput_device)
{
	struct weston_compositor *c;
	struct evdev_device *device;
	struct weston_output *output;
	const char *output_name;
	struct weston_seat *seat;
	struct udev_seat *udev_seat;
98
	struct weston_pointer *pointer;
99 100 101

	c = input->compositor;

102
	udev_seat = get_udev_seat(input, libinput_device);
103 104 105 106 107 108 109 110
	if (!udev_seat)
		return;

	seat = &udev_seat->base;
	device = evdev_device_create(libinput_device, seat);
	if (device == NULL)
		return;

111 112 113
	if (input->configure_device != NULL)
		input->configure_device(c, device->device);
	evdev_device_set_calibration(device);
114 115 116
	udev_seat = (struct udev_seat *) seat;
	wl_list_insert(udev_seat->devices_list.prev, &device->link);

117 118 119 120 121
	pointer = weston_seat_get_pointer(seat);
	if (seat->output && pointer)
		weston_pointer_clamp(pointer,
				     &pointer->x,
				     &pointer->y);
122 123 124 125

	output_name = libinput_device_get_output_name(libinput_device);
	if (output_name) {
		device->output_name = strdup(output_name);
126 127 128 129
		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 */
130 131 132 133 134 135 136 137 138
		output = container_of(c->output_list.next,
				      struct weston_output, link);
		evdev_device_set_output(device, output);
	}

	if (!input->suspended)
		weston_seat_repick(seat);
}

139 140 141 142
static void
device_removed(struct udev_input *input, struct libinput_device *libinput_device)
{
	struct evdev_device *device;
143

144 145 146 147
	device = libinput_device_get_user_data(libinput_device);
	evdev_device_destroy(device);
}

148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
static void
udev_seat_remove_devices(struct udev_seat *seat)
{
	struct evdev_device *device, *next;

	wl_list_for_each_safe(device, next, &seat->devices_list, link) {
		evdev_device_destroy(device);
	}
}

void
udev_input_disable(struct udev_input *input)
{
	if (input->suspended)
		return;

164 165
	wl_event_source_remove(input->libinput_source);
	input->libinput_source = NULL;
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
	libinput_suspend(input->libinput);
	process_events(input);
	input->suspended = 1;
}

static int
udev_input_process_event(struct libinput_event *event)
{
	struct libinput *libinput = libinput_event_get_context(event);
	struct libinput_device *libinput_device =
		libinput_event_get_device(event);
	struct udev_input *input = libinput_get_user_data(libinput);
	int handled = 1;

	switch (libinput_event_get_type(event)) {
	case LIBINPUT_EVENT_DEVICE_ADDED:
		device_added(input, libinput_device);
		break;
	case LIBINPUT_EVENT_DEVICE_REMOVED:
185
		device_removed(input, libinput_device);
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
		break;
	default:
		handled = 0;
	}

	return handled;
}

static void
process_event(struct libinput_event *event)
{
	if (udev_input_process_event(event))
		return;
	if (evdev_device_process_event(event))
		return;
}

static void
process_events(struct udev_input *input)
{
	struct libinput_event *event;

	while ((event = libinput_get_event(input->libinput))) {
		process_event(event);
		libinput_event_destroy(event);
	}
}

static int
udev_input_dispatch(struct udev_input *input)
{
	if (libinput_dispatch(input->libinput) != 0)
		weston_log("libinput: Failed to dispatch libinput\n");

	process_events(input);

	return 0;
}

static int
libinput_source_dispatch(int fd, uint32_t mask, void *data)
{
	struct udev_input *input = data;

	return udev_input_dispatch(input) != 0;
}

static int
open_restricted(const char *path, int flags, void *user_data)
{
	struct udev_input *input = user_data;
	struct weston_launcher *launcher = input->compositor->launcher;

	return weston_launcher_open(launcher, path, flags);
}

static void
close_restricted(int fd, void *user_data)
{
	struct udev_input *input = user_data;
	struct weston_launcher *launcher = input->compositor->launcher;

	weston_launcher_close(launcher, fd);
}

const struct libinput_interface libinput_interface = {
	open_restricted,
	close_restricted,
};

int
udev_input_enable(struct udev_input *input)
{
	struct wl_event_loop *loop;
	struct weston_compositor *c = input->compositor;
	int fd;
	struct udev_seat *seat;
	int devices_found = 0;

	loop = wl_display_get_event_loop(c->wl_display);
	fd = libinput_get_fd(input->libinput);
	input->libinput_source =
		wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
				     libinput_source_dispatch, input);
	if (!input->libinput_source) {
		return -1;
	}

	if (input->suspended) {
		if (libinput_resume(input->libinput) != 0) {
			wl_event_source_remove(input->libinput_source);
			input->libinput_source = NULL;
			return -1;
		}
		input->suspended = 0;
		process_events(input);
	}

	wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
		evdev_notify_keyboard_focus(&seat->base, &seat->devices_list);

		if (!wl_list_empty(&seat->devices_list))
			devices_found = 1;
	}

291 292 293 294 295 296
	if (devices_found == 0 && !c->require_input) {
		weston_log("warning: no input devices found, but none required "
			   "as per configuration.\n");
		return 0;
	}

297 298 299 300 301 302 303 304 305 306 307 308 309 310
	if (devices_found == 0) {
		weston_log(
			"warning: no input devices on entering Weston. "
			"Possible causes:\n"
			"\t- no permissions to read /dev/input/event*\n"
			"\t- seats misconfigured "
			"(Weston backend option 'seat', "
			"udev device property ID_SEAT)\n");
		return -1;
	}

	return 0;
}

311
static void
Peter Hutterer's avatar
Peter Hutterer committed
312 313 314
libinput_log_func(struct libinput *libinput,
		  enum libinput_log_priority priority,
		  const char *format, va_list args)
315 316 317 318
{
	weston_vlog(format, args);
}

319
int
320
udev_input_init(struct udev_input *input, struct weston_compositor *c,
321 322
		struct udev *udev, const char *seat_id,
		udev_configure_device_t configure_device)
323
{
324
	enum libinput_log_priority priority = LIBINPUT_LOG_PRIORITY_INFO;
325 326
	const char *log_priority = NULL;

327 328 329
	memset(input, 0, sizeof *input);

	input->compositor = c;
330
	input->configure_device = configure_device;
331

332
	log_priority = getenv("WESTON_LIBINPUT_LOG_PRIORITY");
333

Peter Hutterer's avatar
Peter Hutterer committed
334 335 336 337 338 339 340 341
	input->libinput = libinput_udev_create_context(&libinput_interface,
						       input, udev);
	if (!input->libinput) {
		return -1;
	}

	libinput_log_set_handler(input->libinput, &libinput_log_func);

342
	if (log_priority) {
343
		if (strcmp(log_priority, "debug") == 0) {
344
			priority = LIBINPUT_LOG_PRIORITY_DEBUG;
345
		} else if (strcmp(log_priority, "info") == 0) {
346
			priority = LIBINPUT_LOG_PRIORITY_INFO;
347
		} else if (strcmp(log_priority, "error") == 0) {
348
			priority = LIBINPUT_LOG_PRIORITY_ERROR;
349
		}
350 351
	}

352 353
	libinput_log_set_priority(input->libinput, priority);

Peter Hutterer's avatar
Peter Hutterer committed
354 355
	if (libinput_udev_assign_seat(input->libinput, seat_id) != 0) {
		libinput_unref(input->libinput);
356 357
		return -1;
	}
Peter Hutterer's avatar
Peter Hutterer committed
358

359 360 361 362 363 364 365 366 367 368
	process_events(input);

	return udev_input_enable(input);
}

void
udev_input_destroy(struct udev_input *input)
{
	struct udev_seat *seat, *next;

369 370
	if (input->libinput_source)
		wl_event_source_remove(input->libinput_source);
371 372
	wl_list_for_each_safe(seat, next, &input->compositor->seat_list, base.link)
		udev_seat_destroy(seat);
Peter Hutterer's avatar
Peter Hutterer committed
373
	libinput_unref(input->libinput);
374 375 376 377 378 379 380 381 382 383 384 385 386
}

static void
udev_seat_led_update(struct weston_seat *seat_base, enum weston_led leds)
{
	struct udev_seat *seat = (struct udev_seat *) seat_base;
	struct evdev_device *device;

	wl_list_for_each(device, &seat->devices_list, link)
		evdev_led_update(device, leds);
}

static void
387
udev_seat_output_changed(struct udev_seat *seat, struct weston_output *output)
388 389
{
	struct evdev_device *device;
390
	struct weston_output *found;
391

392
	wl_list_for_each(device, &seat->devices_list, link) {
393 394 395 396 397 398 399 400 401
		/* 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;
402
		}
403

404 405 406 407 408 409
		/* 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);
410
	}
411 412
}

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432
static void
notify_output_create(struct wl_listener *listener, void *data)
{
	struct udev_seat *seat = container_of(listener, struct udev_seat,
					      output_create_listener);
	struct weston_output *output = data;

	udev_seat_output_changed(seat, output);
}

static void
notify_output_heads_changed(struct wl_listener *listener, void *data)
{
	struct udev_seat *seat = container_of(listener, struct udev_seat,
					      output_heads_listener);
	struct weston_output *output = data;

	udev_seat_output_changed(seat, output);
}

433 434 435 436 437 438 439 440 441
static struct udev_seat *
udev_seat_create(struct udev_input *input, const char *seat_name)
{
	struct weston_compositor *c = input->compositor;
	struct udev_seat *seat;

	seat = zalloc(sizeof *seat);
	if (!seat)
		return NULL;
442

443 444 445 446 447 448 449
	weston_seat_init(&seat->base, c, seat_name);
	seat->base.led_update = udev_seat_led_update;

	seat->output_create_listener.notify = notify_output_create;
	wl_signal_add(&c->output_created_signal,
		      &seat->output_create_listener);

450 451 452 453
	seat->output_heads_listener.notify = notify_output_heads_changed;
	wl_signal_add(&c->output_heads_changed_signal,
		      &seat->output_heads_listener);

454 455 456 457 458 459 460 461
	wl_list_init(&seat->devices_list);

	return seat;
}

static void
udev_seat_destroy(struct udev_seat *seat)
{
462 463 464 465
	struct weston_keyboard *keyboard =
		weston_seat_get_keyboard(&seat->base);

	if (keyboard)
466
		notify_keyboard_focus_out(&seat->base);
467 468

	udev_seat_remove_devices(seat);
469 470
	weston_seat_release(&seat->base);
	wl_list_remove(&seat->output_create_listener.link);
471
	wl_list_remove(&seat->output_heads_listener.link);
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
	free(seat);
}

struct udev_seat *
udev_seat_get_named(struct udev_input *input, const char *seat_name)
{
	struct udev_seat *seat;

	wl_list_for_each(seat, &input->compositor->seat_list, base.link) {
		if (strcmp(seat->base.seat_name, seat_name) == 0)
			return seat;
	}

	return udev_seat_create(input, seat_name);
}