aboutsummaryrefslogtreecommitdiff
path: root/backend/libinput/backend.c
blob: dc018b1059134d2c7b75da8931375f5b8223a0c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <stdlib.h>
#include <assert.h>
#include <libinput.h>
#include <wlr/session.h>
#include <wlr/backend/interface.h>
#include "backend/udev.h"
#include "backend/libinput/backend.h"
#include "common/log.h"

static int wlr_libinput_open_restricted(const char *path,
		int flags, void *_state) {
	struct wlr_backend_state *state = _state;
	return wlr_session_open_file(state->session, path);
}

static void wlr_libinput_close_restricted(int fd, void *_state) {
	struct wlr_backend_state *state = _state;
	wlr_session_close_file(state->session, fd);
}

static const struct libinput_interface libinput_impl = {
	.open_restricted = wlr_libinput_open_restricted,
	.close_restricted = wlr_libinput_close_restricted
};

static int wlr_libinput_readable(int fd, uint32_t mask, void *_state) {
	struct wlr_backend_state *state = _state;
	if (libinput_dispatch(state->libinput) != 0) {
		wlr_log(L_ERROR, "Failed to dispatch libinput");
		// TODO: some kind of abort?
		return 0;
	}
	struct libinput_event *event;
	while ((event = libinput_get_event(state->libinput))) {
		wlr_libinput_event(state, event);
	}
	return 0;
}

static void wlr_libinput_log(struct libinput *libinput,
		enum libinput_log_priority priority, const char *fmt, va_list args) {
	_wlr_vlog(L_ERROR, fmt, args);
}

static bool wlr_libinput_backend_init(struct wlr_backend_state *state) {
	wlr_log(L_DEBUG, "Initializing libinput");
	state->libinput = libinput_udev_create_context(&libinput_impl, state,
			state->udev->udev);
	if (!state->libinput) {
		wlr_log(L_ERROR, "Failed to create libinput context");
		return false;
	}

	// TODO: Let user customize seat used
	if (libinput_udev_assign_seat(state->libinput, "seat0") != 0) {
		wlr_log(L_ERROR, "Failed to assign libinput seat");
		return false;
	}

	// TODO: More sophisticated logging
	libinput_log_set_handler(state->libinput, wlr_libinput_log);
	libinput_log_set_priority(state->libinput, LIBINPUT_LOG_PRIORITY_ERROR);

	struct wl_event_loop *event_loop =
		wl_display_get_event_loop(state->display);
	if (state->input_event) {
		wl_event_source_remove(state->input_event);
	}
	state->input_event = wl_event_loop_add_fd(event_loop,
			libinput_get_fd(state->libinput), WL_EVENT_READABLE,
			wlr_libinput_readable, state);
	if (!state->input_event) {
		wlr_log(L_ERROR, "Failed to create input event on event loop");
		return false;
	}
	wlr_log(L_DEBUG, "libinput sucessfully initialized");
	return true;
}

static void wlr_libinput_backend_destroy(struct wlr_backend_state *state) {
	// TODO
}

static struct wlr_backend_impl backend_impl = {
	.init = wlr_libinput_backend_init,
	.destroy = wlr_libinput_backend_destroy
};

struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
		struct wlr_session *session, struct wlr_udev *udev) {
	assert(display && session && udev);

	struct wlr_backend_state *state = calloc(1, sizeof(struct wlr_backend_state));
	if (!state) {
		wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
		return NULL;
	}

	struct wlr_backend *backend = wlr_backend_create(&backend_impl, state);
	if (!backend) {
		wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
		goto error_state;
	}

	if (!(state->keyboards = list_create())) {
		wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
		goto error_backend;
	}

	state->backend = backend;
	state->session = session;
	state->udev = udev;
	state->display = display;

	return backend;
error_state:
	free(state);
error_backend:
	wlr_backend_destroy(backend);
	return NULL;
}