diff options
Diffstat (limited to 'backend')
| -rw-r--r-- | backend/libinput/pointer.c | 2 | ||||
| -rw-r--r-- | backend/meson.build | 7 | ||||
| -rw-r--r-- | backend/session/direct-freebsd.c | 217 | ||||
| -rw-r--r-- | backend/session/direct-ipc.c | 13 | ||||
| -rw-r--r-- | backend/session/session.c | 6 | ||||
| -rw-r--r-- | backend/wayland/os-compatibility.c | 2 | ||||
| -rw-r--r-- | backend/x11/backend.c | 20 | 
7 files changed, 258 insertions, 9 deletions
diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index 005c9516..ad9b8f02 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -128,7 +128,7 @@ void handle_pointer_axis(struct libinput_event *event,  			}  			wlr_event.delta = libinput_event_pointer_get_axis_value(  					pevent, axies[i]); +			wl_signal_emit(&wlr_dev->pointer->events.axis, &wlr_event);  		} -		wl_signal_emit(&wlr_dev->pointer->events.axis, &wlr_event);  	}  } diff --git a/backend/meson.build b/backend/meson.build index cf62a56f..5ed7b227 100644 --- a/backend/meson.build +++ b/backend/meson.build @@ -1,7 +1,6 @@  backend_files = files(  	'backend.c',  	'session/direct-ipc.c', -	'session/direct.c',  	'session/session.c',  	'drm/atomic.c',  	'drm/backend.c', @@ -26,6 +25,12 @@ backend_files = files(  	'x11/backend.c',  ) +if host_machine.system().startswith('freebsd') +	backend_files += files('session/direct-freebsd.c') +else +	backend_files += files('session/direct.c') +endif +  if systemd.found()  	backend_files += files('session/logind.c')  endif diff --git a/backend/session/direct-freebsd.c b/backend/session/direct-freebsd.c new file mode 100644 index 00000000..fc4bab04 --- /dev/null +++ b/backend/session/direct-freebsd.c @@ -0,0 +1,217 @@ +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <unistd.h> +#include <signal.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <termios.h> +#include <fcntl.h> +#include <sys/types.h> +#include <dev/evdev/input.h> +#include <sys/kbio.h> +#include <sys/consio.h> +#include <wayland-server.h> +#include <wlr/backend/session/interface.h> +#include <wlr/util/log.h> +#include "backend/session/direct-ipc.h" + +const struct session_impl session_direct; + +struct direct_session { +	struct wlr_session base; +	int tty_fd; +	int old_kbmode; +	int sock; +	pid_t child; + +	struct wl_event_source *vt_source; +}; + +static int direct_session_open(struct wlr_session *base, const char *path) { +	struct direct_session *session = wl_container_of(base, session, base); + +	int fd = direct_ipc_open(session->sock, path); +	if (fd < 0) { +		wlr_log(L_ERROR, "Failed to open %s: %s%s", path, strerror(-fd), +			fd == -EINVAL ? "; is another display server running?" : ""); +		return fd; +	} + +	struct stat st; +	if (fstat(fd, &st) < 0) { +		close(fd); +		return -errno; +	} + +	return fd; +} + +static void direct_session_close(struct wlr_session *base, int fd) { +	struct direct_session *session = wl_container_of(base, session, base); + +	struct stat st; +	if (fstat(fd, &st) < 0) { +		wlr_log_errno(L_ERROR, "Stat failed"); +		close(fd); +		return; +	} + +	close(fd); +} + +static bool direct_change_vt(struct wlr_session *base, unsigned vt) { +	struct direct_session *session = wl_container_of(base, session, base); +	return ioctl(session->tty_fd, VT_ACTIVATE, (int)vt) == 0; +} + +static void direct_session_destroy(struct wlr_session *base) { +	struct direct_session *session = wl_container_of(base, session, base); +	struct vt_mode mode = { +		.mode = VT_AUTO, +	}; + +	errno = 0; + +	ioctl(session->tty_fd, KDSKBMODE, session->old_kbmode); +	ioctl(session->tty_fd, KDSETMODE, KD_TEXT); +	ioctl(session->tty_fd, VT_SETMODE, &mode); + +	if (errno) { +		wlr_log(L_ERROR, "Failed to restore tty"); +	} + +	direct_ipc_finish(session->sock, session->child); +	close(session->sock); + +	wl_event_source_remove(session->vt_source); +	close(session->tty_fd); +	free(session); +} + +static int vt_handler(int signo, void *data) { +	struct direct_session *session = data; + +	if (session->base.active) { +		session->base.active = false; +		wl_signal_emit(&session->base.session_signal, session); +		ioctl(session->tty_fd, VT_RELDISP, 1); +	} else { +		ioctl(session->tty_fd, VT_RELDISP, VT_ACKACQ); +		session->base.active = true; +		wl_signal_emit(&session->base.session_signal, session); +	} + +	return 1; +} + +static bool setup_tty(struct direct_session *session, struct wl_display *display) { +	int fd = -1, tty = -1, tty0_fd = -1; +	if ((tty0_fd = open("/dev/ttyv0", O_RDWR | O_CLOEXEC)) < 0) { +		wlr_log_errno(L_ERROR, "Could not open /dev/ttyv0 to find a free vt"); +		goto error; +	} +	if (ioctl(tty0_fd, VT_OPENQRY, &tty) != 0) { +		wlr_log_errno(L_ERROR, "Could not find a free vt"); +		goto error; +	} +	close(tty0_fd); +	char tty_path[64]; +	snprintf(tty_path, sizeof(tty_path), "/dev/ttyv%d", tty - 1); +	wlr_log(L_INFO, "Using tty %s", tty_path); +	fd = open(tty_path, O_RDWR | O_NOCTTY | O_CLOEXEC); + +	if (fd == -1) { +		wlr_log_errno(L_ERROR, "Cannot open tty"); +		return false; +	} + +	ioctl(fd, VT_ACTIVATE, tty); +	ioctl(fd, VT_WAITACTIVE, tty); + +	int old_kbmode; +	if (ioctl(fd, KDGKBMODE, &old_kbmode)) { +		wlr_log_errno(L_ERROR, "Failed to read tty %d keyboard mode", tty); +		goto error; +	} + +	if (ioctl(fd, KDSKBMODE, K_CODE)) { +		wlr_log_errno(L_ERROR, "Failed to set keyboard mode K_CODE on tty %d", tty); +		goto error; +	} + +	if (ioctl(fd, KDSETMODE, KD_GRAPHICS)) { +		wlr_log_errno(L_ERROR, "Failed to set graphics mode on tty %d", tty); +		goto error; +	} + +	struct vt_mode mode = { +		.mode = VT_PROCESS, +		.relsig = SIGUSR1, +		.acqsig = SIGUSR1, +		.frsig = SIGIO, // has to be set +	}; + +	if (ioctl(fd, VT_SETMODE, &mode) < 0) { +		wlr_log(L_ERROR, "Failed to take control of tty %d", tty); +		goto error; +	} + +	struct wl_event_loop *loop = wl_display_get_event_loop(display); +	session->vt_source = wl_event_loop_add_signal(loop, SIGUSR1, +		vt_handler, session); +	if (!session->vt_source) { +		goto error; +	} + +	session->base.vtnr = tty; +	session->tty_fd = fd; +	session->old_kbmode = old_kbmode; + +	return true; + +error: +	// Drop back to tty 1, better than hanging in a useless blank console +	ioctl(fd, VT_ACTIVATE, 1); +	close(fd); +	return false; +} + +static struct wlr_session *direct_session_create(struct wl_display *disp) { +	struct direct_session *session = calloc(1, sizeof(*session)); +	if (!session) { +		wlr_log_errno(L_ERROR, "Allocation failed"); +		return NULL; +	} + +	session->sock = direct_ipc_init(&session->child); +	if (session->sock == -1) { +		goto error_session; +	} + +	if (!setup_tty(session, disp)) { +		goto error_ipc; +	} + +	wlr_log(L_INFO, "Successfully loaded direct session"); + +	snprintf(session->base.seat, sizeof(session->base.seat), "seat0"); +	session->base.impl = &session_direct; +	return &session->base; + +error_ipc: +	direct_ipc_finish(session->sock, session->child); +	close(session->sock); +error_session: +	free(session); +	return NULL; +} + +const struct session_impl session_direct = { +	.create = direct_session_create, +	.destroy = direct_session_destroy, +	.open = direct_session_open, +	.close = direct_session_close, +	.change_vt = direct_change_vt, +}; diff --git a/backend/session/direct-ipc.c b/backend/session/direct-ipc.c index 5f1494a6..0ea51e2f 100644 --- a/backend/session/direct-ipc.c +++ b/backend/session/direct-ipc.c @@ -1,4 +1,8 @@  #define _POSIX_C_SOURCE 200809L +#ifdef __FreeBSD__ +#define __BSD_VISIBLE 1 +#define INPUT_MAJOR 0 +#endif  #include <errno.h>  #include <stdio.h>  #include <stdlib.h> @@ -8,10 +12,12 @@  #include <sys/socket.h>  #include <sys/stat.h>  #include <sys/types.h> -#include <sys/sysmacros.h>  #include <sys/wait.h> -#include <xf86drm.h> +#ifdef __linux__ +#include <sys/sysmacros.h>  #include <linux/major.h> +#endif +#include <xf86drm.h>  #include <wlr/util/log.h>  #include "backend/session/direct-ipc.h" @@ -35,11 +41,12 @@ static bool have_permissions(void) {  }  #else  static bool have_permissions(void) { +#ifdef __linux__  	if (geteuid() != 0) {  		wlr_log(L_ERROR, "Do not have root privileges; cannot become DRM master");  		return false;  	} - +#endif  	return true;  }  #endif diff --git a/backend/session/session.c b/backend/session/session.c index b73952fd..b14ca4d0 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -263,6 +263,11 @@ size_t wlr_session_find_gpus(struct wlr_session *session,  		return explicit_find_gpus(session, ret_len, ret, explicit);  	} +#ifdef __FreeBSD__ +	// XXX: libudev-devd does not return any GPUs (yet?) +	return explicit_find_gpus(session, ret_len, ret, "/dev/drm/0"); +#else +  	struct udev_enumerate *en = udev_enumerate_new(session->udev);  	if (!en) {  		wlr_log(L_ERROR, "Failed to create udev enumeration"); @@ -329,4 +334,5 @@ size_t wlr_session_find_gpus(struct wlr_session *session,  	udev_enumerate_unref(en);  	return i; +#endif  } diff --git a/backend/wayland/os-compatibility.c b/backend/wayland/os-compatibility.c index cd268539..14125793 100644 --- a/backend/wayland/os-compatibility.c +++ b/backend/wayland/os-compatibility.c @@ -29,7 +29,9 @@  #include <unistd.h>  #include <fcntl.h>  #include <errno.h> +#ifdef __linux__  #include <sys/epoll.h> +#endif  #include <string.h>  #include <stdlib.h> diff --git a/backend/x11/backend.c b/backend/x11/backend.c index 1eb5a952..11dd8568 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -1,4 +1,4 @@ -#define _POSIX_C_SOURCE 199309L +#define _POSIX_C_SOURCE 200112L  #include <stdbool.h>  #include <stdio.h>  #include <stdlib.h> @@ -8,7 +8,11 @@  #include <xcb/xcb.h>  #include <xcb/glx.h>  #include <X11/Xlib-xcb.h> +#ifdef __linux__  #include <linux/input-event-codes.h> +#elif __FreeBSD__ +#include <dev/evdev/input-event-codes.h> +#endif  #include <wlr/backend/interface.h>  #include <wlr/backend/x11.h>  #include <wlr/egl.h> @@ -59,8 +63,7 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e  		x11->time = ev->time;  		break;  	} -	case XCB_BUTTON_PRESS: -	case XCB_BUTTON_RELEASE: { +	case XCB_BUTTON_PRESS: {  		xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event;  		if (ev->detail == XCB_BUTTON_INDEX_4 || @@ -75,7 +78,16 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e  				.delta = delta,  			};  			wl_signal_emit(&x11->pointer.events.axis, &axis); -		} else { +			x11->time = ev->time; +			break; +		} +	} +	/* fallthrough */ +	case XCB_BUTTON_RELEASE: { +		xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; + +		if (ev->detail != XCB_BUTTON_INDEX_4 && +				ev->detail != XCB_BUTTON_INDEX_5) {  			struct wlr_event_pointer_button button = {  				.device = &x11->pointer_dev,  				.time_sec = ev->time / 1000,  | 
