|  |  |  | @ -1,50 +1,43 @@ | 
			
		
	
		
			
				
					|  |  |  |  | #define _POSIX_C_SOURCE 200809 | 
			
		
	
		
			
				
					|  |  |  |  | #include <assert.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <cairo.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <errno.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <fcntl.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <pango/pangocairo.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <stdio.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <stdlib.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <string.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <sys/mman.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <time.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <unistd.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include <wayland-client.h> | 
			
		
	
		
			
				
					|  |  |  |  | #include "config.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "pool-buffer.h" | 
			
		
	
		
			
				
					|  |  |  |  | #include "util.h" | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static int create_pool_file(size_t size, char **name) { | 
			
		
	
		
			
				
					|  |  |  |  | 	static const char template[] = "sway-client-XXXXXX"; | 
			
		
	
		
			
				
					|  |  |  |  | 	const char *path = getenv("XDG_RUNTIME_DIR"); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (path == NULL) { | 
			
		
	
		
			
				
					|  |  |  |  | 		fprintf(stderr, "XDG_RUNTIME_DIR is not set\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t name_size = strlen(template) + 1 + strlen(path) + 1; | 
			
		
	
		
			
				
					|  |  |  |  | 	*name = malloc(name_size); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (*name == NULL) { | 
			
		
	
		
			
				
					|  |  |  |  | 		fprintf(stderr, "allocation failed\n"); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	snprintf(*name, name_size, "%s/%s", path, template); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	int fd = mkstemp(*name); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (fd < 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (!sway_set_cloexec(fd, true)) { | 
			
		
	
		
			
				
					|  |  |  |  | 		close(fd); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | static int anonymous_shm_open(void) { | 
			
		
	
		
			
				
					|  |  |  |  | 	int retries = 100; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	do { | 
			
		
	
		
			
				
					|  |  |  |  | 		// try a probably-unique name
 | 
			
		
	
		
			
				
					|  |  |  |  | 		struct timespec ts; | 
			
		
	
		
			
				
					|  |  |  |  | 		clock_gettime(CLOCK_MONOTONIC, &ts); | 
			
		
	
		
			
				
					|  |  |  |  | 		pid_t pid = getpid(); | 
			
		
	
		
			
				
					|  |  |  |  | 		char name[50]; | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(name, sizeof(name), "/sway-%x-%x", | 
			
		
	
		
			
				
					|  |  |  |  | 			(unsigned int)pid, (unsigned int)ts.tv_nsec); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 		// shm_open guarantees that O_CLOEXEC is set
 | 
			
		
	
		
			
				
					|  |  |  |  | 		int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (fd >= 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 			shm_unlink(name); | 
			
		
	
		
			
				
					|  |  |  |  | 			return fd; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ftruncate(fd, size) < 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		close(fd); | 
			
		
	
		
			
				
					|  |  |  |  | 		return -1; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 		--retries; | 
			
		
	
		
			
				
					|  |  |  |  | 	} while (retries > 0 && errno == EEXIST); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	return fd; | 
			
		
	
		
			
				
					|  |  |  |  | 	return -1; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static void buffer_release(void *data, struct wl_buffer *wl_buffer) { | 
			
		
	
	
		
			
				
					|  |  |  | @ -62,17 +55,20 @@ static struct pool_buffer *create_buffer(struct wl_shm *shm, | 
			
		
	
		
			
				
					|  |  |  |  | 	uint32_t stride = width * 4; | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t size = stride * height; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	char *name; | 
			
		
	
		
			
				
					|  |  |  |  | 	int fd = create_pool_file(size, &name); | 
			
		
	
		
			
				
					|  |  |  |  | 	assert(fd != -1); | 
			
		
	
		
			
				
					|  |  |  |  | 	int fd = anonymous_shm_open(); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (fd == -1) { | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	if (ftruncate(fd, size) < 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		close(fd); | 
			
		
	
		
			
				
					|  |  |  |  | 		return NULL; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); | 
			
		
	
		
			
				
					|  |  |  |  | 	struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); | 
			
		
	
		
			
				
					|  |  |  |  | 	buf->buffer = wl_shm_pool_create_buffer(pool, 0, | 
			
		
	
		
			
				
					|  |  |  |  | 			width, height, stride, format); | 
			
		
	
		
			
				
					|  |  |  |  | 	wl_shm_pool_destroy(pool); | 
			
		
	
		
			
				
					|  |  |  |  | 	close(fd); | 
			
		
	
		
			
				
					|  |  |  |  | 	unlink(name); | 
			
		
	
		
			
				
					|  |  |  |  | 	free(name); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	buf->size = size; | 
			
		
	
		
			
				
					|  |  |  |  | 	buf->width = width; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |