diff options
| -rw-r--r-- | backend/session/direct-freebsd.c | 56 | ||||
| -rw-r--r-- | backend/session/direct-ipc.c | 21 | 
2 files changed, 66 insertions, 11 deletions
| diff --git a/backend/session/direct-freebsd.c b/backend/session/direct-freebsd.c index 63e1be01..7784296b 100644 --- a/backend/session/direct-freebsd.c +++ b/backend/session/direct-freebsd.c @@ -23,6 +23,7 @@ const struct session_impl session_direct;  struct direct_session {  	struct wlr_session base;  	int tty_fd; +	int old_tty;  	int old_kbmode;  	int sock;  	pid_t child; @@ -40,12 +41,6 @@ static int direct_session_open(struct wlr_session *base, const char *path) {  		return fd;  	} -	struct stat st; -	if (fstat(fd, &st) < 0) { -		close(fd); -		return -errno; -	} -  	return fd;  } @@ -59,6 +54,20 @@ static void direct_session_close(struct wlr_session *base, int fd) {  		return;  	} +	char *name; +	name = devname(st.st_rdev, S_IFCHR); +	if (name == NULL) { +		wlr_log_errno(WLR_ERROR, "Failed to get device name"); +		close(fd); +		return; +	} + +	if (strncmp(name, "drm/", 4) == 0) { +		direct_ipc_dropmaster(session->sock, fd); +	} else if (strncmp(name, "input/event", 11)) { +		ioctl(fd, EVIOCREVOKE, 0); +	} +  	close(fd);  } @@ -79,6 +88,8 @@ static void direct_session_destroy(struct wlr_session *base) {  	ioctl(session->tty_fd, KDSETMODE, KD_TEXT);  	ioctl(session->tty_fd, VT_SETMODE, &mode); +	ioctl(session->tty_fd, VT_ACTIVATE, session->old_tty); +  	if (errno) {  		wlr_log(WLR_ERROR, "Failed to restore tty");  	} @@ -97,9 +108,29 @@ static int vt_handler(int signo, void *data) {  	if (session->base.active) {  		session->base.active = false;  		wlr_signal_emit_safe(&session->base.session_signal, session); + +		char *name; +		struct wlr_device *dev; +		wl_list_for_each(dev, &session->base.devices, link) { +			name = devname(dev->dev, S_IFCHR); +			if (name != NULL && strncmp(name, "drm/", 4) == 0) { +				direct_ipc_dropmaster(session->sock, dev->fd); +			} +		} +  		ioctl(session->tty_fd, VT_RELDISP, 1);  	} else {  		ioctl(session->tty_fd, VT_RELDISP, VT_ACKACQ); + +		char *name; +		struct wlr_device *dev; +		wl_list_for_each(dev, &session->base.devices, link) { +			name = devname(dev->dev, S_IFCHR); +			if (name != NULL && strncmp(name, "drm/", 4) == 0) { +				direct_ipc_setmaster(session->sock, dev->fd); +			} +		} +  		session->base.active = true;  		wlr_signal_emit_safe(&session->base.session_signal, session);  	} @@ -108,11 +139,15 @@ static int vt_handler(int signo, void *data) {  }  static bool setup_tty(struct direct_session *session, struct wl_display *display) { -	int fd = -1, tty = -1, tty0_fd = -1; +	int fd = -1, tty = -1, tty0_fd = -1, old_tty = 1;  	if ((tty0_fd = open("/dev/ttyv0", O_RDWR | O_CLOEXEC)) < 0) {  		wlr_log_errno(WLR_ERROR, "Could not open /dev/ttyv0 to find a free vt");  		goto error;  	} +	if (ioctl(tty0_fd, VT_GETACTIVE, &old_tty) != 0) { +		wlr_log_errno(WLR_ERROR, "Could not get active vt"); +		goto error; +	}  	if (ioctl(tty0_fd, VT_OPENQRY, &tty) != 0) {  		wlr_log_errno(WLR_ERROR, "Could not find a free vt");  		goto error; @@ -168,13 +203,16 @@ static bool setup_tty(struct direct_session *session, struct wl_display *display  	session->base.vtnr = tty;  	session->tty_fd = fd; +	session->old_tty = old_tty;  	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); +	// In case we could not get the last active one, drop back to tty 1, +	// better than hanging in a useless blank console. Otherwise activate the +	// last active. +	ioctl(fd, VT_ACTIVATE, old_tty);  	close(fd);  	return false;  } diff --git a/backend/session/direct-ipc.c b/backend/session/direct-ipc.c index 5fdb95ac..99ffcb1b 100644 --- a/backend/session/direct-ipc.c +++ b/backend/session/direct-ipc.c @@ -142,6 +142,7 @@ static void communicate(int sock) {  				goto error;  			} +#ifndef __FreeBSD__  			struct stat st;  			if (fstat(fd, &st) < 0) {  				ret = errno; @@ -157,6 +158,19 @@ static void communicate(int sock) {  			if (maj == DRM_MAJOR && drmSetMaster(fd)) {  				ret = errno;  			} +#else +			if (strncmp(msg.path, "/dev/drm/", 9) && +				strncmp(msg.path, "/dev/input/event", 16)) { + +				ret = ENOTSUP; +				goto error; +			} + +			if (strncmp(msg.path, "/dev/drm/", 9) == 0 && drmSetMaster(fd)) { +				ret = errno; +			} +#endif +  error:  			send_msg(sock, ret ? -1 : fd, &ret, sizeof(ret));  			if (fd >= 0) { @@ -193,8 +207,11 @@ int direct_ipc_open(int sock, const char *path) {  	send_msg(sock, -1, &msg, sizeof(msg)); -	int fd, err; -	recv_msg(sock, &fd, &err, sizeof(err)); +	int fd, err, ret; +	int retry = 0; +	do { +		ret = recv_msg(sock, &fd, &err, sizeof(err)); +	} while (ret == 0 && retry++ < 3);  	return err ? -err : fd;  } | 
