commit ac63183

shrub  ·  2026-08-06 18:33:20 +0000 UTC
parent fa87d67
drop evdev-only seat
5 files changed,  +7, -704
+1, -2
 1@@ -18,7 +18,6 @@ neu features
 2 - fullscreen
 3 - double window borders
 4 - screenshots
 5-- evdev-only input backend
 6 - layer shell support
 7 - window decorations
 8 
 9@@ -35,7 +34,7 @@ you will need:
10 - wayland-server, wayland-client
11 - libdrm, pixman, xkbcommon
12 - [neuwld](https://git.sr.ht/~shrub900/neuwld)
13-- on linux, either libinput or evdev, depending on your choice of input backend, neither on BSD
14+- libinput on Linux and wscons on BSD
15 - xcb, xcb-composite, xcb-ewmh and xcb-icccm if you want Xwayland support.
16 
17 to build, i use muon and samu. you can probably do something similar with meson and ninja.
+0, -1
1@@ -42,7 +42,6 @@ libswc_src = files(
2 
3   input_backend == 'libinput' ? 'seat.c' : [],
4   input_backend == 'wscons' ? 'seat-ws.c' : [],
5-  input_backend == 'evdev' ? 'seat-evdev.c' : [],
6 
7   xwayland.found() ? ['xserver.c', 'xwm.c'] : [],  
8 )
+0, -691
  1@@ -1,691 +0,0 @@
  2-#include "compositor.h"
  3-#include "data_device.h"
  4-#include "event.h"
  5-#include "internal.h"
  6-#include "keyboard.h"
  7-#include "launch.h"
  8-#include "pointer.h"
  9-#include "screen.h"
 10-#include "seat.h"
 11-#include "surface.h"
 12-#include "util.h"
 13-
 14-#include <ctype.h>
 15-#include <dirent.h>
 16-#include <errno.h>
 17-#include <fcntl.h>
 18-#include <limits.h>
 19-#include <stdbool.h>
 20-#include <stdint.h>
 21-#include <stdio.h>
 22-#include <stdlib.h>
 23-#include <string.h>
 24-#include <sys/ioctl.h>
 25-#include <unistd.h>
 26-
 27-#include <linux/input.h>
 28-
 29-struct seat {
 30-	struct swc_seat base;
 31-
 32-	char *name;
 33-	uint32_t capabilities;
 34-
 35-	int mouse_fd;
 36-	int kbd_fd;
 37-	bool ignore;
 38-
 39-	struct xkb_rule_names names;
 40-
 41-	struct wl_event_source *mouse_source;
 42-	struct wl_event_source *kbd_source;
 43-
 44-	struct wl_listener swc_listener;
 45-
 46-	struct wl_listener keyboard_focus_listener;
 47-	struct pointer pointer;
 48-	struct wl_listener data_device_listener;
 49-
 50-	struct wl_global *global;
 51-	struct wl_list resources;
 52-
 53-	wl_fixed_t abs_x;
 54-	wl_fixed_t abs_y;
 55-	bool abs_initialized;
 56-
 57-	bool shared_fd;
 58-};
 59-
 60-static void
 61-handle_keyboard_focus_event(struct wl_listener *listener, void *data)
 62-{
 63-	struct seat *seat =
 64-	    wl_container_of(listener, seat, keyboard_focus_listener);
 65-	struct event *ev = data;
 66-	struct input_focus_event_data *event_data = ev->data;
 67-
 68-	if (ev->type != INPUT_FOCUS_EVENT_CHANGED) {
 69-		return;
 70-	}
 71-
 72-	if (event_data->new) {
 73-		struct wl_client *client =
 74-		    wl_resource_get_client(event_data->new->surface->resource);
 75-
 76-		/* offer the selection to the new focus */
 77-		data_device_offer_selection(seat->base.data_device, client);
 78-	}
 79-}
 80-
 81-static void
 82-handle_data_device_event(struct wl_listener *listener, void *data)
 83-{
 84-	struct seat *seat = wl_container_of(listener, seat, data_device_listener);
 85-	struct event *ev = data;
 86-
 87-	if (ev->type != DATA_DEVICE_EVENT_SELECTION_CHANGED) {
 88-		return;
 89-	}
 90-
 91-	if (seat->base.keyboard->focus.client) {
 92-		data_device_offer_selection(seat->base.data_device,
 93-		                            seat->base.keyboard->focus.client);
 94-	}
 95-}
 96-
 97-static void
 98-handle_swc_event(struct wl_listener *listener, void *data)
 99-{
100-	struct seat *seat = wl_container_of(listener, seat, swc_listener);
101-	struct event *ev = data;
102-
103-	switch (ev->type) {
104-	case SWC_EVENT_DEACTIVATED:
105-		seat->ignore = true;
106-		keyboard_reset(seat->base.keyboard);
107-		break;
108-	case SWC_EVENT_ACTIVATED:
109-		seat->ignore = false;
110-		break;
111-	}
112-}
113-
114-/* da seat */
115-static void
116-get_pointer(struct wl_client *client, struct wl_resource *resource, uint32_t id)
117-{
118-	struct seat *seat = wl_resource_get_user_data(resource);
119-
120-	pointer_bind(&seat->pointer, client, wl_resource_get_version(resource), id);
121-}
122-
123-static void
124-get_keyboard(struct wl_client *client, struct wl_resource *resource,
125-             uint32_t id)
126-{
127-	struct seat *seat = wl_resource_get_user_data(resource);
128-
129-	keyboard_bind(seat->base.keyboard, client,
130-	              wl_resource_get_version(resource), id);
131-}
132-
133-static void
134-get_touch(struct wl_client *client, struct wl_resource *resource, uint32_t id)
135-{
136-}
137-
138-static struct wl_seat_interface seat_impl = {
139-    .get_pointer = get_pointer,
140-    .get_keyboard = get_keyboard,
141-    .get_touch = get_touch,
142-};
143-
144-static void
145-bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
146-{
147-	struct seat *seat = data;
148-	struct wl_resource *resource;
149-
150-	if (version > 4) {
151-		version = 4;
152-	}
153-
154-	resource = wl_resource_create(client, &wl_seat_interface, version, id);
155-	wl_resource_set_implementation(resource, &seat_impl, seat,
156-	                               &remove_resource);
157-	wl_list_insert(&seat->resources, wl_resource_get_link(resource));
158-
159-	if (version >= 2) {
160-		wl_seat_send_name(resource, seat->name);
161-	}
162-
163-	wl_seat_send_capabilities(resource, seat->capabilities);
164-}
165-
166-static uint32_t
167-event_time_ms(const struct input_event *ev)
168-{
169-	return (uint32_t)(ev->time.tv_sec * 1000 + ev->time.tv_usec / 1000);
170-}
171-
172-static void
173-handle_evdev_key(struct seat *seat, const struct input_event *ev)
174-{
175-	uint32_t state;
176-	uint32_t time = event_time_ms(ev);
177-
178-	if (ev->value == 2) {
179-		return;
180-	}
181-
182-	if (ev->code >= BTN_MISC) {
183-		pointer_handle_button(seat->base.pointer, time, ev->code,
184-		                      ev->value ? WL_POINTER_BUTTON_STATE_PRESSED
185-		                                : WL_POINTER_BUTTON_STATE_RELEASED);
186-	} else {
187-		if (ev->code > 255) {
188-			return;
189-		}
190-		state = (ev->value ? WL_KEYBOARD_KEY_STATE_PRESSED
191-		                   : WL_KEYBOARD_KEY_STATE_RELEASED);
192-		keyboard_handle_key(seat->base.keyboard, time, ev->code, state);
193-	}
194-}
195-
196-static void
197-handle_evdev_rel(struct seat *seat, const struct input_event *ev)
198-{
199-	uint32_t time = event_time_ms(ev);
200-	wl_fixed_t value;
201-
202-	switch (ev->code) {
203-	case REL_X:
204-		pointer_handle_relative_motion(seat->base.pointer, time,
205-		                               wl_fixed_from_int(ev->value), 0);
206-		break;
207-	case REL_Y:
208-		pointer_handle_relative_motion(seat->base.pointer, time, 0,
209-		                               wl_fixed_from_int(ev->value));
210-		break;
211-	case REL_WHEEL:
212-		value = wl_fixed_from_int(ev->value * 10);
213-		pointer_handle_axis(
214-		    seat->base.pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL,
215-		    WL_POINTER_AXIS_SOURCE_WHEEL, value, ev->value * 120);
216-		break;
217-	case REL_HWHEEL:
218-		value = wl_fixed_from_int(ev->value * 10);
219-		pointer_handle_axis(
220-		    seat->base.pointer, time, WL_POINTER_AXIS_HORIZONTAL_SCROLL,
221-		    WL_POINTER_AXIS_SOURCE_WHEEL, value, ev->value * 120);
222-		break;
223-	default:
224-		break;
225-	}
226-}
227-
228-static void
229-handle_evdev_abs(struct seat *seat, const struct input_event *ev)
230-{
231-	uint32_t time = event_time_ms(ev);
232-
233-	switch (ev->code) {
234-	case ABS_X:
235-		seat->abs_x = wl_fixed_from_int(ev->value);
236-		seat->abs_initialized = true;
237-		break;
238-	case ABS_Y:
239-		seat->abs_y = wl_fixed_from_int(ev->value);
240-		seat->abs_initialized = true;
241-		break;
242-	default:
243-		return;
244-	}
245-
246-	if (seat->abs_initialized) {
247-		pointer_handle_absolute_motion(seat->base.pointer, time, seat->abs_x,
248-		                               seat->abs_y);
249-	}
250-}
251-
252-static int
253-handle_evdev_data(int fd, uint32_t mask, void *data)
254-{
255-	struct seat *seat = data;
256-	struct input_event ev;
257-	ssize_t n;
258-
259-	while (!seat->ignore) {
260-		n = read(fd, &ev, sizeof(ev));
261-		if (n == -1) {
262-			if (errno == EAGAIN || errno == EINTR) {
263-				break;
264-			}
265-			return 0;
266-		}
267-		if (n != (ssize_t)sizeof(ev)) {
268-			break;
269-		}
270-
271-		switch (ev.type) {
272-		case EV_KEY:
273-			handle_evdev_key(seat, &ev);
274-			break;
275-		case EV_REL:
276-			handle_evdev_rel(seat, &ev);
277-			break;
278-		case EV_ABS:
279-			handle_evdev_abs(seat, &ev);
280-			break;
281-		case EV_SYN:
282-			if (ev.code == SYN_REPORT) {
283-				pointer_handle_frame(seat->base.pointer);
284-			}
285-			break;
286-		default:
287-			break;
288-		}
289-	}
290-
291-	return 0;
292-}
293-
294-static bool
295-test_bit(const unsigned long *bits, size_t bit)
296-{
297-	return (bits[bit / (sizeof(unsigned long) * 8)] >>
298-	        (bit % (sizeof(unsigned long) * 8))) &
299-	       1;
300-}
301-
302-static bool
303-contains_ci(const char *haystack, const char *needle)
304-{
305-	size_t nlen;
306-	const char *h;
307-
308-	if (!haystack || !needle || !*needle) {
309-		return false;
310-	}
311-
312-	nlen = strlen(needle);
313-	for (h = haystack; *h; ++h) {
314-		size_t i;
315-		for (i = 0; i < nlen; ++i) {
316-			unsigned char hc = (unsigned char)h[i];
317-			unsigned char nc = (unsigned char)needle[i];
318-			if (!h[i] || tolower(hc) != tolower(nc)) {
319-				break;
320-			}
321-		}
322-		if (i == nlen) {
323-			return true;
324-		}
325-	}
326-	return false;
327-}
328-
329-static bool
330-is_keyboard_device(int fd)
331-{
332-	unsigned long ev_bits[(EV_MAX + 8 * sizeof(unsigned long) - 1) /
333-	                      (8 * sizeof(unsigned long))];
334-	unsigned long key_bits[(KEY_MAX + 8 * sizeof(unsigned long) - 1) /
335-	                       (8 * sizeof(unsigned long))];
336-
337-	memset(ev_bits, 0, sizeof(ev_bits));
338-	memset(key_bits, 0, sizeof(key_bits));
339-
340-	if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
341-		return false;
342-	}
343-	if (!test_bit(ev_bits, EV_KEY)) {
344-		return false;
345-	}
346-	if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits) < 0) {
347-		return false;
348-	}
349-
350-	return test_bit(key_bits, KEY_A) && test_bit(key_bits, KEY_Z) &&
351-	       test_bit(key_bits, KEY_ENTER) && test_bit(key_bits, KEY_ESC) &&
352-	       test_bit(key_bits, KEY_SPACE);
353-}
354-
355-static bool
356-is_pointer_device(int fd)
357-{
358-	unsigned long ev_bits[(EV_MAX + 8 * sizeof(unsigned long) - 1) /
359-	                      (8 * sizeof(unsigned long))];
360-	unsigned long rel_bits[(REL_MAX + 8 * sizeof(unsigned long) - 1) /
361-	                       (8 * sizeof(unsigned long))];
362-	unsigned long key_bits[(KEY_MAX + 8 * sizeof(unsigned long) - 1) /
363-	                       (8 * sizeof(unsigned long))];
364-
365-	memset(ev_bits, 0, sizeof(ev_bits));
366-	memset(rel_bits, 0, sizeof(rel_bits));
367-	memset(key_bits, 0, sizeof(key_bits));
368-
369-	if (ioctl(fd, EVIOCGBIT(0, sizeof(ev_bits)), ev_bits) < 0) {
370-		return false;
371-	}
372-
373-	if (test_bit(ev_bits, EV_REL)) {
374-		if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bits)), rel_bits) < 0) {
375-			return false;
376-		}
377-		if (test_bit(rel_bits, REL_X) && test_bit(rel_bits, REL_Y)) {
378-			return true;
379-		}
380-	}
381-
382-	if (test_bit(ev_bits, EV_KEY)) {
383-		if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bits)), key_bits) < 0) {
384-			return false;
385-		}
386-		if (test_bit(key_bits, BTN_LEFT) && test_bit(key_bits, BTN_RIGHT)) {
387-			return true;
388-		}
389-	}
390-
391-	return false;
392-}
393-
394-static bool
395-get_ev_bits(int fd, unsigned long *ev_bits, size_t ev_bits_len)
396-{
397-	memset(ev_bits, 0, ev_bits_len);
398-	return ioctl(fd, EVIOCGBIT(0, ev_bits_len), ev_bits) >= 0;
399-}
400-
401-static int
402-score_candidate(int fd, bool want_keyboard, const char *id_name)
403-{
404-	char name[256];
405-	unsigned long ev_bits[(EV_MAX + 8 * sizeof(unsigned long) - 1) /
406-	                      (8 * sizeof(unsigned long))];
407-	bool is_kbd;
408-	bool is_ptr;
409-	int score = 10;
410-
411-	is_kbd = is_keyboard_device(fd);
412-	is_ptr = is_pointer_device(fd);
413-
414-	if (want_keyboard && !is_kbd) {
415-		return -1;
416-	}
417-	if (!want_keyboard && !is_ptr) {
418-		return -1;
419-	}
420-
421-	if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
422-		name[0] = '\0';
423-	}
424-
425-	if (!get_ev_bits(fd, ev_bits, sizeof(ev_bits))) {
426-		memset(ev_bits, 0, sizeof(ev_bits));
427-	}
428-
429-	if (want_keyboard) {
430-		if (is_ptr) {
431-			score -= 6;
432-		}
433-		if (contains_ci(id_name, "mouse") || contains_ci(name, "mouse")) {
434-			score -= 12;
435-		}
436-		if (contains_ci(id_name, "kbd") || contains_ci(id_name, "keyboard")) {
437-			score += 4;
438-		}
439-		if (contains_ci(name, "keyboard")) {
440-			score += 2;
441-		}
442-		if (test_bit(ev_bits, EV_LED)) {
443-			score += 3;
444-		}
445-		if (test_bit(ev_bits, EV_REP)) {
446-			score += 1;
447-		}
448-	} else {
449-		if (contains_ci(id_name, "mouse") || contains_ci(name, "mouse")) {
450-			score += 4;
451-		}
452-		if (contains_ci(id_name, "kbd") || contains_ci(id_name, "keyboard")) {
453-			score -= 6;
454-		}
455-		if (contains_ci(name, "keyboard")) {
456-			score -= 4;
457-		}
458-	}
459-
460-	return score;
461-}
462-
463-static bool
464-pick_best_device(const char *dir_path, const char *name_prefix,
465-                 const char *name_substr, bool want_keyboard, char *out,
466-                 size_t out_len)
467-{
468-	DIR *dir;
469-	struct dirent *ent;
470-	bool found = false;
471-	int best_score = -1;
472-	size_t prefix_len = name_prefix ? strlen(name_prefix) : 0;
473-
474-	dir = opendir(dir_path);
475-	if (!dir) {
476-		return false;
477-	}
478-
479-	while ((ent = readdir(dir)) != NULL) {
480-		char path[PATH_MAX];
481-		int fd;
482-		int score;
483-
484-		if (ent->d_name[0] == '.') {
485-			continue;
486-		}
487-		if (name_prefix && strncmp(ent->d_name, name_prefix, prefix_len) != 0) {
488-			continue;
489-		}
490-		if (name_substr && !strstr(ent->d_name, name_substr)) {
491-			continue;
492-		}
493-
494-		snprintf(path, sizeof(path), "%s/%s", dir_path, ent->d_name);
495-		fd = launch_open_device(path, O_RDONLY | O_NONBLOCK);
496-		if (fd == -1) {
497-			continue;
498-		}
499-
500-		score = score_candidate(fd, want_keyboard, ent->d_name);
501-		if (score < 0) {
502-			close(fd);
503-			continue;
504-		}
505-
506-		if (score > best_score) {
507-			snprintf(out, out_len, "%s", path);
508-			best_score = score;
509-			found = true;
510-		}
511-
512-		close(fd);
513-	}
514-
515-	closedir(dir);
516-	return found;
517-}
518-
519-static bool
520-initialize_evdev(struct seat *seat)
521-{
522-	char kbd_path[PATH_MAX];
523-	char mouse_path[PATH_MAX];
524-	const char *kbd_dev = EVDEV_KBD_DEVICE;
525-	const char *mouse_dev = EVDEV_POINTER_DEVICE;
526-
527-	if (pick_best_device("/dev/input/by-id", NULL, "event-kbd", true, kbd_path,
528-	                     sizeof(kbd_path))) {
529-		kbd_dev = kbd_path;
530-	} else if (pick_best_device("/dev/input/by-path", NULL, "event-kbd", true,
531-	                            kbd_path, sizeof(kbd_path))) {
532-		kbd_dev = kbd_path;
533-	} else if (pick_best_device("/dev/input", "event", NULL, true, kbd_path,
534-	                            sizeof(kbd_path))) {
535-		kbd_dev = kbd_path;
536-	}
537-
538-	if (pick_best_device("/dev/input/by-id", NULL, "event-mouse", false,
539-	                     mouse_path, sizeof(mouse_path))) {
540-		mouse_dev = mouse_path;
541-	} else if (pick_best_device("/dev/input/by-path", NULL, "event-mouse",
542-	                            false, mouse_path, sizeof(mouse_path))) {
543-		mouse_dev = mouse_path;
544-	} else if (pick_best_device("/dev/input", "event", NULL, false, mouse_path,
545-	                            sizeof(mouse_path))) {
546-		mouse_dev = mouse_path;
547-	}
548-
549-	DEBUG("evdev devices: keyboard=%s pointer=%s\n", kbd_dev, mouse_dev);
550-
551-	seat->kbd_fd = launch_open_device(kbd_dev, O_RDONLY | O_NONBLOCK);
552-	if (seat->kbd_fd == -1) {
553-		ERROR("Could not open evdev keyboard device %s\n", kbd_dev);
554-		goto error0;
555-	}
556-
557-	if (strcmp(kbd_dev, mouse_dev) == 0) {
558-		seat->mouse_fd = seat->kbd_fd;
559-		seat->shared_fd = true;
560-		return true;
561-	}
562-
563-	seat->mouse_fd = launch_open_device(mouse_dev, O_RDONLY | O_NONBLOCK);
564-	if (seat->mouse_fd == -1) {
565-		ERROR("Could not open evdev pointer device %s\n", mouse_dev);
566-		goto error1;
567-	}
568-
569-	return true;
570-
571-error1:
572-	close(seat->kbd_fd);
573-error0:
574-	return false;
575-}
576-
577-struct swc_seat *
578-seat_create(struct wl_display *display, const char *seat_name)
579-{
580-	struct seat *seat;
581-
582-	seat = malloc(sizeof(*seat));
583-	if (!seat) {
584-		goto error0;
585-	}
586-
587-	memset(&seat->names, 0, sizeof(seat->names));
588-	seat->names.rules = "base";
589-	seat->names.model = "pc105";
590-	seat->names.layout = "us";
591-	seat->names.variant = "basic";
592-	seat->shared_fd = false;
593-
594-	seat->name = strdup(seat_name);
595-	if (!seat->name) {
596-		ERROR("Could not allocate seat name string\n");
597-		goto error1;
598-	}
599-
600-	if (!initialize_evdev(seat)) {
601-		goto error2;
602-	}
603-
604-	seat->global =
605-	    wl_global_create(display, &wl_seat_interface, 4, seat, &bind_seat);
606-	if (!seat->global) {
607-		goto error2;
608-	}
609-	seat->capabilities =
610-	    WL_SEAT_CAPABILITY_KEYBOARD | WL_SEAT_CAPABILITY_POINTER;
611-	wl_list_init(&seat->resources);
612-
613-	seat->swc_listener.notify = &handle_swc_event;
614-	wl_signal_add(&swc.event_signal, &seat->swc_listener);
615-
616-	seat->base.data_device = data_device_create();
617-	if (!seat->base.data_device) {
618-		ERROR("could not initialize data device\n");
619-		goto error3;
620-	}
621-	seat->data_device_listener.notify = &handle_data_device_event;
622-	wl_signal_add(&seat->base.data_device->event_signal,
623-	              &seat->data_device_listener);
624-
625-	seat->base.keyboard = keyboard_create(&seat->names);
626-	if (!seat->base.keyboard) {
627-		ERROR("could not initialize keyboard\n");
628-		goto error4;
629-	}
630-	seat->keyboard_focus_listener.notify = handle_keyboard_focus_event;
631-	wl_signal_add(&seat->base.keyboard->focus.event_signal,
632-	              &seat->keyboard_focus_listener);
633-
634-	if (!pointer_initialize(&seat->pointer)) {
635-		ERROR("Could not initialize pointer\n");
636-		goto error5;
637-	}
638-	seat->base.pointer = &seat->pointer;
639-
640-	seat->kbd_source =
641-	    wl_event_loop_add_fd(swc.event_loop, seat->kbd_fd, WL_EVENT_READABLE,
642-	                         &handle_evdev_data, seat);
643-	if (!seat->shared_fd) {
644-		seat->mouse_source =
645-		    wl_event_loop_add_fd(swc.event_loop, seat->mouse_fd,
646-		                         WL_EVENT_READABLE, &handle_evdev_data, seat);
647-	} else {
648-		seat->mouse_source = NULL;
649-	}
650-
651-	seat->abs_initialized = false;
652-
653-	return &seat->base;
654-
655-error5:
656-	keyboard_destroy(seat->base.keyboard);
657-error4:
658-	data_device_destroy(seat->base.data_device);
659-error3:
660-	wl_global_destroy(seat->global);
661-error2:
662-	free(seat->name);
663-error1:
664-	free(seat);
665-error0:
666-	return NULL;
667-}
668-
669-void
670-seat_destroy(struct swc_seat *seat_base)
671-{
672-	struct seat *seat = wl_container_of(seat_base, seat, base);
673-
674-	if (seat->mouse_source) {
675-		wl_event_source_remove(seat->mouse_source);
676-	}
677-	wl_event_source_remove(seat->kbd_source);
678-	if (seat->mouse_source) {
679-		close(seat->mouse_fd);
680-		seat->mouse_fd = -1;
681-	}
682-	close(seat->kbd_fd);
683-	seat->kbd_fd = -1;
684-
685-	pointer_finalize(&seat->pointer);
686-	keyboard_destroy(seat->base.keyboard);
687-	data_device_destroy(seat->base.data_device);
688-
689-	wl_global_destroy(seat->global);
690-	free(seat->name);
691-	free(seat);
692-}
+5, -7
 1@@ -58,8 +58,11 @@ libinput = dependency('libinput', version: '>=0.4', required: input_backend == '
 2 
 3 if input_backend == 'auto'
 4   if os == 'linux'
 5-    input_backend = libinput.found() ? 'libinput' : 'evdev'
 6-  elif os == 'netbsd'
 7+    if not libinput.found()
 8+      error('libinput is required for the Linux input backend')
 9+    endif
10+    input_backend = 'libinput'
11+  elif os == 'netbsd' or os == 'openbsd'
12     input_backend = 'wscons'
13   else
14     error('Failed to determine input backend for ' + os)
15@@ -72,11 +75,6 @@ if input_backend == 'libinput'
16     add_project_arguments('-DENABLE_LIBUDEV', language: 'c')
17   endif
18   requires_private += [libinput, udev]
19-elif input_backend == 'evdev'
20-  add_project_arguments([
21-    '-DEVDEV_KBD_DEVICE="@0@"'.format(get_option('evdev-keyboard')),
22-    '-DEVDEV_POINTER_DEVICE="@0@"'.format(get_option('evdev-pointer')),
23-  ], language: 'c')
24 endif
25 
26 subdir('protocol')
+1, -3
1@@ -1,7 +1,5 @@
2 option('xwayland', type: 'feature', value: 'auto', description: 'Automatic Xwayland handling')
3-option('input', type: 'combo', value: 'auto', choices: ['auto', 'libinput', 'evdev', 'wscons'], description: 'Input backend to use')
4+option('input', type: 'combo', value: 'auto', choices: ['auto', 'libinput', 'wscons'], description: 'Input backend to use')
5 option('udev', type: 'feature', value: 'auto', description: 'libinput libudev support')
6-option('evdev-keyboard', type: 'string', value: '/dev/input/event0', description: 'evdev keyboard device to use')
7-option('evdev-pointer', type: 'string', value: '/dev/input/event1', description: 'evdev pointer device to use')
8 option('extra', type: 'boolean', value: true, description: 'Build swc utility applications')
9 option('example', type: 'boolean', value: false, description: 'Build swc example compositor')