| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | #include <assert.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | #include <stdint.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-12 21:29:23 +01:00
										 |  |  | #include <stdio.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | #include <sys/mman.h>
 | 
					
						
							| 
									
										
										
										
											2018-02-12 21:29:23 +01:00
										 |  |  | #include <sys/types.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | #include <wayland-client.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-21 10:27:45 -04:00
										 |  |  | #include <wlr/interfaces/wlr_output.h>
 | 
					
						
							| 
									
										
										
										
											2018-03-20 23:10:42 +01:00
										 |  |  | #include <wlr/render/wlr_renderer.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-21 12:10:07 -04:00
										 |  |  | #include <wlr/util/log.h>
 | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | #include "backend/wayland.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-12 21:29:23 +01:00
										 |  |  | #include "util/signal.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | #include "xdg-shell-unstable-v6-client-protocol.h"
 | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | int os_create_anonymous_file(off_t size); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | static struct wl_callback_listener frame_listener; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-26 22:39:23 +01:00
										 |  |  | static void surface_frame_callback(void *data, struct wl_callback *cb, | 
					
						
							|  |  |  | 		uint32_t time) { | 
					
						
							| 
									
										
										
										
											2018-01-18 13:06:57 +01:00
										 |  |  | 	struct wlr_wl_backend_output *output = data; | 
					
						
							| 
									
										
										
										
											2018-01-26 22:39:23 +01:00
										 |  |  | 	assert(output); | 
					
						
							| 
									
										
										
										
											2017-06-26 11:34:22 -04:00
										 |  |  | 	wl_callback_destroy(cb); | 
					
						
							| 
									
										
										
										
											2018-01-18 13:06:57 +01:00
										 |  |  | 	output->frame_callback = NULL; | 
					
						
							| 
									
										
										
										
											2018-01-30 14:45:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	wlr_output_send_frame(&output->wlr_output); | 
					
						
							| 
									
										
										
										
											2017-06-26 11:34:22 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static struct wl_callback_listener frame_listener = { | 
					
						
							|  |  |  | 	.done = surface_frame_callback | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static bool output_set_custom_mode(struct wlr_output *_output, | 
					
						
							| 
									
										
										
										
											2017-12-11 12:14:23 +01:00
										 |  |  | 		int32_t width, int32_t height, int32_t refresh) { | 
					
						
							|  |  |  | 	struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output; | 
					
						
							|  |  |  | 	wl_egl_window_resize(output->egl_window, width, height, 0, 0); | 
					
						
							| 
									
										
										
										
											2017-12-17 18:02:55 +01:00
										 |  |  | 	wlr_output_update_custom_mode(&output->wlr_output, width, height, 0); | 
					
						
							| 
									
										
										
										
											2017-12-11 12:14:23 +01:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static bool output_make_current(struct wlr_output *wlr_output, | 
					
						
							| 
									
										
										
										
											2018-01-21 00:06:35 +01:00
										 |  |  | 		int *buffer_age) { | 
					
						
							|  |  |  | 	struct wlr_wl_backend_output *output = | 
					
						
							|  |  |  | 		(struct wlr_wl_backend_output *)wlr_output; | 
					
						
							|  |  |  | 	return wlr_egl_make_current(&output->backend->egl, output->egl_surface, | 
					
						
							|  |  |  | 		buffer_age); | 
					
						
							| 
									
										
										
										
											2017-06-26 11:34:22 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static bool output_swap_buffers(struct wlr_output *wlr_output, | 
					
						
							| 
									
										
										
										
											2018-02-09 22:54:14 +01:00
										 |  |  | 		pixman_region32_t *damage) { | 
					
						
							| 
									
										
										
										
											2018-01-21 00:06:35 +01:00
										 |  |  | 	struct wlr_wl_backend_output *output = | 
					
						
							|  |  |  | 		(struct wlr_wl_backend_output *)wlr_output; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-30 14:45:02 +01:00
										 |  |  | 	if (output->frame_callback != NULL) { | 
					
						
							|  |  |  | 		wlr_log(L_ERROR, "Skipping buffer swap"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | 	output->frame_callback = wl_surface_frame(output->surface); | 
					
						
							|  |  |  | 	wl_callback_add_listener(output->frame_callback, &frame_listener, output); | 
					
						
							| 
									
										
										
										
											2018-01-21 00:06:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-09 22:54:14 +01:00
										 |  |  | 	return wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface, | 
					
						
							|  |  |  | 		damage); | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static void output_transform(struct wlr_output *_output, | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 		enum wl_output_transform transform) { | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	struct wlr_wl_backend_output *output = (struct wlr_wl_backend_output *)_output; | 
					
						
							|  |  |  | 	output->wlr_output.transform = transform; | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static bool output_set_cursor(struct wlr_output *_output, | 
					
						
							| 
									
										
										
										
											2017-10-06 09:07:08 +03:00
										 |  |  | 		const uint8_t *buf, int32_t stride, uint32_t width, uint32_t height, | 
					
						
							| 
									
										
										
										
											2017-10-12 09:40:51 +02:00
										 |  |  | 		int32_t hotspot_x, int32_t hotspot_y, bool update_pixels) { | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	struct wlr_wl_backend_output *output = | 
					
						
							|  |  |  | 		(struct wlr_wl_backend_output *)_output; | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	struct wlr_wl_backend *backend = output->backend; | 
					
						
							| 
									
										
										
										
											2017-10-08 21:21:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-01 14:25:41 +01:00
										 |  |  | 	// TODO: use output->wlr_output.transform to transform pixels and hotpot
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	output->cursor.hotspot_x = hotspot_x; | 
					
						
							|  |  |  | 	output->cursor.hotspot_y = hotspot_y; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-12 09:40:51 +02:00
										 |  |  | 	if (!update_pixels) { | 
					
						
							|  |  |  | 		// Update hotspot without changing cursor image
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:24:58 +01:00
										 |  |  | 		update_wl_output_cursor(output); | 
					
						
							| 
									
										
										
										
											2017-10-12 09:40:51 +02:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-08 21:21:06 +02:00
										 |  |  | 	if (!buf) { | 
					
						
							| 
									
										
										
										
											2017-10-12 09:40:51 +02:00
										 |  |  | 		// Hide cursor
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 		if (output->cursor.surface) { | 
					
						
							|  |  |  | 			wl_surface_destroy(output->cursor.surface); | 
					
						
							|  |  |  | 			munmap(output->cursor.data, output->cursor.buf_size); | 
					
						
							|  |  |  | 			output->cursor.surface = NULL; | 
					
						
							|  |  |  | 			output->cursor.buf_size = 0; | 
					
						
							| 
									
										
										
										
											2017-10-18 19:14:16 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2018-04-25 23:24:58 +01:00
										 |  |  | 		update_wl_output_cursor(output); | 
					
						
							| 
									
										
										
										
											2017-10-08 21:21:06 +02:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	if (!backend->shm || !backend->pointer) { | 
					
						
							|  |  |  | 		wlr_log(L_INFO, "cannot set cursor, no shm or pointer"); | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	if (!output->cursor.surface) { | 
					
						
							|  |  |  | 		output->cursor.surface = | 
					
						
							|  |  |  | 			wl_compositor_create_surface(output->backend->compositor); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	uint32_t size = stride * height; | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	if (output->cursor.buf_size != size) { | 
					
						
							|  |  |  | 		if (output->cursor.buffer) { | 
					
						
							|  |  |  | 			wl_buffer_destroy(output->cursor.buffer); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 		if (size > output->cursor.buf_size) { | 
					
						
							|  |  |  | 			if (output->cursor.pool) { | 
					
						
							|  |  |  | 				wl_shm_pool_destroy(output->cursor.pool); | 
					
						
							|  |  |  | 				output->cursor.pool = NULL; | 
					
						
							|  |  |  | 				munmap(output->cursor.data, output->cursor.buf_size); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 		if (!output->cursor.pool) { | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 			int fd = os_create_anonymous_file(size); | 
					
						
							|  |  |  | 			if (fd < 0) { | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 				wlr_log_errno(L_INFO, | 
					
						
							|  |  |  | 					"creating anonymous file for cursor buffer failed"); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 				return false; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 			output->cursor.data = mmap(NULL, size, PROT_READ | PROT_WRITE, | 
					
						
							|  |  |  | 				MAP_SHARED, fd, 0); | 
					
						
							|  |  |  | 			if (output->cursor.data == MAP_FAILED) { | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 				close(fd); | 
					
						
							|  |  |  | 				wlr_log_errno(L_INFO, "mmap failed"); | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 			output->cursor.pool = wl_shm_create_pool(backend->shm, fd, size); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 			close(fd); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 		output->cursor.buffer = wl_shm_pool_create_buffer(output->cursor.pool, | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 			0, width, height, stride, WL_SHM_FORMAT_ARGB8888); | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 		output->cursor.buf_size = size; | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	memcpy(output->cursor.data, buf, size); | 
					
						
							|  |  |  | 	wl_surface_attach(output->cursor.surface, output->cursor.buffer, 0, 0); | 
					
						
							|  |  |  | 	wl_surface_damage(output->cursor.surface, 0, 0, width, height); | 
					
						
							|  |  |  | 	wl_surface_commit(output->cursor.surface); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:24:58 +01:00
										 |  |  | 	update_wl_output_cursor(output); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static void output_destroy(struct wlr_output *wlr_output) { | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	struct wlr_wl_backend_output *output = | 
					
						
							| 
									
										
										
										
											2018-01-30 19:45:57 +01:00
										 |  |  | 		(struct wlr_wl_backend_output *)wlr_output; | 
					
						
							|  |  |  | 	if (output == NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 21:48:59 +01:00
										 |  |  | 	wl_list_remove(&output->link); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	if (output->cursor.buf_size != 0) { | 
					
						
							|  |  |  | 		assert(output->cursor.data); | 
					
						
							|  |  |  | 		assert(output->cursor.buffer); | 
					
						
							|  |  |  | 		assert(output->cursor.pool); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		wl_buffer_destroy(output->cursor.buffer); | 
					
						
							|  |  |  | 		munmap(output->cursor.data, output->cursor.buf_size); | 
					
						
							|  |  |  | 		wl_shm_pool_destroy(output->cursor.pool); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	if (output->cursor.surface) { | 
					
						
							|  |  |  | 		wl_surface_destroy(output->cursor.surface); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-12 11:43:36 -04:00
										 |  |  | 	if (output->frame_callback) { | 
					
						
							|  |  |  | 		wl_callback_destroy(output->frame_callback); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-12-13 21:48:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-24 23:44:43 +01:00
										 |  |  | 	wlr_egl_destroy_surface(&output->backend->egl, output->egl_surface); | 
					
						
							| 
									
										
										
										
											2017-06-20 19:01:20 +02:00
										 |  |  | 	wl_egl_window_destroy(output->egl_window); | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 	zxdg_toplevel_v6_destroy(output->xdg_toplevel); | 
					
						
							|  |  |  | 	zxdg_surface_v6_destroy(output->xdg_surface); | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 	wl_surface_destroy(output->surface); | 
					
						
							|  |  |  | 	free(output); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:24:58 +01:00
										 |  |  | void update_wl_output_cursor(struct wlr_wl_backend_output *output) { | 
					
						
							| 
									
										
										
										
											2017-10-29 17:43:26 +01:00
										 |  |  | 	if (output->backend->pointer && output->enter_serial) { | 
					
						
							|  |  |  | 		wl_pointer_set_cursor(output->backend->pointer, output->enter_serial, | 
					
						
							|  |  |  | 			output->cursor.surface, output->cursor.hotspot_x, | 
					
						
							|  |  |  | 			output->cursor.hotspot_y); | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | bool output_move_cursor(struct wlr_output *_output, int x, int y) { | 
					
						
							| 
									
										
										
										
											2017-08-14 18:19:42 +02:00
										 |  |  | 	// TODO: only return true if x == current x and y == current y
 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-25 23:51:00 +01:00
										 |  |  | static const struct wlr_output_impl output_impl = { | 
					
						
							|  |  |  | 	.set_custom_mode = output_set_custom_mode, | 
					
						
							|  |  |  | 	.transform = output_transform, | 
					
						
							|  |  |  | 	.destroy = output_destroy, | 
					
						
							|  |  |  | 	.make_current = output_make_current, | 
					
						
							|  |  |  | 	.swap_buffers = output_swap_buffers, | 
					
						
							|  |  |  | 	.set_cursor = output_set_cursor, | 
					
						
							|  |  |  | 	.move_cursor = output_move_cursor, | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-19 19:55:18 +01:00
										 |  |  | bool wlr_output_is_wl(struct wlr_output *wlr_output) { | 
					
						
							|  |  |  | 	return wlr_output->impl == &output_impl; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | static void xdg_surface_handle_configure(void *data, struct zxdg_surface_v6 *xdg_surface, | 
					
						
							|  |  |  | 		uint32_t serial) { | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	struct wlr_wl_backend_output *output = data; | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 	assert(output && output->xdg_surface == xdg_surface); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	zxdg_surface_v6_ack_configure(xdg_surface, serial); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// nothing else?
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | static struct zxdg_surface_v6_listener xdg_surface_listener = { | 
					
						
							|  |  |  | 	.configure = xdg_surface_handle_configure, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void xdg_toplevel_handle_configure(void *data, struct zxdg_toplevel_v6 *xdg_toplevel, | 
					
						
							|  |  |  | 		int32_t width, int32_t height, struct wl_array *states) { | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	struct wlr_wl_backend_output *output = data; | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 	assert(output && output->xdg_toplevel == xdg_toplevel); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 10:22:54 +02:00
										 |  |  | 	if (width == 0 && height == 0) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 	// loop over states for maximized etc?
 | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	wl_egl_window_resize(output->egl_window, width, height, 0, 0); | 
					
						
							| 
									
										
										
										
											2017-12-17 18:02:55 +01:00
										 |  |  | 	wlr_output_update_custom_mode(&output->wlr_output, width, height, 0); | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | static void xdg_toplevel_handle_close(void *data, struct zxdg_toplevel_v6 *xdg_toplevel) { | 
					
						
							|  |  |  | 	struct wlr_wl_backend_output *output = data; | 
					
						
							| 
									
										
										
										
											2017-11-01 20:14:52 +01:00
										 |  |  | 	assert(output && output->xdg_toplevel == xdg_toplevel); | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-13 21:48:59 +01:00
										 |  |  | 	wlr_output_destroy((struct wlr_output *)output); | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | static struct zxdg_toplevel_v6_listener xdg_toplevel_listener = { | 
					
						
							|  |  |  | 	.configure = xdg_toplevel_handle_configure, | 
					
						
							|  |  |  | 	.close = xdg_toplevel_handle_close, | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 18:22:21 -04:00
										 |  |  | struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) { | 
					
						
							|  |  |  | 	assert(wlr_backend_is_wl(_backend)); | 
					
						
							| 
									
										
										
										
											2017-08-12 11:43:36 -04:00
										 |  |  | 	struct wlr_wl_backend *backend = (struct wlr_wl_backend *)_backend; | 
					
						
							| 
									
										
										
										
											2017-09-23 00:29:53 -04:00
										 |  |  | 	if (!backend->started) { | 
					
						
							| 
									
										
										
										
											2017-06-20 18:22:21 -04:00
										 |  |  | 		++backend->requested_outputs; | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	struct wlr_wl_backend_output *output; | 
					
						
							|  |  |  | 	if (!(output = calloc(sizeof(struct wlr_wl_backend_output), 1))) { | 
					
						
							| 
									
										
										
										
											2017-08-14 16:16:20 +02:00
										 |  |  | 		wlr_log(L_ERROR, "Failed to allocate wlr_wl_backend_output"); | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-01-04 12:46:15 +01:00
										 |  |  | 	wlr_output_init(&output->wlr_output, &backend->backend, &output_impl, | 
					
						
							|  |  |  | 		backend->local_display); | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	struct wlr_output *wlr_output = &output->wlr_output; | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-17 18:02:55 +01:00
										 |  |  | 	wlr_output_update_custom_mode(wlr_output, 1280, 720, 0); | 
					
						
							| 
									
										
										
										
											2017-06-20 15:29:27 -04:00
										 |  |  | 	strncpy(wlr_output->make, "wayland", sizeof(wlr_output->make)); | 
					
						
							|  |  |  | 	strncpy(wlr_output->model, "wayland", sizeof(wlr_output->model)); | 
					
						
							| 
									
										
										
										
											2017-10-14 23:33:00 +03:00
										 |  |  | 	snprintf(wlr_output->name, sizeof(wlr_output->name), "WL-%d", | 
					
						
							| 
									
										
										
										
											2017-10-23 21:03:00 +02:00
										 |  |  | 		wl_list_length(&backend->outputs) + 1); | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	output->backend = backend; | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	output->surface = wl_compositor_create_surface(backend->compositor); | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 	if (!output->surface) { | 
					
						
							|  |  |  | 		wlr_log_errno(L_ERROR, "Could not create output surface"); | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 	output->xdg_surface = | 
					
						
							|  |  |  | 		zxdg_shell_v6_get_xdg_surface(backend->shell, output->surface); | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 	if (!output->xdg_surface) { | 
					
						
							|  |  |  | 		wlr_log_errno(L_ERROR, "Could not get xdg surface"); | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 	output->xdg_toplevel = | 
					
						
							|  |  |  | 		zxdg_surface_v6_get_toplevel(output->xdg_surface); | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 	if (!output->xdg_toplevel) { | 
					
						
							|  |  |  | 		wlr_log_errno(L_ERROR, "Could not get xdg toplevel"); | 
					
						
							|  |  |  | 		goto error; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-16 21:01:39 +02:00
										 |  |  | 	zxdg_toplevel_v6_set_app_id(output->xdg_toplevel, "wlroots"); | 
					
						
							|  |  |  | 	zxdg_toplevel_v6_set_title(output->xdg_toplevel, "wlroots"); | 
					
						
							| 
									
										
										
										
											2017-08-16 19:19:31 +02:00
										 |  |  | 	zxdg_surface_v6_add_listener(output->xdg_surface, | 
					
						
							|  |  |  | 			&xdg_surface_listener, output); | 
					
						
							|  |  |  | 	zxdg_toplevel_v6_add_listener(output->xdg_toplevel, | 
					
						
							|  |  |  | 			&xdg_toplevel_listener, output); | 
					
						
							| 
									
										
										
										
											2017-08-17 00:52:01 +02:00
										 |  |  | 	wl_surface_commit(output->surface); | 
					
						
							| 
									
										
										
										
											2017-06-20 18:27:05 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	output->egl_window = wl_egl_window_create(output->surface, | 
					
						
							| 
									
										
										
										
											2017-06-20 17:51:45 -04:00
										 |  |  | 			wlr_output->width, wlr_output->height); | 
					
						
							| 
									
										
										
										
											2018-03-20 23:10:42 +01:00
										 |  |  | 	output->egl_surface = wlr_egl_create_surface(&backend->egl, | 
					
						
							|  |  |  | 		output->egl_window); | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-17 10:22:54 +02:00
										 |  |  | 	wl_display_roundtrip(output->backend->remote_display); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-20 17:51:45 -04:00
										 |  |  | 	// start rendering loop per callbacks by rendering first frame
 | 
					
						
							| 
									
										
										
										
											2018-03-20 23:10:42 +01:00
										 |  |  | 	if (!wlr_egl_make_current(&output->backend->egl, output->egl_surface, | 
					
						
							|  |  |  | 			NULL)) { | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 		goto error; | 
					
						
							| 
									
										
										
										
											2017-06-20 17:51:45 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 23:10:42 +01:00
										 |  |  | 	wlr_renderer_begin(backend->renderer, wlr_output->width, wlr_output->height); | 
					
						
							|  |  |  | 	wlr_renderer_clear(backend->renderer, (float[]){ 1.0, 1.0, 1.0, 1.0 }); | 
					
						
							|  |  |  | 	wlr_renderer_end(backend->renderer); | 
					
						
							| 
									
										
										
										
											2017-06-20 17:51:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-13 10:51:50 -04:00
										 |  |  | 	output->frame_callback = wl_surface_frame(output->surface); | 
					
						
							|  |  |  | 	wl_callback_add_listener(output->frame_callback, &frame_listener, output); | 
					
						
							| 
									
										
										
										
											2017-06-20 17:51:45 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 23:10:42 +01:00
										 |  |  | 	if (!wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface, | 
					
						
							|  |  |  | 			NULL)) { | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 		goto error; | 
					
						
							| 
									
										
										
										
											2017-06-20 17:51:45 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-10-14 23:33:00 +03:00
										 |  |  | 	wl_list_insert(&backend->outputs, &output->link); | 
					
						
							| 
									
										
										
										
											2018-01-04 12:46:15 +01:00
										 |  |  | 	wlr_output_update_enabled(wlr_output, true); | 
					
						
							| 
									
										
										
										
											2018-02-12 10:36:43 +01:00
										 |  |  | 	wlr_signal_emit_safe(&backend->backend.events.new_output, wlr_output); | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | 	return wlr_output; | 
					
						
							| 
									
										
										
										
											2017-08-16 19:33:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | error: | 
					
						
							|  |  |  | 	wlr_output_destroy(&output->wlr_output); | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							| 
									
										
										
										
											2017-06-19 22:36:40 +02:00
										 |  |  | } |